245 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * @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 <stdarg.h>
 | |
| #include <time.h>
 | |
| #include <pwd.h>
 | |
| #ifdef USE_SHADOW
 | |
| 	#include <shadow.h>
 | |
| #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;
 | |
| }
 |