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" \
+ "
" \
+ "
" \
+ "
" \
+ "" \
+ "" \
+ ""
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);
}