Kagera Session Manager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sessmgr.c 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /**
  2. * @PROJECT Session Manager
  3. * @COPYRIGHT See COPYING in the top level directory
  4. * @FILE sessmgr.h
  5. * @PURPOSE WebUI session manager
  6. * @DEVELOPERS Eric Bishop <eric@gargoyle-router.com>
  7. * Rafal Kupiec <belliash@asiotec.eu.org>
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <pwd.h>
  14. #include <stdarg.h>
  15. #include <time.h>
  16. #include "sessmgr.h"
  17. #include "sha256.h"
  18. char* get_cookie_time(time_t t) {
  19. struct tm* utc = gmtime(&t);
  20. char wday[4];
  21. char month[4];
  22. switch(utc->tm_wday) {
  23. case 0:
  24. sprintf(wday, "Sun");
  25. break;
  26. case 1:
  27. sprintf(wday, "Mon");
  28. break;
  29. case 2:
  30. sprintf(wday, "Tue");
  31. break;
  32. case 3:
  33. sprintf(wday, "Wed");
  34. break;
  35. case 4:
  36. sprintf(wday, "Thu");
  37. break;
  38. case 5:
  39. sprintf(wday, "Fri");
  40. break;
  41. case 6:
  42. sprintf(wday, "Sat");
  43. break;
  44. }
  45. switch(utc->tm_mon) {
  46. case 0:
  47. sprintf(month, "Jan");
  48. break;
  49. case 1:
  50. sprintf(month, "Feb");
  51. break;
  52. case 2:
  53. sprintf(month, "Mar");
  54. break;
  55. case 3:
  56. sprintf(month, "Apr");
  57. break;
  58. case 4:
  59. sprintf(month, "May");
  60. break;
  61. case 5:
  62. sprintf(month, "Jun");
  63. break;
  64. case 6:
  65. sprintf(month, "Jul");
  66. break;
  67. case 7:
  68. sprintf(month, "Aug");
  69. break;
  70. case 8:
  71. sprintf(month, "Sep");
  72. break;
  73. case 9:
  74. sprintf(month, "Oct");
  75. break;
  76. case 10:
  77. sprintf(month, "Nov");
  78. break;
  79. case 11:
  80. sprintf(month, "Dec");
  81. break;
  82. }
  83. char utc_str[200];
  84. 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);
  85. return safe_strdup(utc_str);
  86. }
  87. char* get_root_hash(void) {
  88. char* root_hash = get_root_hash_from_file("/etc/shadow");
  89. if(root_hash == NULL) {
  90. root_hash = get_root_hash_from_file("/etc/passwd");
  91. }
  92. return root_hash;
  93. }
  94. char* get_root_hash_from_file(const char* passwd_file) {
  95. int found = 0;
  96. FILE *pw = fopen(passwd_file, "r");
  97. char* root_hash = NULL;
  98. if(pw != NULL) {
  99. char line[512];
  100. char* test = fgets(line, 511, pw);
  101. while(test != NULL && !found) {
  102. if(strlen(test) > 5) {
  103. test[4] = '\0';
  104. if(strcmp(test, "root") == 0) {
  105. char* hash_end;
  106. found = 1;
  107. test = test + 5;
  108. hash_end = strchr(test, ':');
  109. *hash_end = '\0';
  110. root_hash = safe_strdup(test);
  111. }
  112. }
  113. test = fgets(line, 511, pw);
  114. }
  115. fclose(pw);
  116. }
  117. return root_hash;
  118. }
  119. int main(int argc, char **argv) {
  120. char *password = NULL;
  121. char *cookie_hash = NULL;
  122. char *cookie_exp = NULL;
  123. char *user_agent = NULL;
  124. char *src_ip = NULL;
  125. char *redirect = NULL;
  126. int timeout_minutes = DEFAULT_SESSION_TIMEOUT;
  127. unsigned long browser_time = 0;
  128. int loggedout = 0;
  129. int unconditionally_generate = 0;
  130. int next_opt;
  131. int read;
  132. 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) {
  133. switch(next_opt) {
  134. case 'p':
  135. case 'P':
  136. password = safe_strdup(optarg);
  137. break;
  138. case 'c':
  139. case 'C':
  140. cookie_hash = safe_strdup(optarg);
  141. break;
  142. case 'e':
  143. case 'E':
  144. cookie_exp = safe_strdup(optarg);
  145. break;
  146. case 'a':
  147. case 'A':
  148. user_agent = safe_strdup(optarg);
  149. break;
  150. case 'i':
  151. case 'I':
  152. src_ip = safe_strdup(optarg);
  153. break;
  154. case 'r':
  155. case 'R':
  156. redirect = safe_strdup(optarg);
  157. break;
  158. case 't':
  159. case 'T':
  160. read = sscanf(optarg, "%d", &timeout_minutes);
  161. if(read > 0) {
  162. timeout_minutes = timeout_minutes > 0 ? timeout_minutes : DEFAULT_SESSION_TIMEOUT;
  163. } else {
  164. timeout_minutes = DEFAULT_SESSION_TIMEOUT;
  165. }
  166. timeout_minutes *= 60;
  167. break;
  168. case 'b':
  169. case 'B':
  170. read = sscanf(optarg, "%ld", &browser_time);
  171. browser_time = read > 0 ? browser_time : 0;
  172. break;
  173. case 'l':
  174. case 'L':
  175. loggedout = 1;
  176. break;
  177. case 'g':
  178. case 'G':
  179. unconditionally_generate = 1;
  180. break;
  181. }
  182. }
  183. int expired = 0;
  184. int valid = 0;
  185. char* root_hash = get_root_hash();
  186. if(loggedout == 1) {
  187. printf("echo \"Set-Cookie:kagera_sid=loggedout;\"; ");
  188. } else if(root_hash != NULL) {
  189. time_t now;
  190. time(&now);
  191. if(password != NULL) {
  192. valid = strcmp(crypt(password, root_hash), root_hash) == 0 ? 1 : 0;
  193. if(valid) {
  194. printf("logger -t webui \"Kagera Administration Interface authorization succeeded from ${REMOTE_ADDR}\"; ");
  195. }
  196. } else if(cookie_hash != NULL && cookie_exp != NULL && user_agent != NULL && src_ip != NULL) {
  197. time_t exp_time;
  198. int read = sscanf(cookie_exp, "%ld", &exp_time);
  199. if(read > 0) {
  200. expired = 1;
  201. if(exp_time > now && (exp_time - (timeout_minutes) - 2) <= now) {
  202. expired = 0;
  203. }
  204. }
  205. char *combined = safe_strcat(4, root_hash, cookie_exp, user_agent, src_ip);
  206. char* hashed = get_sha256_hash_hex_str(combined);
  207. if(strcmp(hashed, cookie_hash) == 0) {
  208. if(expired == 0 && read > 0) {
  209. valid = 1;
  210. }
  211. } else {
  212. expired = 0;
  213. }
  214. free(hashed);
  215. free(combined);
  216. }
  217. if(unconditionally_generate == 1) {
  218. valid = 1;
  219. }
  220. if(valid == 1 && src_ip != NULL && user_agent != NULL) {
  221. char* new_hash;
  222. char* combined;
  223. char new_exp[100] = "";
  224. time_t new_exp_t = now + (timeout_minutes);
  225. sprintf(new_exp, "%ld", new_exp_t);
  226. char* cookie_exp;
  227. if(browser_time > 0 && ((browser_time - now) < (-5*60) || (browser_time - now) > (5*60))) {
  228. time_t cookie_exp_t = browser_time+(timeout_minutes);
  229. cookie_exp = get_cookie_time(cookie_exp_t);
  230. } else {
  231. cookie_exp = get_cookie_time(new_exp_t);
  232. }
  233. combined = safe_strcat(4, root_hash, new_exp, user_agent, src_ip);
  234. new_hash = get_sha256_hash_hex_str(combined);
  235. if(browser_time == 0) {
  236. printf("echo \"Set-Cookie:kagera_sid=%s; Path=/;\"; echo \"Set-Cookie:kagera_exp=%s; Path=/;\"; ", new_hash, new_exp);
  237. } else {
  238. 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);
  239. }
  240. free(new_hash);
  241. free(combined);
  242. free(cookie_exp);
  243. } else {
  244. printf("KAGERA_LOGGEDOUT=1\n");
  245. }
  246. free(root_hash);
  247. }
  248. if(redirect != NULL) {
  249. char str[20] = "";
  250. if(expired == 1) {
  251. sprintf(str, "&expired=1");
  252. } else if(loggedout == 1) {
  253. sprintf(str, "&loggedout=1");
  254. }
  255. printf("echo \"HTTP/1.1 301 Moved Permanently;\"; echo \"Location: %s%s\"; exit", redirect, str);
  256. }
  257. return 0;
  258. }
  259. void* safe_malloc(size_t size) {
  260. void* val = malloc(size);
  261. if(val == NULL) {
  262. fprintf(stderr, "ERROR: MALLOC FAILURE!\n");
  263. exit(1);
  264. }
  265. return val;
  266. }
  267. char* safe_strcat(int num_strs, ...) {
  268. va_list strs;
  269. int new_length = 0;
  270. int i;
  271. int next_start;
  272. char* new_str;
  273. va_start(strs, num_strs);
  274. for(i=0; i < num_strs; i++) {
  275. char* next_arg = va_arg(strs, char*);
  276. if(next_arg != NULL) {
  277. new_length = new_length + strlen(next_arg);
  278. }
  279. }
  280. va_end(strs);
  281. new_str = safe_malloc((1 + new_length) * sizeof(char));
  282. va_start(strs, num_strs);
  283. next_start = 0;
  284. for(i=0; i < num_strs; i++) {
  285. char* next_arg = va_arg(strs, char*);
  286. if(next_arg != NULL) {
  287. int next_length = strlen(next_arg);
  288. memcpy(new_str+next_start,next_arg, next_length);
  289. next_start = next_start+next_length;
  290. }
  291. }
  292. new_str[next_start] = '\0';
  293. return new_str;
  294. }
  295. char* safe_strdup(const char* str) {
  296. char* new_str = NULL;
  297. if(str != NULL) {
  298. new_str = strdup(str);
  299. if(new_str == NULL) {
  300. fprintf(stderr, "ERROR: MALLOC FAILURE!\n");
  301. exit(1);
  302. }
  303. }
  304. return new_str;
  305. }