[rs-commit] r422 - in /mod_cms_verify/trunk: README mod_cms_verify.c

rs-commit at redwax.eu rs-commit at redwax.eu
Sat Aug 7 21:34:07 CEST 2021


Author: dirkx at redwax.eu
Date: Sat Aug  7 21:34:06 2021
New Revision: 422

Log:
Fix pool cleanup registration of state; add JSON variant support for detached sigs.

Modified:
    mod_cms_verify/trunk/README
    mod_cms_verify/trunk/mod_cms_verify.c

Modified: mod_cms_verify/trunk/README
==============================================================================
--- mod_cms_verify/trunk/README	(original)
+++ mod_cms_verify/trunk/README	Sat Aug  7 21:34:06 2021
@@ -28,5 +28,10 @@
 	fi
 	exit 0
 
-to confirm that this worked.
+to confirm that this worked. Besides DER PKCS#7 the JSOn format:
 
+	{ "payload": "... base64 string ..", "signature": "... base64 string .." }
+
+is also accepted/detected; with signature a detached signature on the decoded payload string. And the signature
+again a PKCS#7 DER once decoded.
+

Modified: mod_cms_verify/trunk/mod_cms_verify.c
==============================================================================
--- mod_cms_verify/trunk/mod_cms_verify.c	(original)
+++ mod_cms_verify/trunk/mod_cms_verify.c	Sat Aug  7 21:34:06 2021
@@ -205,6 +205,67 @@
     return NULL;
 }
 
+static char * _extract_json(apr_pool_t *p, const char * data, apr_size_t len, 
+	const unsigned char ** signature,  apr_size_t * signature_len,
+	const unsigned char ** payload, apr_size_t * payload_len
+) {
+    const unsigned char ** dst = NULL;
+    const char * ptr = data;
+    const char * end = data + len;
+    apr_size_t n, *dst_len;
+
+    *signature = NULL;
+    *payload = NULL;
+    *signature_len = 0;
+    *payload_len = 0;
+
+    for(;ptr < end && isspace(*ptr); ptr++) {};
+    if (*ptr++ != '{')
+	return "No starting {";
+
+    while(!*signature || !*payload) 
+    {
+        for(;ptr < end && (isspace(*ptr) || *ptr ==','); ptr++,len--) {};
+
+	if (end - ptr < 12) 
+		return "Not enough data";
+
+	if (strncmp("\"signature\"",ptr,11) == 0) {
+		ptr += 11; 
+		dst = signature;
+		dst_len = signature_len;
+	}
+	else 
+        if (strncmp("\"payload\"",ptr,9) == 0) {
+		ptr += 9;	
+		dst = payload;
+		dst_len = payload_len;
+	}
+	else {
+		return "Not some dict we know about";
+	};
+
+        for(;ptr < end && isspace(*ptr); ptr++,len--) {};
+        if (*ptr++ != ':')
+	   return "No value for dict entry";
+
+        for(;ptr < end && isspace(*ptr); ptr++,len--) {};
+        if (*ptr++ != '"')
+	   return "No start to the value";
+
+        for(n=0;ptr+n < end && ptr[n] != '"'; n++) {};
+        if (ptr >= end)
+	   return "No end to the value";
+      
+        if (((*dst = apr_palloc(p, apr_base64_decode_len(ptr))) == NULL) ||
+            ((*dst_len = apr_base64_decode_binary ((unsigned char *)*dst,ptr)) <= 0)
+           ) return "Could not decode base64";
+
+        ptr += n + 1;
+    };
+    return NULL;
+}
+
 static apr_bucket *_verify(request_rec *r, BIO * in)
 {
     verify_config_rec *conf = ap_get_module_config(r->per_dir_config,
@@ -216,16 +277,40 @@
     X509 *signer = NULL;
     char *dn = NULL;
     BIO *out = NULL;
-
+    const char *ptr = NULL;
+    const unsigned char * sig, *pay;
+    apr_size_t lsig, lpay;
+    long len = 0;
+    int flags = 0;
+    const char * err = NULL;
+
+    len = BIO_get_mem_data(in, &ptr);
+    if (NULL == (err = _extract_json(r->pool, ptr, len, &sig, &lsig, &pay, &lpay))) {
+        if (!(ci = d2i_CMS_ContentInfo(NULL, &sig, lsig))) {
+		ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, HANDLER ": could not decode: %s",
+		      ERR_reason_error_string(ERR_get_error()));
+		goto exit;
+        };
+ 	len = lpay;
+	ptr = (const char *)pay;
+        ptr = apr_pmemdup(r->pool, ptr, len);
+	flags |= CMS_DETACHED;
+
+        BIO_reset(in);
+        BIO_write(in, ptr, len);
+	out = NULL;
+    } else
     if (!(out = BIO_new(BIO_s_mem())) ||
 	!(ci = d2i_CMS_bio(in, NULL))) {
 	ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, HANDLER ": could not decode: %s",
 		      ERR_reason_error_string(ERR_get_error()));
 	goto exit;
-    };
-    BIO_reset(in);
-
-    if (1 != CMS_verify(ci, conf->other_certs, conf->trusted_certs, NULL, out, 0)) {
+    } else {
+       ptr = NULL;
+       BIO_reset(in);
+    };
+
+    if (1 != CMS_verify(ci, conf->other_certs, conf->trusted_certs, (out == NULL) ? in : NULL, out, flags)) {
 	ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, HANDLER ": signature check failed: %s",
 		      ERR_reason_error_string(ERR_get_error()));
 	goto exit;
@@ -242,10 +327,10 @@
 
     ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, HANDLER ": valid signature, subject=<%s>.", dn);
 
-    const char *ptr = NULL;
-    long len = BIO_get_mem_data(out, &ptr);
-
-    ptr = apr_pmemdup(r->pool, ptr, len);
+    if (ptr == NULL) {
+    	len = BIO_get_mem_data(out, &ptr);
+    	ptr = apr_pmemdup(r->pool, ptr, len);
+    };
     ret = apr_bucket_pool_create(ptr, len, r->pool, r->connection->bucket_alloc);
 
 exit:
@@ -283,7 +368,7 @@
     if (state == NULL) {
 	f->ctx = state = apr_palloc(r->pool, sizeof *state);
 	state->pbb_tmp = apr_brigade_create(r->pool, c->bucket_alloc);
-	apr_pool_cleanup_register(r->pool, state->pbb_tmp, state_cleanup, apr_pool_cleanup_null);
+	apr_pool_cleanup_register(r->pool, state, state_cleanup, apr_pool_cleanup_null);
 	state->in = BIO_new(BIO_s_mem());
   	state->lenin = 0;
     };



More information about the rs-commit mailing list