]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - apps/lib/http_server.c
str[n]casecmp => OPENSSL_strncasecmp
[thirdparty/openssl.git] / apps / lib / http_server.c
index 1858d04ccb56dda2c01a007008126dc2737acfb3..36ea7a3bdc677170dd14a955ee153bfcedc31786 100644 (file)
@@ -17,7 +17,6 @@
 # define _POSIX_C_SOURCE 2
 #endif
 
-#include <string.h>
 #include <ctype.h>
 #include "http_server.h"
 #include "internal/sockets.h"
@@ -37,6 +36,7 @@ static int verbosity = LOG_INFO;
 #define HTTP_VERSION_PATT "1." /* allow 1.x */
 #define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT
 #define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */
+#define HTTP_VERSION_STR " "HTTP_PREFIX_VERSION
 
 #ifdef HTTP_DAEMON
 
@@ -216,18 +216,27 @@ void spawn_loop(const char *prog)
 #endif
 
 #ifndef OPENSSL_NO_SOCK
-BIO *http_server_init_bio(const char *prog, const char *port)
+BIO *http_server_init(const char *prog, const char *port, int verb)
 {
     BIO *acbio = NULL, *bufbio;
     int asock;
+    int port_num;
 
+    if (verb >= 0) {
+        if (verb > LOG_TRACE) {
+            log_message(prog, LOG_ERR,
+                        "Logging verbosity level %d too high", verb);
+            return NULL;
+        }
+        verbosity = verb;
+    }
     bufbio = BIO_new(BIO_f_buffer());
     if (bufbio == NULL)
         goto err;
     acbio = BIO_new(BIO_s_accept());
     if (acbio == NULL
         || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0
-        || BIO_set_accept_port(acbio, port) < 0) {
+        || BIO_set_accept_port(acbio, port /* may be "0" */) < 0) {
         log_message(prog, LOG_ERR, "Error setting up accept BIO");
         goto err;
     }
@@ -241,7 +250,8 @@ BIO *http_server_init_bio(const char *prog, const char *port)
 
     /* Report back what address and port are used */
     BIO_get_fd(acbio, &asock);
-    if (!report_server_accept(bio_out, asock, 1)) {
+    port_num = report_server_accept(bio_out, asock, 1, 1);
+    if (port_num == 0) {
         log_message(prog, LOG_ERR, "Error printing ACCEPT string");
         goto err;
     }
@@ -283,8 +293,7 @@ static int urldecode(char *p)
 int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
                              char **ppath, BIO **pcbio, BIO *acbio,
                              int *found_keep_alive,
-                             const char *prog, const char *port,
-                             int accept_get, int timeout)
+                             const char *prog, int accept_get, int timeout)
 {
     BIO *cbio = *pcbio, *getbio = NULL, *b64 = NULL;
     int len;
@@ -298,15 +307,24 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
         *ppath = NULL;
 
     if (cbio == NULL) {
+        char *port;
+
+        get_sock_info_address(BIO_get_fd(acbio, NULL), NULL, &port);
+        if (port == NULL) {
+            log_message(prog, LOG_ERR, "Cannot get port listening on");
+            goto fatal;
+        }
         log_message(prog, LOG_DEBUG,
-                    "Awaiting new connection on port %s...", port);
+                    "Awaiting new connection on port %s ...", port);
+        OPENSSL_free(port);
+
         if (BIO_do_accept(acbio) <= 0)
             /* Connection loss before accept() is routine, ignore silently */
             return ret;
 
         *pcbio = cbio = BIO_pop(acbio);
     } else {
-        log_message(prog, LOG_DEBUG, "Awaiting next request...");
+        log_message(prog, LOG_DEBUG, "Awaiting next request ...");
     }
     if (cbio == NULL) {
         /* Cannot call http_server_send_status(cbio, ...) */
@@ -336,15 +354,12 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
         *end = '\0';
     log_message(prog, LOG_INFO, "Received request, 1st line: %s", reqbuf);
 
-    meth = reqbuf;
-    url = meth + 3;
-    if ((accept_get && strncmp(meth, "GET ", 4) == 0)
-            || (url++, strncmp(meth, "POST ", 5) == 0)) {
-        static const char http_version_str[] = " "HTTP_PREFIX_VERSION;
-        static const size_t http_version_str_len = sizeof(http_version_str) - 1;
+    url = meth = reqbuf;
+    if ((accept_get && CHECK_AND_SKIP_PREFIX(url, "GET "))
+            || CHECK_AND_SKIP_PREFIX(url, "POST ")) {
 
         /* Expecting (GET|POST) {sp} /URL {sp} HTTP/1.x */
-        *(url++) = '\0';
+        url[-1] = '\0';
         while (*url == ' ')
             url++;
         if (*url != '/') {
@@ -360,7 +375,7 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
         for (end = url; *end != '\0'; end++)
             if (*end == ' ')
                 break;
-        if (strncmp(end, http_version_str, http_version_str_len) != 0) {
+        if (!HAS_PREFIX(end, HTTP_VERSION_STR)) {
             log_message(prog, LOG_WARNING,
                         "Invalid %s -- bad HTTP/version string: %s",
                         meth, end + 1);
@@ -370,7 +385,7 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
         *end = '\0';
         /* above HTTP 1.0, connection persistence is the default */
         if (found_keep_alive != NULL)
-            *found_keep_alive = end[http_version_str_len] > '0';
+            *found_keep_alive = end[sizeof(HTTP_VERSION_STR) - 1] > '0';
 
         /*-
          * Skip "GET / HTTP..." requests often used by load-balancers.
@@ -453,10 +468,11 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
         }
         *line_end = '\0';
         /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
-        if (found_keep_alive != NULL && strcasecmp(key, "Connection") == 0) {
-            if (strcasecmp(value, "keep-alive") == 0)
+        if (found_keep_alive != NULL
+            && OPENSSL_strcasecmp(key, "Connection") == 0) {
+            if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
                 *found_keep_alive = 1;
-            else if (strcasecmp(value, "close") == 0)
+            else if (OPENSSL_strcasecmp(value, "close") == 0)
                 *found_keep_alive = 0;
         }
     }