From 7e8560f57a341ce8248916bf06265c84446801d4 Mon Sep 17 00:00:00 2001 From: Lefteris Chatzimparmpas Date: Mon, 13 May 2013 00:48:42 +0200 Subject: [PATCH] Compare serial number of certificates The serial number of the certificates is checked together with the issuer, since some certificates have the same subject and issuer but a different serial number. Also, the certificate subject, issuer and serial number are also written to the certificates file just before the certificate itself, in order to make it easier to distinguish each certificate in the file. --- src/cert.c | 77 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/src/cert.c b/src/cert.c index 51acf3f..3d31e14 100644 --- a/src/cert.c +++ b/src/cert.c @@ -19,6 +19,7 @@ extern environment env; int check_cert(X509 *pcert, unsigned char *pmd, unsigned int *pmdlen); void print_cert(X509 *cert, unsigned char *md, unsigned int *mdlen); +char *get_serial(X509 *cert); int write_cert(X509 *cert); int mismatch_cert(void); @@ -100,7 +101,7 @@ check_cert(X509 *pcert, unsigned char *pmd, unsigned int *pmdlen) while ((cert = PEM_read_X509(fd, &cert, NULL, NULL)) != NULL) { if (X509_subject_name_cmp(cert, pcert) != 0 || - X509_issuer_name_cmp(cert, pcert) != 0) + X509_issuer_and_serial_cmp(cert, pcert) != 0) continue; if (!X509_digest(cert, EVP_md5(), md, &mdlen) || @@ -129,15 +130,19 @@ void print_cert(X509 *cert, unsigned char *md, unsigned int *mdlen) { unsigned int i; - char *c; + char *s; - c = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); - printf("Server certificate subject: %s\n", c); - xfree(c); + s = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + printf("Server certificate subject: %s\n", s); + xfree(s); - c = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); - printf("Server certificate issuer: %s\n", c); - xfree(c); + s = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); + printf("Server certificate issuer: %s\n", s); + xfree(s); + + s = get_serial(cert); + printf("Server certificate serial: %s\n", s); + xfree(s); printf("Server key fingerprint: "); for (i = 0; i < *mdlen; i++) @@ -145,6 +150,42 @@ print_cert(X509 *cert, unsigned char *md, unsigned int *mdlen) } +/* + * Extract certificate serial number as a string. + */ +char * +get_serial(X509 *cert) +{ + ASN1_INTEGER* serial; + char *buf; + long num; + int i; + size_t len; + + serial = X509_get_serialNumber(cert); + buf = xmalloc(LINE_MAX); + *buf = '\0'; + if (serial->length <= (int)sizeof(long)) { + num = ASN1_INTEGER_get(serial); + if (serial->type == V_ASN1_NEG_INTEGER) { + snprintf(buf, LINE_MAX, "-%lX", -num); + } else { + snprintf(buf, LINE_MAX, "%lX", num); + } + } else { + if (serial->type == V_ASN1_NEG_INTEGER) { + snprintf(buf, LINE_MAX, "-"); + } + for (i = 0; i < serial->length; i++) { + len = strlen(buf); + snprintf(buf + len, LINE_MAX - len, "%02X", + serial->data[i]); + } + } + return buf; +} + + /* * Write the SSL/TLS certificate after asking the user to accept/reject it. */ @@ -152,13 +193,14 @@ int write_cert(X509 *cert) { FILE *fd; - char c, buf[64]; + char c, buf[LINE_MAX]; char *certf; + char *s; do { printf("(R)eject, accept (t)emporarily or " "accept (p)ermanently? "); - if (fgets(buf, sizeof(buf), stdin) == NULL) + if (fgets(buf, LINE_MAX, stdin) == NULL) return -1; c = tolower((int)(*buf)); } while (c != 'r' && c != 't' && c != 'p'); @@ -175,8 +217,19 @@ write_cert(X509 *cert) if (fd == NULL) return -1; + s = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + fprintf(fd, "Subject: %s\n", s); + xfree(s); + s = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); + fprintf(fd, "Issuer: %s\n", s); + xfree(s); + s = get_serial(cert); + fprintf(fd, "Serial: %s\n", s); + xfree(s); + PEM_write_X509(fd, cert); + fprintf(fd, "\n"); fclose(fd); return 0; @@ -190,12 +243,12 @@ write_cert(X509 *cert) int mismatch_cert(void) { - char c, buf[64]; + char c, buf[LINE_MAX]; do { printf("ATTENTION: SSL/TLS certificate fingerprint mismatch.\n" "Proceed with the connection (y/n)? "); - if (fgets(buf, sizeof(buf), stdin) == NULL) + if (fgets(buf, LINE_MAX, stdin) == NULL) return -1; c = tolower((int)(*buf)); } while (c != 'y' && c != 'n');