00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <config.h>
00027 #include "midgard/midgard_connection.h"
00028 #include "midgard/authfailure.h"
00029 #include "defaults.h"
00030 #include "fmt_russian.h"
00031 #include "midgard/midgard_quota.h"
00032 #if HAVE_CRYPT_H
00033 # include <crypt.h>
00034 #else
00035 # define _XOPEN_SOURCE
00036 #endif
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040 #ifdef WIN32
00041 # include <windows.h>
00042 #endif
00043 #include <glib.h>
00044 #include <ctype.h>
00045 #ifndef WIN32
00046 # include <unistd.h>
00047 #endif
00048 #include <signal.h>
00049
00050 #ifdef WIN32
00051 # include <process.h>
00052 # include "win32/flock.h"
00053 # include "win32/win95nt.h"
00054 #else
00055 # include <sys/utsname.h>
00056 # include <sys/file.h>
00057 # include <sys/wait.h>
00058 # include <netdb.h>
00059 #endif
00060
00061 #include <sys/stat.h>
00062
00063 #if HAVE_MIDGARD_VC
00064 # include <sys/time.h>
00065 #endif
00066
00067 #ifndef MAXHOSTNAMELEN
00068 # define MAXHOSTNAMELEN 255
00069 #endif
00070
00071 #ifndef G_LOG_DOMAIN
00072 #undef G_LOG_DOMAIN
00073 #define G_LOG_DOMAIN="midgard-core"
00074 #endif
00075
00076 #include "midgard_mysql.h"
00077 #include "midgard/midgard_legacy.h"
00078
00079 static FILE *_log_file = NULL;
00080
00081 void mgd_log_debug_none(const gchar *domain, GLogLevelFlags level,
00082 const gchar *msg, gpointer userdata)
00083 {
00084 }
00085
00086 void mgd_log_debug_default(const gchar *domain, GLogLevelFlags level,
00087 const gchar *msg, gpointer userdata)
00088 {
00089 int fno;
00090 guint mlevel = (guint) userdata;
00091 gchar *level_ad = NULL;
00092
00093 switch (level) {
00094 case G_LOG_FLAG_RECURSION:
00095 level_ad = "RECURSION";
00096 break;
00097
00098 case G_LOG_FLAG_FATAL:
00099 level_ad = "FATAL! ";
00100 break;
00101
00102 case G_LOG_LEVEL_ERROR:
00103 level_ad = "ERROR";
00104 break;
00105
00106 case G_LOG_LEVEL_CRITICAL:
00107 level_ad = "CRITICAL ";
00108 break;
00109
00110 case G_LOG_LEVEL_WARNING:
00111 level_ad = "WARNING";
00112 break;
00113
00114 case G_LOG_LEVEL_MESSAGE:
00115 level_ad = "m";
00116 break;
00117
00118 case G_LOG_LEVEL_INFO:
00119 level_ad = "info";
00120 break;
00121
00122 case G_LOG_LEVEL_DEBUG:
00123 level_ad = "debug";
00124 break;
00125
00126 default:
00127
00128
00129 level_ad = "Unknown level";
00130 break;
00131 }
00132
00133 if (mlevel >= level) {
00134
00135 if (_log_file == NULL) _log_file = stderr;
00136 fno = fileno(_log_file);
00137
00138 if (fno != 2) flock(fno, LOCK_EX);
00139
00140 fprintf(_log_file, "%s ", domain != NULL ? domain : "midgard-core");
00141
00142 fprintf(_log_file, "(pid:%ld):", (unsigned long)getpid());
00143
00144 fprintf(_log_file, "(%s):", level_ad);
00145 fprintf(_log_file, " %s\n", msg);
00146
00147 fflush(_log_file);
00148 if (fno != 2) flock(fno, LOCK_UN);
00149 }
00150 }
00151
00152 void mgd_init()
00153 {
00154 mgd_init_ex(0, NULL);
00155 }
00156
00157 guint mgd_parse_log_levels(const char *levels)
00158 {
00159 const char *c;
00160 guint mask = 0;
00161 int level = 0;
00162
00163 for (c = levels; *c != '\0'; ) {
00164
00165 if (!isalpha(*c)) { c++; continue; }
00166
00167
00168 switch (tolower(*c)) {
00169
00170
00171
00172
00173
00174 case 'e': level = G_LOG_LEVEL_ERROR; break;
00175 case 'c': level = G_LOG_LEVEL_CRITICAL; break;
00176 case 'w': level = G_LOG_LEVEL_WARNING; break;
00177 case 'm': level = G_LOG_LEVEL_MESSAGE; break;
00178 case 'i': level = G_LOG_LEVEL_INFO; break;
00179 case 'd': level = G_LOG_LEVEL_DEBUG; break;
00180 default: level = 4; break;
00181 }
00182
00183
00184 for (c++; *c != '\0' && isalpha(*c); c++) {}
00185
00186
00187 if (level == 0) continue;
00188
00189
00190 if (*c == '+') {
00191 mask |= level;
00192 continue;
00193 }
00194
00195
00196 for (; level && level > G_LOG_FLAG_FATAL; level >>= 1) {
00197 mask |= level;
00198 }
00199
00200 }
00201
00202 return mask;
00203 }
00204
00205 void mgd_init_ex(guint log_levels, char *logname)
00206 {
00207 if (mgd_parser_list())
00208 return;
00209
00210
00211
00212 (void) mgd_parser_create("latin1", "latin1", 1);
00213 (void) mgd_parser_init_raw("russian", "KOI8-R");
00214 (void) mgd_parser_init_raw("utf-8", "UTF-8");
00215
00216 if (logname == NULL) {
00217 _log_file = stderr;
00218 } else {
00219 _log_file = fopen(logname, "a");
00220 if (_log_file == NULL) {
00221 _log_file = stderr;
00222 g_log("midgard-core", G_LOG_LEVEL_WARNING,
00223 "Could not open logfile '%s', using stderr", logname);
00224 }
00225 }
00226 }
00227
00228 void mgd_done()
00229 {
00230 mgd_parser_free_all();
00231 }
00232
00233 const char *mgd_version()
00234 {
00235 return MIDGARD_LIB_VERSION;
00236 }
00237
00238 midgard *mgd_setup()
00239 {
00240 midgard *mgd;
00241
00242 mgd = g_new(midgard, 1);
00243 if (!mgd)
00244 return NULL;
00245
00246 mgd->res = NULL;
00247
00248 mgd->pool = mgd_alloc_pool();
00249 if (!mgd->pool) {
00250 free(mgd);
00251 return NULL;
00252 }
00253
00254 mgd->tmp = mgd_alloc_pool();
00255 if (!mgd->tmp) {
00256 mgd_free_pool(mgd->pool);
00257 free(mgd);
00258 return NULL;
00259 }
00260
00261 mgd->current_user = &mgd->user_at_pagestart;
00262
00263 mgd->user_at_pagestart.id = 0;
00264 mgd->setuid_user.id = 0;
00265 mgd->user_at_pagestart.is_admin = 0;
00266 mgd->setuid_user.is_admin = 0;
00267 mgd->user_at_pagestart.is_root = 0;
00268 mgd->setuid_user.is_root = 0;
00269 mgd->user_at_pagestart.sitegroup = 0;
00270 mgd->setuid_user.sitegroup = 0;
00271 mgd->user_at_pagestart.member_of = NULL;
00272 mgd->setuid_user.member_of = NULL;
00273
00274 mgd->username = NULL;
00275
00276 mgd->parser = mgd_parser_list();
00277
00278 mgd->msql = g_new(midgard_mysql, 1);
00279 mgd->msql->mysql = NULL;
00280 mgd->blobdir = NULL;
00281
00282 mgd->ah_prefix = NULL;
00283 mgd->auth_type = MGD_AUTHTYPE_NORMAL;
00284
00285 #if HAVE_MIDGARD_MULTILANG
00286 mgd->lang = 0;
00287 mgd->default_lang = 0;
00288 mgd->a_lang = 0;
00289 mgd->p_lang = 0;
00290 #endif
00291
00292 #if HAVE_MIDGARD_VC
00293 mgd->cvs_script = NULL;
00294 #endif
00295
00296 #if HAVE_MIDGARD_QUOTA
00297 mgd->quota = 0;
00298 mgd->quota_err = 0;
00299 mgd->qlimits = g_hash_table_new(g_str_hash, g_str_equal);
00300 #endif
00301
00302 mgd->loglevel = mgd_parse_log_levels("warn");
00303 mgd->logfile = NULL;
00304 mgd->loghandler = 0;
00305 mgd->person = NULL;
00306 mgd->schema = NULL;
00307 mgd->err = NULL;
00308
00309 mgd->_mgd = midgard_connection_new();
00310 mgd->_mgd->mgd = mgd;
00311 mgd->pamfile = "midgard";
00312
00313 return mgd;
00314 }
00315
00316 void mgd_set_authtype(midgard *mgd, midgard_auth_type authtype)
00317 {
00318 mgd->auth_type = authtype;
00319 }
00320
00321 void mgd_easy_connect(midgard *mgd, const char *host, const char *database,
00322 const char *user, const char *password)
00323 {
00324 int connected;
00325
00326
00327 mgd->msql->mysql = mysql_init(NULL);
00328
00329
00330
00331 if (mgd->msql->mysql != NULL)
00332 mysql_options(mgd->msql->mysql, MYSQL_SET_CHARSET_NAME, "utf8");
00333
00334
00335
00336 connected = mgd->msql->mysql &&
00337 mysql_real_connect(mgd->msql->mysql, host,
00338 user, password, database, 0, NULL, 0);
00339
00340 if (!mgd->msql->mysql || !connected) {
00341
00342
00343
00344 g_warning(" %s@%s://%s connection failed: %s",
00345 user, host, database,
00346 mgd->msql->mysql ? mysql_error(mgd->msql->mysql) : "<mysql server not found?>");
00347
00348 if (mgd->msql->mysql) mysql_close(mgd->msql->mysql);
00349 mgd->msql->mysql = NULL;
00350 }
00351 }
00352
00353 midgard *mgd_connect(const char *hostname, const char *database,
00354 const char *username, const char *password)
00355 {
00356 midgard *mgd = mgd_setup();
00357
00358 if (mgd == NULL)
00359 return NULL;
00360
00361
00362 if (!hostname)
00363 hostname = MGD_MYSQL_HOST;
00364 if (!username)
00365 username = MGD_MYSQL_USERNAME;
00366 if (!password)
00367 password = MGD_MYSQL_PASSWORD;
00368 if (!database)
00369 database = MGD_MYSQL_DATABASE;
00370
00371
00372 mgd_easy_connect(mgd, hostname, database, username, password);
00373
00374 if (!mgd->msql->mysql) {
00375 mgd_free_pool(mgd->tmp);
00376 mgd_free_pool(mgd->pool);
00377 free(mgd);
00378 return NULL;
00379 }
00380
00381 return mgd;
00382 }
00383
00384
00385
00386 void mgd_close(midgard * mgd)
00387 {
00388 assert(mgd);
00389 mgd_clear(mgd, MGD_CLEAR_ALL);
00390
00391 if (mgd->msql->mysql) {
00392 mysql_close(mgd->msql->mysql);
00393 mgd->msql->mysql = NULL;
00394 }
00395
00396 if (mgd->user_at_pagestart.member_of != NULL)
00397 free(mgd->user_at_pagestart.member_of);
00398 if (mgd->setuid_user.member_of != NULL)
00399 free(mgd->setuid_user.member_of);
00400
00401 mgd_free_pool(mgd->tmp);
00402 mgd_free_pool(mgd->pool);
00403 free(mgd);
00404 }
00405
00406
00407 int mgd_select_db(midgard * mgd, const char *database)
00408 {
00409 int errcode;
00410
00411 assert(mgd);
00412 assert(database);
00413
00414 if ((errcode = mysql_select_db(mgd->msql->mysql, database)) == 0) return 1;
00415
00416 g_log("midgard-lib", G_LOG_LEVEL_ERROR,
00417 "Midgard: mgd_select_db(%s) failed: %s (%d)\n",
00418 database, mysql_error(mgd->msql->mysql), errcode);
00419 return 0;
00420 }
00421
00422 int mgd_assert_db_connection(midgard *mgd, const char *hostname, const char *database,
00423 const char* username, const char *pass)
00424 {
00425 void (*handler) (int);
00426
00427 handler=signal(SIGPIPE, SIG_IGN);
00428
00429
00430 #if defined(CR_SERVER_GONE_ERROR)
00431 mysql_stat(mgd->msql->mysql);
00432 if (mysql_errno(mgd->msql->mysql) == CR_SERVER_GONE_ERROR) {
00433 #else
00434 if (!strcasecmp(mysql_stat(mgd->msql->mysql), "mysql server has gone away")) {
00435 #endif
00436 mysql_close(mgd->msql->mysql);
00437 sleep(1);
00438 mgd_easy_connect(mgd, hostname, database, username, pass);
00439 }
00440
00441 signal(SIGPIPE, handler);
00442 return (mgd->msql->mysql != NULL);
00443 }
00444
00445 #ifdef HAVE_LIBPAM
00446
00447 #ifdef HAVE_SECURITY_PAM_APPL_H
00448 #include <security/pam_appl.h>
00449 #endif
00450
00451 #ifdef HAVE_PAM_PAM_APPL_H
00452 #include <pam/pam_appl.h>
00453 #endif
00454
00455 typedef struct {
00456 char *username;
00457 char *password;
00458 } _midgard_pam_appdata;
00459
00460 static int _midgard_pam_conv(int num_msg, const struct pam_message **msg,
00461 struct pam_response **resp, void *appdata_ptr)
00462 {
00463 _midgard_pam_appdata *appdata = (_midgard_pam_appdata*) appdata_ptr;
00464 int i = 0, j = 0;
00465
00466 if (num_msg && msg && *msg && resp && appdata_ptr) {
00467 *resp = malloc(sizeof(struct pam_response)*num_msg);
00468 if (*resp) {
00469
00470 for(; i < num_msg; i++) {
00471 (*resp)[i].resp_retcode = 0;
00472 (*resp)[i].resp = NULL;
00473 switch((*msg)[i].msg_style) {
00474
00475 case PAM_PROMPT_ECHO_ON:
00476 (*resp)[i].resp = strdup(appdata->username);
00477 break;
00478
00479 case PAM_PROMPT_ECHO_OFF:
00480 (*resp)[i].resp = strdup(appdata->password);
00481 break;
00482 }
00483
00484
00485
00486 if (!(*resp)[i].resp) {
00487 for(j = i; j >= 0 ; j--) {
00488 if ((*resp)[j].resp)
00489 free((*resp)[j].resp);
00490 }
00491 free(*resp);
00492 *resp = NULL;
00493 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
00494 "Return PAM_CONV_ERROR due to strdup() failure");
00495 return PAM_CONV_ERR;
00496 }
00497 }
00498 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Return PAM_SUCCESS");
00499 return PAM_SUCCESS;
00500 }
00501 }
00502 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Return PAM_CONV_ERROR");
00503 return PAM_CONV_ERR;
00504 }
00505 #endif
00506
00507 #define MGD_USERNAME_MAXLEN 80
00508
00509 static int mgd_auth_su(midgard * mgd, const char *username,
00510 const char *password, int su, int setuid, int trusted)
00511 {
00512 midgard_res *res;
00513 int i;
00514 const char *cipher, *passwd;
00515 int host_sitegroup, req_sitegroup, admingroup;
00516 char *sitegroup;
00517 int rootuser = 0;
00518 char delim = '+';
00519 int grant;
00520 char *reauth = NULL;
00521
00522 assert(mgd);
00523
00524 if (mgd->msql->mysql == NULL)
00525 return MGD_AUTH_NOT_CONNECTED;
00526
00527 host_sitegroup = mgd->current_user->sitegroup;
00528 mgd_clear(mgd, MGD_CLEAR_BASE);
00529
00530 if (setuid) {
00531 mgd->current_user = &mgd->setuid_user;
00532 mgd_clear(mgd, MGD_CLEAR_BASE);
00533 mgd->current_user->sitegroup = host_sitegroup;
00534 }
00535
00536
00537 if (!username || !*username) {
00538 return MGD_AUTH_ANONYMOUS;
00539 }
00540
00541 if (strlen(username) > MGD_USERNAME_MAXLEN)
00542 return MGD_AUTH_INVALID_NAME;
00543
00544 #define MIDGARD_LOGIN_SG_ROOT_SEP "*!$"
00545
00546 #define MIDGARD_LOGIN_SG_ROOT_ROOT '*'
00547 #define MIDGARD_LOGIN_SG_ROOT_ADMIN '!'
00548 #define MIDGARD_LOGIN_SG_ROOT_USER '$'
00549 #define MIDGARD_LOGIN_SG_ADMIN_USER ';'
00550 #define MIDGARD_LOGIN_SG_USER_USER '+'
00551 #define MIDGARD_LOGIN_SG_REAUTH '='
00552
00553 gchar *uname = g_strdup(username);
00554
00555 sitegroup = strpbrk(uname, MIDGARD_LOGIN_SG_SEPARATOR);
00556
00557 if (sitegroup) {
00558 delim = *sitegroup;
00559 *sitegroup = '\0';
00560 sitegroup++;
00561 rootuser = (strchr(MIDGARD_LOGIN_SG_ROOT_SEP, delim) != NULL);
00562
00563 if (rootuser && !*sitegroup) return MGD_AUTH_SG_NOTFOUND;
00564
00565 } else if (host_sitegroup == 0) {
00566 delim = MIDGARD_LOGIN_SG_ROOT_ROOT;
00567 rootuser = 1;
00568 } else {
00569 delim = MIDGARD_LOGIN_SG_USER_USER;
00570 rootuser = 0;
00571 }
00572
00573 reauth = strchr(uname, MIDGARD_LOGIN_SG_REAUTH);
00574 if (reauth) {
00575 *reauth = '\0';
00576 reauth++;
00577 }
00578
00579 if ((su == 1) && (sitegroup || reauth)) {
00580 g_free(uname);
00581 return MGD_AUTH_REAUTH;
00582 }
00583
00584 if (sitegroup && *sitegroup) {
00585 res =
00586 mgd_ungrouped_select(mgd, "id,admingroup", "sitegroup",
00587 "name=$q", NULL, sitegroup);
00588
00589
00590 if (!res || !mgd_fetch(res)) {
00591 if (res)
00592 mgd_release(res);
00593 g_free(uname);
00594 return MGD_AUTH_SG_NOTFOUND;
00595 }
00596
00597 req_sitegroup = mgd_sql2id(res, 0);
00598 admingroup = mgd_sql2id(res, 1);
00599 mgd_release(res);
00600 }
00601 else {
00602 req_sitegroup = host_sitegroup;
00603 admingroup = 0;
00604
00605 res =
00606 mgd_ungrouped_select(mgd, "admingroup", "sitegroup",
00607 "id=$d", NULL, host_sitegroup);
00608
00609 if (res) {
00610 if (mgd_fetch(res))
00611 admingroup = mgd_sql2id(res, 0);
00612 mgd_release(res);
00613 }
00614 }
00615
00616 if (rootuser) {
00617 res = mgd_ungrouped_select(mgd, "person.id,person.password",
00618 "person,member",
00619 "person.username=$q AND person.sitegroup=0"
00620 " AND member.uid = person.id AND member.gid=0",
00621 NULL, uname);
00622 }
00623 else {
00624 res = mgd_ungrouped_select(mgd, "id,password", "person",
00625 "username=$q AND sitegroup=$d",
00626 NULL, uname, req_sitegroup);
00627 }
00628
00629
00630 if (!res) {
00631 g_free(uname);
00632 return MGD_AUTH_NOTFOUND;
00633 }
00634
00635
00636 if (mgd_rows(res) != 1) {
00637 mgd_release(res);
00638 return MGD_AUTH_DUPLICATE;
00639 }
00640
00641
00642 if (!res) {
00643 g_free(uname);
00644 return MGD_AUTH_NOTFOUND;
00645 }
00646
00647 while (mgd->current_user->id == 0 && mgd_fetch(res)) {
00648
00649 switch(mgd->auth_type) {
00650 case MGD_AUTHTYPE_NORMAL:
00651
00652
00653
00654
00655 if( 0 > 1)
00656 goto fallback;
00657
00658 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
00659 "Authentication type: NORMAL");
00660 fallback:
00661 passwd = mgd_colvalue(res, 1);
00662
00663 if (passwd[0] == '*' && passwd[1] == '*') {
00664 passwd += 2;
00665 cipher = password;
00666 }
00667 else
00668 #ifdef WIN32
00669 g_warning("crypt not supported on Win32");
00670 #else
00671
00672 cipher = (const char *)crypt(password, passwd);
00673 #endif
00674
00675 if (
00676 su || trusted ||
00677 !strcmp(cipher, passwd))
00678 mgd->current_user->id = mgd_sql2id(res, 0);
00679 break;
00680 #ifdef HAVE_LIBPAM
00681 case MGD_AUTHTYPE_PAM:
00682
00683 {
00684 _midgard_pam_appdata appdata = {
00685 (char*) uname,
00686 (char*) password
00687 };
00688
00689 struct pam_conv pconv = {
00690 _midgard_pam_conv,
00691 &appdata
00692 };
00693
00694 pam_handle_t *phandle = NULL;
00695
00696 int result = pam_start(mgd->pamfile, uname, &pconv, &phandle);
00697 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
00698 "PAM start result: %d", result);
00699
00700 if (result == PAM_SUCCESS)
00701 result = pam_authenticate(phandle, 0);
00702 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
00703 "PAM authenticate result: %d", result);
00704 if (su || (result == PAM_SUCCESS)) {
00705 mgd->current_user->id = mgd_sql2id(res, 0);
00706 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
00707 "PAM auth was successful, new user id: %d", mgd->current_user->id);
00708 }
00709 result = pam_end(phandle, su ? PAM_SUCCESS : result);
00710 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
00711 "PAM end result: %d", result);
00712 if (mgd->current_user->id == 0) {
00713
00714 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
00715 "PAM auth was unsuccessful, going to normal auth");
00716 goto fallback;
00717 }
00718 }
00719 break;
00720 #endif
00721 default:
00722 g_error("Unsupported midgard authentication type %d", mgd->auth_type);
00723 }
00724 }
00725
00726 mgd_release(res);
00727
00728 if (mgd->current_user->id == 0) {
00729 g_free(uname);
00730 return MGD_AUTH_INVALID_PWD;
00731 }
00732
00733
00734 res = mgd_ungrouped_select(mgd, "gid", "member",
00735 "uid=$i AND sitegroup in (0, $i)",
00736 "gid DESC", mgd->current_user->id, req_sitegroup);
00737
00738 if (res) {
00739 mgd->current_user->member_of =
00740 (int *) realloc(mgd->current_user->member_of,
00741 sizeof (int) * (mgd_rows(res) + 1));
00742 i = 0;
00743 while (mgd_fetch(res)) {
00744 if ((mgd->current_user->member_of[i] = mgd_sql2id(res, 0)) != 0) {
00745 if (mgd->current_user->member_of[i] == admingroup)
00746 mgd->current_user->is_admin = 1;
00747 i++;
00748 } else {
00749 mgd->current_user->is_admin = 1;
00750 mgd->current_user->is_root = 1;
00751 }
00752 }
00753
00754 mgd->current_user->member_of[i] = 0;
00755 mgd_release(res);
00756 }
00757
00758 grant = (rootuser && mgd->current_user->is_root);
00759 if (!grant && !rootuser && !mgd->current_user->is_root) {
00760 if (host_sitegroup != 0 && req_sitegroup == host_sitegroup)
00761 grant = 1;
00762 if (host_sitegroup == 0 && req_sitegroup != 0)
00763 grant = 1;
00764 }
00765
00766 if (!grant) {
00767 mgd_clear(mgd, MGD_CLEAR_BASE);
00768 }
00769 else {
00770
00771 mgd->current_user->sitegroup = req_sitegroup;
00772 }
00773
00774 switch (delim) {
00775 case MIDGARD_LOGIN_SG_ROOT_USER:
00776 case MIDGARD_LOGIN_SG_ADMIN_USER:
00777 mgd->current_user->is_admin = 0;
00778 case MIDGARD_LOGIN_SG_ROOT_ADMIN:
00779 mgd->current_user->is_root = 0;
00780 }
00781
00782 if (su == 1) {
00783 if (!grant || mgd->current_user->sitegroup == 0
00784 || !mgd->current_user->is_admin || !reauth) {
00785 mgd_clear(mgd, MGD_CLEAR_BASE);
00786 }
00787 else {
00788
00789 mgd_auth_su(mgd, reauth, "", 1, 0, FALSE);
00790 }
00791 }
00792
00793
00794
00795 if (mgd->schema != NULL ) {
00796 if(g_type_from_name("midgard_person") > 0){
00797 MgdObject *pobject = midgard_object_new_by_id(mgd,
00798 "midgard_person",
00799 (gchar *) mgd->current_user->id);
00800 mgd->person = pobject;
00801 }
00802 }
00803 g_free(uname);
00804 return mgd->current_user->id;
00805 }
00806
00807 int mgd_auth(midgard * mgd,
00808 const char *username, const char *password, int setuid)
00809 {
00810 return mgd_auth_su(mgd, username, password, 0, setuid, FALSE);
00811 }
00812
00813 int mgd_auth_trusted(midgard *mgd, const char *username) {
00814
00815
00816
00817 return mgd_auth_su(mgd, username, NULL, 0, FALSE, TRUE);
00818 }
00819
00820 int mgd_auth_is_setuid(midgard * mgd)
00821 {
00822 return (mgd->current_user == &mgd->setuid_user);
00823 }
00824
00825 MGD_API int mgd_auth_unsetuid(midgard * mgd, long int rsg)
00826 {
00827 if (mgd->current_user == &mgd->user_at_pagestart) return 0;
00828 mgd->current_user = &mgd->user_at_pagestart;
00829 mgd->current_user->sitegroup = rsg;
00830 g_log("midgard-lib", G_LOG_LEVEL_DEBUG, "Unset for SG: %d", (int) rsg);
00831 return 1;
00832 }
00833
00834 void mgd_clear(midgard * mgd, int clearflags)
00835 {
00836 assert(mgd);
00837
00838
00839 mgd->current_user->id = 0;
00840 mgd->current_user->is_admin = 0;
00841 mgd->current_user->is_root = 0;
00842 if (clearflags & MGD_CLEAR_SITEGROUP) { mgd->current_user->sitegroup = 0; }
00843 mgd->username = NULL;
00844
00845 if (mgd->current_user->member_of != NULL)
00846 free(mgd->current_user->member_of);
00847 mgd->current_user->member_of = NULL;
00848
00849
00850 if (clearflags & MGD_CLEAR_PARSER) { mgd->parser = mgd_parser_list(); }
00851
00852
00853 while (mgd->res) mgd_release(mgd->res);
00854
00855 mgd_clear_pool(mgd->pool);
00856 }
00857
00858 int mgd_errno(midgard * mgd)
00859 {
00860 assert(mgd);
00861 return mysql_errno(mgd->msql->mysql);
00862 }
00863
00864 const char *mgd_error(midgard * mgd)
00865 {
00866 assert(mgd);
00867 return mysql_error(mgd->msql->mysql);
00868 }
00869
00870 int mgd_select_parser(midgard * mgd, const char *name)
00871 {
00872 return mgd_parser_activate(mgd, name);
00873 }
00874
00875 const char *mgd_get_parser_name(midgard * mgd)
00876 {
00877 if (mgd && mgd->parser)
00878 return mgd->parser->name;
00879 return NULL;
00880 }
00881
00882 const char *mgd_get_encoding(midgard * mgd)
00883 {
00884 if (mgd && mgd->parser)
00885 return mgd->parser->encoding;
00886 return NULL;
00887 }
00888
00889 int mgd_mail_need_qp(midgard * mgd)
00890 {
00891 if (mgd && mgd->parser)
00892 return mgd->parser->need_qp;
00893 return 0;
00894 }
00895
00896 void mgd_set_sitegroup(midgard * mgd, int sitegroup)
00897 {
00898 assert(mgd);
00899 mgd->current_user->sitegroup = sitegroup;
00900 }
00901 int mgd_sitegroup(midgard * mgd)
00902 {
00903 assert(mgd);
00904 return mgd->current_user->sitegroup;
00905 }
00906
00907 int mgd_user(midgard * mgd)
00908 {
00909 assert(mgd);
00910 return mgd->current_user->id;
00911 }
00912
00913 int mgd_isauser(midgard * mgd)
00914 {
00915 assert(mgd);
00916 return (mgd->current_user->id != 0);
00917 }
00918
00919 int mgd_isadmin(midgard * mgd)
00920 {
00921 assert(mgd);
00922 return mgd->current_user->is_admin;
00923 }
00924
00925 int mgd_isroot(midgard * mgd)
00926 {
00927 assert(mgd);
00928 return mgd->current_user->is_root;
00929 }
00930
00931 void mgd_force_root(midgard * mgd)
00932 {
00933 assert(mgd);
00934 mgd->current_user->is_root = 1;
00935 mgd->current_user->is_admin = 1;
00936 mgd->current_user->id = 0;
00937 }
00938
00939 void mgd_force_admin(midgard * mgd)
00940 {
00941 assert(mgd);
00942 mgd->current_user->is_admin = 1;
00943 mgd->current_user->id = 0;
00944 }
00945
00946
00947 #if HAVE_MIDGARD_MULTILANG
00948 int mgd_lang(midgard * mgd)
00949 {
00950 assert(mgd);
00951 return mgd->lang;
00952 }
00953
00954 void mgd_set_default_lang(midgard *mgd, int lang)
00955 {
00956 g_assert(mgd);
00957 mgd->default_lang = lang;
00958 mgd->lang = lang;
00959 }
00960
00961 int mgd_get_default_lang(midgard *mgd)
00962 {
00963 g_assert(mgd);
00964 return mgd->default_lang;
00965 }
00966
00967 int mgd_parameters_defaultlang(midgard * mgd)
00968 {
00969 assert(mgd);
00970 return mgd->p_lang;
00971 }
00972 int mgd_attachments_defaultlang(midgard * mgd)
00973 {
00974 assert(mgd);
00975 return mgd->a_lang;
00976 }
00977
00978 #endif
00979 int mgd_isuser(midgard * mgd, int user)
00980 {
00981 assert(mgd);
00982 return (mgd->current_user->id == user);
00983 }
00984
00985 int mgd_ismember(midgard * mgd, int group)
00986 {
00987 int i;
00988 int *member_of;
00989
00990 assert(mgd);
00991
00992 member_of = mgd->current_user->member_of;
00993
00994 if (member_of == NULL) return 0;
00995
00996 for (i = 0; member_of[i]; i++) if (member_of[i] == group) return 1;
00997
00998 return 0;
00999 }
01000
01001 int *mgd_groups(midgard * mgd)
01002 {
01003 return mgd->current_user->member_of;
01004 }
01005
01006 midgard_res *mgd_query(midgard * mgd, const char *query, ...)
01007 {
01008 midgard_res *res;
01009 va_list args;
01010 va_start(args, query);
01011 res = mgd_vquery(mgd, query, args);
01012 va_end(args);
01013 return res;
01014 }
01015
01016 midgard_res *mgd_vquery(midgard * mgd, const char *query, va_list args)
01017 {
01018 midgard_res *res;
01019 midgard_pool *pool;
01020 MYSQL_RES *mres;
01021 int rv;
01022 char *fquery;
01023 assert(mgd);
01024 assert(query);
01025
01026 if (mgd->msql->mysql == NULL)
01027 return NULL;
01028
01029
01030 pool = mgd_alloc_pool();
01031 if (!pool)
01032 return NULL;
01033 fquery = mgd_vformat(mgd, pool, query, args);
01034 if (!fquery) {
01035 mgd_free_pool(pool);
01036 return NULL;
01037 }
01038
01039 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", fquery);
01040
01041 rv = mysql_query(mgd->msql->mysql, fquery);
01042
01043 if (rv != 0) {
01044 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
01045 "QUERY: \n"
01046 "%s \n"
01047 "FAILED: \n"
01048 "%s",
01049 fquery, mysql_error(mgd->msql->mysql));
01050 return NULL;
01051 }
01052
01053 g_free(fquery);
01054 mgd_free_pool(pool);
01055
01056
01057 mres = mysql_store_result(mgd->msql->mysql);
01058 if (!mres)
01059 return NULL;
01060 if (mysql_num_rows(mres) == 0) {
01061 mysql_free_result(mres);
01062 return NULL;
01063 }
01064
01065 res = g_new(midgard_res, 1);
01066 if (!res) {
01067 mysql_free_result(mres);
01068 return NULL;
01069 }
01070 res->pool = mgd_alloc_pool();
01071 if (!res->pool) {
01072 free(res);
01073 mysql_free_result(mres);
01074 return NULL;
01075 }
01076 res->mgd = mgd;
01077 res->msql = g_new(midgard_mysql, 1);
01078 res->msql->res = mres;
01079 res->msql->row = NULL;
01080 res->rown = 0;
01081 res->rows = mysql_num_rows(mres);
01082 res->cols = mysql_num_fields(mres);
01083 res->msql->fields = mysql_fetch_fields(mres);
01084
01085
01086 if (mgd->res)
01087 mgd->res->prev = res;
01088 res->prev = NULL;
01089 res->next = mgd->res;
01090 mgd->res = res;
01091
01092 return res;
01093 }
01094
01095 midgard_res *mgd_ungrouped_select(midgard * mgd,
01096 const char *fields, const char *from,
01097 const char *where, const char *sort, ...)
01098 {
01099 midgard_res *res;
01100 va_list args;
01101 va_start(args, sort);
01102 res = mgd_ungrouped_vselect(mgd, fields, from, where, sort, args);
01103 va_end(args);
01104 return res;
01105 }
01106
01107 midgard_res *mgd_sitegroup_select(midgard * mgd,
01108 const char *fields, const char *from,
01109 const char *where, const char *sort, ...)
01110 {
01111 midgard_res *res;
01112 va_list args;
01113 va_start(args, sort);
01114 res = mgd_sitegroup_vselect(mgd, fields, from, where, sort, args);
01115 va_end(args);
01116 return res;
01117 }
01118
01119 midgard_res *mgd_ungrouped_vselect(midgard * mgd,
01120 const char *fields, const char *from,
01121 const char *where, const char *sort,
01122 va_list args)
01123 {
01124 midgard_res *res;
01125 assert(fields && from);
01126 GString *query = g_string_new("SELECT ");
01127
01128
01129 if (where)
01130 if (sort)
01131 g_string_append_printf(query,
01132 "%s FROM %s WHERE %s ORDER BY %s",
01133 fields, from, where, sort);
01134 else
01135 g_string_append_printf(query,
01136 "%s FROM %s WHERE %s",
01137 fields, from, where);
01138
01139 else if (sort)
01140 g_string_append_printf(query,
01141 "%s FROM %s ORDER BY %s",
01142 fields, from, sort);
01143 else
01144 g_string_append_printf(query,
01145 "%s FROM %s ",
01146 fields, from);
01147
01148
01149 gchar *tmpstr = g_string_free(query, FALSE);
01150
01151 res = mgd_vquery(mgd, tmpstr, args);
01152 g_free(tmpstr);
01153
01154 return res;
01155 }
01156
01157
01158 char *mgd_sitegroup_clause(midgard * mgd, midgard_pool * pool,
01159 const char *tables)
01160 {
01161 char *table , *tmptable;
01162 const char *sgclause;
01163
01164 if (mgd->current_user->is_root) {
01165 return g_strdup("");
01166 }
01167
01168
01169 tmptable = g_strdup(tables);
01170 table = strtok((gchar *)tmptable, " ,");
01171
01172 while (table && !*table)
01173 table = strtok(NULL, " ,");
01174
01175 if (!table) {
01176 return g_strdup("AND 0=1");
01177 }
01178
01179 #if HAVE_MIDGARD_MULTILANG
01180 if (!strstr(table, "_i")) {
01181 #endif
01182 sgclause = mgd_format(mgd, pool, "AND ($s.sitegroup in (0,$d)",
01183 table, mgd->current_user->sitegroup);
01184 #if HAVE_MIDGARD_MULTILANG
01185 } else {
01186 sgclause = mgd_strdup(pool, "1=1");
01187 }
01188 #endif
01189
01190 if (!sgclause) {
01191 return g_strdup("AND 0=2");
01192 }
01193
01194 for (table = strtok(NULL, " ,"); table; table = strtok(NULL, " ,")) {
01195 if (!*table)
01196 continue;
01197
01198 #if HAVE_MIDGARD_MULTILANG
01199 if (!strstr(table, "_i")) {
01200 #endif
01201 sgclause =
01202 mgd_format(mgd, pool, "$s AND $s.sitegroup in (0, $d)",
01203 sgclause, table, mgd->current_user->sitegroup);
01204 #if HAVE_MIDGARD_MULTILANG
01205 }
01206 #endif
01207
01208 if (!sgclause) {
01209 return g_strdup("AND 0=3");
01210 }
01211 }
01212
01213 g_free(table);
01214 return mgd_format(mgd, pool, "$s)", sgclause);
01215 }
01216
01217 midgard_res *mgd_sitegroup_vselect(midgard * mgd,
01218 const char *fields, const char *from,
01219 const char *where, const char *sort,
01220 va_list args)
01221 {
01222 midgard_res *res;
01223 const char *query;
01224 midgard_pool *pool;
01225 const char *sgclause;
01226 assert(fields && from);
01227 pool = mgd_alloc_pool();
01228 if (!pool)
01229 return NULL;
01230
01231 sgclause = mgd_sitegroup_clause(mgd, pool, from);
01232
01233 if (sort)
01234 query = mgd_format(mgd, pool,
01235 "SELECT $s FROM $s WHERE ($s) $s"
01236 " ORDER BY $s",
01237 fields, from, where ? where : "1=1",
01238 sgclause, sort);
01239 else
01240 query = mgd_format(mgd, pool,
01241 "SELECT $s FROM $s WHERE ($s) $s",
01242 fields, from, where ? where : "1=1",
01243 sgclause);
01244
01245 g_free((gchar *)sgclause);
01246
01247 if (!query) {
01248 mgd_free_pool(pool);
01249 return NULL;
01250 }
01251
01252
01253 res = mgd_vquery(mgd, query, args);
01254 g_free((gchar *)query);
01255
01256 mgd_free_pool(pool);
01257 return res;
01258 }
01259
01260 midgard_res *mgd_ungrouped_record(midgard * mgd,
01261 const char *fields, const char *table, int id)
01262 {
01263 midgard_res *res;
01264 const char *query;
01265 midgard_pool *pool;
01266 pool = mgd_alloc_pool();
01267 if (!pool)
01268 return NULL;
01269
01270
01271 #if ! HAVE_MIDGARD_MULTILANG
01272 query = mgd_format(mgd, pool, "SELECT $s FROM $s WHERE id=$i",
01273 fields, table, id);
01274 #else
01275 query = mgd_format(mgd, pool, "SELECT $s FROM $s WHERE $s.id=$i",
01276 fields, table, table, id);
01277 #endif
01278 if (!query) {
01279 mgd_free_pool(pool);
01280 return NULL;
01281 }
01282
01283
01284 res = mgd_query(mgd, query);
01285 g_free((gchar *)query);
01286
01287 mgd_free_pool(pool);
01288 return res;
01289 }
01290
01291 midgard_res *mgd_sitegroup_record(midgard * mgd,
01292 const char *fields, const char *table, int id)
01293 {
01294 midgard_res *res;
01295 const char *query;
01296 midgard_pool *pool;
01297
01298 pool = mgd_alloc_pool();
01299 if (!pool)
01300 return NULL;
01301
01302
01303 query = mgd_format(mgd, pool,
01304 "SELECT $s,sitegroup FROM $s WHERE id=$i AND (sitegroup in (0, $d) OR $d<>0)",
01305 fields, table, id,
01306 mgd->current_user->sitegroup,
01307 mgd->current_user->