su_inline int tls_post_connection_check(tport_t *self, tls_t *tls) { X509 *cert; int extcount; int i, j, error; if (!tls) return -1; cert = SSL_get_peer_certificate(tls->con); if (!cert) { SU_DEBUG_7(("%s(%p): Peer did not provide X.509 Certificate.\n", __func__, (void *) self)); if (self->tp_accepted && tls->verify_incoming) return X509_V_ERR_CERT_UNTRUSTED; else if (!self->tp_accepted && tls->verify_outgoing) return X509_V_ERR_CERT_UNTRUSTED; else return X509_V_OK; } tls->subjects = su_strlst_create(tls->home); if (!tls->subjects) return X509_V_ERR_OUT_OF_MEM; extcount = X509_get_ext_count(cert); /* Find matching subjectAltName.DNS */ for (i = 0; i < extcount; i++) { X509_EXTENSION *ext; char const *name; #if OPENSSL_VERSION_NUMBER > 0x10000000L const X509V3_EXT_METHOD *vp; #else X509V3_EXT_METHOD *vp; #endif STACK_OF(CONF_VALUE) *values; CONF_VALUE *value; void *d2i; ext = X509_get_ext(cert, i); name = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); if (strcmp(name, "subjectAltName") != 0) continue; vp = X509V3_EXT_get(ext); if (!vp) continue; d2i = X509V3_EXT_d2i(ext); values = vp->i2v(vp, d2i, NULL); for (j = 0; j < sk_CONF_VALUE_num(values); j++) { value = sk_CONF_VALUE_value(values, j); if (strcmp(value->name, "DNS") == 0) su_strlst_dup_append(tls->subjects, value->value); if (strcmp(value->name, "IP") == 0) su_strlst_dup_append(tls->subjects, value->value); else if (strcmp(value->name, "URI") == 0) su_strlst_dup_append(tls->subjects, value->value); } } { X509_NAME *subject; char name[256]; subject = X509_get_subject_name(cert); if (subject) { if (X509_NAME_get_text_by_NID(subject, NID_commonName, name, sizeof name) > 0) { usize_t k, N = su_strlst_len(tls->subjects); name[(sizeof name) - 1] = '\0'; for (k = 0; k < N; k++) if (su_casematch(su_strlst_item(tls->subjects, k), name) == 0) break; if (k >= N) su_strlst_dup_append(tls->subjects, name); } } } X509_free(cert); error = SSL_get_verify_result(tls->con); if (cert && error == X509_V_OK) tls->x509_verified = 1; if (tport_log->log_level >= 7) { int i, len = su_strlst_len(tls->subjects); for (i=0; i < len; i++) SU_DEBUG_7(("%s(%p): Peer Certificate Subject %i: %s\n", \ __func__, (void *)self, i, su_strlst_item(tls->subjects, i))); if (i == 0) SU_DEBUG_7(("%s(%p): Peer Certificate provided no usable subjects.\n", __func__, (void *)self)); } /* Verify incoming connections */ if (self->tp_accepted) { if (!tls->verify_incoming) return X509_V_OK; if (!tls->x509_verified) return error; if (tls->verify_subj_in) { su_strlst_t const *subjects = self->tp_pri->pri_primary->tp_subjects; int i, items; items = subjects ? su_strlst_len(subjects) : 0; if (items == 0) return X509_V_OK; for (i=0; i < items; i++) { if (tport_subject_search(su_strlst_item(subjects, i), tls->subjects)) return X509_V_OK; } SU_DEBUG_3(("%s(%p): Peer Subject Mismatch (incoming connection)\n", \ __func__, (void *)self)); return X509_V_ERR_CERT_UNTRUSTED; } } /* Verify outgoing connections */ else { char const *subject = self->tp_canon; if (!tls->verify_outgoing) return X509_V_OK; if (!tls->x509_verified || !subject) return error; if (tls->verify_subj_out) { if (tport_subject_search(subject, tls->subjects)) return X509_V_OK; /* Subject match found in verified certificate chain */ SU_DEBUG_3(("%s(%p): Peer Subject Mismatch (%s)\n", \ __func__, (void *)self, subject)); return X509_V_ERR_CERT_UNTRUSTED; } } return error; }
static int test_strlst(void) { su_home_t home[1] = { SU_HOME_INIT(home) }; su_strlst_t *l, *l1, *l2; char *s; char foo[] = "foo"; char bar[] = "bar"; char baz[] = "baz"; su_home_stat_t parent[1], kids[2]; BEGIN(); parent->hs_size = (sizeof parent); kids[0].hs_size = (sizeof kids[0]); kids[1].hs_size = (sizeof kids[1]); su_home_init_stats(home); /* Test API for invalid arguments */ TEST_1(l = su_strlst_create(NULL)); TEST_1(l2 = su_strlst_dup(home, l)); TEST_VOID(su_strlst_destroy(l2)); TEST_1(!su_strlst_dup(home, NULL)); TEST_1(l1 = su_strlst_copy(home, l)); TEST_VOID(su_strlst_destroy(l1)); TEST_1(!su_strlst_copy(home, NULL)); TEST_VOID(su_strlst_destroy(NULL)); TEST_VOID(su_strlst_destroy(l)); TEST_1(!su_strlst_dup_append(NULL, "aa")); TEST_1(!su_strlst_append(NULL, "bee")); TEST_1(!su_strlst_item(NULL, 1)); TEST_1(!su_strlst_set_item(NULL, 1, "cee")); TEST_1(!su_strlst_remove(NULL, 1)); TEST_S(s = su_strlst_join(NULL, home, "a"), ""); TEST_VOID(su_free(home, s)); TEST_1(!su_strlst_split(home, NULL, ".")); TEST_1(s = su_strdup(home, "aaa")); TEST_1(l = su_strlst_split(home, s, NULL)); TEST_S(su_strlst_item(l, 0), "aaa"); TEST_VOID(su_strlst_destroy(l)); TEST_VOID(su_free(home, s)); TEST_1(!su_strlst_dup_split(home, NULL, ".")); TEST_1(l1 = su_strlst_dup_split(home, "aaa", "")); TEST_S(su_strlst_item(l1, 0), "aaa"); TEST_VOID(su_strlst_destroy(l1)); TEST_SIZE(su_strlst_len(NULL), 0); TEST_1(!su_strlst_get_array(NULL)); TEST_VOID(su_strlst_free_array(NULL, NULL)); TEST_1(l = su_strlst_create(home)); TEST_VOID(su_strlst_free_array(l, NULL)); TEST_S(su_strlst_dup_append(l, "oh"), "oh"); TEST_VOID(su_strlst_free_array(l, NULL)); TEST_VOID(su_strlst_destroy(l)); /* Test functionality */ TEST_1(l = su_strlst_create(home)); su_home_init_stats(su_strlst_home(l)); TEST_S(su_strlst_join(l, home, "bar"), ""); TEST_S(su_strlst_append(l, foo), "foo"); TEST_S(su_strlst_dup_append(l, bar), "bar"); TEST_S(su_strlst_append(l, baz), "baz"); TEST_S((s = su_strlst_join(l, home, "!")), "foo!bar!baz"); TEST_S(su_strlst_item(l, 0), foo); TEST_S(su_strlst_item(l, 1), bar); TEST_S(su_strlst_item(l, 2), baz); TEST_P(su_strlst_item(l, 3), NULL); TEST_P(su_strlst_item(l, (unsigned)-1), NULL); TEST_1(l1 = su_strlst_copy(su_strlst_home(l), l)); TEST_1(l2 = su_strlst_dup(su_strlst_home(l), l)); strcpy(foo, "hum"); strcpy(bar, "pah"); strcpy(baz, "hah"); TEST_S(su_strlst_dup_append(l1, "kuik"), "kuik"); TEST_S(su_strlst_dup_append(l2, "uik"), "uik"); TEST_S((s = su_strlst_join(l, home, ".")), "hum.bar.hah"); TEST_S((su_strlst_join(l1, home, ".")), "hum.bar.hah.kuik"); TEST_S((su_strlst_join(l2, home, ".")), "foo.bar.baz.uik"); su_strlst_destroy(l2); su_home_get_stats(su_strlst_home(l), 0, kids, sizeof kids); TEST_SIZE(kids->hs_clones, 2); TEST64(kids->hs_allocs.hsa_number, 3); TEST64(kids->hs_frees.hsf_number, 1); su_strlst_destroy(l); TEST_S(s, "hum.bar.hah"); TEST_1(l = su_strlst_create(home)); su_home_init_stats(su_strlst_home(l)); TEST_S(su_strlst_join(l, home, "bar"), ""); TEST_S(su_strlst_append(l, "a"), "a"); TEST_S(su_strlst_append(l, "b"), "b"); TEST_S(su_strlst_append(l, "c"), "c"); TEST_S(su_strlst_append(l, "d"), "d"); TEST_S(su_strlst_append(l, "e"), "e"); TEST_S(su_strlst_append(l, "f"), "f"); TEST_S(su_strlst_append(l, "g"), "g"); TEST_S(su_strlst_append(l, "h"), "h"); TEST_S(su_strlst_append(l, "i"), "i"); TEST_S(su_strlst_append(l, "j"), "j"); TEST_S((s = su_strlst_join(l, home, "")), "abcdefghij"); TEST_S(su_strlst_append(l, "a"), "a"); TEST_S(su_strlst_append(l, "b"), "b"); TEST_S(su_strlst_append(l, "c"), "c"); TEST_S(su_strlst_append(l, "d"), "d"); TEST_S(su_strlst_append(l, "e"), "e"); TEST_S(su_strlst_append(l, "f"), "f"); TEST_S(su_strlst_append(l, "g"), "g"); TEST_S(su_strlst_append(l, "h"), "h"); TEST_S(su_strlst_append(l, "i"), "i"); TEST_S(su_strlst_append(l, "j"), "j"); TEST_S((s = su_strlst_join(l, home, "")), "abcdefghijabcdefghij"); su_home_get_stats(su_strlst_home(l), 0, kids + 1, (sizeof kids[1])); su_home_stat_add(kids, kids + 1); su_strlst_destroy(l); su_home_get_stats(home, 1, parent, (sizeof parent)); su_home_check(home); su_home_deinit(home); su_home_init(home); { char s[] = "foo\nfaa\n"; TEST_1((l = su_strlst_split(home, s, "\n"))); TEST_SIZE(su_strlst_len(l), 3); TEST_1(su_strlst_append(l, "bar")); TEST_S(su_strlst_join(l, home, "\n"), "foo\nfaa\n\nbar"); } { char s[] = "foo"; TEST_1((l = su_strlst_split(home, s, "\n"))); TEST_SIZE(su_strlst_len(l), 1); } { char s[] = "\n\n"; TEST_1((l = su_strlst_split(home, s, "\n"))); TEST_SIZE(su_strlst_len(l), 3); } { char s[] = ""; TEST_1((l = su_strlst_split(home, s, "\n"))); TEST_SIZE(su_strlst_len(l), 1); } { int i; #define S \ "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\n" \ "n\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n" \ "A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\n" \ "N\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ\n" char s[] = S; TEST_1((l = su_strlst_split(home, s, "\n"))); TEST_SIZE(su_strlst_len(l), 53); TEST_1(su_strlst_append(l, "bar")); TEST_S(su_strlst_join(l, home, "\n"), S "\nbar"); TEST_1(!su_strlst_remove(l, 54)); for (i = 0; i < 54; i++) { TEST_1(su_strlst_remove(l, 0)); TEST_1(!su_strlst_remove(l, 53 - i)); TEST_SIZE(su_strlst_len(l), 53 - i); } TEST_1(!su_strlst_remove(l, 0)); TEST_SIZE(su_strlst_len(l), 0); } { char const *s0; TEST_1(l = su_strlst_create_with(NULL, s0 = "a", "b", NULL)); TEST_1(su_strlst_item(l, 0) == s0); TEST_S(su_strlst_item(l, 0), "a"); TEST_S(su_strlst_item(l, 1), "b"); TEST_1(su_strlst_item(l, 2) == NULL); TEST_S(su_slprintf(l, "1: %u", 1), "1: 1"); TEST_S(su_slprintf(l, "1.0: %g", 1.0), "1.0: 1"); TEST_1(su_strlst_append(l, "")); TEST_S(su_strlst_join(l, home, "\n"), "a\n" "b\n" "1: 1\n" "1.0: 1\n"); TEST_VOID(su_strlst_destroy(l)); TEST_1(l2 = su_strlst_create_with_dup(NULL, s0 = "0", "1", "2", "3", "4", "5", "6", "7", NULL)); TEST_1(su_strlst_item(l2, 0) != s0); TEST_S(su_strlst_item(l2, 0), "0"); TEST_S(su_strlst_item(l2, 1), "1"); TEST_S(su_strlst_item(l2, 2), "2"); TEST_S(su_strlst_item(l2, 3), "3"); TEST_S(su_strlst_item(l2, 4), "4"); TEST_S(su_strlst_item(l2, 5), "5"); TEST_S(su_strlst_item(l2, 6), "6"); TEST_S(su_strlst_item(l2, 7), "7"); TEST_1(su_strlst_item(l2, 8) == NULL); TEST_S(su_strlst_join(l2, home, ""), "01234567"); TEST_VOID(su_strlst_destroy(l2)); } su_home_check(home); su_home_deinit(home); END(); }