1 #include "opensrf/osrf_app_session.h"
2 #include "opensrf/osrf_application.h"
3 #include "objson/object.h"
4 #include "opensrf/log.h"
5 #include "oils_utils.h"
6 #include "oils_constants.h"
7 #include "oils_event.h"
9 #define OILS_AUTH_CACHE_PRFX "oils_auth_"
11 #define MODULENAME "open-ils.auth"
13 int osrfAppInitialize();
14 int osrfAppChildInit();
15 int osrfMathRun( osrfMethodContext* );
18 int osrfAppInitialize() {
20 osrfAppRegisterMethod(
22 "open-ils.auth.authenticate.init",
24 "Start the authentication process and returns the intermediate authentication seed"
25 " PARAMS( username )", 1, 0 );
27 osrfAppRegisterMethod(
29 "open-ils.auth.authenticate.complete",
31 "Completes the authentication process and returns the auth token "
32 "PARAMS(username, md5sum( seed + password ) )", 2, 0 );
34 osrfAppRegisterMethod(
36 "open-ils.auth.session.retrieve",
37 "oilsAuthSessionRetrieve",
38 "Returns the user object (password blanked) for the given login session "
39 "PARAMS( authToken )", 1, 0 );
41 osrfAppRegisterMethod(
43 "open-ils.auth.session.delete",
44 "oilsAuthSessionDelete",
45 "Destroys the given login session "
46 "PARAMS( authToken )", 1, 0 );
51 int osrfAppChildInit() {
55 int oilsAuthInit( osrfMethodContext* ctx ) {
56 OSRF_METHOD_VERIFY_CONTEXT(ctx);
59 char* username = NULL;
64 if( (username = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 0))) ) {
66 seed = va_list_to_string( "%d.%d.%s", time(NULL), getpid(), username );
67 key = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, username );
69 md5seed = md5sum(seed);
70 osrfCachePutString( key, md5seed, 30 );
72 osrfLogDebug( "oilsAuthInit(): has seed %s and key %s", md5seed, key );
74 resp = jsonNewObject(md5seed);
75 osrfAppRespondComplete( ctx, resp );
88 int oilsAuthComplete( osrfMethodContext* ctx ) {
89 OSRF_METHOD_VERIFY_CONTEXT(ctx);
91 char* uname = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 0));
92 char* password = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 1));
93 char* storageMethod = "open-ils.storage.direct.actor.user.search.usrname.atomic";
94 osrfMessage* omsg = NULL;
96 if( uname && password ) {
98 oilsEvent* response = NULL;
100 /* grab the user object from storage */
101 osrfLogDebug( "oilsAuth calling method %s with username %s", storageMethod, uname );
103 osrfAppSession* session = osrfAppSessionClientInit( "open-ils.storage" ); /**/
104 jsonObject* params = jsonParseString("[\"%s\"]", uname);
105 int reqid = osrfAppSessionMakeRequest( session, params, storageMethod, 1, NULL );
106 jsonObjectFree(params);
107 osrfLogInternal("oilsAuth waiting from response from storage...");
108 omsg = osrfAppSessionRequestRecv( session, reqid, 60 ); /**/
109 osrfLogInternal("oilsAuth storage request returned");
112 osrfAppSessionFree(session);
113 return osrfAppRequestRespondException( ctx->session, ctx->request,
114 "No response from storage server for method %s", storageMethod );
117 jsonObject* userObj = osrfMessageGetResult(omsg);
119 char* _j = jsonObjectToJSON(userObj);
120 osrfLogDebug( "Auth received user object from storage: %s", _j );
123 /* the method is atomic, grab the first user we receive */
124 if( userObj ) userObj = jsonObjectGetIndex(userObj, 0);
126 if(!userObj) { /* XXX needs to be a 'friendly' exception */
127 osrfMessageFree(omsg);
128 osrfAppSessionFree(session);
129 response = oilsNewEvent( OILS_EVENT_AUTH_FAILED );
130 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
131 oilsEventFree(response);
136 char* realPassword = oilsFMGetString( userObj, "passwd" ); /**/
137 char* seed = osrfCacheGetString( "%s%s", OILS_AUTH_CACHE_PRFX, uname ); /**/
140 osrfMessageFree(omsg);
141 osrfAppSessionFree(session);
142 return osrfAppRequestRespondException( ctx->session,
143 ctx->request, "No authentication seed found. "
144 "open-ils.auth.authenticate.init must be called first");
147 osrfLogDebug( "oilsAuth retrieved seed from cache: %s", seed );
148 char* maskedPw = md5sum( "%s%s", seed, realPassword );
149 if(!maskedPw) return -1;
150 osrfLogDebug( "oilsAuth generated masked password %s. "
151 "Testing against provided password %s", maskedPw, password );
154 if( !strcmp( maskedPw, password ) ) {
156 osrfLogActivity( "User %s successfully logged in", uname );
158 char* string = va_list_to_string( "%d.%d.%s", getpid(), time(NULL), uname ); /**/
159 char* authToken = md5sum(string); /**/
160 char* authKey = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
162 osrfLogInternal("oilsAuthComplete(): Setting fieldmapper string on the user object");
163 oilsFMSetString( userObj, "passwd", "" );
164 osrfCachePutObject( authKey, userObj, 28800 ); /* XXX config value */
165 osrfLogInternal("oilsAuthComplete(): Placed user object into cache");
166 response = oilsNewEvent2( OILS_EVENT_SUCCESS, jsonNewObject(authToken) );
167 free(string); free(authToken); free(authKey);
171 response = oilsNewEvent( OILS_EVENT_AUTH_FAILED );
172 osrfLogInfo( "Login failed for for %s", uname );
175 osrfLogInternal("oilsAuthComplete responding to client");
176 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
177 oilsEventFree(response);
178 osrfMessageFree(omsg);
179 osrfAppSessionFree(session);
182 return osrfAppRequestRespondException( ctx->session, ctx->request,
183 "username and password required for method: %s", ctx->method->name );
190 int oilsAuthSessionRetrieve( osrfMethodContext* ctx ) {
191 OSRF_METHOD_VERIFY_CONTEXT(ctx);
193 char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
194 jsonObject* userObj = NULL;
197 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
198 userObj = osrfCacheGetObject( key ); /**/
202 osrfAppRespondComplete( ctx, userObj );
203 jsonObjectFree(userObj);
207 int oilsAuthSessionDelete( osrfMethodContext* ctx ) {
208 OSRF_METHOD_VERIFY_CONTEXT(ctx);
210 char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
211 jsonObject* resp = NULL;
214 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
215 osrfCacheRemove(key);
216 resp = jsonNewObject(authToken); /**/
220 osrfAppRespondComplete( ctx, resp );
221 jsonObjectFree(resp);