This patch should wrap up the major changes to the tport module. A new pointer (tpn_subject) has been added to the tp_name_t structure, which defines the subject name of the intended recipient of each message.
As before, these patches should not change the behavior of NTA or NUA. The next patch will be directed at those modules (that is, once I wrap my head around what is going on in NTA). Here is a quick rundown on the (intended) behavior of the subject verification code: *** For established TLS Connections *** tport_is_verified() - Indicates whether or not an active TLS tport secondary has a verified certificate. tport_delivered_from_subjects() - Provides a list of the verified certificate subjects associated with the peer that delivered a message. tport_subject_search() - Searches a list of certificate subjects. - Supports peer certificates with URI subjects and wildcard hostnames. *** For Outgoing Messages on New Connections *** The goal here was to allow the higher levels to call tport_tsend() with any tpn_subject and guarantee that the message will only be delivered to a completely authenticated peer. I think pseudocode will provide a better overview of what should happen: if (TPORT_TLS_VERIFY_PEER(1) is not set) send message else if (peer_cert does not verify) do not send message else if (tpn_subject is not set) send message else if (peer_cert->subjects includes tpn_subject) send message else do not send message
New patches: [TLS Subject Checking in tport Jarod Neuner <janeu...@networkharbor.com>**20090105222710 sofia-sip/tport.h: * Add (tp_name_t *)->tpn_subject - The peer of an outgoing connection must present a matching subject in its certificate. * tport_delivered_from_subjects() returns type (su_strlst_t const *) * Export tport_subject_search() tport.c * Add tport_subject_search() - Matches explicit and wildcard certificate subjects. - Subject can be a hostname or a URI. Valid tpn_subject examples include: example.com al...@example.com sip:al...@example.com sips:al...@example.com any-proto:al...@example.com - Note: Matching against a wildcard tpn_subject will fail. * tport_by_addrinfo() matches the tpn_subject field, where applicable. * tport_name_dup() copies the tpn_subject field. tport_tls.h: * Add tls_init_secondary() * Remove tls_init_slave() & tls_init_client() tport_tls.c: * tls_post_connection_check() verifies the subject on new outgoing connections. * tls_init_secondary() - Replaces tls_init_slave(), tls_init_client(), and tls_clone(). tport_type_tls.c: * Removed erroneous reference to tport_tls_deliver() * Fix a memory leak caused by duplicate calls to tls_clone(). * Populate the (tport_t *)->tp_subjects field with peer certificate data for new secondary connections. ] { hunk ./libsofia-sip-ua/tport/sofia-sip/tport.h 155 + * + * The tpn_subject specifies the desired subject name in the peer TLS + * certificates. hunk ./libsofia-sip-ua/tport/sofia-sip/tport.h 166 + char const *tpn_subject; /**< TLS Subjects (NULL matches any subject) */ hunk ./libsofia-sip-ua/tport/sofia-sip/tport.h 346 -TPORT_DLL su_strlst_t *tport_delivered_from_subjects(tport_t *tp, msg_t const *msg); +TPORT_DLL su_strlst_t const *tport_delivered_from_subjects(tport_t *tp, + msg_t const *msg); + +/** Check if the given subject string is found in su_strlst_t */ +TPORT_DLL int tport_subject_search(char const *, su_strlst_t const *); hunk ./libsofia-sip-ua/tport/tport.c 276 - return tport_has_tls(self) && self->tp_verified; + return tport_has_tls(self) && self->tp_is_connected && self->tp_verified; hunk ./libsofia-sip-ua/tport/tport.c 646 + else if (tpn->tpn_subject && + !(tp->tp_name->tpn_subject = su_strdup(tp->tp_home, tpn->tpn_subject))) + *return_culprit = "alloc subjects"; hunk ./libsofia-sip-ua/tport/tport.c 3052 -su_strlst_t *tport_delivered_from_subjects(tport_t *tp, msg_t const *msg) +su_strlst_t const *tport_delivered_from_subjects(tport_t *tp, msg_t const *msg) hunk ./libsofia-sip-ua/tport/tport.c 3076 +/** Search for subject in lst of TLS Certificate subjects */ +int +tport_subject_search(char const *subject, su_strlst_t const *lst) +{ + int idx, ilen; + const char *lststr; + unsigned uname; /* is subject of the form 'un...@host'? */ + + if (!subject || !strcmp(tpn_any, subject)) + return 1; + + if (!lst) + return 0; + + uname = strchr(subject,'@') ? 1 :0; + + ilen = su_strlst_len(lst); + + for (idx = 0; idx < ilen; idx++) { + lststr = su_strlst_item(lst, idx); + + if (!strcasecmp(subject, lststr)) + return 1; + + /* check wildcard certificate subjects */ + if (!uname && memcmp("*.", lststr, 2)) { + const char *subsubject = subject; + lststr++; + while((subsubject = strchr(subsubject,'.'))) + if (!strcasecmp(subsubject, lststr)) + return 1; + } + } + + return 0; +} + hunk ./libsofia-sip-ua/tport/tport.c 4624 + if (tpn->tpn_subject && tport_has_tls(sub)) { + if (tport_is_verified(sub)) { + if (!tport_subject_search(tpn->tpn_subject, sub->tp_subjects)) + continue; + } else { + /* tport_subject_search() is always called after verification */ + if (strcasecmp(tpn->tpn_subject, sub->tp_name->tpn_subject)) + continue; + } + } + hunk ./libsofia-sip-ua/tport/tport.c 4727 - size_t n_proto, n_host, n_port, n_canon, n_comp = 0; + size_t n_proto, n_host, n_port, n_canon, n_comp = 0, n_subj = 0; hunk ./libsofia-sip-ua/tport/tport.c 4745 + if (src->tpn_subject != NULL) + n_subj = strlen(src->tpn_subject) + 1; + hunk ./libsofia-sip-ua/tport/tport.c 4754 - s = su_alloc(home, n_proto + n_canon + n_host + n_port + n_comp); + s = su_alloc(home, n_proto + n_canon + n_host + n_port + n_comp + n_subj); hunk ./libsofia-sip-ua/tport/tport.c 4776 + if (n_subj) + dst->tpn_subject = memcpy(s, src->tpn_subject, n_subj), s += n_subj; + else + dst->tpn_subject = NULL; + hunk ./libsofia-sip-ua/tport/tport_tls.c 363 -tls_t *tls_clone(tls_t *master, int sock, int accept) +tls_t *tls_init_secondary(tls_t *master, int sock, int accept) hunk ./libsofia-sip-ua/tport/tport_tls.c 370 + tls->verify_outgoing = master->verify_outgoing; + tls->verify_incoming = master->verify_incoming; hunk ./libsofia-sip-ua/tport/tport_tls.c 385 - tls_log_errors(1, "tls_clone", 0); + tls_log_errors(1, "tls_init_secondary", 0); hunk ./libsofia-sip-ua/tport/tport_tls.c 399 -tls_t *tls_init_slave(tls_t *master, int sock) -{ - int accept; - return tls_clone(master, sock, accept = 1); -} - -tls_t *tls_init_client(tls_t *master, int sock) -{ - int accept; - return tls_clone(master, sock, accept = 0); -} - -static -int tls_post_connection_check(tls_t *tls) +su_inline +int tls_post_connection_check(tls_t *tls, char const *subject) hunk ./libsofia-sip-ua/tport/tport_tls.c 409 - if (!cert) - return X509_V_OK; - - extcount = X509_get_ext_count(cert); + if (!cert) { + if (tls->accept && tls->verify_incoming) + return X509_V_ERR_CERT_UNTRUSTED; + else if (!tls->accept && tls->verify_outgoing) + return X509_V_ERR_CERT_UNTRUSTED; + else if (!tls->accept && subject) + return X509_V_ERR_CERT_UNTRUSTED; + else + return X509_V_OK; + } hunk ./libsofia-sip-ua/tport/tport_tls.c 420 + tls->subject = su_strlst_create(tls->home); hunk ./libsofia-sip-ua/tport/tport_tls.c 422 - tls->subject = su_strlst_create(tls->home); + return X509_V_ERR_OUT_OF_MEM; + + extcount = X509_get_ext_count(cert); hunk ./libsofia-sip-ua/tport/tport_tls.c 449 + if (strcmp(value->name, "IP") == 0) + su_strlst_dup_append(tls->subject, value->value); hunk ./libsofia-sip-ua/tport/tport_tls.c 453 - char const *url = strchr(uri, ':'); - if (url++) - su_strlst_append(tls->subject, url); + char const *uname = strchr(uri, ':'); + if (uname++) + su_strlst_append(tls->subject, uname); hunk ./libsofia-sip-ua/tport/tport_tls.c 490 - return X509_V_OK; - else if (!tls->accept && !tls->verify_outgoing) - return X509_V_OK; + return X509_V_OK; /* do not reject incoming connections */ + if (tls->accept) + return error; /* No subject matching on incoming connections */ + if (!tls->accept && !tls->verify_outgoing) + return X509_V_OK; /* do not reject outgoing connections */ + if (tls->verified && subject && tport_subject_search(subject, tls->subject)) + return X509_V_OK; /* Subject match found in verified certificate chain */ + hunk ./libsofia-sip-ua/tport/tport_tls.c 738 - int ret, status; + int ret, status, ok; hunk ./libsofia-sip-ua/tport/tport_tls.c 760 - if ( tls_post_connection_check(tls) == X509_V_OK ) { + ok = tls_post_connection_check(tls, self->tp_name->tpn_subject); + if ( ok == X509_V_OK ) { hunk ./libsofia-sip-ua/tport/tport_tls.c 781 - self->tp_subjects = tls->subject == NULL ? NULL : - su_strlst_dup(self->tp_home, tls->subject); + self->tp_subjects = tls->subject; hunk ./libsofia-sip-ua/tport/tport_tls.h 81 -tls_t *tls_init_slave(tls_t *tls_master, int sock); -tls_t *tls_init_client(tls_t *tls_master, int sock); +tls_t *tls_init_secondary(tls_t *tls_master, int sock, int accept); hunk ./libsofia-sip-ua/tport/tport_type_tls.c 97 -#if notyet -static void tport_tls_deliver(tport_t *self, msg_t *msg, su_time_t now); -#endif hunk ./libsofia-sip-ua/tport/tport_type_tls.c 246 - if (accepted) { - tlstp->tlstp_context = tls_init_slave(master, socket); - if (!tlstp->tlstp_context) - return *return_reason = "tls_init_slave", -1; - } + tlstp->tlstp_context = tls_init_secondary(master, socket, accepted); + if (!tlstp->tlstp_context) + return *return_reason = "tls_init_slave", -1; hunk ./libsofia-sip-ua/tport/tport_type_tls.c 436 - tport_tls_primary_t *tlspri = (tport_tls_primary_t *)self->tp_pri; hunk ./libsofia-sip-ua/tport/tport_type_tls.c 442 - if (tlstp->tlstp_context == NULL) { - tls_t *master = tlspri->tlspri_master; - tlstp->tlstp_context = tls_init_client(master, self->tp_socket); - if (!tlstp->tlstp_context) - return -1; - } - hunk ./libsofia-sip-ua/tport/tport_type_tls.c 549 - tport_tls_t *tlstp = (tport_tls_t *)self; - tport_tls_primary_t *tlspri = (tport_tls_primary_t *)self->tp_pri; hunk ./libsofia-sip-ua/tport/tport_type_tls.c 562 - tlstp->tlstp_context = tls_init_slave(tlspri->tlspri_master, s); - hunk ./libsofia-sip-ua/tport/tport_type_tls.c 625 - if (tport_setname(self, tpn->tpn_proto, ai, tpn->tpn_canon) != -1 - && - tport_register_secondary(self, tls_connect, events) != -1) { - tport_tls_t *tlstp = (tport_tls_t *)self; - tport_tls_primary_t *tlspri = (tport_tls_primary_t *)self->tp_pri; - tlstp->tlstp_context = tls_init_client(tlspri->tlspri_master, s); - } - else + if (tport_setname(self, tpn->tpn_proto, ai, tpn->tpn_canon) == -1) + goto sys_error; + else if (tport_register_secondary(self, tls_connect, events) == -1) hunk ./libsofia-sip-ua/tport/tport_type_tls.c 629 + else if (tpn->tpn_subject) { + self->tp_name->tpn_subject = su_strdup(self->tp_home, tpn->tpn_subject); + if (!self->tp_name->tpn_subject) + goto sys_error; + } } Context: [tport_type_tls.c: no tport_tls_deliver() yet Pekka Pessi <first.l...@nokia.com>**20090105124324] [tport_tls.c: silences warnings on signedness Pekka Pessi <first.l...@nokia.com>**20090105124304] [tport_tls.c: su_home_new() already zeros the allocated memory Pekka Pessi <first.l...@nokia.com>**20090105124209] [nua_session.c: default to initiate session refreshes Pekka Pessi <first.l...@nokia.com>**20090105123112 Use local refresher unless remote end explicitly indicates that it takes care of refreshing the session. Bug reported and initial patch by Timo Bruhn. ] [RELEASE: added Jarod's description of TLS improvements Pekka Pessi <first.l...@nokia.com>**20090105102201] [su_kqueue_port.c: explicit cast from int to (void *) Michael Jerris <m...@jerris.com>**20090105100939 Fix silly compiler warning caused by freebsd not making int same size as void* on some 64 bit amd (SFSIP-113). ] [tport_logging.c: do not use stamp as format string Pekka Pessi <first.l...@nokia.com>**20081219165102 Original patch by Mike Jerris. ] [nta.c: be consistent with maxsize and max_proceeding types Pekka Pessi <first.l...@nokia.com>**20081219143853 Original patch by Mike Jerris ] [su_alloc.c: always unlock home before destroying mutexes Pekka Pessi <first.l...@nokia.com>**20081215151620] [sresolv: made sres_record_class static Pekka Pessi <first.l...@nokia.com>**20081215165706 Should never been global. ] [test_nua.c: made usage static Pekka Pessi <first.l...@nokia.com>**20081215164317] [RELEASE: mention removed globals Pekka Pessi <first.l...@nokia.com>**20081215165436] [sofia-resolv/sres_cache.h: added prototype for sres_cache_clean() Pekka Pessi <first.l...@nokia.com>**20081215165021] [sofia-sip/heap.h: added protype for su_smoothsort() Pekka Pessi <first.l...@nokia.com>**20081215163340] [su_tag.h: added prototype for tl_vllen() Pekka Pessi <first.l...@nokia.com>**20081215163316] [su_tag_class.h: added prototypes for tag functions Pekka Pessi <first.l...@nokia.com>**20081215163255 Protypes for t_filter(), t_null_filter(), t_end_filter(), t_socket_snprintf(), t_socket_ref_set() have been missing. ] [Early TLS Handshake and Verification Jarod Neuner <janeu...@networkharbor.com>**20081216221937 tport_type_tls.c: * tport_tls_accept(): - Replaces tport_accept for incoming TLS connections. * tport_tls_connect(): - Replaces tport_base_connect() for outgoing TLS connections. tport_tls.c: * tls_t now use a memory home instead of malloc. * removed tls_check_hosts() * tls_connect(): - Replaces tport_base_connect for TLS connection setup. - Completes TLS handshake and verifies peer certificates. - Destroys suspect TLS connections before sending/receiving payload. - Populates a su_strlst_t with subjects from the peer certificate. tport.c: * tport_is_verified() - true if peer certificate validated successfully * tport_delivered_from_subjects() - Certificate subjects listed in the peer certificate. ] [Helper functions for vtp_connect and vtp_wakeup_pri. Jarod Neuner <janeu...@networkharbor.com>**20081216175826 - Expose tport_setname() and tport_wakeup() via tport_internal.h - Add tport_register_secondary() for adding secondaries to a root, and to alleviate the need to export tprb_append. ] [nta: NULL host and port in user Via are filled automaticaly Stas Maximov <smaxi...@ieee.org>**20081215143145 NULL host or port in user-supplied Via header will be filled automaticaly by NTA, just like branch and rport params. Added related test case to test_nta_api.c. ] [su_taglist.c. removed globals which should have been static in first place Pekka Pessi <first.l...@nokia.com>**20081211173213 - t_null_next(), t_null_move(), t_null_dup(), t_null_copy(), t_null_find() - t_skip_next(), t_skip_move(), t_skip_len(), t_skip_dup(), t_skip_filter() - t_next_next(), t_next_move(), t_next_len(), t_next_dup(), t_next_filter() ] [su: removed private functions accidentally declared as globals Pekka Pessi <first.l...@nokia.com>**20081208145904 su_t64_to_time(), mutex_trylocker(), su_port_set_system_preferences() ] [sofia-sip/su_uniqueid.h: proper prototype for su_random() Pekka Pessi <first.l...@nokia.com>**20081211173249] [su/addrinfo.c, su/localinfo.c: made usage() static Pekka Pessi <first.l...@nokia.com>**20081211173029 Make -Wmissing-prototypes happy. ] [sdp_print.c: print sdptl in lowercase, too Pekka Pessi <first.l...@nokia.com>**20081211120209] [RELEASE, configure.ac: opening development head Pekka Pessi <first.l...@nokia.com>**20081209171108] [TAG rel-sofia-sip-1_12_10 Pekka Pessi <first.l...@nokia.com>**20081209122326] Patch bundle hash: 176dd7a52efc58a954df69dcfada23aaf201a917
------------------------------------------------------------------------------
_______________________________________________ Sofia-sip-devel mailing list Sofia-sip-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sofia-sip-devel