Commit 001889bd authored by valenok's avatar valenok

fixed chat to example some extent

parent 64ca2965
...@@ -202,16 +202,10 @@ static void ajax_send_message(struct mg_connection *conn, ...@@ -202,16 +202,10 @@ static void ajax_send_message(struct mg_connection *conn,
// we came from, so that after the authorization we could redirect back. // we came from, so that after the authorization we could redirect back.
static void redirect_to_login(struct mg_connection *conn, static void redirect_to_login(struct mg_connection *conn,
const struct mg_request_info *request_info) { const struct mg_request_info *request_info) {
const char *host;
host = mg_get_header(conn, "Host");
mg_printf(conn, "HTTP/1.1 302 Found\r\n" mg_printf(conn, "HTTP/1.1 302 Found\r\n"
"Set-Cookie: original_url=%s://%s%s\r\n" "Set-Cookie: original_url=%s\r\n"
"Location: %s\r\n\r\n", "Location: %s\r\n\r\n",
request_info->is_ssl ? "https" : "http", request_info->uri, login_url);
host ? host : "127.0.0.1",
request_info->uri,
login_url);
} }
// Return 1 if username/password is allowed, 0 otherwise. // Return 1 if username/password is allowed, 0 otherwise.
...@@ -238,12 +232,11 @@ static struct session *new_session(void) { ...@@ -238,12 +232,11 @@ static struct session *new_session(void) {
} }
// Generate session ID. buf must be 33 bytes in size. // Generate session ID. buf must be 33 bytes in size.
// Note that it is easy to steal session cookies by sniffing traffic.
// This is why all communication must be SSL-ed.
static void generate_session_id(char *buf, const char *random, static void generate_session_id(char *buf, const char *random,
const char *user, const struct mg_request_info *request_info) { const char *user) {
char remote_ip[20], remote_port[20]; mg_md5(buf, random, user, NULL);
snprintf(remote_ip, sizeof(remote_ip), "%ld", request_info->remote_ip);
snprintf(remote_port, sizeof(remote_port), "%d", request_info->remote_port);
mg_md5(buf, random, user, remote_port, remote_ip, NULL);
} }
static void send_server_message(const char *fmt, ...) { static void send_server_message(const char *fmt, ...) {
...@@ -264,13 +257,12 @@ static void send_server_message(const char *fmt, ...) { ...@@ -264,13 +257,12 @@ static void send_server_message(const char *fmt, ...) {
// Login page form sends user name and password to this endpoint. // Login page form sends user name and password to this endpoint.
static void authorize(struct mg_connection *conn, static void authorize(struct mg_connection *conn,
const struct mg_request_info *request_info) { const struct mg_request_info *request_info) {
char user[MAX_USER_LEN], password[MAX_USER_LEN], original_url[200]; char user[MAX_USER_LEN], password[MAX_USER_LEN];
struct session *session; struct session *session;
// Fetch user name and password. // Fetch user name and password.
get_qsvar(request_info, "user", user, sizeof(user)); get_qsvar(request_info, "user", user, sizeof(user));
get_qsvar(request_info, "password", password, sizeof(password)); get_qsvar(request_info, "password", password, sizeof(password));
mg_get_cookie(conn, "original_url", original_url, sizeof(original_url));
if (check_password(user, password) && (session = new_session()) != NULL) { if (check_password(user, password) && (session = new_session()) != NULL) {
// Authentication success: // Authentication success:
...@@ -286,17 +278,14 @@ static void authorize(struct mg_connection *conn, ...@@ -286,17 +278,14 @@ static void authorize(struct mg_connection *conn,
// Secure application must use HTTPS all the time. // Secure application must use HTTPS all the time.
my_strlcpy(session->user, user, sizeof(session->user)); my_strlcpy(session->user, user, sizeof(session->user));
snprintf(session->random, sizeof(session->random), "%d", rand()); snprintf(session->random, sizeof(session->random), "%d", rand());
generate_session_id(session->session_id, session->random, generate_session_id(session->session_id, session->random, session->user);
session->user, request_info);
send_server_message("<%s> joined", session->user); send_server_message("<%s> joined", session->user);
mg_printf(conn, "HTTP/1.1 302 Found\r\n" mg_printf(conn, "HTTP/1.1 302 Found\r\n"
"Set-Cookie: session=%s; max-age=3600; http-only\r\n" // Session ID "Set-Cookie: session=%s; max-age=3600; http-only\r\n" // Session ID
"Set-Cookie: user=%s\r\n" // Set user, needed by Javascript code "Set-Cookie: user=%s\r\n" // Set user, needed by Javascript code
"Set-Cookie: original_url=/; max-age=0\r\n" // Delete original_url "Set-Cookie: original_url=/; max-age=0\r\n" // Delete original_url
"Location: %s\r\n\r\n", "Location: /\r\n\r\n",
session->session_id, session->session_id, session->user);
session->user,
original_url[0] == '\0' ? "/" : original_url);
} else { } else {
// Authentication failure, redirect to login. // Authentication failure, redirect to login.
redirect_to_login(conn, request_info); redirect_to_login(conn, request_info);
...@@ -310,24 +299,35 @@ static int is_authorized(const struct mg_connection *conn, ...@@ -310,24 +299,35 @@ static int is_authorized(const struct mg_connection *conn,
char valid_id[33]; char valid_id[33];
int authorized = 0; int authorized = 0;
// Always authorize accesses to login page and to authorize URI
if (!strcmp(request_info->uri, login_url) ||
!strcmp(request_info->uri, authorize_url)) {
return 1;
}
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
if ((session = get_session(conn)) != NULL) { if ((session = get_session(conn)) != NULL) {
generate_session_id(valid_id, session->random, session->user, request_info); generate_session_id(valid_id, session->random, session->user);
if (strcmp(valid_id, session->session_id) == 0) { if (strcmp(valid_id, session->session_id) == 0) {
session->expire = time(0) + SESSION_TTL; session->expire = time(0) + SESSION_TTL;
authorized = 1; authorized = 1;
} }
} }
printf("session: %p\n", session);
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
return authorized; return authorized;
} }
// Return 1 if authorization is required for requested URL, 0 otherwise. static void redirect_to_ssl(struct mg_connection *conn,
static int must_authorize(const struct mg_request_info *request_info) { const struct mg_request_info *request_info) {
return (strcmp(request_info->uri, login_url) != 0 && const char *p, *host = mg_get_header(conn, "Host");
strcmp(request_info->uri, authorize_url) != 0); if (host != NULL && (p = strchr(host, ':')) != NULL) {
mg_printf(conn, "HTTP/1.1 302 Found\r\n"
"Location: https://%.*s:8082/%s:8082\r\n\r\n",
p - host, host, request_info->uri);
} else {
mg_printf(conn, "%s", "HTTP/1.1 500 Error\r\n\r\nHost: header is not set");
}
} }
static void *event_handler(enum mg_event event, static void *event_handler(enum mg_event event,
...@@ -336,7 +336,9 @@ static void *event_handler(enum mg_event event, ...@@ -336,7 +336,9 @@ static void *event_handler(enum mg_event event,
void *processed = "yes"; void *processed = "yes";
if (event == MG_NEW_REQUEST) { if (event == MG_NEW_REQUEST) {
if (must_authorize(request_info) && !is_authorized(conn, request_info)) { if (!request_info->is_ssl) {
redirect_to_ssl(conn, request_info);
} else if (!is_authorized(conn, request_info)) {
redirect_to_login(conn, request_info); redirect_to_login(conn, request_info);
} else if (strcmp(request_info->uri, authorize_url) == 0) { } else if (strcmp(request_info->uri, authorize_url) == 0) {
authorize(conn, request_info); authorize(conn, request_info);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment