summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2014-05-08 20:38:46 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2014-05-08 20:38:46 +0100
commit6a8a60e0f273b61a24a48afd3217ff84106779bd (patch)
treef9d90797eda5bab3369b0b4385c4293656d9b96e /src
parent4466248715466b6f251454283642b74de65e9d9a (diff)
Enable operator md5 and sha1 use on certificate variables. Bug 1170
Diffstat (limited to 'src')
-rw-r--r--src/src/expand.c91
-rw-r--r--src/src/functions.h3
-rw-r--r--src/src/tlscert-gnu.c47
-rw-r--r--src/src/tlscert-openssl.c36
4 files changed, 150 insertions, 27 deletions
diff --git a/src/src/expand.c b/src/src/expand.c
index de911db90..9532d9d33 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -5724,19 +5724,16 @@ while (*s != 0)
{
int c;
uschar *arg = NULL;
- uschar *sub = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
- if (sub == NULL) goto EXPAND_FAILED;
- s++;
+ uschar *sub;
+ var_entry *vp;
/* Owing to an historical mis-design, an underscore may be part of the
operator name, or it may introduce arguments. We therefore first scan the
table of names that contain underscores. If there is no match, we cut off
the arguments and then scan the main table. */
- c = chop_match(name, op_table_underscore,
- sizeof(op_table_underscore)/sizeof(uschar *));
-
- if (c < 0)
+ if ((c = chop_match(name, op_table_underscore,
+ sizeof(op_table_underscore)/sizeof(uschar *))) < 0)
{
arg = Ustrchr(name, '_');
if (arg != NULL) *arg = 0;
@@ -5746,6 +5743,34 @@ while (*s != 0)
if (arg != NULL) *arg++ = '_'; /* Put back for error messages */
}
+ /* Deal specially with operators that might take a certificate variable
+ as we do not want to do the usual expansion. For most, expand the string.*/
+ switch(c)
+ {
+ case EOP_SHA1:
+ case EOP_MD5:
+ if (s[1] == '$')
+ {
+ uschar * s1 = s;
+ sub = expand_string_internal(s+2, TRUE, &s1, skipping,
+ FALSE, &resetok);
+ if (!sub) goto EXPAND_FAILED; /*{*/
+ if (*s1 != '}') goto EXPAND_FAILED_CURLY;
+ if ((vp = find_var_ent(sub)) && vp->type == vtype_cert)
+ {
+ s = s1+1;
+ break;
+ }
+ }
+ vp = NULL;
+ /*FALLTHROUGH*/
+ default:
+ sub = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
+ if (!sub) goto EXPAND_FAILED;
+ s++;
+ break;
+ }
+
/* If we are skipping, we don't need to perform the operation at all.
This matters for operations like "mask", because the data may not be
in the correct format when skipping. For example, the expression may test
@@ -5830,30 +5855,42 @@ while (*s != 0)
}
case EOP_MD5:
- {
- md5 base;
- uschar digest[16];
- int j;
- char st[33];
- md5_start(&base);
- md5_end(&base, sub, Ustrlen(sub), digest);
- for(j = 0; j < 16; j++) sprintf(st+2*j, "%02x", digest[j]);
- yield = string_cat(yield, &size, &ptr, US st, (int)strlen(st));
+ if (vp && *(void **)vp->value)
+ {
+ uschar * cp = tls_cert_fprt_md5(*(void **)vp->value);
+ yield = string_cat(yield, &size, &ptr, cp, (int)strlen(cp));
+ }
+ else
+ {
+ md5 base;
+ uschar digest[16];
+ int j;
+ char st[33];
+ md5_start(&base);
+ md5_end(&base, sub, Ustrlen(sub), digest);
+ for(j = 0; j < 16; j++) sprintf(st+2*j, "%02x", digest[j]);
+ yield = string_cat(yield, &size, &ptr, US st, (int)strlen(st));
+ }
continue;
- }
case EOP_SHA1:
- {
- sha1 base;
- uschar digest[20];
- int j;
- char st[41];
- sha1_start(&base);
- sha1_end(&base, sub, Ustrlen(sub), digest);
- for(j = 0; j < 20; j++) sprintf(st+2*j, "%02X", digest[j]);
- yield = string_cat(yield, &size, &ptr, US st, (int)strlen(st));
+ if (vp && *(void **)vp->value)
+ {
+ uschar * cp = tls_cert_fprt_sha1(*(void **)vp->value);
+ yield = string_cat(yield, &size, &ptr, cp, (int)strlen(cp));
+ }
+ else
+ {
+ sha1 base;
+ uschar digest[20];
+ int j;
+ char st[41];
+ sha1_start(&base);
+ sha1_end(&base, sub, Ustrlen(sub), digest);
+ for(j = 0; j < 20; j++) sprintf(st+2*j, "%02X", digest[j]);
+ yield = string_cat(yield, &size, &ptr, US st, (int)strlen(st));
+ }
continue;
- }
/* Convert hex encoding to base64 encoding */
diff --git a/src/src/functions.h b/src/src/functions.h
index 8d249b8f2..38ba7f39d 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -39,6 +39,9 @@ extern uschar * tls_cert_subject(void *, uschar * mod);
extern uschar * tls_cert_subject_altname(void *, uschar * mod);
extern uschar * tls_cert_version(void *, uschar * mod);
+extern uschar * tls_cert_fprt_md5(void *);
+extern uschar * tls_cert_fprt_sha1(void *);
+
extern int tls_client_start(int, host_item *, address_item *,
void *);
extern void tls_close(BOOL, BOOL);
diff --git a/src/src/tlscert-gnu.c b/src/src/tlscert-gnu.c
index 61b526a69..32b1986b8 100644
--- a/src/src/tlscert-gnu.c
+++ b/src/src/tlscert-gnu.c
@@ -375,6 +375,53 @@ for(index = 0;; index++)
}
+/*****************************************************
+* Certificate operator routines
+*****************************************************/
+static uschar *
+fingerprint(gnutls_x509_crt_t cert, gnutls_digest_algorithm_t algo)
+{
+int ret;
+size_t siz = 0;
+uschar * cp;
+uschar * cp2;
+uschar * cp3;
+
+if ((ret = gnutls_x509_crt_get_fingerprint(cert, algo, NULL, &siz))
+ != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ expand_string_message =
+ string_sprintf("%s: gf0 fail: %d %s\n", __FUNCTION__,
+ ret, gnutls_strerror(ret));
+ return NULL;
+ }
+cp = store_get(siz*3+1);
+if ((ret = gnutls_x509_crt_get_fingerprint(cert, algo, cp, &siz)) < 0)
+ {
+ expand_string_message =
+ string_sprintf("%s: gf1 fail: %d %s\n", __FUNCTION__,
+ ret, gnutls_strerror(ret));
+ return NULL;
+ }
+for (cp3 = cp2 = cp+siz; cp < cp2; cp++, cp3+=2)
+ sprintf(cp3, "%02X",*cp);
+return cp2;
+}
+
+
+uschar *
+tls_cert_fprt_md5(void * cert)
+{
+return fingerprint((gnutls_x509_crt_t)cert, GNUTLS_DIG_MD5);
+}
+
+uschar *
+tls_cert_fprt_sha1(void * cert)
+{
+return fingerprint((gnutls_x509_crt_t)cert, GNUTLS_DIG_SHA1);
+}
+
+
/* vi: aw ai sw=2
*/
/* End of tlscert-gnu.c */
diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c
index 53945a1e0..cddde4cdc 100644
--- a/src/src/tlscert-openssl.c
+++ b/src/src/tlscert-openssl.c
@@ -322,6 +322,42 @@ if (dps) for (i = 0; i < dpsnum; i++)
return list;
}
+
+
+/*****************************************************
+* Certificate operator routines
+*****************************************************/
+static uschar *
+fingerprint(X509 * cert, const EVP_MD * fdig)
+{
+int j;
+unsigned int n;
+uschar md[EVP_MAX_MD_SIZE];
+uschar * cp;
+
+if (!X509_digest(cert,fdig,md,&n))
+ {
+ expand_string_message = US"tls_cert_fprt: out of mem\n";
+ return NULL;
+ }
+cp = store_get(n*2+1);
+for (j = 0; j < (int)n; j++) sprintf(cp+2*j, "%02X", md[j]);
+return(cp);
+}
+
+uschar *
+tls_cert_fprt_md5(void * cert)
+{
+return fingerprint((X509 *)cert, EVP_md5());
+}
+
+uschar *
+tls_cert_fprt_sha1(void * cert)
+{
+return fingerprint((X509 *)cert, EVP_sha1());
+}
+
+
/* vi: aw ai sw=2
*/
/* End of tlscert-openssl.c */