making the module name match apache2s requirements
[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         osrfAppRegisterMethod( 
20                 MODULENAME, 
21                 "open-ils.auth.authenticate.init", 
22                 "oilsAuthInit", 
23                 "Start the authentication process and returns the intermediate authentication seed"
24                 " PARAMS( username )", 1, 0 );
25
26         osrfAppRegisterMethod( 
27                 MODULENAME, 
28                 "open-ils.auth.authenticate.complete", 
29                 "oilsAuthComplete", 
30                 "Completes the authentication process and returns the auth token "
31                 "PARAMS(username, md5sum( seed + password ) )", 2, 0 );
32
33         osrfAppRegisterMethod( 
34                 MODULENAME, 
35                 "open-ils.auth.session.retrieve", 
36                 "oilsAuthSessionRetrieve", 
37                 "Returns the user object (password blanked) for the given login session "
38                 "PARAMS( authToken )", 1, 0 );
39
40         osrfAppRegisterMethod( 
41                 MODULENAME, 
42                 "open-ils.auth.session.delete", 
43                 "oilsAuthSessionDelete", 
44                 "Destroys the given login session "
45                 "PARAMS( authToken )",  1, 0 );
46
47         return 0;
48 }
49
50 int osrfAppChildInit() {
51         return 0;
52 }
53
54 int oilsAuthInit( osrfMethodContext* ctx ) {
55         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
56
57         jsonObject* resp;
58         char* username = NULL;
59         char* seed = NULL;
60         char* md5seed = NULL;
61         char* key = NULL;
62
63         if( (username = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 0))) ) {
64
65                 seed = va_list_to_string( "%d.%d.%s", time(NULL), getpid(), username );
66                 key = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, username );
67
68                 md5seed = md5sum(seed);
69                 osrfCachePutString( key, md5seed, 30 );
70
71                 osrfLog( OSRF_DEBUG, "oilsAuthInit(): has seed %s and key %s", md5seed, key );
72
73                 resp = jsonNewObject(md5seed);  
74                 osrfAppRespondComplete( ctx, resp );
75
76                 jsonObjectFree(resp);
77                 free(seed);
78                 free(md5seed);
79                 free(key);
80                 return 0;
81         }
82
83         return -1;
84 }
85
86
87 int oilsAuthComplete( osrfMethodContext* ctx ) {
88         OSRF_METHOD_VERIFY_CONTEXT(ctx); 
89
90         char* uname = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 0));
91         char* password = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 1));
92         char* storageMethod = "open-ils.storage.direct.actor.user.search.usrname.atomic";
93
94         if( uname && password ) {
95
96                 /* grab the user object from storage */
97                 osrfLog( OSRF_DEBUG, "oilsAuth calling method %s with username %s", storageMethod, uname );
98
99                 osrfAppSession* session = osrfAppSessionClientInit( "open-ils.storage" ); /**/
100                 jsonObject* params = jsonNewObject(uname); /**/
101                 int reqid = osrfAppSessionMakeRequest( session, params, storageMethod, 1, NULL );
102                 jsonObjectFree(params);
103                 osrfMessage* omsg = osrfAppSessionRequestRecv( session, reqid, 60 ); /**/
104
105                 if(!omsg) { 
106                         osrfAppSessionFree(session);
107                         return osrfAppRequestRespondException( ctx->session, ctx->request,
108                                 "No response from storage server for method %s", storageMethod ); 
109                 }
110
111                 jsonObject* userObj = osrfMessageGetResult(omsg);
112
113                 char* _j = jsonObjectToJSON(userObj);
114                 osrfLog( OSRF_DEBUG, "Auth received user object from storage: %s", _j );
115                 free(_j);
116
117                 /* the method is atomic, grab the first user we receive */
118                 if( userObj ) userObj = jsonObjectGetIndex(userObj, 0);
119                 
120                 if(!userObj) { /* XXX needs to be a 'friendly' exception */
121                         osrfMessageFree(omsg);
122                         osrfAppSessionFree(session);
123                         return osrfAppRequestRespondException( ctx->session, 
124                                         ctx->request, "User %s not found in the database", uname );
125                 }
126
127                 char* realPassword = oilsFMGetString( userObj, "passwd" ); /**/
128                 char* seed = osrfCacheGetString( "%s%s", OILS_AUTH_CACHE_PRFX, uname ); /**/
129
130                 if(!seed) {
131                         osrfMessageFree(omsg);
132                         osrfAppSessionFree(session);
133                         return osrfAppRequestRespondException( ctx->session,
134                                 ctx->request, "No authentication seed found. "
135                                 "open-ils.auth.authenticate.init must be called first");
136                 }
137
138                 osrfLog( OSRF_DEBUG, "oilsAuth retrieved seed from cache: %s", seed );
139                 char* maskedPw = md5sum( "%s%s", seed, realPassword );
140                 if(!maskedPw) return -1;
141                 osrfLog( OSRF_DEBUG, "oilsAuth generated masked password %s. "
142                                 "Testing against provided password %s", maskedPw, password );
143
144                 jsonObject* response;
145
146                 if( !strcmp( maskedPw, password ) ) {
147
148                         osrfLog( OSRF_INFO, "Login successful for %s", uname );
149                         char* string = va_list_to_string( "%d.%d.%s", getpid(), time(NULL), uname ); /**/
150                         char* authToken = md5sum(string); /**/
151                         char* authKey = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
152
153                         oilsFMSetString( userObj, "passwd", "" );
154                         osrfCachePutObject( authKey, userObj, 28800 ); /* XXX config value */
155                         response = jsonNewObject( authToken );
156                         free(string); free(authToken); free(authKey);
157
158                 } else {
159
160                         osrfLog( OSRF_INFO, "Login failed for for %s", uname );
161                         response = jsonNewNumberObject(0);
162                 }
163
164                 osrfAppRespondComplete( ctx, 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         osrfAppRespondComplete( ctx, 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         osrfAppRespondComplete( ctx, resp );
209         jsonObjectFree(resp);
210         return 0;
211 }
212
213
214