-
-/*********************************************************************
- *
- * Function : make_certs_path
- *
- * Description : Creates path to file from three pieces. This function
- * takes parameters and puts them in one new mallocated
- * char * in correct order. Returned variable must be freed
- * by caller. This function is mainly used for creating
- * paths of certificates and keys files.
- *
- * Parameters :
- * 1 : conf_dir = Name/path of directory where is the file.
- * '.' can be used for current directory.
- * 2 : file_name = Name of file in conf_dir without suffix.
- * 3 : suffix = Suffix of given file_name.
- *
- * Returns : path => Path was built up successfully
- * NULL => Path can't be built up
- *
- *********************************************************************/
-static char *make_certs_path(const char *conf_dir, const char *file_name,
- const char *suffix)
-{
- /* Test if all given parameters are valid */
- if (conf_dir == NULL || *conf_dir == '\0' || file_name == NULL ||
- *file_name == '\0' || suffix == NULL || *suffix == '\0')
- {
- log_error(LOG_LEVEL_ERROR,
- "make_certs_path failed: bad input parameters");
- return NULL;
- }
-
- char *path = NULL;
- size_t path_size = strlen(conf_dir)
- + strlen(file_name) + strlen(suffix) + 2;
-
- /* Setting delimiter and editing path length */
-#if defined(_WIN32) || defined(__OS2__)
- char delim[] = "\\";
- path_size += 1;
-#else /* ifndef _WIN32 || __OS2__ */
- char delim[] = "/";
-#endif /* ifndef _WIN32 || __OS2__ */
-
- /*
- * Building up path from many parts
- */
-#if defined(unix)
- if (*conf_dir != '/' && basedir && *basedir)
- {
- /*
- * Replacing conf_dir with basedir. This new variable contains
- * absolute path to cwd.
- */
- path_size += strlen(basedir) + 2;
- path = zalloc_or_die(path_size);
-
- strlcpy(path, basedir, path_size);
- strlcat(path, delim, path_size);
- strlcat(path, conf_dir, path_size);
- strlcat(path, delim, path_size);
- strlcat(path, file_name, path_size);
- strlcat(path, suffix, path_size);
- }
- else
-#endif /* defined unix */
- {
- path = zalloc_or_die(path_size);
-
- strlcpy(path, conf_dir, path_size);
- strlcat(path, delim, path_size);
- strlcat(path, file_name, path_size);
- strlcat(path, suffix, path_size);
- }
-
- return path;
-}
-
-
-/*********************************************************************
- *
- * Function : get_certificate_serial
- *
- * Description : Computes serial number for new certificate from host
- * name hash. This hash must be already saved in csp
- * structure.
- *
- * Parameters :
- * 1 : csp = Current client state (buffers, headers, etc...)
- *
- * Returns : Serial number for new certificate
- *
- *********************************************************************/
-static unsigned long get_certificate_serial(struct client_state *csp)
-{
- unsigned long exp = 1;
- unsigned long serial = 0;
-
- int i = CERT_SERIAL_NUM_LENGTH;
- /* Length of hash is 16 bytes, we must avoid to read next chars */
- if (i > 16)
- {
- i = 16;
- }
- if (i < 2)
- {
- i = 2;
- }
-
- for (; i >= 0; i--)
- {
- serial += exp * (unsigned)csp->http->hash_of_host[i];
- exp *= 256;
- }
- return serial;
-}
-
-
-/*********************************************************************
- *
- * Function : ssl_send_certificate_error
- *
- * Description : Sends info about invalid server certificate to client.
- * Sent message is including all trusted chain certificates,
- * that can be downloaded in web browser.
- *
- * Parameters :
- * 1 : csp = Current client state (buffers, headers, etc...)
- *
- * Returns : N/A
- *
- *********************************************************************/
-extern void ssl_send_certificate_error(struct client_state *csp)
-{
- size_t message_len = 0;
- int ret = 0;
- struct certs_chain *cert = NULL;
-
- /* Header of message with certificate informations */
- const char message_begin[] =
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "Connection: close\r\n\r\n"
- "<html><body><h1>Server certificate verification failed</h1><p>Reason: ";
- const char message_end[] = "</body></html>\r\n\r\n";
- char reason[INVALID_CERT_INFO_BUF_SIZE];
- memset(reason, 0, sizeof(reason));
-
- /* Get verification message from verification return code */
- mbedtls_x509_crt_verify_info(reason, sizeof(reason), " ",
- csp->server_cert_verification_result);
-
- /*
- * Computing total length of message with all certificates inside
- */
- message_len = strlen(message_begin) + strlen(message_end)
- + strlen(reason) + strlen("</p>") + 1;
-
- cert = &(csp->server_certs_chain);
- while (cert->next != NULL)
- {
- size_t base64_len = 4 * ((strlen(cert->file_buf) + 2) / 3) + 1;
-
- message_len += strlen(cert->text_buf) + strlen("<pre></pre>\n")
- + base64_len + strlen("<a href=\"data:application"
- "/x-x509-ca-cert;base64,\">Download certificate</a>");
- cert = cert->next;
- }
-
- /*
- * Joining all blocks in one long message
- */
- char message[message_len];
- memset(message, 0, message_len);
-
- strlcpy(message, message_begin, message_len);
- strlcat(message, reason , message_len);
- strlcat(message, "</p>" , message_len);
-
- cert = &(csp->server_certs_chain);
- while (cert->next != NULL)
- {
- size_t olen = 0;
- size_t base64_len = 4 * ((strlen(cert->file_buf) + 2) / 3) + 1; /* +1 for terminating null*/
- char base64_buf[base64_len];
- memset(base64_buf, 0, base64_len);
-
- /* Encoding certificate into base64 code */
- ret = mbedtls_base64_encode((unsigned char*)base64_buf,
- base64_len, &olen, (const unsigned char*)cert->file_buf,
- strlen(cert->file_buf));
- if (ret != 0)
- {
- log_error(LOG_LEVEL_ERROR,
- "Encoding to base64 failed, buffer is to small");
- }
-
- strlcat(message, "<pre>", message_len);
- strlcat(message, cert->text_buf, message_len);
- strlcat(message, "</pre>\n", message_len);
-
- if (ret == 0)
- {
- strlcat(message, "<a href=\"data:application/x-x509-ca-cert;base64,",
- message_len);
- strlcat(message, base64_buf, message_len);
- strlcat(message, "\">Download certificate</a>", message_len);
- }
-
- cert = cert->next;
- }
- strlcat(message, message_end, message_len);
-
- /*
- * Sending final message to client
- */
- ssl_send_data(&(csp->mbedtls_client_attr.ssl),
- (const unsigned char *)message, strlen(message));
- /*
- * Waiting before closing connection. Some browsers don't show received
- * message if there isn't this delay.
- */
- sleep(1);
-
- free_certificate_chain(csp);
-}
-
-