cdb0e84a58778ea09271d9ce7bb370ded688bdfa
[working/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/osrf_log.h"
5 #include "oils_utils.h"
6
7 #define OILS_AUTH_CACHE_PRFX "oils_auth_"
8
9
10 #define MODULENAME "open-ils.auth"
11
12 int osrfAppInitialize();
13 int osrfAppChildInit();
14 int osrfMathRun( osrfMethodContext* );
15
16
17 int osrfAppInitialize() {
18
19         osrfLogInit(MODULENAME);
20
21         osrfAppRegisterMethod( 
22                 MODULENAME, 
23                 "open-ils.auth.authenticate.init", 
24                 "oilsAuthInit", 
25                 "Start the authentication process and returns the intermediate authentication seed",
26                 " [ username ]", 1 );
27
28         osrfAppRegisterMethod( 
29                 MODULENAME, 
30                 "open-ils.auth.authenticate.complete", 
31                 "oilsAuthComplete", 
32                 "Completes the authentication process and returns the auth token",
33                 "[ username, md5sum( seed + password ) ]", 2 );
34
35         osrfAppRegisterMethod( 
36                 MODULENAME, 
37                 "open-ils.auth.session.retrieve", 
38                 "oilsAuthSessionRetrieve", 
39                 "Returns the user object (password blanked) for the given login session",
40                 "[ authToken ]", 1 );
41
42         osrfAppRegisterMethod( 
43                 MODULENAME, 
44                 "open-ils.auth.session.delete", 
45                 "oilsAuthSessionDelete", 
46                 "Destroys the given login session",
47                 "[ authToken ]",  1 );
48
49         return 0;
50 }
51
52 int osrfAppChildInit() {
53         return 0;
54 }
55
56 int oilsAuthInit( osrfMethodContext* ctx ) {
57         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
58
59         jsonObject* resp;
60         char* username = NULL;
61         char* seed = NULL;
62         char* md5seed = NULL;
63         char* key = NULL;
64
65         if( (username = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 0))) ) {
66
67                 seed = va_list_to_string( "%d.%d.%s", time(NULL), getpid(), username );
68                 key = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, username );
69
70                 md5seed = md5sum(seed);
71                 osrfCachePutString( key, md5seed, 30 );
72
73                 osrfLog( OSRF_DEBUG, "oilsAuthInit(): has seed %s and key %s", md5seed, key );
74
75                 resp = jsonNewObject(md5seed);  
76                 osrfAppRequestRespondComplete( ctx->session, ctx->request, resp );
77
78                 jsonObjectFree(resp);
79                 free(seed);
80                 free(md5seed);
81                 free(key);
82                 return 0;
83         }
84
85         return -1;
86 }
87
88
89 int oilsAuthComplete( osrfMethodContext* ctx ) {
90         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
91
92         char* uname = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 0));
93         char* password = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 1));
94         char* storageMethod = "open-ils.storage.direct.actor.user.search.usrname.atomic";
95
96         if( uname && password ) {
97
98                 /* grab the user object from storage */
99                 osrfLog( OSRF_DEBUG, "oilsAuth calling method %s with username %s", storageMethod, uname );
100
101                 osrfAppSession* session = osrfAppSessionClientInit( "open-ils.storage" ); /**/
102                 jsonObject* params = jsonNewObject(uname); /**/
103                 int reqid = osrfAppSessionMakeRequest( session, params, storageMethod, 1, NULL );
104                 jsonObjectFree(params);
105                 osrfMessage* omsg = osrfAppSessionRequestRecv( session, reqid, 60 ); /**/
106
107                 if(!omsg) { 
108                         osrfAppSessionFree(session);
109                         return osrfAppRequestRespondException( ctx->session, ctx->request,
110                                 "No response from storage server for method %s", storageMethod ); 
111                 }
112
113                 jsonObject* userObj = osrfMessageGetResult(omsg);
114
115                 char* _j = jsonObjectToJSON(userObj);
116                 osrfLog( OSRF_DEBUG, "Auth received user object from storage: %s", _j );
117                 free(_j);
118
119                 /* the method is atomic, grab the first user we receive */
120                 if( userObj ) userObj = jsonObjectGetIndex(userObj, 0);
121                 
122                 if(!userObj) { /* XXX needs to be a 'friendly' exception */
123                         osrfMessageFree(omsg);
124                         osrfAppSessionFree(session);
125                         return osrfAppRequestRespondException( ctx->session, 
126                                         ctx->request, "User %s not found in the database", uname );
127                 }
128
129                 char* realPassword = oilsFMGetString( userObj, "passwd" ); /**/
130                 char* seed = osrfCacheGetString( "%s%s", OILS_AUTH_CACHE_PRFX, uname ); /**/
131
132                 if(!seed) {
133                         osrfMessageFree(omsg);
134                         osrfAppSessionFree(session);
135                         return osrfAppRequestRespondException( ctx->session,
136                                 ctx->request, "No authentication seed found. "
137                                 "open-ils.auth.authenticate.init must be called first");
138                 }
139
140                 osrfLog( OSRF_DEBUG, "oilsAuth retrieved seed from cache: %s", seed );
141                 char* maskedPw = md5sum( "%s%s", seed, realPassword );
142                 if(!maskedPw) return -1;
143                 osrfLog( OSRF_DEBUG, "oilsAuth generated masked password %s. "
144                                 "Testing against provided password %s", maskedPw, password );
145
146                 jsonObject* response;
147
148                 if( !strcmp( maskedPw, password ) ) {
149
150                         osrfLog( OSRF_INFO, "Login successful for %s", uname );
151                         char* string = va_list_to_string( "%d.%d.%s", getpid(), time(NULL), uname ); /**/
152                         char* authToken = md5sum(string); /**/
153                         char* authKey = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
154                         oilsFMSetString( userObj, "passwd", "" );
155                         osrfCachePutObject( authKey, userObj, 28800 ); /* XXX config value */
156                         response = jsonNewObject( authToken );
157                         free(string); free(authToken); free(authKey);
158
159                 } else {
160                         osrfLog( OSRF_INFO, "Login failed for for %s", uname );
161                         response = jsonNewNumberObject(0);
162                 }
163
164                 osrfAppRequestRespondComplete( ctx->session, ctx->request, response ); 
165                 jsonObjectFree(response);
166                 osrfMessageFree(omsg);
167                 osrfAppSessionFree(session);
168
169         } else {
170                 return osrfAppRequestRespondException( ctx->session, ctx->request, 
171                         "username and password required for method: %s", ctx->method->name );
172         }
173
174         return 0;
175
176 }
177
178 int oilsAuthSessionRetrieve( osrfMethodContext* ctx ) {
179         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
180
181         char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
182         jsonObject* userObj = NULL;
183
184         if( authToken ){
185                 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
186                 userObj = osrfCacheGetObject( key ); /**/
187                 free(key);
188         }
189
190         osrfAppRequestRespondComplete( ctx->session, ctx->request, userObj );
191         jsonObjectFree(userObj);
192         return 0;
193 }
194
195 int oilsAuthSessionDelete( osrfMethodContext* ctx ) {
196         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
197
198         char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
199         jsonObject* resp = NULL;
200
201         if( authToken ) {
202                 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
203                 osrfCacheRemove(key);
204                 resp = jsonNewObject(authToken); /**/
205                 free(key);
206         }
207
208         osrfAppRequestRespondComplete( ctx->session, ctx->request, resp );
209         jsonObjectFree(resp);
210         return 0;
211 }
212
213
214