EXPORT_C void *X509V3_EXT_d2i(X509_EXTENSION *ext) { X509V3_EXT_METHOD *method; const unsigned char *p; if(!(method = X509V3_EXT_get(ext))) return NULL; p = ext->value->data; if(method->it) return ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it)); return method->d2i(NULL, &p, ext->value->length); }
int protocol_checkcert(void *peer, X509 * cert) { struct in_network net; int i, j; const unsigned char *p; void *ext_str = NULL; const STACK_OF(X509_EXTENSION) * exts = cert->cert_info->extensions; X509_EXTENSION *ext; X509V3_EXT_METHOD *method; STACK_OF(GENERAL_SUBTREE) * trees; GENERAL_SUBTREE *tree; for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { ext = sk_X509_EXTENSION_value(exts, i); if ((method = X509V3_EXT_get(ext)) && method->ext_nid == NID_name_constraints) { p = ext->value->data; if (method->it) ext_str = ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it)); else ext_str = method->d2i(NULL, &p, ext->value->length); trees = ((NAME_CONSTRAINTS *) ext_str)->permittedSubtrees; for (j = 0; j < sk_GENERAL_SUBTREE_num(trees); j++) { tree = sk_GENERAL_SUBTREE_value(trees, j); if (tree->base->type == GEN_IPADD) p = tree->base->d.ip->data; if (tree->base->d.ip->length == 8) { net.addr.s_addr = *((uint32_t *) p); net.netmask.s_addr = *((uint32_t *) & p[4]); printf("%s/", inet_ntoa(net.addr)); printf("%s\n", inet_ntoa(net.netmask)); } //else if(len == 32) //IPv6 // See openssl/crypto/x509v3/v3_ncons.c:static int print_nc_ipadd() //else //DNS // GENERAL_NAME_print(bp, tree->base); } } } return 0; }
static int verify_cert_hostname(X509 *cert, char *hostname) { int extcount, i, j, ok = 0; char name[256]; X509_NAME *subj; const char *extstr; CONF_VALUE *nval; const unsigned char *data; X509_EXTENSION *ext; X509V3_EXT_METHOD *meth; STACK_OF(CONF_VALUE) *val; if ((extcount = X509_get_ext_count(cert)) > 0) { for (i = 0; !ok && i < extcount; i++) { ext = X509_get_ext(cert, i); extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); if (!strcasecmp(extstr, "subjectAltName")) { if (!(meth = (X509V3_EXT_METHOD *)X509V3_EXT_get(ext))) break; data = ext->value->data; val = meth->i2v(meth, meth->d2i(0, &data, ext->value->length), 0); for (j = 0; j < sk_CONF_VALUE_num(val); j++) { nval = sk_CONF_VALUE_value(val, j); if (!strcasecmp(nval->name, "DNS") && !strcasecmp(nval->value, hostname)) { ok = 1; break; } } } } } if (!ok && (subj = X509_get_subject_name(cert)) && X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0) { name[sizeof(name) - 1] = '\0'; if (!strcasecmp(name, hostname)) ok = 1; } return ok; }
/* * Check that the common name matches the host name */ static int check_cert_chain(conn_t * conn, SSL * ssl, ruleset_t * rs) { X509 *peer; X509_NAME *xn; static char subject[1024]; int r = FALSE, extc; if (SSL_get_verify_result(ssl) != X509_V_OK) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Certificate doesn't verify"); return FALSE; } /* * Check the cert chain. The chain length is automatically checked by * OpenSSL when we set the verify depth in the ctx */ peer = SSL_get_peer_certificate(ssl); if (!peer) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"No peer certificate"); return TRUE; } /* * check subjectaltname */ if ((extc = X509_get_ext_count(peer)) > 0) { int i; for (i = 0; r == FALSE && i < extc; i++) { X509_EXTENSION *ext; const char *extstr; ext = X509_get_ext(peer, i); extstr = OBJ_nid2sn(OBJ_obj2nid (X509_EXTENSION_get_object(ext))); if (strcmp(extstr, "subjectAltName") == 0) { int j; unsigned char *data; STACK_OF(CONF_VALUE) * val; CONF_VALUE *nval; X509V3_EXT_METHOD *meth; if ((meth = X509V3_EXT_get(ext)) == 0) break; data = ext->value->data; val = meth->i2v(meth, meth->d2i(NULL, &data, ext->value->length), NULL); for (j = 0; r == FALSE && i < sk_CONF_VALUE_num(val); j++) { nval = sk_CONF_VALUE_value(val, j); if (strcasecmp(nval->name, "DNS") == 0 && strcasecmp(nval->value, conn->sri. hostname)) { r = TRUE; } } } } } if (r == FALSE) { /* * Check the subject name */ xn = X509_get_subject_name(peer); X509_NAME_get_text_by_NID(xn, NID_commonName, subject, 1024); subject[1023] = '\0'; traceLog(LOG_DEBUG,"\"%s\" = \"%s\" ?", subject, conn->sri.hostname); if (strcasecmp(subject, conn->sri.hostname) == 0) { r = TRUE; } } if (r == TRUE) { conn->subjectDN = X509_NAME_oneline(X509_get_subject_name(peer), NULL, 0); conn->issuerDN = X509_NAME_oneline(X509_get_issuer_name(peer), NULL, 0); } X509_free(peer); return r; }
static PyObject * _get_peer_alt_names (X509 *certificate) { /* this code follows the procedure outlined in OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print() function to extract the STACK_OF(GENERAL_NAME), then iterates through the stack to add the names. */ int i, j; PyObject *peer_alt_names = Py_None; PyObject *v, *t; X509_EXTENSION *ext = NULL; GENERAL_NAMES *names = NULL; GENERAL_NAME *name; X509V3_EXT_METHOD *method; BIO *biobuf = NULL; char buf[2048]; char *vptr; int len; const unsigned char *p; if (certificate == NULL) return peer_alt_names; /* get a memory buffer */ biobuf = BIO_new(BIO_s_mem()); i = 0; while ((i = X509_get_ext_by_NID( certificate, NID_subject_alt_name, i)) >= 0) { if (peer_alt_names == Py_None) { peer_alt_names = PyList_New(0); if (peer_alt_names == NULL) goto fail; } /* now decode the altName */ ext = X509_get_ext(certificate, i); if(!(method = X509V3_EXT_get(ext))) { PyErr_SetString (PySSLErrorObject, ERRSTR("No method for internalizing subjectAltName!")); goto fail; } p = ext->value->data; if (method->it) names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it))); else names = (GENERAL_NAMES*) (method->d2i(NULL, &p, ext->value->length)); for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { /* get a rendering of each name in the set of names */ name = sk_GENERAL_NAME_value(names, j); if (name->type == GEN_DIRNAME) { /* we special-case DirName as a tuple of tuples of attributes */ t = PyTuple_New(2); if (t == NULL) { goto fail; } v = PyUnicode_FromString("DirName"); if (v == NULL) { Py_DECREF(t); goto fail; } PyTuple_SET_ITEM(t, 0, v); v = _create_tuple_for_X509_NAME (name->d.dirn); if (v == NULL) { Py_DECREF(t); goto fail; } PyTuple_SET_ITEM(t, 1, v); } else { /* for everything else, we use the OpenSSL print form */ (void) BIO_reset(biobuf); GENERAL_NAME_print(biobuf, name); len = BIO_gets(biobuf, buf, sizeof(buf)-1); if (len < 0) { _setSSLError(NULL, 0, __FILE__, __LINE__); goto fail; } vptr = strchr(buf, ':'); if (vptr == NULL) goto fail; t = PyTuple_New(2); if (t == NULL) goto fail; v = PyUnicode_FromStringAndSize(buf, (vptr - buf)); if (v == NULL) { Py_DECREF(t); goto fail; } PyTuple_SET_ITEM(t, 0, v); v = PyUnicode_FromStringAndSize((vptr + 1), (len - (vptr - buf + 1))); if (v == NULL) { Py_DECREF(t); goto fail; } PyTuple_SET_ITEM(t, 1, v); } /* and add that rendering to the list */ if (PyList_Append(peer_alt_names, t) < 0) { Py_DECREF(t); goto fail; } Py_DECREF(t); } } BIO_free(biobuf); if (peer_alt_names != Py_None) { v = PyList_AsTuple(peer_alt_names); Py_DECREF(peer_alt_names); return v; } else { return peer_alt_names; } fail: if (biobuf != NULL) BIO_free(biobuf); if (peer_alt_names != Py_None) { Py_XDECREF(peer_alt_names); } return NULL; }
/** Search for a hostname match in the SubjectAlternativeNames. */ uint32_t check_san (SSL *ssl, const char *hostname) { X509 *cert; int extcount, ok = 0; /* What an OpenSSL mess ... */ if (NULL == (cert = SSL_get_peer_certificate(ssl))) { die ("Getting certificate failed\n"); } if ((extcount = X509_get_ext_count(cert)) > 0) { int i; for (i = 0; i < extcount; ++i) { const char *extstr; X509_EXTENSION *ext; ext = X509_get_ext(cert, i); extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); if (!strcmp(extstr, "subjectAltName")) { int j; void *extvalstr; const unsigned char *tmp; STACK_OF(CONF_VALUE) *val; CONF_VALUE *nval; X509V3_EXT_METHOD *method; if (!(method = X509V3_EXT_get(ext))) { break; } tmp = ext->value->data; if (method->it) { extvalstr = ASN1_item_d2i(NULL, &tmp, ext->value->length, ASN1_ITEM_ptr(method->it)); } else { extvalstr = method->d2i(NULL, &tmp, ext->value->length); } if (!extvalstr) { break; } if (method->i2v) { val = method->i2v(method, extvalstr, NULL); for (j = 0; j < sk_CONF_VALUE_num(val); ++j) { nval = sk_CONF_VALUE_value(val, j); if ((!strcasecmp(nval->name, "DNS") && !strcasecmp(nval->value, host) ) || (!strcasecmp(nval->name, "iPAddress") && !strcasecmp(nval->value, host))) { verb ("V: subjectAltName matched: %s, type: %s\n", nval->value, nval->name); // We matched this; so it's safe to print ok = 1; break; } verb ("V: subjectAltName found but not matched: %s, type: %s\n", nval->value, nval->name); // XXX: Clean this string! } } } else { verb ("V: found non subjectAltName extension\n"); } if (ok) { break; } } } else { verb ("V: no X509_EXTENSION field(s) found\n"); } X509_free(cert); return ok; }
long ipfix_ssl_post_connection_check(SSL *ssl, char *host) { X509 *cert; X509_NAME *subj; char data[256]; int extcount; int ok = 0; /* Checking the return from SSL_get_peer_certificate here is not strictly * necessary. */ if (!(cert = SSL_get_peer_certificate(ssl)) || !host) goto err_occured; if ((extcount = X509_get_ext_count(cert)) > 0) { int i; for (i = 0; i < extcount; i++) { char *extstr; X509_EXTENSION *ext; ext = X509_get_ext(cert, i); extstr = (char*) OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); if (!strcmp(extstr, "subjectAltName")) { int j; const unsigned char *data; STACK_OF(CONF_VALUE) *val; CONF_VALUE *nval; X509V3_EXT_METHOD *meth; void *ext_str = NULL; if (!(meth = X509V3_EXT_get(ext))) break; data = ext->value->data; #if (OPENSSL_VERSION_NUMBER > 0x00907000L) if (meth->it) ext_str = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); else ext_str = meth->d2i(NULL, &data, ext->value->length); #else ext_str = meth->d2i(NULL, &data, ext->value->length); #endif val = meth->i2v(meth, ext_str, NULL); for (j = 0; j < sk_CONF_VALUE_num(val); j++) { nval = sk_CONF_VALUE_value(val, j); if (!strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) { ok = 1; break; } } } if (ok) break; } } if (!ok && (subj = X509_get_subject_name(cert)) && X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0) { data[255] = 0; if (strcasecmp(data, host) != 0) goto err_occured; } X509_free(cert); return SSL_get_verify_result(ssl); err_occured: if (cert) X509_free(cert); return X509_V_ERR_APPLICATION_VERIFICATION; }