Brute Force protection for authentication
authorThomas Berezansky <tsbere@mvlc.org>
Tue, 30 Aug 2011 15:55:35 +0000 (11:55 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 4 Oct 2011 16:54:21 +0000 (12:54 -0400)
Count auth failures in memcache.
If 10+ have occurred cause failure.

After 90 seconds of no activity counter resets.

Signed-off-by: Thomas Berezansky <tsbere@mvlc.org>
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/c-apps/oils_auth.c

index a4e30da..735d96b 100644 (file)
@@ -8,6 +8,7 @@
 #include "openils/oils_event.h"
 
 #define OILS_AUTH_CACHE_PRFX "oils_auth_"
+#define OILS_AUTH_COUNT_SFFX "_count"
 
 #define MODULENAME "open-ils.auth"
 
@@ -19,6 +20,9 @@
 // Default time for extending a persistent session: ten minutes
 #define DEFAULT_RESET_INTERVAL 10 * 60
 
+#define OILS_AUTH_COUNT_MAX 10
+#define OILS_AUTH_COUNT_INTERVAL 90
+
 int osrfAppInitialize();
 int osrfAppChildInit();
 
@@ -131,8 +135,14 @@ int oilsAuthInit( osrfMethodContext* ctx ) {
 
                        // Build a key and a seed; store them in memcache.
                        char* key  = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, username );
+                       char* countkey = va_list_to_string( "%s%s%s", OILS_AUTH_CACHE_PRFX, username, OILS_AUTH_COUNT_SFFX );
                        char* seed = md5sum( "%d.%ld.%s", (int) time(NULL), (long) getpid(), username );
+                       jsonObject* countobject = osrfCacheGetObject( countkey );
+                       if(!countobject) {
+                               countobject = jsonNewNumberObject( (double) 0 );
+                       }
                        osrfCachePutString( key, seed, 30 );
+                       osrfCachePutObject( countkey, countobject, OILS_AUTH_COUNT_INTERVAL );
 
                        osrfLogDebug( OSRF_LOG_MARK, "oilsAuthInit(): has seed %s and key %s", seed, key );
 
@@ -141,6 +151,8 @@ int oilsAuthInit( osrfMethodContext* ctx ) {
 
                        free( seed );
                        free( key );
+                       free( countkey );
+                       jsonObjectFree( countobject );
                }
 
                // Return the seed to the client.
@@ -257,6 +269,23 @@ static int oilsAuthVerifyPassword( const osrfMethodContext* ctx,
 
        free(maskedPw);
 
+       char* countkey = va_list_to_string( "%s%s%s", OILS_AUTH_CACHE_PRFX, uname, OILS_AUTH_COUNT_SFFX );
+       jsonObject* countobject = osrfCacheGetObject( countkey );
+       if(countobject) {
+               double failcount = jsonObjectGetNumber( countobject );
+               if(failcount >= OILS_AUTH_COUNT_MAX) {
+                       ret = 0;
+            osrfLogInternal(OSRF_LOG_MARK, "oilsAuth found too many recent failures: %d, forcing failure state.", failcount);
+               }
+               if(ret == 0) {
+                       failcount += 1;
+               }
+               jsonObjectSetNumber( countobject, failcount );
+               osrfCachePutObject( countkey, countobject, OILS_AUTH_COUNT_INTERVAL );
+               jsonObjectFree(countobject);
+       }
+       free(countkey);
+
        return ret;
 }