Initial import
This commit is contained in:
317
sessmgr.c
Normal file
317
sessmgr.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* @PROJECT Session Manager
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE sessmgr.h
|
||||
* @PURPOSE WebUI session manager
|
||||
* @DEVELOPERS Eric Bishop <eric@gargoyle-router.com>
|
||||
* Rafal Kupiec <belliash@asiotec.eu.org>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "sessmgr.h"
|
||||
#include "sha256.h"
|
||||
|
||||
char* get_cookie_time(time_t t) {
|
||||
struct tm* utc = gmtime(&t);
|
||||
char wday[4];
|
||||
char month[4];
|
||||
switch(utc->tm_wday) {
|
||||
case 0:
|
||||
sprintf(wday, "Sun");
|
||||
break;
|
||||
case 1:
|
||||
sprintf(wday, "Mon");
|
||||
break;
|
||||
case 2:
|
||||
sprintf(wday, "Tue");
|
||||
break;
|
||||
case 3:
|
||||
sprintf(wday, "Wed");
|
||||
break;
|
||||
case 4:
|
||||
sprintf(wday, "Thu");
|
||||
break;
|
||||
case 5:
|
||||
sprintf(wday, "Fri");
|
||||
break;
|
||||
case 6:
|
||||
sprintf(wday, "Sat");
|
||||
break;
|
||||
}
|
||||
switch(utc->tm_mon) {
|
||||
case 0:
|
||||
sprintf(month, "Jan");
|
||||
break;
|
||||
case 1:
|
||||
sprintf(month, "Feb");
|
||||
break;
|
||||
case 2:
|
||||
sprintf(month, "Mar");
|
||||
break;
|
||||
case 3:
|
||||
sprintf(month, "Apr");
|
||||
break;
|
||||
case 4:
|
||||
sprintf(month, "May");
|
||||
break;
|
||||
case 5:
|
||||
sprintf(month, "Jun");
|
||||
break;
|
||||
case 6:
|
||||
sprintf(month, "Jul");
|
||||
break;
|
||||
case 7:
|
||||
sprintf(month, "Aug");
|
||||
break;
|
||||
case 8:
|
||||
sprintf(month, "Sep");
|
||||
break;
|
||||
case 9:
|
||||
sprintf(month, "Oct");
|
||||
break;
|
||||
case 10:
|
||||
sprintf(month, "Nov");
|
||||
break;
|
||||
case 11:
|
||||
sprintf(month, "Dec");
|
||||
break;
|
||||
}
|
||||
char utc_str[200];
|
||||
sprintf(utc_str, "%s, %d %s %d %02d:%02d:%02d UTC", wday, utc->tm_mday, month, (utc->tm_year + 1900), utc->tm_hour, utc->tm_min, utc->tm_sec);
|
||||
return safe_strdup(utc_str);
|
||||
}
|
||||
|
||||
char* get_root_hash(void) {
|
||||
char* root_hash = get_root_hash_from_file("/etc/shadow");
|
||||
if(root_hash == NULL) {
|
||||
root_hash = get_root_hash_from_file("/etc/passwd");
|
||||
}
|
||||
return root_hash;
|
||||
}
|
||||
|
||||
char* get_root_hash_from_file(const char* passwd_file) {
|
||||
int found = 0;
|
||||
FILE *pw = fopen(passwd_file, "r");
|
||||
char* root_hash = NULL;
|
||||
if(pw != NULL) {
|
||||
char line[512];
|
||||
char* test = fgets(line, 511, pw);
|
||||
while(test != NULL && !found) {
|
||||
if(strlen(test) > 5) {
|
||||
test[4] = '\0';
|
||||
if(strcmp(test, "root") == 0) {
|
||||
char* hash_end;
|
||||
found = 1;
|
||||
test = test + 5;
|
||||
hash_end = strchr(test, ':');
|
||||
*hash_end = '\0';
|
||||
root_hash = safe_strdup(test);
|
||||
}
|
||||
}
|
||||
test = fgets(line, 511, pw);
|
||||
}
|
||||
fclose(pw);
|
||||
}
|
||||
return root_hash;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *password = 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 unconditionally_generate = 0;
|
||||
int next_opt;
|
||||
int read;
|
||||
|
||||
while((next_opt = getopt(argc, argv, "p:P:c:C:e:E:a:A:i:I:r:R:t:T:b:B:lL:gG")) != -1) {
|
||||
switch(next_opt) {
|
||||
case 'p':
|
||||
case 'P':
|
||||
password = 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;
|
||||
case 'g':
|
||||
case 'G':
|
||||
unconditionally_generate = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int expired = 0;
|
||||
int valid = 0;
|
||||
char* root_hash = get_root_hash();
|
||||
if(loggedout == 1) {
|
||||
printf("echo \"Set-Cookie:kagera_sid=loggedout;\"; ");
|
||||
} else if(root_hash != NULL) {
|
||||
time_t now;
|
||||
time(&now);
|
||||
if(password != NULL) {
|
||||
valid = strcmp(crypt(password, root_hash), root_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, root_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(unconditionally_generate == 1) {
|
||||
valid = 1;
|
||||
}
|
||||
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, root_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_exp=%s; Path=/;\"; ", new_hash, new_exp);
|
||||
} else {
|
||||
printf("echo \"Set-Cookie:kagera_sid=%s; Expires=%s; Path=/;\"; echo \"Set-Cookie:kagera_exp=%s; Expires=%s; Path=/;\"; ", new_hash, cookie_exp, new_exp, cookie_exp);
|
||||
}
|
||||
free(new_hash);
|
||||
free(combined);
|
||||
free(cookie_exp);
|
||||
} else {
|
||||
printf("KAGERA_LOGGEDOUT=1\n");
|
||||
}
|
||||
free(root_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;
|
||||
}
|
Reference in New Issue
Block a user