/** * @PROJECT Session Manager * @COPYRIGHT See COPYING in the top level directory * @FILE sessmgr.h * @PURPOSE WebUI session manager * @DEVELOPERS Eric Bishop * Rafal Kupiec */ #include #include #include #include #include #include #include #ifdef USE_SHADOW #include #endif #include "sessmgr.h" #include "sha256.h" char* get_admin_hash(const char* username) { char* admin_hash = NULL; if(username) { #ifdef USE_SHADOW struct spwd* pw; if((pw = getspnam(username)) != NULL) { admin_hash = strdup(pw->sp_pwdp); } #else struct passwd* pw; if((pw = getpwnam(username)) != NULL) { admin_hash = strdup(pw->pw_passwd); } #endif } return admin_hash; } char* get_cookie_time(time_t t) { struct tm* utc = gmtime(&t); char *wdays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char utc_str[200]; sprintf(utc_str, "%s, %d %s %d %02d:%02d:%02d UTC", wdays[utc->tm_wday], utc->tm_mday, months[utc->tm_mon], (utc->tm_year + 1900), utc->tm_hour, utc->tm_min, utc->tm_sec); return safe_strdup(utc_str); } int main(int argc, char **argv) { char *password = NULL; char *username = NULL; char *cookie_hash = NULL; char *cookie_exp = NULL; char *user_agent = NULL; char *src_ip = NULL; char *redirect = NULL; int timeout_minutes = DEFAULT_SESSION_TIMEOUT; unsigned long browser_time = 0; int loggedout = 0; int next_opt; int read; while((next_opt = getopt(argc, argv, "p:P:u:U:c:C:e:E:a:A:i:I:r:R:t:T:b:B:lL")) != -1) { switch(next_opt) { case 'p': case 'P': password = safe_strdup(optarg); break; case 'u': case 'U': username = safe_strdup(optarg); break; case 'c': case 'C': cookie_hash = safe_strdup(optarg); break; case 'e': case 'E': cookie_exp = safe_strdup(optarg); break; case 'a': case 'A': user_agent = safe_strdup(optarg); break; case 'i': case 'I': src_ip = safe_strdup(optarg); break; case 'r': case 'R': redirect = safe_strdup(optarg); break; case 't': case 'T': read = sscanf(optarg, "%d", &timeout_minutes); if(read > 0) { timeout_minutes = timeout_minutes > 0 ? timeout_minutes : DEFAULT_SESSION_TIMEOUT; } else { timeout_minutes = DEFAULT_SESSION_TIMEOUT; } timeout_minutes *= 60; break; case 'b': case 'B': read = sscanf(optarg, "%ld", &browser_time); browser_time = read > 0 ? browser_time : 0; break; case 'l': case 'L': loggedout = 1; break; } } int expired = 0; int valid = 0; char* admin_hash = get_admin_hash(username); if(loggedout == 1) { printf("echo \"Set-Cookie:kagera_sid=loggedout;\"; echo \"Set-Cookie:kagera_usr=loggedout;\"; "); } else if(admin_hash != NULL) { time_t now; time(&now); if(password != NULL) { valid = strcmp(crypt(password, admin_hash), admin_hash) == 0 ? 1 : 0; if(valid) { printf("logger -t webui \"Kagera Administration Interface authorization succeeded from ${REMOTE_ADDR}\"; "); } } else if(cookie_hash != NULL && cookie_exp != NULL && user_agent != NULL && src_ip != NULL) { time_t exp_time; int read = sscanf(cookie_exp, "%ld", &exp_time); if(read > 0) { expired = 1; if(exp_time > now && (exp_time - (timeout_minutes) - 2) <= now) { expired = 0; } } char *combined = safe_strcat(4, admin_hash, cookie_exp, user_agent, src_ip); char* hashed = get_sha256_hash_hex_str(combined); if(strcmp(hashed, cookie_hash) == 0) { if(expired == 0 && read > 0) { valid = 1; } } else { expired = 0; } free(hashed); free(combined); } if(valid == 1 && src_ip != NULL && user_agent != NULL) { char* new_hash; char* combined; char new_exp[100] = ""; time_t new_exp_t = now + (timeout_minutes); sprintf(new_exp, "%ld", new_exp_t); char* cookie_exp; if(browser_time > 0 && ((browser_time - now) < (-5*60) || (browser_time - now) > (5*60))) { time_t cookie_exp_t = browser_time+(timeout_minutes); cookie_exp = get_cookie_time(cookie_exp_t); } else { cookie_exp = get_cookie_time(new_exp_t); } combined = safe_strcat(4, admin_hash, new_exp, user_agent, src_ip); new_hash = get_sha256_hash_hex_str(combined); if(browser_time == 0) { printf("echo \"Set-Cookie:kagera_sid=%s; Path=/;\"; echo \"Set-Cookie:kagera_usr=%s; Path=/;\"; echo \"Set-Cookie:kagera_exp=%s; Path=/;\"; ", new_hash, username, new_exp); } else { printf("echo \"Set-Cookie:kagera_sid=%s; Expires=%s; Path=/;\"; echo \"Set-Cookie:kagera_usr=%s; Expires=%s; Path=/;\"; echo \"Set-Cookie:kagera_exp=%s; Expires=%s; Path=/;\"; ", new_hash, cookie_exp, username, cookie_exp, new_exp, cookie_exp); } free(new_hash); free(combined); free(cookie_exp); printf("VALIDSESS=1\n"); } free(admin_hash); } if(redirect != NULL) { char str[20] = ""; if(expired == 1) { sprintf(str, "&expired=1"); } else if(loggedout == 1) { sprintf(str, "&loggedout=1"); } printf("echo \"HTTP/1.1 301 Moved Permanently;\"; echo \"Location: %s%s\"; exit", redirect, str); } return 0; } void* safe_malloc(size_t size) { void* val = malloc(size); if(val == NULL) { fprintf(stderr, "ERROR: MALLOC FAILURE!\n"); exit(1); } return val; } char* safe_strcat(int num_strs, ...) { va_list strs; int new_length = 0; int i; int next_start; char* new_str; va_start(strs, num_strs); for(i=0; i < num_strs; i++) { char* next_arg = va_arg(strs, char*); if(next_arg != NULL) { new_length = new_length + strlen(next_arg); } } va_end(strs); new_str = safe_malloc((1 + new_length) * sizeof(char)); va_start(strs, num_strs); next_start = 0; for(i=0; i < num_strs; i++) { char* next_arg = va_arg(strs, char*); if(next_arg != NULL) { int next_length = strlen(next_arg); memcpy(new_str+next_start,next_arg, next_length); next_start = next_start+next_length; } } new_str[next_start] = '\0'; return new_str; } char* safe_strdup(const char* str) { char* new_str = NULL; if(str != NULL) { new_str = strdup(str); if(new_str == NULL) { fprintf(stderr, "ERROR: MALLOC FAILURE!\n"); exit(1); } } return new_str; }