diff --git a/goodies/index.html b/goodies/index.html new file mode 100644 index 0000000..fef0ab8 --- /dev/null +++ b/goodies/index.html @@ -0,0 +1,96 @@ + + + + + + + + + +
+ uts-server, a simple RFC 3161 timestamp server +
+
+ For timestamping a file with OpenSSL and curl, run the following commands + (setting the $UTS_SERVER_URL, $FILE and $FILE_TIMESTAMP variables): +
+ openssl ts -query -data "$FILE" -out "ts_req.ts";
+ curl "$UTS_SERVER_URL" -H "Content-Type: application/timestamp-query" \
+ -f -g --data-binary "@ts_req.ts" -o "$FILE_TIMESTAMP" +
+ For verifying the timestamp with OpenSSL, download the CA, and run the following command: +
+ openssl ts -verify -in "$FILE_TIMESTAMP" -data "$FILE" -CAfile ca.pem +
+
+ +
+
+ + + diff --git a/inc/context.h b/inc/context.h index ff88fa1..aee62c0 100644 --- a/inc/context.h +++ b/inc/context.h @@ -12,7 +12,11 @@ #define LOGHANDLER_OPTIONS 3 #define TSA_OPTIONS 4 #define PATH_HTTP_OPTIONS 5 + +/* name of the configuration file section */ #define MAIN_CONF_SECTION "main" +#define OID_SECTION "oids" +#define TSA_SECTION "tsa" #define RFC3161_OPTIONS_LEN \ sizeof(rfc3161_options) / sizeof(struct rfc3161_option) @@ -42,6 +46,7 @@ typedef struct { // just to track for freeing later CONF *conf; char *cust_conf[20]; + char *ca_file; } rfc3161_context; // definition of structure to describe diff --git a/inc/http.h b/inc/http.h index e89e902..4221f35 100644 --- a/inc/http.h +++ b/inc/http.h @@ -6,3 +6,117 @@ struct tuser_data { }; int http_server_start(char *conffile, char *conf_wd, bool stdout_dbg); + +#define STATIC_PAGE \ + "HTTP/1.1 200 OK\r\n" \ + "Content-Type: text/html\r\n" \ + "Content-Length: 2509\r\n" \ + "\r\n" \ + "" \ + "" \ + " " \ + " " \ + " " \ + " " \ + "" \ + "" \ + "" \ + "
" \ + " uts-server, a simple RFC 3161 timestamp server" \ + "
" \ + "
" \ + " For timestamping a file with OpenSSL and curl, run the following " \ + "commands" \ + " (setting the $UTS_SERVER_URL, $FILE and $FILE_TIMESTAMP variables):" \ + "
" \ + " openssl ts -query -data \"$FILE\" -out " \ + "\"ts_req.ts\";
" \ + " curl \"$UTS_SERVER_URL\" -H " \ + "\"Content-Type: application/timestamp-query\" \\
" \ + " -f -g --data-binary \"@ts_req.ts\" -o \"$FILE_TIMESTAMP\"" \ + "
" \ + " For verifying the timestamp with OpenSSL, download the CA, and run " \ + "the following command:" \ + "
" \ + " openssl ts -verify -in \"$FILE_TIMESTAMP\" -data \"$FILE\" -CAfile ca.pem" \ + "
" \ + "
" \ + " " \ + "
" \ + "
" \ + "
" \ + "
" \ + " uts-server" \ + " • © 2019 • Pierre-François Carpentier • Released under the MIT " \ + "License" \ + "
" \ + "
" \ + "" \ + "" diff --git a/inc/rfc3161.h b/inc/rfc3161.h index 0f88494..93f6984 100644 --- a/inc/rfc3161.h +++ b/inc/rfc3161.h @@ -39,10 +39,6 @@ #endif #endif -/* Name of config entry that defines the OID file. */ -#define OID_SECTION "oids" -#define TSA_SECTION "tsa" - // number of char we get to log for the serial #define SERIAL_ID_SIZE 8 diff --git a/src/lib/http.c b/src/lib/http.c index 9ab3c18..88786bf 100644 --- a/src/lib/http.c +++ b/src/lib/http.c @@ -102,22 +102,6 @@ void log_request(const struct mg_request_info *request_info, char *request_id, null_undef(content_type)); } -// This function will be called by civetweb on every new request. -static int begin_request_handler(struct mg_connection *conn) { - const struct mg_request_info *request_info = mg_get_request_info(conn); - - mg_printf(conn, - "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: 46\r\n" // Always set Content-Length - "\r\n" - "uts-server, a simple RFC 3161 timestamp server"); - - // Returning non-zero tells civetweb that our function has replied to - // the client, and civetweb should not send client any more data. - return 1; -} - int rfc3161_handler(struct mg_connection *conn, void *context) { // some timer stuff clock_t start = clock(), diff; @@ -208,11 +192,7 @@ int rfc3161_handler(struct mg_connection *conn, void *context) { } else { // default reply if we don't have a time-stamp request resp_code = 200; - mg_printf(conn, "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: 46\r\n" - "\r\n" - "uts-server, a simple RFC 3161 timestamp server"); + mg_printf(conn, STATIC_PAGE); } // initialize a serial_id if not created by create_response if (serial_id == NULL) { @@ -231,6 +211,37 @@ int rfc3161_handler(struct mg_connection *conn, void *context) { return 1; } +int ca_serve_handler(struct mg_connection *conn, void *context) { + /* In this handler, we ignore the req_info and send the file "filename". */ + const struct mg_request_info *request_info = mg_get_request_info(conn); + clock_t start = clock(), diff; + rfc3161_context *ct = (rfc3161_context *)context; + const char *filename = ct->ca_file; + if (strlen(filename) == 0){ + uts_logger(context, LOG_NOTICE, "'certs' param in '[ tsa ]' section not filed"); + mg_send_http_error(conn, 404, "CA file not available"); + diff = clock() - start; + log_request(request_info, "CA_DL ", ct, 404, + (diff * 1000000 / CLOCKS_PER_SEC)); + return 1; + } + if (access(filename, F_OK) != -1) { + mg_send_file(conn, filename); + const struct mg_response_info *ri = mg_get_response_info(conn); + diff = clock() - start; + log_request(request_info, "CA_DL ", ct, 200, + (diff * 1000000 / CLOCKS_PER_SEC)); + + } else { + uts_logger(context, LOG_NOTICE, "CA file '%s' not available", filename); + mg_send_http_error(conn, 404, "CA file not available"); + diff = clock() - start; + log_request(request_info, "CA_DL ", ct, 404, + (diff * 1000000 / CLOCKS_PER_SEC)); + } + return 1; +} + int http_server_start(char *conffile, char *conf_wd, bool stdout_dbg) { struct mg_context *ctx; struct mg_callbacks callbacks; @@ -250,7 +261,6 @@ int http_server_start(char *conffile, char *conf_wd, bool stdout_dbg) { // Prepare callbacks structure. We have only one callback, the rest are // NULL. memset(&callbacks, 0, sizeof(callbacks)); - memset(&user_data, 0, sizeof(user_data)); callbacks.log_message = &log_civetweb; @@ -258,12 +268,12 @@ int http_server_start(char *conffile, char *conf_wd, bool stdout_dbg) { ctx = mg_start(&callbacks, &user_data, ct->http_options); if (ctx != NULL) { mg_set_request_handler(ctx, "/", rfc3161_handler, (void *)ct); + mg_set_request_handler(ctx, "/ca.pem", ca_serve_handler, (void *)ct); // Wait until some signals are received while (g_uts_sig == 0) { sleep(1); } - // getchar(); } else { uts_logger(ct, LOG_ERR, "Failed to start uts-server: %s", ((user_data.first_message == NULL) diff --git a/src/lib/utils.c b/src/lib/utils.c index 2657894..d7c5c93 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -387,6 +387,9 @@ int set_params(rfc3161_context *ct, char *conf_file, char *conf_wd) { break; } } + + ct->ca_file = calloc(PATH_MAX, sizeof(char)); + realpath(NCONF_get_string(ct->conf, TSA_SECTION, "certs"), ct->ca_file); // like any good daemon, return to '/' once the configuration is loaded chdir("/"); return ret; @@ -405,6 +408,7 @@ void free_uts_context(rfc3161_context *ct) { free(ct->cust_conf[i]); } free(ct->ts_ctx_pool); + free(ct->ca_file); NCONF_free(ct->conf); free(ct); }