authentication.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include <stdlib.h>
  2. #include <time.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include "mongoose.h"
  6. /*
  7. * Cookie based authentication
  8. * taken from http://en.wikipedia.org/wiki/HTTP_cookie#Authentication
  9. *
  10. * 1. The user inserts his or her username and password in the text fields
  11. * of a login page and sends them to the server;
  12. * 2. The server receives the username and password and checks them; if
  13. * correct, it sends back a page confirming that login has been successful
  14. * together with a cookie containing a random session ID that coincides with
  15. * a session stored in a database. This cookie is usually made valid for
  16. * only the current browser session, however it may also be set to expire at
  17. * a future date. The random session ID is then provided on future visits
  18. * and provides a way for the server to uniquely identify the browser and
  19. * confirm that the browser already has an authenticated user.
  20. * 3. Every time the user requests a page from the server, the browser
  21. * automatically sends the cookie back to the server; the server compares
  22. * the cookie with the stored ones; if a match is found, the server knows
  23. * which user has requested that page.
  24. */
  25. static void
  26. login_page(struct mg_connection *conn,
  27. const struct mg_request_info *ri, void *data)
  28. {
  29. char *name, *pass, uri[100];
  30. const char *cookie;
  31. name = mg_get_var(conn, "name");
  32. pass = mg_get_var(conn, "pass");
  33. cookie = mg_get_header(conn, "Cookie");
  34. /*
  35. * Here user name and password must be checked against some
  36. * database - this is step 2 from the algorithm described above.
  37. * This is an example, so hardcode name and password to be
  38. * admin/admin, and if this is so, set "allow=yes" cookie and
  39. * redirect back to the page where we have been redirected to login.
  40. */
  41. if (name != NULL && pass != NULL &&
  42. strcmp(name, "admin") == 0 && strcmp(pass, "admin") == 0) {
  43. if (cookie == NULL || sscanf(cookie, "uri=%99s", uri) != 1)
  44. (void) strcpy(uri, "/");
  45. /* Set allow=yes cookie, which is expected by authorize() */
  46. mg_printf(conn, "HTTP/1.1 301 Moved Permanently\r\n"
  47. "Location: %s\r\n"
  48. "Set-Cookie: allow=yes;\r\n\r\n", uri);
  49. } else {
  50. /* Print login page */
  51. mg_printf(conn, "HTTP/1.1 200 OK\r\n"
  52. "content-Type: text/html\r\n\r\n"
  53. "Please login (enter admin/admin to pass)<br>"
  54. "<form method=post>"
  55. "Name: <input type=text name=name></input><br/>"
  56. "Password: <input type=password name=pass></input><br/>"
  57. "<input type=submit value=Login></input>"
  58. "</form>");
  59. }
  60. if (name != NULL)
  61. mg_free(name);
  62. if (pass != NULL)
  63. mg_free(pass);
  64. }
  65. static void
  66. authorize(struct mg_connection *conn,
  67. const struct mg_request_info *ri, void *data)
  68. {
  69. const char *cookie, *domain;
  70. cookie = mg_get_header(conn, "Cookie");
  71. if (!strcmp(ri->uri, "/login")) {
  72. /* Always authorize accesses to the login page */
  73. mg_authorize(conn);
  74. } else if (cookie != NULL && strstr(cookie, "allow=yes") != NULL) {
  75. /* Valid cookie is present, authorize */
  76. mg_authorize(conn);
  77. } else {
  78. /* Not authorized. Redirect to the login page */
  79. mg_printf(conn, "HTTP/1.1 301 Moved Permanently\r\n"
  80. "Set-Cookie: uri=%s;\r\n"
  81. "Location: /login\r\n\r\n", ri->uri);
  82. }
  83. }
  84. int
  85. main(int argc, char *argv[])
  86. {
  87. struct mg_context *ctx;
  88. ctx = mg_start();
  89. mg_set_option(ctx, "ports", "8080");
  90. mg_set_auth_callback(ctx, "/*", &authorize, NULL);
  91. mg_set_uri_callback(ctx, "/login", &login_page, NULL);
  92. for (;;)
  93. sleep(1);
  94. }