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 02:17:12 +0000 (22:17 -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 b553c5f..ee04276 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"
 
@@ -15,6 +16,9 @@
 #define OILS_AUTH_STAFF "staff"
 #define OILS_AUTH_TEMP "temp"
 
+#define OILS_AUTH_COUNT_MAX 10
+#define OILS_AUTH_COUNT_INTERVAL 90
+
 int osrfAppInitialize();
 int osrfAppChildInit();
 
@@ -90,6 +94,7 @@ int oilsAuthInit( osrfMethodContext* ctx ) {
        char* seed              = NULL;
        char* md5seed   = NULL;
        char* key               = NULL;
+       char* countkey  = NULL;
 
        if( (username = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0))) ) {
 
@@ -103,10 +108,16 @@ int oilsAuthInit( osrfMethodContext* ctx ) {
 
                        seed = va_list_to_string( "%d.%ld.%s", time(NULL), (long) getpid(), username );
                        key = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, username );
+                       countkey = va_list_to_string( "%s%s%s", OILS_AUTH_CACHE_PRFX, username, OILS_AUTH_COUNT_SFFX );
+
+                       jsonObject* countobject = osrfCacheGetObject( countkey );
+                       if(!countobject) {
+                               countobject = jsonNewNumberObject( (double) 0 );
+                       }
        
                        md5seed = md5sum(seed);
                        osrfCachePutString( key, md5seed, 30 );
-       
+                       osrfCachePutObject( countkey, countobject, OILS_AUTH_COUNT_INTERVAL );
                        osrfLogDebug( OSRF_LOG_MARK, "oilsAuthInit(): has seed %s and key %s", md5seed, key );
        
                        resp = jsonNewObject(md5seed);  
@@ -115,6 +126,8 @@ int oilsAuthInit( osrfMethodContext* ctx ) {
                        free(seed);
                        free(md5seed);
                        free(key);
+                       free( countkey );
+                       jsonObjectFree( countobject );
                }
 
                jsonObjectFree(resp);
@@ -195,6 +208,23 @@ static int oilsAuthVerifyPassword( const osrfMethodContext* ctx,
        free(seed);
        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;
 }