}
// free() response
-static char* oilsAuthGetSalt(int userId) {
+static char* oilsAuthGetSalt(int user_id) {
char* salt_str = NULL;
- jsonObject* params = jsonParseFmt(
- "{\"from\":[\"actor.get_salt\",%d,\"%s\"]}", userId, "main");
+ jsonObject* params = jsonParseFmt( // free
+ "{\"from\":[\"actor.get_salt\",%d,\"%s\"]}", user_id, "main");
- jsonObject* salt_obj = oilsUtilsQuickReq(
- "open-ils.cstore", "open-ils.cstore.json_query", params);
+ jsonObject* salt_obj = // free
+ oilsUtilsCStoreReq("open-ils.cstore.json_query", params);
jsonObjectFree(params);
means that the client process needs either to be the same process that called the init
method or to receive the seed from the process that did so.
*/
-static int oilsAuthVerifyPassword( const osrfMethodContext* ctx,
- const jsonObject* userObj, const char* uname,
- const char* password, const char* nonce ) {
-
- // Get the username seed, as stored previously in memcache by the init method
- char* seed = osrfCacheGetString( "%s%s%s", OILS_AUTH_CACHE_PRFX, uname, nonce );
- if(!seed) {
- return osrfAppRequestRespondException( ctx->session,
- ctx->request, "No authentication seed found. "
- "open-ils.auth.authenticate.init must be called first "
- " (check that memcached is running and can be connected to) "
- );
- }
-
- // We won't be needing the seed again, remove it
- osrfCacheRemove( "%s%s%s", OILS_AUTH_CACHE_PRFX, uname, nonce );
+static int oilsAuthVerifyPassword( const osrfMethodContext* ctx, int user_id,
+ const char* identifier, const char* password, const char* nonce) {
- // Get the hashed password from the user object
- char* realPassword = oilsFMGetString( userObj, "passwd" );
+ int verified = 0;
- osrfLogInternal(OSRF_LOG_MARK, "oilsAuth retrieved real password: [%s]", realPassword);
- osrfLogDebug(OSRF_LOG_MARK, "oilsAuth retrieved seed from cache: %s", seed );
+ // We won't be needing the seed again, remove it
+ osrfCacheRemove("%s%s%s", OILS_AUTH_CACHE_PRFX, identifier, nonce);
- // Concatenate them and take an MD5 hash of the result
- char* maskedPw = md5sum( "%s%s", seed, realPassword );
+ // Ask the DB to verify the user's password.
+ // Here, the password is md5(md5(password) + salt)
- free(realPassword);
- free(seed);
+ jsonObject* params = jsonParseFmt( // free
+ "{\"from\":[\"actor.verify_passwd\",%d,\"main\",\"%s\"]}",
+ user_id, password);
- if( !maskedPw ) {
- // This happens only if md5sum() runs out of memory
- free( maskedPw );
- return -1; // md5sum() ran out of memory
- }
+ jsonObject* verify_obj = // free
+ oilsUtilsCStoreReq("open-ils.cstore.json_query", params);
- osrfLogDebug(OSRF_LOG_MARK, "oilsAuth generated masked password %s. "
- "Testing against provided password %s", maskedPw, password );
+ jsonObjectFree(params);
- int ret = 0;
- if( !strcmp( maskedPw, password ) )
- ret = 1;
+ if (verify_obj) {
+ verified = oilsUtilsIsDBTrue(
+ jsonObjectGetString(
+ jsonObjectGetKeyConst(
+ verify_obj, "actor.verify_passwd")));
- free(maskedPw);
+ jsonObjectFree(verify_obj);
+ }
- char* countkey = va_list_to_string( "%s%s%s", OILS_AUTH_CACHE_PRFX, uname, OILS_AUTH_COUNT_SFFX );
+ char* countkey = va_list_to_string("%s%s%s",
+ OILS_AUTH_CACHE_PRFX, identifier, OILS_AUTH_COUNT_SFFX );
jsonObject* countobject = osrfCacheGetObject( countkey );
if(countobject) {
long failcount = (long) jsonObjectGetNumber( countobject );
if(failcount >= _oilsAuthBlockCount) {
- ret = 0;
- osrfLogInfo(OSRF_LOG_MARK, "oilsAuth found too many recent failures for '%s' : %i, forcing failure state.", uname, failcount);
+ verified = 0;
+ osrfLogInfo(OSRF_LOG_MARK,
+ "oilsAuth found too many recent failures for '%s' : %i, "
+ "forcing failure state.", identifier, failcount);
}
- if(ret == 0) {
+ if(verified == 0) {
failcount += 1;
}
jsonObjectSetNumber( countobject, failcount );
}
free(countkey);
- return ret;
+ return verified;
}
/**
const jsonObject* args = jsonObjectGetIndex(ctx->params, 0);
const char* uname = jsonObjectGetString(jsonObjectGetKeyConst(args, "username"));
+ const char* identifier = jsonObjectGetString(jsonObjectGetKeyConst(args, "identifier"));
const char* password = jsonObjectGetString(jsonObjectGetKeyConst(args, "password"));
const char* type = jsonObjectGetString(jsonObjectGetKeyConst(args, "type"));
int orgloc = (int) jsonObjectGetNumber(jsonObjectGetKeyConst(args, "org"));
const char* ws = (workstation) ? workstation : "";
if (!nonce) nonce = "";
+ // we no longer care how the identifier reaches us,
+ // as long as we have one.
+ if (!identifier) {
+ if (uname) {
+ identifier = uname;
+ } else if (barcode) {
+ identifier = barcode;
+ }
+ }
+
+ if (!identifier) {
+ return osrfAppRequestRespondException(ctx->session, ctx->request,
+ "username/barcode and password required for method: %s",
+ ctx->method->name);
+ }
+
+
/* Use __FILE__, harmless_line_number for creating
* OILS_EVENT_AUTH_FAILED events (instead of OSRF_LOG_MARK) to avoid
* giving away information about why an authentication attempt failed.
if( !type )
type = OILS_AUTH_STAFF;
- if( !( (uname || barcode) && password) ) {
- return osrfAppRequestRespondException( ctx->session, ctx->request,
- "username/barcode and password required for method: %s", ctx->method->name );
- }
+ oilsEvent* response = NULL; // free
+ jsonObject* userObj = NULL; // free
+ int card_active = 1; // boolean; assume active until proven otherwise
+ int using_card = 0; // true if this is a barcode login
- oilsEvent* response = NULL;
- jsonObject* userObj = NULL;
- int card_active = 1; // boolean; assume active until proven otherwise
-
- // Fetch a row from the actor.usr table, by username if available,
- // or by barcode if not.
- if(uname) {
- userObj = oilsUtilsFetchUserByUsername( uname );
- if( userObj && JSON_NULL == userObj->type ) {
- jsonObjectFree( userObj );
- userObj = NULL; // username not found
- }
- }
- else if(barcode) {
- // Read from actor.card by barcode
-
- osrfLogInfo( OSRF_LOG_MARK, "Fetching user by barcode %s", barcode );
-
- jsonObject* params = jsonParseFmt("{\"barcode\":\"%s\"}", barcode);
- jsonObject* card = oilsUtilsQuickReq(
- "open-ils.cstore", "open-ils.cstore.direct.actor.card.search", params );
- jsonObjectFree( params );
-
- if( card && card->type != JSON_NULL ) {
- // Determine whether the card is active
- char* card_active_str = oilsFMGetString( card, "active" );
- card_active = oilsUtilsIsDBTrue( card_active_str );
- free( card_active_str );
-
- // Look up the user who owns the card
- char* userid = oilsFMGetString( card, "usr" );
- jsonObjectFree( card );
- params = jsonParseFmt( "[%s]", userid );
- free( userid );
- userObj = oilsUtilsQuickReq(
- "open-ils.cstore", "open-ils.cstore.direct.actor.user.retrieve", params );
- jsonObjectFree( params );
- if( userObj && JSON_NULL == userObj->type ) {
- // user not found (shouldn't happen, due to foreign key)
- jsonObjectFree( userObj );
- userObj = NULL;
+ char* cache_key = va_list_to_string(
+ "%s%s%s", OILS_AUTH_CACHE_PRFX, identifier, nonce);
+ jsonObject* cacheObj = osrfCacheGetObject(cache_key); // free
+
+ if (!cacheObj) {
+ return osrfAppRequestRespondException(ctx->session,
+ ctx->request, "No authentication seed found. "
+ "open-ils.auth.authenticate.init must be called first "
+ " (check that memcached is running and can be connected to) "
+ );
+ }
+
+ int user_id = jsonObjectGetNumber(
+ jsonObjectGetKeyConst(cacheObj, "user_id"));
+
+ jsonObject* param = jsonNewNumberObject(user_id); // free
+ userObj = oilsUtilsCStoreReq(
+ "open-ils.cstore.direct.actor.user.retrieve", param);
+ jsonObjectFree(param);
+
+ using_card = (jsonObjectGetKeyConst(cacheObj, "barcode") != NULL);
+
+ if (using_card) {
+ // see if the card is inactive
+
+ jsonObject* params = jsonParseFmt("{\"barcode\":\"%s\"}", identifier);
+ jsonObject* card = oilsUtilsCStoreReq(
+ "open-ils.cstore.direct.actor.card.search", params);
+ jsonObjectFree(params);
+
+ if (card) {
+ if (card->type != JSON_NULL) {
+ char* card_active_str = oilsFMGetString(card, "active");
+ card_active = oilsUtilsIsDBTrue(card_active_str);
+ free(card_active_str);
}
+ jsonObjectFree(card);
}
}
int barred = 0, deleted = 0;
char *barred_str, *deleted_str;
- if(userObj) {
- barred_str = oilsFMGetString( userObj, "barred" );
- barred = oilsUtilsIsDBTrue( barred_str );
- free( barred_str );
+ if (userObj) {
+ barred_str = oilsFMGetString(userObj, "barred");
+ barred = oilsUtilsIsDBTrue(barred_str);
+ free(barred_str);
- deleted_str = oilsFMGetString( userObj, "deleted" );
- deleted = oilsUtilsIsDBTrue( deleted_str );
- free( deleted_str );
+ deleted_str = oilsFMGetString(userObj, "deleted");
+ deleted = oilsUtilsIsDBTrue(deleted_str);
+ free(deleted_str);
}
if(!userObj || barred || deleted) {
// Such a user exists and isn't barred or deleted.
// Now see if he or she has the right credentials.
- int passOK = -1;
- if(uname)
- passOK = oilsAuthVerifyPassword( ctx, userObj, uname, password, nonce );
- else if (barcode)
- passOK = oilsAuthVerifyPassword( ctx, userObj, barcode, password, nonce );
+ int passOK = oilsAuthVerifyPassword(
+ ctx, user_id, identifier, password, nonce);
if( passOK < 0 ) {
jsonObjectFree(userObj);
}
free(active);
- osrfLogInfo( OSRF_LOG_MARK, "Fetching card by barcode %s", barcode );
-
if( !card_active ) {
osrfLogInfo( OSRF_LOG_MARK, "barcode %s is not active, returning event", barcode );
response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_CARD_INACTIVE" );