00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <assert.h>
00034
00035 #include <libxml/tree.h>
00036
00040 #ifndef DRIVERAPIVERSION
00041 # define DRIVERAPIVERSION 2
00042 #endif
00043
00047 #include <sqlite3.h>
00048
00049 #include <eurephia_nullsafe.h>
00050 #include <eurephia_context.h>
00051 #include <eurephia_log.h>
00052 #include <eurephia_xml.h>
00053 #include <eurephia_values.h>
00054 #include <eurephiadb_session_struct.h>
00055 #include <eurephiadb_mapping.h>
00056 #include <passwd.h>
00057
00058 #ifndef DRIVER_MODE
00059 #define DRIVER_MODE
00060 #endif
00061 #include <eurephiadb_driver.h>
00062
00063 #include "../sqlite.h"
00064
00065 #if (DRIVERAPIVERSION > 1) || defined(DOXYGEN)
00066
00067
00068
00069
00070
00071
00085 static xmlDoc *auth_user(eurephiaCTX *ctx, const char *req_access, const char *uname, const char *pwd) {
00086 xmlDoc *res_d = NULL;
00087 xmlNode *info_n = NULL;
00088 dbresult *res = NULL;
00089 char *crpwd = NULL, *dbpwd = NULL;
00090 char *activated = NULL, *deactivated = NULL, *blid = NULL, *uid = NULL;
00091 int access = 0;
00092 char interface;
00093
00094 DEBUG(ctx, 21, "Function call: auth_user(ctx, '%s, '%s', 'xxxxxxxx')", req_access, uname);
00095
00096 assert(ctx != NULL);
00097
00098 switch( ctx->context_type ) {
00099 case ECTX_ADMIN_CONSOLE:
00100 interface = 'C';
00101 break;
00102 case ECTX_ADMIN_WEB:
00103 interface = 'W';
00104 break;
00105 default:
00106 eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type);
00107 return NULL;
00108 }
00109
00110 if( (strlen_nullsafe(uname) < 4) || (strlen_nullsafe(pwd) < 4) ) {
00111 eurephia_log(ctx, LOG_WARNING, 0,
00112 "Username and/or password is either null or less than 4 bytes");
00113 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Username or password is too short");
00114 }
00115
00116
00117
00118
00119 res = sqlite_query(ctx,
00120 "SELECT activated, deactivated, bl.blid, "
00121 " password, uid "
00122 " FROM openvpn_users ou"
00123 " LEFT JOIN openvpn_blacklist bl USING (username)"
00124 " WHERE ou.username = '%q'",
00125 uname);
00126
00127 if( res == NULL ) {
00128 eurephia_log(ctx, LOG_FATAL, 0, "Could not authenticate user against the database");
00129 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00130 }
00131
00132 if( sqlite_get_numtuples(res) == 1 ) {
00133 activated = sqlite_get_value(res, 0, 0);
00134 deactivated = sqlite_get_value(res, 0, 1);
00135 blid = sqlite_get_value(res, 0, 2);
00136 dbpwd = sqlite_get_value(res, 0, 3);
00137 uid = strdup_nullsafe(sqlite_get_value(res, 0, 4));
00138
00139 if( blid != NULL ) {
00140 eurephia_log(ctx, LOG_WARNING, 0,
00141 "User account '%s' is BLACKLISTED. You have no access.", uname);
00142 sqlite_free_results(res);
00143 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00144 }
00145
00146 if( activated == NULL ) {
00147 eurephia_log(ctx, LOG_WARNING, 0, "User account '%s' is not yet activated.", uname);
00148 sqlite_free_results(res);
00149 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00150 }
00151
00152 if( deactivated != NULL ) {
00153 eurephia_log(ctx, LOG_WARNING, 0, "User account '%s' is deactivated.", uname);
00154 sqlite_free_results(res);
00155 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00156 }
00157
00158 if( dbpwd == NULL ) {
00159 eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed. DB error.");
00160 sqlite_free_results(res);
00161 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00162 } else {
00163 int pwdok = 0;
00164
00165 crpwd = eurephia_pwd_crypt(ctx, pwd, dbpwd);
00166 pwdok = ((crpwd != NULL) && (strcmp(crpwd, dbpwd) == 0) ? 1 : 0);
00167 memset(crpwd, 0, strlen_nullsafe(crpwd));
00168 memset(dbpwd, 0, strlen_nullsafe(dbpwd));
00169 free_nullsafe(ctx, crpwd);
00170 if( pwdok == 0 ) {
00171 eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed.");
00172 sleep(2);
00173 sqlite_free_results(res);
00174 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00175 }
00176 }
00177 sqlite_free_results(res);
00178
00179
00180
00181
00182 res = sqlite_query(ctx,
00183 "SELECT (count(*) = 1) AS access "
00184 " FROM eurephia_adminaccess"
00185 " WHERE uid = '%q' AND interface = '%c' AND access = '%q'",
00186 uid, interface, req_access);
00187
00188 if( res == NULL ) {
00189 eurephia_log(ctx, LOG_FATAL, 0, "Could not check access level");
00190 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,"Failed to validate access level");
00191 }
00192 access = atoi_nullsafe(sqlite_get_value(res, 0, 0));
00193 sqlite_free_results(res);
00194
00195 if( access == 0 ) {
00196 eurephia_log(ctx, LOG_WARNING, 0,
00197 "User account '%s' is lacking privileges for this operation", uname);
00198 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00199 }
00200 } else {
00201 eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed. No unique records found.");
00202 sqlite_free_results(res);
00203 sleep(2);
00204 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed");
00205 }
00206
00207
00208 info_n = xmlNewNode(NULL, (xmlChar *) "UserAccount");
00209 assert( info_n != NULL );
00210 xmlNewProp(info_n, (xmlChar *) "uid", (xmlChar *) uid);
00211 res_d = eurephiaXML_ResultMsg(ctx, exmlRESULT, info_n, "Successful authentication");
00212 xmlFreeNode(info_n);
00213 free_nullsafe(ctx, uid);
00214 return res_d;
00215 }
00216
00217
00229 static xmlDoc *auth_session(eurephiaCTX *ctx, const char *sesskey, const char *req_access) {
00230 dbresult *res = NULL;
00231 int valid = 0, access = 0, expire_time = 0;
00232 char interface;
00233
00234 DEBUG(ctx, 21, "Function call: auth_session(ctx, '%s, '%s')", sesskey, req_access);
00235 assert( (ctx != NULL) && (sesskey != NULL) );
00236
00237 switch( ctx->context_type ) {
00238 case ECTX_ADMIN_CONSOLE:
00239 interface = 'C';
00240 break;
00241 case ECTX_ADMIN_WEB:
00242 interface = 'W';
00243 break;
00244 default:
00245 eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type);
00246 return NULL;
00247 }
00248
00249
00250
00251 expire_time = (60 * atoi_nullsafe(defaultValue(eGet_value(ctx->dbc->config,
00252 "eurephiadmin_autologout"),
00253 "10")
00254 )
00255 );
00256 res = sqlite_query(ctx,
00257 "SELECT (strftime('%%s',CURRENT_TIMESTAMP)-strftime('%%s',last_action)) > %i AS exp,"
00258 " (access IS NOT NULL) AS access"
00259 " FROM eurephia_adminlog"
00260 " LEFT JOIN eurephia_adminaccess USING(uid,interface)"
00261 " WHERE status IN (1,2)"
00262 " AND sessionkey = '%q'"
00263 " AND access = '%q'"
00264 " AND interface = '%c'",
00265 expire_time, sesskey, req_access, interface);
00266
00267 if( (res == NULL) ) {
00268 eurephia_log(ctx, LOG_FATAL, 0, "Could not validate session");
00269 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Session authentication failed");
00270 }
00271
00272 valid = (atoi_nullsafe(sqlite_get_value(res, 0, 0)) == 0);
00273 access = (atoi_nullsafe(sqlite_get_value(res, 0, 1)) == 1);
00274 sqlite_free_results(res);
00275
00276
00277 if( valid && access ) {
00278 res = sqlite_query(ctx,
00279 "UPDATE eurephia_adminlog"
00280 " SET last_action = CURRENT_TIMESTAMP, status = 2"
00281 " WHERE sessionkey = '%q'", sesskey);
00282 if( res == NULL ) {
00283 eurephia_log(ctx, LOG_ERROR, 0, "Could not register session activity");
00284 }
00285 sqlite_free_results(res);
00286
00287 } else {
00288
00289 res = sqlite_query(ctx,
00290 "UPDATE eurephia_adminlog"
00291 " SET logout = CURRENT_TIMESTAMP, status = %i"
00292 " WHERE sessionkey = '%q'",
00293 (access ? 4 : 5), sesskey);
00294 if( res == NULL ) {
00295 eurephia_log(ctx, LOG_ERROR, 0, "Could not register old session as logged out");
00296 }
00297 sqlite_free_results(res);
00298
00299
00300 res = sqlite_query(ctx, "DELETE FROM openvpn_sessions WHERE sessionkey = '%q'",
00301 sesskey);
00302 if( res == NULL ) {
00303 eurephia_log(ctx, LOG_ERROR, 0,
00304 "Could not delete session variables (%s))", sesskey);
00305 } else if( !access ) {
00306 eurephia_log(ctx, LOG_WARNING, 0, "User account is lacking privileges");
00307 }
00308 sqlite_free_results(res);
00309 }
00310
00311 if (valid && access) {
00312 return eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, "Session authenticated");
00313 } else {
00314 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Session authentication failed");
00315
00316 }
00317 }
00318
00319
00330 static xmlDoc *register_login(eurephiaCTX *ctx, const int uid, const char *sesskey) {
00331 dbresult *res = NULL;
00332 char interface;
00333
00334 DEBUG(ctx, 21, "Function call: register_login(ctx, %i, '%s')", uid, sesskey);
00335 assert( ctx != NULL );
00336
00337 if( (sesskey == NULL) || (uid < 1) ) {
00338 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Invalid data for login registration");
00339 }
00340
00341 switch( ctx->context_type ) {
00342 case ECTX_ADMIN_CONSOLE:
00343 interface = 'C'; break;
00344 case ECTX_ADMIN_WEB:
00345 interface = 'W'; break;
00346 default:
00347 eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type);
00348 return NULL;
00349 }
00350
00351
00352 res = sqlite_query(ctx,
00353 "INSERT INTO eurephia_adminlog "
00354 " (uid, interface, status, login, last_action, sessionkey) "
00355 "VALUES ('%i','%c',1,CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '%q')",
00356 uid, interface, sesskey);
00357 if( !res ) {
00358 eurephia_log(ctx, LOG_FATAL, 0, "Failed to register the session in the database");
00359 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,
00360 "Failed to register the session in the database");
00361 }
00362 sqlite_free_results(res);
00363 return eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, "Session is registered as logged in");
00364 }
00365
00366
00376 static xmlDoc *register_logout(eurephiaCTX *ctx, const char *sessionkey) {
00377 dbresult *res = NULL;
00378
00379 DEBUG(ctx, 21, "Function call: register_logout(ctx, '%s')", sessionkey);
00380 assert((ctx != NULL) && (sessionkey != NULL));
00381
00382 if( (ctx->context_type != ECTX_ADMIN_CONSOLE) && (ctx->context_type != ECTX_ADMIN_WEB) ) {
00383 eurephia_log(ctx, LOG_CRITICAL, 0,
00384 "eurephia admin function call attempted with wrong context type");
00385 return NULL;
00386 }
00387
00388
00389 res = sqlite_query(ctx,
00390 "UPDATE eurephia_adminlog "
00391 " SET logout = CURRENT_TIMESTAMP, status = 3"
00392 " WHERE sessionkey = '%q'",
00393 sessionkey);
00394 if( !res || (sqlite_get_affected_rows(res) == 0) ) {
00395 eurephia_log(ctx, LOG_FATAL, 0,
00396 "Failed to register the session as logged out (updated %i rows)",
00397 sqlite_get_affected_rows(res));
00398 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,
00399 "Failed to register the session as logged out");
00400 }
00401 sqlite_free_results(res);
00402
00403
00404 res = sqlite_query(ctx, "DELETE FROM openvpn_sessions WHERE sessionkey = '%q'", sessionkey);
00405 if( !res || (sqlite_get_affected_rows(res) == 0) ) {
00406 eurephia_log(ctx, LOG_ERROR, 0,
00407 "Could not delete session variables (%s))", sessionkey);
00408 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,
00409 "Could not delete session variables (%s))", sessionkey);
00410 }
00411 sqlite_free_results(res);
00412
00413 return eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, "Session is logged out");
00414 }
00415
00416
00420 xmlDoc *eDBadminAuthenticate(eurephiaCTX *ctx, xmlDoc *qryxml) {
00421 xmlDoc *res_d = NULL;
00422 xmlNode *qry_n = NULL;
00423 char *mode = NULL;
00424 int type = 0;
00425
00426 DEBUG(ctx, 20, "Function call: eDBadminAuthenticate(ctx, xmlDoc)");
00427 assert( (ctx != NULL) && (qryxml != NULL) );
00428
00429 if( (ctx->context_type != ECTX_ADMIN_CONSOLE) && (ctx->context_type != ECTX_ADMIN_WEB) ) {
00430 eurephia_log(ctx, LOG_CRITICAL, 0,
00431 "eurephia admin function call attempted with wrong context type");
00432 return NULL;
00433 }
00434
00435 qry_n = eurephiaXML_getRoot(ctx, qryxml, "Authenticate", 1);
00436 if( qry_n != NULL ) {
00437 type = 1;
00438 goto accept;
00439 }
00440
00441 qry_n = eurephiaXML_getRoot(ctx, qryxml, "Register", 1);
00442 if( qry_n != NULL ) {
00443 type = 2;
00444 goto accept;
00445 }
00446
00447 eurephia_log(ctx, LOG_ERROR, 0, "Could not find a valid XML request for eDBadminAuthenticate()");
00448 return NULL;
00449
00450 accept:
00451 mode = xmlGetAttrValue(qry_n->properties, "mode");
00452 if( mode == NULL ) {
00453 eurephia_log(ctx, LOG_ERROR, 0, "Invalid authentication request");
00454 return NULL;
00455 }
00456
00457 switch( type ) {
00458 case 1:
00459 if( strcmp(mode, "user") == 0 ) {
00460
00461 const char *reqacc = NULL, *uname = NULL, *pwd = NULL;
00462 uname = xmlGetNodeContent(qry_n, "username");
00463 pwd = xmlGetNodeContent(qry_n, "password");
00464 reqacc = xmlGetNodeContent(qry_n, "accesslevel");
00465 res_d = auth_user(ctx, reqacc, uname, pwd);
00466 } else if ( strcmp(mode, "session") == 0 ) {
00467 const char *sesskey = NULL, *reqacc = NULL;
00468 sesskey = xmlGetNodeContent(qry_n, "sessionkey");
00469 reqacc = xmlGetNodeContent(qry_n, "accesslevel");
00470 res_d = auth_session(ctx, sesskey, reqacc);
00471 }
00472 break;
00473
00474 case 2:
00475 if( strcmp(mode, "login") == 0 ) {
00476 const char *sesskey = NULL;
00477 unsigned int uid = 0;
00478
00479 uid = atoi_nullsafe(xmlGetAttrValue(qry_n->properties, "uid"));
00480 sesskey = xmlExtractContent(qry_n);
00481 res_d = register_login(ctx, uid, sesskey);
00482 } else if( strcmp(mode, "logout") == 0 ) {
00483 const char *sesskey = NULL;
00484
00485 sesskey = xmlExtractContent(qry_n);
00486 res_d = register_logout(ctx, sesskey);
00487 }
00488 break;
00489
00490 default:
00491 eurephia_log(ctx, LOG_FATAL, 0, "The unthinkable has just happened (type %i)", type);
00492 res_d = NULL;
00493 break;
00494 }
00495 return res_d;
00496 }
00497
00498 #endif