Explorar el Código

Document mg_check_digest_access_authentication and add an example

bel2125 hace 7 años
padre
commit
efb1cdbb4c

+ 4 - 0
docs/api/mg_check_digest_access_authentication.md

@@ -23,6 +23,10 @@ information, matching user and password encoded within the password file.
 If the authentication realm (also called authentication domain) is NULL, the parameter
 If the authentication realm (also called authentication domain) is NULL, the parameter
 `authentication_domain` as specified in the server configuration (`mg_start()`) is used.
 `authentication_domain` as specified in the server configuration (`mg_start()`) is used.
 
 
+A positive return value means, the user name, realm and a correct password hash have been
+found in the passwords file.
+A return of 0 means, reading the password file succeeded, but there was no matching user,
+realm and password.
 The function returns a negative number on errors.
 The function returns a negative number on errors.
 
 
 ### See Also
 ### See Also

+ 80 - 1
examples/embedded_c/embedded_c.c

@@ -86,9 +86,14 @@ ExampleHandler(struct mg_connection *conn, void *cbdata)
 
 
 #ifdef USE_WEBSOCKET
 #ifdef USE_WEBSOCKET
 	mg_printf(conn,
 	mg_printf(conn,
-	          "<p>To test websocket handler <a href=\"/websocket\">click "
+	          "<p>To test the websocket handler <a href=\"/websocket\">click "
 	          "websocket</a></p>");
 	          "websocket</a></p>");
 #endif
 #endif
+
+	mg_printf(conn,
+	          "<p>To test the authentication handler <a href=\"/auth\">click "
+	          "auth</a></p>");
+
 	mg_printf(conn, "<p>To exit <a href=\"%s\">click exit</a></p>", EXIT_URI);
 	mg_printf(conn, "<p>To exit <a href=\"%s\">click exit</a></p>", EXIT_URI);
 	mg_printf(conn, "</body></html>\n");
 	mg_printf(conn, "</body></html>\n");
 	return 1;
 	return 1;
@@ -519,6 +524,76 @@ PostResponser(struct mg_connection *conn, void *cbdata)
 
 
 
 
 int
 int
+AuthStartHandler(struct mg_connection *conn, void *cbdata)
+{
+	static unsigned long long firstload = 0;
+	const char *passfile = "password_example_file.txt";
+	const char *realm = "password_example";
+	const char *user = "user";
+	char passwd[64];
+
+	if (firstload == 0) {
+
+		/* Set a random password (4 digit number - bad idea from a security
+		 * point of view, but this is an API demo, not a security tutorial),
+		 * and store it in some directory within the document root (extremely
+		 * bad idea, but this is still not a security tutorial).
+		 * The reason we create a new password every time the server starts
+		 * is just for demonstration - we don't want the browser to store the
+		 * password, so when we repeat the test we start with a new password.
+		 */
+		firstload = (unsigned long long)time(NULL);
+		sprintf(passwd, "%04u", (unsigned int)(firstload % 10000));
+		mg_modify_passwords_file(passfile, realm, user, passwd);
+
+		/* Just tell the user the new password generated for this test. */
+		mg_printf(conn,
+		          "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
+		          "close\r\n\r\n");
+
+		mg_printf(conn, "<!DOCTYPE html>\n");
+		mg_printf(conn, "<html>\n<head>\n");
+		mg_printf(conn, "<meta charset=\"UTF-8\">\n");
+		mg_printf(conn, "<title>Auth handlerexample</title>\n");
+		mg_printf(conn, "</head>\n");
+
+		mg_printf(conn, "<body>\n");
+		mg_printf(conn,
+		          "<p>The first time you visit this page, it's free!</p>\n");
+		mg_printf(conn,
+		          "<p>Next time, use username \"%s\" and password \"%s\"</p>\n",
+		          user,
+		          passwd);
+		mg_printf(conn, "</body>\n</html>\n");
+
+		return 1;
+	}
+
+	if (mg_check_digest_access_authentication(conn, realm, passfile) > 0) {
+		/* No valid authorization */
+		mg_send_digest_access_authentication_request(conn, realm);
+		return 1;
+	}
+
+	mg_printf(conn,
+	          "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
+	          "close\r\n\r\n");
+
+	mg_printf(conn, "<!DOCTYPE html>\n");
+	mg_printf(conn, "<html>\n<head>\n");
+	mg_printf(conn, "<meta charset=\"UTF-8\">\n");
+	mg_printf(conn, "<title>Auth handlerexample</title>\n");
+	mg_printf(conn, "</head>\n");
+
+	mg_printf(conn, "<body>\n");
+	mg_printf(conn, "<p>This is the password protected contents</p>\n");
+	mg_printf(conn, "</body>\n</html>\n");
+
+	return 1;
+}
+
+
+int
 WebSocketStartHandler(struct mg_connection *conn, void *cbdata)
 WebSocketStartHandler(struct mg_connection *conn, void *cbdata)
 {
 {
 	mg_printf(conn,
 	mg_printf(conn,
@@ -940,6 +1015,10 @@ main(int argc, char *argv[])
 	/* Add HTTP site to open a websocket connection */
 	/* Add HTTP site to open a websocket connection */
 	mg_set_request_handler(ctx, "/websocket", WebSocketStartHandler, 0);
 	mg_set_request_handler(ctx, "/websocket", WebSocketStartHandler, 0);
 
 
+	/* Add HTTP site with auth */
+	mg_set_request_handler(ctx, "/auth", AuthStartHandler, 0);
+
+
 #ifdef USE_WEBSOCKET
 #ifdef USE_WEBSOCKET
 	/* WS site for the websocket connection */
 	/* WS site for the websocket connection */
 	mg_set_websocket_handler(ctx,
 	mg_set_websocket_handler(ctx,

+ 18 - 1
include/civetweb.h

@@ -788,7 +788,24 @@ mg_send_digest_access_authentication_request(struct mg_connection *conn,
                                              const char *realm);
                                              const char *realm);
 
 
 
 
-/* TODO: Test and document */
+/* Check if the current request has a valid authentication token set.
+ * A file is used to provide a list of valid user names, realms and
+ * password hashes. The file can be created and modified using the
+ * mg_modify_passwords_file API function.
+ * Parameters:
+ *   conn: Current connection handle.
+ *   realm: Authentication realm. If NULL is supplied, the sever domain
+ *          set in the authentication_domain configuration is used.
+ *   filename: Path and name of a file storing multiple password hashes.
+ * Return:
+ *   > 0   Valid authentication
+ *   0     Invalid authentication
+ *   < 0   Error (all values < 0 should be considered as invalid
+ *         authentication, future error codes will have negative
+ *         numbers)
+ *   -1    Parameter error
+ *   -2    File not found
+ */
 CIVETWEB_API int
 CIVETWEB_API int
 mg_check_digest_access_authentication(struct mg_connection *conn,
 mg_check_digest_access_authentication(struct mg_connection *conn,
                                       const char *realm,
                                       const char *realm,

+ 1 - 1
src/main.c

@@ -192,7 +192,7 @@ static NO_RETURN void
 die(const char *fmt, ...)
 die(const char *fmt, ...)
 {
 {
 	va_list ap;
 	va_list ap;
-    char msg[512] = "";
+	char msg[512] = "";
 
 
 	va_start(ap, fmt);
 	va_start(ap, fmt);
 	(void)vsnprintf(msg, sizeof(msg) - 1, fmt, ap);
 	(void)vsnprintf(msg, sizeof(msg) - 1, fmt, ap);