]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/c-apps/oils_auth.c
Added new C event code for handling the auth login events
[Evergreen.git] / Open-ILS / src / c-apps / oils_auth.c
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"
8
9 #define OILS_AUTH_CACHE_PRFX "oils_auth_"
10
11 #define MODULENAME "open-ils.auth"
12
13 int osrfAppInitialize();
14 int osrfAppChildInit();
15 int osrfMathRun( osrfMethodContext* );
16
17
18 int osrfAppInitialize() {
19
20         osrfAppRegisterMethod( 
21                 MODULENAME, 
22                 "open-ils.auth.authenticate.init", 
23                 "oilsAuthInit", 
24                 "Start the authentication process and returns the intermediate authentication seed"
25                 " PARAMS( username )", 1, 0 );
26
27         osrfAppRegisterMethod( 
28                 MODULENAME, 
29                 "open-ils.auth.authenticate.complete", 
30                 "oilsAuthComplete", 
31                 "Completes the authentication process and returns the auth token "
32                 "PARAMS(username, md5sum( seed + password ) )", 2, 0 );
33
34         osrfAppRegisterMethod( 
35                 MODULENAME, 
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 );
40
41         osrfAppRegisterMethod( 
42                 MODULENAME, 
43                 "open-ils.auth.session.delete", 
44                 "oilsAuthSessionDelete", 
45                 "Destroys the given login session "
46                 "PARAMS( authToken )",  1, 0 );
47
48         return 0;
49 }
50
51 int osrfAppChildInit() {
52         return 0;
53 }
54
55 int oilsAuthInit( osrfMethodContext* ctx ) {
56         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
57
58         jsonObject* resp;
59         char* username = NULL;
60         char* seed = NULL;
61         char* md5seed = NULL;
62         char* key = NULL;
63
64         if( (username = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 0))) ) {
65
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 );
68
69                 md5seed = md5sum(seed);
70                 osrfCachePutString( key, md5seed, 30 );
71
72                 osrfLogDebug( "oilsAuthInit(): has seed %s and key %s", md5seed, key );
73
74                 resp = jsonNewObject(md5seed);  
75                 osrfAppRespondComplete( ctx, resp );
76
77                 jsonObjectFree(resp);
78                 free(seed);
79                 free(md5seed);
80                 free(key);
81                 return 0;
82         }
83
84         return -1;
85 }
86
87
88 int oilsAuthComplete( osrfMethodContext* ctx ) {
89         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
90
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;
95
96         if( uname && password ) {
97
98                 oilsEvent* response = NULL;
99
100                 /* grab the user object from storage */
101                 osrfLogDebug( "oilsAuth calling method %s with username %s", storageMethod, uname );
102
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");
110
111                 if(!omsg) { 
112                         osrfAppSessionFree(session);
113                         return osrfAppRequestRespondException( ctx->session, ctx->request,
114                                 "No response from storage server for method %s", storageMethod ); 
115                 }
116
117                 jsonObject* userObj = osrfMessageGetResult(omsg);
118
119                 char* _j = jsonObjectToJSON(userObj);
120                 osrfLogDebug( "Auth received user object from storage: %s", _j );
121                 free(_j);
122
123                 /* the method is atomic, grab the first user we receive */
124                 if( userObj ) userObj = jsonObjectGetIndex(userObj, 0);
125                 
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);
132                         return 0;
133
134                 }
135
136                 char* realPassword = oilsFMGetString( userObj, "passwd" ); /**/
137                 char* seed = osrfCacheGetString( "%s%s", OILS_AUTH_CACHE_PRFX, uname ); /**/
138
139                 if(!seed) {
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");
145                 }
146
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 );
152
153
154                 if( !strcmp( maskedPw, password ) ) {
155
156                         osrfLogActivity( "User %s successfully logged in", uname );
157
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 ); /**/
161
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);
168
169                 } else {
170
171                         response = oilsNewEvent( OILS_EVENT_AUTH_FAILED );
172                         osrfLogInfo( "Login failed for for %s", uname );
173                 }
174
175                 osrfLogInternal("oilsAuthComplete responding to client");
176                 osrfAppRespondComplete( ctx, oilsEventToJSON(response) ); 
177                 oilsEventFree(response);
178                 osrfMessageFree(omsg);
179                 osrfAppSessionFree(session);
180
181         } else {
182                 return osrfAppRequestRespondException( ctx->session, ctx->request, 
183                         "username and password required for method: %s", ctx->method->name );
184         }
185
186         return 0;
187
188 }
189
190 int oilsAuthSessionRetrieve( osrfMethodContext* ctx ) {
191         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
192
193         char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
194         jsonObject* userObj = NULL;
195
196         if( authToken ){
197                 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
198                 userObj = osrfCacheGetObject( key ); /**/
199                 free(key);
200         }
201
202         osrfAppRespondComplete( ctx, userObj );
203         jsonObjectFree(userObj);
204         return 0;
205 }
206
207 int oilsAuthSessionDelete( osrfMethodContext* ctx ) {
208         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
209
210         char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
211         jsonObject* resp = NULL;
212
213         if( authToken ) {
214                 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
215                 osrfCacheRemove(key);
216                 resp = jsonNewObject(authToken); /**/
217                 free(key);
218         }
219
220         osrfAppRespondComplete( ctx, resp );
221         jsonObjectFree(resp);
222         return 0;
223 }
224
225
226