}
/**
- Verifies that the user has permission to login with the
- given type. If the permission fails, an oilsEvent is returned
- to the caller.
- @return -1 if the permission check failed, 0 if the permission
- is granted
-*/
-static int oilsAuthCheckLoginPerm(
- osrfMethodContext* ctx, const jsonObject* userObj, const char* type ) {
-
- if(!(userObj && type)) return -1;
- oilsEvent* perm = NULL;
-
- if(!strcasecmp(type, OILS_AUTH_OPAC)) {
- char* permissions[] = { "OPAC_LOGIN" };
- perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
-
- } else if(!strcasecmp(type, OILS_AUTH_STAFF)) {
- char* permissions[] = { "STAFF_LOGIN" };
- perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
-
- } else if(!strcasecmp(type, OILS_AUTH_TEMP)) {
- char* permissions[] = { "STAFF_LOGIN" };
- perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
- } else if(!strcasecmp(type, OILS_AUTH_PERSIST)) {
- char* permissions[] = { "PERSISTENT_LOGIN" };
- perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
- }
-
- if(perm) {
- osrfAppRespondComplete( ctx, oilsEventToJSON(perm) );
- oilsEventFree(perm);
- return -1;
- }
-
- return 0;
-}
-
-/**
Returns 1 if the password provided matches the user's real password
Returns 0 otherwise
Returns -1 on error
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
char* cache_key = va_list_to_string(
"%s%s%s", OILS_AUTH_CACHE_PRFX, identifier, nonce);
"open-ils.cstore.direct.actor.user.retrieve", param);
jsonObjectFree(param);
- using_card = (jsonObjectGetKeyConst(cacheObj, "barcode") != NULL);
+ char* freeable_uname = NULL;
+ if (!uname) {
+ uname = freeable_uname = oilsFMGetString(userObj, "usrname");
+ }
- if (using_card) {
- // see if the card is inactive
+ // See if the user is allowed to login.
- jsonObject* params = jsonParseFmt("{\"barcode\":\"%s\"}", identifier);
- jsonObject* card = oilsUtilsCStoreReq(
- "open-ils.cstore.direct.actor.card.search", params);
- jsonObjectFree(params);
+ jsonObject* params = jsonNewObject(NULL);
+ jsonObjectSetKey(params, "user_id",
+ jsonNewNumberObject(oilsFMGetObjectId(userObj)));
+ jsonObjectSetKey(params,"org_unit", jsonNewNumberObject(orgloc));
+ jsonObjectSetKey(params, "login_type", jsonNewObject(type));
- 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);
- }
- }
+ jsonObject* authEvt = oilsUtilsQuickReq( // freed after password test
+ "open-ils.auth_internal",
+ "open-ils.auth_internal.user.validate", params);
+ jsonObjectFree(params);
- int barred = 0, deleted = 0;
- char *barred_str, *deleted_str;
+ if (!authEvt) {
+ // Something went seriously wrong. Get outta here before
+ // we start segfaulting.
+ jsonObjectFree(userObj);
+ if(freeable_uname) free(freeable_uname);
+ return -1;
+ }
- if (userObj) {
- barred_str = oilsFMGetString(userObj, "barred");
- barred = oilsUtilsIsDBTrue(barred_str);
- free(barred_str);
+ const char* evtCode =
+ jsonObjectGetString(jsonObjectGetKey(authEvt, "textcode"));
- deleted_str = oilsFMGetString(userObj, "deleted");
- deleted = oilsUtilsIsDBTrue(deleted_str);
- free(deleted_str);
- }
+ // For security/privacy sake, only report that a patron is
+ // inactive if the correct password is provided below.
+ int user_inactive = !strcmp(evtCode, "PATRON_INACTIVE");
- if(!userObj || barred || deleted) {
- response = oilsNewEvent( __FILE__, harmless_line_number, OILS_EVENT_AUTH_FAILED );
- osrfLogInfo(OSRF_LOG_MARK, "failed login: username=%s, barcode=%s, workstation=%s",
- uname, (barcode ? barcode : "(none)"), ws );
- osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
- oilsEventFree(response);
- return 0; // No such user
- }
+ if (strcmp(evtCode, "SUCCESS") && !user_inactive) { // validate failed
+ osrfLogInfo(OSRF_LOG_MARK,
+ "failed login: username=%s, barcode=%s, workstation=%s",
+ uname, (barcode ? barcode : "(none)"), ws);
+ osrfAppRespondComplete(ctx, authEvt);
+ jsonObjectFree(authEvt);
+ jsonObjectFree(userObj);
+ if(freeable_uname) free(freeable_uname);
+ return 0; // No such user
+ }
// Such a user exists and isn't barred or deleted.
// Now see if he or she has the right credentials.
ctx, user_id, identifier, password, nonce);
if( passOK < 0 ) {
+ jsonObjectFree(authEvt);
jsonObjectFree(userObj);
+ if(freeable_uname) free(freeable_uname);
return passOK;
}
- // See if the account is active
- char* active = oilsFMGetString(userObj, "active");
- if( !oilsUtilsIsDBTrue(active) ) {
- if( passOK )
- response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_INACTIVE" );
- else
- response = oilsNewEvent( __FILE__, harmless_line_number, OILS_EVENT_AUTH_FAILED );
-
- osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
- oilsEventFree(response);
- jsonObjectFree(userObj);
- free(active);
- return 0;
- }
- free(active);
-
- if( !card_active ) {
- osrfLogInfo( OSRF_LOG_MARK, "barcode %s is not active, returning event", barcode );
- response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_CARD_INACTIVE" );
- osrfAppRespondComplete( ctx, oilsEventToJSON( response ) );
- oilsEventFree( response );
- jsonObjectFree( userObj );
- return 0;
- }
-
-
- // See if the user is even allowed to log in
- if( oilsAuthCheckLoginPerm( ctx, userObj, type ) == -1 ) {
- jsonObjectFree(userObj);
- return 0;
- }
+ if (passOK && user_inactive) {
+ // Patron is inactive but provided the correct password.
+ // Return the original PATRON_INACTIVE event.
+ osrfAppRespondComplete(ctx, authEvt);
+ jsonObjectFree(authEvt);
+ jsonObjectFree(userObj);
+ if(freeable_uname) free(freeable_uname);
+ return 0;
+ }
- char* freeable_uname = NULL;
- if(!uname) {
- uname = freeable_uname = oilsFMGetString( userObj, "usrname" );
- }
+ jsonObjectFree(authEvt); // we're all done with this now.
if( passOK ) { // login successful
// Default time for extending a persistent session: ten minutes
#define DEFAULT_RESET_INTERVAL 10 * 60
+int safe_line = __LINE__;
+#define OILS_LOG_MARK_SAFE __FILE__,safe_line
+
int osrfAppInitialize();
int osrfAppChildInit();
"the user is authenticated", 1, 0
);
+ osrfAppRegisterMethod(
+ MODULENAME,
+ "open-ils.auth_internal.user.validate",
+ "oilsAutInternalValidate",
+ "Determines whether a user should be allowed to login. "
+ "Returns SUCCESS oilsEvent when the user is valid, otherwise "
+ "returns a non-SUCCESS oilsEvent object", 1, 0
+ );
+
return 0;
}
return NULL;
}
+/**
+ Verifies that the user has permission to login with the given type.
+ Caller is responsible for freeing returned oilsEvent.
+ @return oilsEvent* if the permission check failed, NULL otherwise.
+*/
+static oilsEvent* oilsAuthCheckLoginPerm(osrfMethodContext* ctx,
+ int user_id, int org_id, const char* type ) {
+
+ char* perms[1];
+
+ if (!strcasecmp(type, OILS_AUTH_OPAC)) {
+ perms[0] = "OPAC_LOGIN";
+
+ } else if (!strcasecmp(type, OILS_AUTH_STAFF)) {
+ perms[0] = "STAFF_LOGIN";
+
+ } else if (!strcasecmp(type, OILS_AUTH_TEMP)) {
+ perms[0] = "STAFF_LOGIN";
+
+ } else if (!strcasecmp(type, OILS_AUTH_PERSIST)) {
+ perms[0] = "PERSISTENT_LOGIN";
+ }
+
+ return oilsUtilsCheckPerms(user_id, org_id, perms, 1);
+}
+
+
/**
@brief Implement the session create method
"Missing parameters for method: %s", ctx->method->name );
}
- oilsEvent* response = NULL;
+ oilsEvent* response = NULL;
// fetch the user object
jsonObject* idParam = jsonNewNumberStringObject(user_id);
return 0;
}
+
+int oilsAutInternalValidate(osrfMethodContext* ctx) {
+ OSRF_METHOD_VERIFY_CONTEXT(ctx);
+
+ const jsonObject* args = jsonObjectGetIndex(ctx->params, 0);
+
+ const char* user_id = jsonObjectGetString(jsonObjectGetKeyConst(args, "user_id"));
+ const char* barcode = jsonObjectGetString(jsonObjectGetKeyConst(args, "barcode"));
+ const char* org_unit = jsonObjectGetString(jsonObjectGetKeyConst(args, "org_unit"));
+ const char* login_type = jsonObjectGetString(jsonObjectGetKeyConst(args, "login_type"));
+
+ if ( !(user_id && login_type && org_unit) ) {
+ return osrfAppRequestRespondException( ctx->session, ctx->request,
+ "Missing parameters for method: %s", ctx->method->name );
+ }
+
+ oilsEvent* response = NULL;
+ jsonObject *userObj = NULL, *params = NULL;
+ char* tmp_str = NULL;
+ int user_exists = 0, user_active = 0,
+ user_barred = 0, user_deleted = 0;
+
+ // Confirm user exists, active=true, barred=false, deleted=false
+ params = jsonNewNumberStringObject(user_id);
+ userObj = oilsUtilsCStoreReq(
+ "open-ils.cstore.direct.actor.user.retrieve", params);
+ jsonObjectFree(params);
+
+ if (userObj && userObj->type != JSON_NULL) {
+ user_exists = 1;
+
+ tmp_str = oilsFMGetString(userObj, "active");
+ user_active = oilsUtilsIsDBTrue(tmp_str);
+ free(tmp_str);
+
+ tmp_str = oilsFMGetString(userObj, "barred");
+ user_barred = oilsUtilsIsDBTrue(tmp_str);
+ free(tmp_str);
+
+ tmp_str = oilsFMGetString(userObj, "deleted");
+ user_deleted = oilsUtilsIsDBTrue(tmp_str);
+ free(tmp_str);
+ }
+
+ if (!user_exists || user_barred || user_deleted) {
+ response = oilsNewEvent(OILS_LOG_MARK_SAFE, OILS_EVENT_AUTH_FAILED);
+ }
+
+ if (!response && !user_active) {
+ // In some cases, it's useful for the caller to know if the
+ // patron was unable to login becuase the account is inactive.
+ // Return a specific event for this.
+ response = oilsNewEvent(OILS_LOG_MARK_SAFE, "PATRON_INACTIVE");
+ }
+
+ if (!response && barcode) {
+ // Caller provided a barcode. Ensure it exists and is active.
+
+ int card_ok = 0;
+ params = jsonParseFmt("{\"barcode\":\"%s\"}", barcode);
+ jsonObject* card = oilsUtilsCStoreReq(
+ "open-ils.cstore.direct.actor.card.search", params);
+ jsonObjectFree(params);
+
+ if (card && card->type != JSON_NULL) {
+ tmp_str = oilsFMGetString(card, "active");
+ card_ok = oilsUtilsIsDBTrue(tmp_str);
+ free(tmp_str);
+ }
+
+ jsonObjectFree(card); // card=NULL OK here.
+
+ if (!card_ok) {
+ response = oilsNewEvent(
+ OILS_LOG_MARK_SAFE, "PATRON_CARD_INACTIVE");
+ }
+ }
+
+ if (!response) { // Still OK
+ // Confirm user has permission to login w/ the requested type.
+ response = oilsAuthCheckLoginPerm(
+ ctx, atoi(user_id), atoi(org_unit), login_type);
+ }
+
+
+ if (!response) {
+ // No tests failed. Return SUCCESS.
+ response = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_SUCCESS);
+ }
+
+
+ jsonObjectFree(userObj); // userObj=NULL OK here.
+ osrfAppRespondComplete(ctx, oilsEventToJSON(response));
+ oilsEventFree(response);
+
+ return 0;
+}
+