Index: generic/tlsX509.c ================================================================== --- generic/tlsX509.c +++ generic/tlsX509.c @@ -69,34 +69,31 @@ Tcl_Obj* Tls_NewX509Obj(Tcl_Interp *interp, X509 *cert) { Tcl_Obj *certPtr = Tcl_NewListObj(0, NULL); BIO *bio; - int n; - unsigned long flags; + int nid, pknid, bits, num_of_exts, len; + uint32_t xflags; char subject[BUFSIZ]; char issuer[BUFSIZ]; char serial[BUFSIZ]; char notBefore[BUFSIZ]; char notAfter[BUFSIZ]; char buffer[BUFSIZ]; - char certStr[CERT_STR_SIZE], *certStr_p; - int certStr_len, toRead; - unsigned char sha1_hash_binary[SHA_DIGEST_LENGTH]; - unsigned char sha256_hash_binary[SHA256_DIGEST_LENGTH]; - int nid, pknid, bits, num_of_exts, len; - uint32_t xflags; + char certStr[CERT_STR_SIZE]; + unsigned char md[EVP_MAX_MD_SIZE]; STACK_OF(GENERAL_NAME) *san; certStr[0] = 0; subject[0] = 0; issuer[0] = 0; serial[0] = 0; notBefore[0] = 0; notAfter[0] = 0; if ((bio = BIO_new(BIO_s_mem())) != NULL) { - flags = XN_FLAG_RFC2253 | ASN1_STRFLGS_UTF8_CONVERT; + int n; + unsigned long flags = XN_FLAG_RFC2253 | ASN1_STRFLGS_UTF8_CONVERT; flags &= ~ASN1_STRFLGS_ESC_MSB; /* Get subject name */ if (X509_NAME_print_ex(bio, X509_get_subject_name(cert), 0, flags) > 0) { n = BIO_read(bio, subject, min(BIO_pending(bio), BUFSIZ - 1)); @@ -118,14 +115,14 @@ (void)BIO_flush(bio); } /* Get certificate */ if (PEM_write_bio_X509(bio, cert)) { - certStr_p = certStr; - certStr_len = 0; + char *certStr_p = certStr; + int certStr_len = 0; while (1) { - toRead = min(BIO_pending(bio), CERT_STR_SIZE - certStr_len - 1); + int toRead = min(BIO_pending(bio), CERT_STR_SIZE - certStr_len - 1); toRead = min(toRead, BUFSIZ); if (toRead == 0) { break; } dprintf("Reading %i bytes from the certificate...", toRead); @@ -149,18 +146,18 @@ Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("all", -1)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(all, n)); } /* Get Validity - Not Before */ - if (ASN1_TIME_print(bio, X509_get_notBefore(cert))) { + if (ASN1_TIME_print(bio, X509_get0_notBefore(cert))) { n = BIO_read(bio, notBefore, min(BIO_pending(bio), BUFSIZ - 1)); notBefore[max(n, 0)] = 0; (void)BIO_flush(bio); } /* Get Validity - Not After */ - if (ASN1_TIME_print(bio, X509_get_notAfter(cert))) { + if (ASN1_TIME_print(bio, X509_get0_notAfter(cert))) { n = BIO_read(bio, notAfter, min(BIO_pending(bio), BUFSIZ - 1)); notAfter[max(n, 0)] = 0; (void)BIO_flush(bio); } @@ -174,18 +171,18 @@ /* Signature algorithm */ Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("signature", -1)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(OBJ_nid2ln(X509_get_signature_nid(cert)),-1)); /* SHA1 Fingerprint of cert - DER representation */ - X509_digest(cert, EVP_sha1(), sha1_hash_binary, &len); - len = String_to_Hex(sha1_hash_binary, len, buffer, BUFSIZ); + X509_digest(cert, EVP_sha1(), md, &len); + len = String_to_Hex(md, len, buffer, BUFSIZ); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("sha1_hash", -1)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); /* SHA256 Fingerprint of cert - DER representation */ - X509_digest(cert, EVP_sha256(), sha256_hash_binary, &len); - len = String_to_Hex(sha256_hash_binary, len, buffer, BUFSIZ); + X509_digest(cert, EVP_sha256(), md, &len); + len = String_to_Hex(md, len, buffer, BUFSIZ); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("sha256_hash", -1)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("subject", -1)); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(subject, -1)); @@ -292,18 +289,17 @@ sk_GENERAL_NAME_pop_free(san, GENERAL_NAME_free); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("subjectAltName", -1)); Tcl_ListObjAppendElement(interp, certPtr, namesPtr); } - /* Certificate Alias */ + /* Certificate Alias as UTF-8 string */ { unsigned char *bstring; len = 0; bstring = X509_alias_get0(cert, &len); - len = String_to_Hex(bstring, len, buffer, BUFSIZ); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("alias", -1)); - Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj((char *)bstring, len)); } /* Get Subject Key id, Authority Key id */ { ASN1_OCTET_STRING *astring; @@ -310,20 +306,20 @@ /* X509_keyid_get0 */ astring = X509_get0_subject_key_id(cert); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("subjectKeyIdentifier", -1)); if (astring != NULL) { len = String_to_Hex((char *)ASN1_STRING_get0_data(astring), ASN1_STRING_length(astring), buffer, BUFSIZ); - Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewByteArrayObj(buffer, len)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); } else { Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("", -1)); } astring = X509_get0_authority_key_id(cert); Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("authorityKeyIdentifier", -1)); if (astring != NULL) { len = String_to_Hex((char *)ASN1_STRING_get0_data(astring), ASN1_STRING_length(astring), buffer, BUFSIZ); - Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewByteArrayObj(buffer, len)); + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); } else { Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("", -1)); } /* const GENERAL_NAMES *X509_get0_authority_issuer(cert); @@ -364,8 +360,27 @@ Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj(buffer, len)); } else { Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("", -1)); } } + + /* Certificate purposes */ + { + Tcl_Obj *purpPtr = Tcl_NewListObj(0, NULL); + for (int j = 0; j < X509_PURPOSE_get_count(); j++) { + X509_PURPOSE *ptmp = X509_PURPOSE_get0(j); + Tcl_Obj *tmpPtr = Tcl_NewListObj(0, NULL); + + for (int i = 0; i < 2; i++) { + int idret = X509_check_purpose(cert, X509_PURPOSE_get_id(ptmp), i); + Tcl_ListObjAppendElement(interp, tmpPtr, Tcl_NewStringObj(i ? "CA" : "nonCA", -1)); + Tcl_ListObjAppendElement(interp, tmpPtr, Tcl_NewStringObj(idret ? "Yes" : "No", -1)); + } + Tcl_ListObjAppendElement(interp, purpPtr, Tcl_NewStringObj(X509_PURPOSE_get0_name(ptmp), -1)); + Tcl_ListObjAppendElement(interp, purpPtr, tmpPtr); + } + Tcl_ListObjAppendElement(interp, certPtr, Tcl_NewStringObj("certificatePurpose", -1)); + Tcl_ListObjAppendElement(interp, certPtr, purpPtr); + } return certPtr; }