Pārlūkot izejas kodu

Document/Comment example for embedding the certificate into the C source

This example was a request in #1030
bel2125 3 gadi atpakaļ
vecāks
revīzija
556821b516
3 mainītis faili ar 63 papildinājumiem un 13 dzēšanām
  1. 5 0
      examples/README.md
  2. 57 13
      examples/embed_certificate/ec_example.c
  3. 1 0
      format.bat

+ 5 - 0
examples/README.md

@@ -19,6 +19,11 @@ The ([https](https://github.com/civetweb/civetweb/tree/master/examples/https)) e
 a HTTPS server with improved security settings.
 It does not hold any source, but only a configuration file and some documentation how to use it.
 
+The ([embed_certificate](https://github.com/civetweb/civetweb/tree/master/examples/embed_certificate)) example 
+shows embed civetweb in a C application without using additional files on the disk. The HTTPS certificate is
+directly embedded in the code and all content is generated by a callback. It is a template for using civetweb
+on (embedded) devices without a file system - or for systems that do not want CivetWeb to access the disk.
+
 The [multidomain](https://github.com/civetweb/civetweb/tree/master/examples/multidomain) example demonstrates 
 how to host multiple domains with different HTTPS certificates. 
 It uses the standalone server (civetweb.c + main.c) and existing certificates.

+ 57 - 13
examples/embed_certificate/ec_example.c

@@ -1,12 +1,21 @@
-#include <stdio.h>
+/* Example for embedding a server including the HTTPS server key and
+ * certificate. All response is generated from a callback. The server
+ * does not access the file system at all. */
+/* Building: change into the examples/embed_certificate folder and
+ * use "./build.sh" on Linux (no, you don't need a Makefile). */
+
 #include <openssl/ssl.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "civetweb.h"
 
-/* server.crt BASE64 to HEX */
+/* This array corresponds to the content of the file
+ * /resources/cert/server.crt converted from BASE64 to HEX.
+ * When using this code, you need to REPLACE IT BY YOUR OWN CERTIFICATE!
+ */
 const uint8_t SSL_CERT_ASN1[] = {
     0x30, 0x82, 0x04, 0x40, 0x30, 0x82, 0x03, 0x28, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x49, 0x65, 0x5b, 0x35, 0xce, 0x42, 0x20, 0x15, 0xa7,
@@ -100,7 +109,11 @@ const uint8_t SSL_CERT_ASN1[] = {
     0xf7, 0xee, 0x48, 0x41, 0x93, 0x69, 0x7c, 0x3e, 0x47, 0xf0, 0x5e, 0x60,
     0x5d, 0x1d, 0xa3, 0x67, 0x59, 0x3c, 0xf9, 0x3c, 0x49, 0x63, 0x74, 0x84};
 
-/* server.key BASE64 to HEX */
+
+/* This array corresponds to the content of the file
+ * /resources/cert/server.key converted from BASE64 to HEX.
+ * When using this code, you need to REPLACE IT BY YOUR OWN PRIVATE KEY!
+ */
 const uint8_t SSL_KEY_ASN1[] = {
     0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
     0xca, 0x25, 0x51, 0xe7, 0xb4, 0x06, 0x2d, 0x11, 0xe1, 0x33, 0xfb, 0xde,
@@ -204,6 +217,17 @@ const uint8_t SSL_KEY_ASN1[] = {
     0xcc, 0x75};
 
 
+/* This is an example for a custom SSL initialization function.
+ * It will setup the certificate and private key defined in the arrays above.
+ * Thus, they do not need to be located in files in the file system.
+ * To slightly improve security, you could use some encryption for the arrays
+ * above, and only decrypt it in memory before passing to the SSL_CTX_use_*
+ * functions. Then the data will not exist in the executable stored at the
+ * disk, but only in memory at runtime - making reverse engineering more
+ * complex. Here we use unencrypted versions, so you could test the conversion
+ * process from server.key/server.crt to these arrays on your own, and see if
+ * you come to the same result.
+ */
 static int
 init_ssl(void *ssl_ctx, void *user_data)
 {
@@ -224,12 +248,18 @@ init_ssl(void *ssl_ctx, void *user_data)
 }
 
 
+/* This handler function will serve all requests to the server.
+ * In a realistic example, you would have multiple handler functions for
+ * different URLs.
+ */
 static int
 request_handler(struct mg_connection *conn, void *cbdata)
 {
+	/* Get the URI from the request info. */
 	const struct mg_request_info *ri = mg_get_request_info(conn);
 	unsigned uri_len = (unsigned)strlen(ri->local_uri);
 
+	/* Example: get a cookie named "c" from the client. */
 	const char *cookie = mg_get_header(conn, "Cookie");
 	unsigned long cookie_number = 0;
 	if (cookie) {
@@ -241,22 +271,29 @@ request_handler(struct mg_connection *conn, void *cbdata)
 			}
 		}
 	}
+	/* Calculate a value for a new cookie. Here just increment the previous
+	 * value. Thus, we count the number of times a client visited this a
+	 * page generated by this handler function. */
 	char new_cookie[32];
 	sprintf(new_cookie, "c=%u", cookie_number + 1);
 
-	int status = 200;
+	/* Generate a response text and status code. */
+	int status;
 	char response[1024];
 
 	if (uri_len <= 100) {
+		status = 200; /* 200 = OK */
 		sprintf(response,
 		        "Hello at %s\nYou have visited %u sites here before!",
 		        ri->local_uri,
 		        cookie_number);
 	} else {
-		status = 404;
+		/* We don't like this URL */
+		status = 404; /* 404 = Not Found */
 		sprintf(response, "No such URL\n");
 	}
 
+	/* This sequence can be used to send a response including a cookie. */
 	unsigned content_len = (unsigned)strlen(response);
 	char content_len_text[32];
 	sprintf(content_len_text, "%u", content_len);
@@ -275,6 +312,7 @@ request_handler(struct mg_connection *conn, void *cbdata)
 }
 
 
+/* Main: Initialize and run the server */
 int
 main(int argc, char *argv[])
 {
@@ -289,14 +327,20 @@ main(int argc, char *argv[])
 
 	init.user_data = NULL;
 
-	const char *options[] = {"listening_ports", "80r,443s",
-	                         "authentication_domain", "localhost",
-	                         "enable_auth_domain_check", "no",
-	                         "ssl_protocol_version", "4",
-	                         "ssl_cipher_list", "ECDH+AESGCM+AES256:!aNULL:!MD5:!DSS",
-                             "strict_transport_security_max_age", "15552000",
-	                         NULL, NULL}
-                             ;
+	const char *options[] = {"listening_ports",
+	                         "80r,443s",
+	                         "authentication_domain",
+	                         "localhost",
+	                         "enable_auth_domain_check",
+	                         "no",
+	                         "ssl_protocol_version",
+	                         "4",
+	                         "ssl_cipher_list",
+	                         "ECDH+AESGCM+AES256:!aNULL:!MD5:!DSS",
+	                         "strict_transport_security_max_age",
+	                         "15552000",
+	                         NULL,
+	                         NULL};
 	init.configuration_options = options;
 
 	struct mg_error_data error = {0};

+ 1 - 0
format.bat

@@ -40,4 +40,5 @@ clang-format -i fuzztest/fuzzmain.c
 
 clang-format -i examples/embedded_c/embedded_c.c
 clang-format -i examples/rest/rest.c
+clang-format -i examples/embed_certificate/ec_example.c