cookie_auth.c
Go to the documentation of this file.
00001 // Copyright (c) 2014 Cesanta Software
00002 // All rights reserved
00003 
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <time.h>
00007 #include "mongoose.h"
00008 
00009 static const char *s_login_uri = "/login.html";
00010 static const char *s_secret = ":-)";  // Must be known only to server
00011 
00012 static void generate_ssid(const char *user_name, const char *expiration_date,
00013                           char *ssid, size_t ssid_size) {
00014   char hash[33];
00015   mg_md5(hash, user_name, ":", expiration_date, ":", s_secret, NULL);
00016   snprintf(ssid, ssid_size, "%s|%s|%s", user_name, expiration_date, hash);
00017 }
00018 
00019 static int check_auth(struct mg_connection *conn) {
00020   char ssid[100], calculated_ssid[100], name[100], expire[100];
00021 
00022   // Always authenticate requests to login page
00023   if (strcmp(conn->uri, s_login_uri) == 0) {
00024     return MG_TRUE;
00025   }
00026 
00027   // Look for session ID in the Cookie.
00028   // That session ID can be validated against the database that stores
00029   // current active sessions.
00030   mg_parse_header(mg_get_header(conn, "Cookie"), "ssid", ssid, sizeof(ssid));
00031   if (sscanf(ssid, "%[^|]|%[^|]|", name, expire) == 2) {
00032     generate_ssid(name, expire, calculated_ssid, sizeof(calculated_ssid));
00033     if (strcmp(ssid, calculated_ssid) == 0) {
00034       return MG_TRUE;  // Authenticate
00035     }
00036   }
00037 
00038   // Auth failed, do NOT authenticate, redirect to login page
00039   mg_printf(conn, "HTTP/1.1 302 Moved\r\nLocation: %s\r\n\r\n", s_login_uri);
00040   return MG_FALSE;
00041 }
00042 
00043 static int check_login_form_submission(struct mg_connection *conn) {
00044   char name[100], password[100], ssid[100], expire[100], expire_epoch[100];
00045 
00046   mg_get_var(conn, "name", name, sizeof(name));
00047   mg_get_var(conn, "password", password, sizeof(password));
00048 
00049   // A real authentication mechanism should be employed here.
00050   // Also, the whole site should be served through HTTPS.
00051   if (strcmp(name, "Joe") == 0 && strcmp(password, "Doe") == 0) {
00052     // Generate expiry date
00053     time_t t = time(NULL) + 3600;  // Valid for 1 hour
00054     snprintf(expire_epoch, sizeof(expire_epoch), "%lu", (unsigned long) t);
00055     strftime(expire, sizeof(expire), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
00056     generate_ssid(name, expire_epoch, ssid, sizeof(ssid));
00057     // Set "session id" cookie, there could be some data encoded in it.
00058     mg_printf(conn,
00059               "HTTP/1.1 302 Moved\r\n"
00060               "Set-Cookie: ssid=%s; expire=\"%s\"; http-only; HttpOnly;\r\n"
00061               "Location: /\r\n\r\n",
00062               ssid, expire);
00063     return MG_TRUE;
00064   }
00065   return MG_FALSE;
00066 }
00067 
00068 static int serve_request(struct mg_connection *conn) {
00069   if (strcmp(conn->uri, s_login_uri) == 0 &&
00070       strcmp(conn->request_method, "POST") == 0) {
00071     return check_login_form_submission(conn);
00072   }
00073   return MG_FALSE;  // Serve files in the document_root
00074 }
00075 
00076 static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
00077   switch (ev) {
00078     case MG_AUTH: return check_auth(conn);
00079     case MG_REQUEST: return serve_request(conn);
00080     default: return MG_FALSE;
00081   }
00082 }
00083 
00084 int main(void) {
00085   struct mg_server *server = mg_create_server(NULL, ev_handler);
00086   mg_set_option(server, "listening_port", "8080");
00087   mg_set_option(server, "document_root", ".");
00088 
00089   printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
00090   for (;;) {
00091     mg_poll_server(server, 1000);
00092   }
00093   mg_destroy_server(&server);
00094 
00095   return 0;
00096 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:02