mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-24 03:47:39 +00:00
Thu Jan 15 09:50:45 CST 2009 Jarod Neuner <janeuner@networkharbor.com>
* TLS Subject Checking in tport sofia-sip/tport.h: * tport_delivered_from_subjects() returns type (su_strlst_t const *) * Export tport_subject_search() sofia-sip/tport_tag.h + tport_tag.c: * Remove TPTAG_TLS_VERIFY_PEER() - Depreciated. Use TPTAG_TLS_VERIFY_POLICY instead. - Binary Compatibility is preserved. * Add TPTAG_TLS_VERIFY_POLICY() - tport can verify incoming and/or outgoing connections, using: 1) Certificate Signatures only - or - 2) Certificate Signatures and Certificate Subjects * Add TPTAG_TLS_VERIFY_DEPTH() - Restrict certificate chain verification to a set length. * Add TPTAG_TLS_VERIFY_DATE() - Disable notBefore/notAfter checking (application: embedded devices) * Add TPTAG_TLS_VERIFY_SUBJECTS() - Incoming connections must present client certificates with subjects that match an item in this list. - Intended Use: Proxy Authentication * Replaced TPTAG_TRUSTED() with TPTAG_X509_SUBJECT() - Commented out for future use. - Intended Use: SIP User Identities in Server Certificates. * Add appropriate doxygen documentation. tport.c * Add tport_subject_search() - Subject can be a hostname, IP Address, or a URI. - Valid subject examples include: example.com alice@example.com sip:alice@example.com sips:alice@example.com * tport_by_addrinfo() matches tpn_canon against the subject list of reusable TLS connections. tport_tls.h: * Add tls_init_secondary() * Remove tls_init_slave() & tls_init_client() tport_tls.c: * tls_verify_cb() supports TPTAG_TLS_VERIFY_DATE() * tls_post_connection_check() verifies certificate subjects. * 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. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11830 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
27a5a679be
commit
38dabb3635
@ -1 +1 @@
|
|||||||
Wed Feb 11 11:03:24 CST 2009
|
Wed Feb 11 11:03:50 CST 2009
|
||||||
|
@ -339,7 +339,11 @@ TPORT_DLL int tport_delivered_from(tport_t *tp, msg_t const *msg,
|
|||||||
tp_name_t name[1]);
|
tp_name_t name[1]);
|
||||||
|
|
||||||
/** Return TLS Subjects provided by the source transport */
|
/** Return TLS Subjects provided by the source transport */
|
||||||
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 *);
|
||||||
|
|
||||||
/** Check if transport named is already resolved */
|
/** Check if transport named is already resolved */
|
||||||
TPORT_DLL int tport_name_is_resolved(tp_name_t const *);
|
TPORT_DLL int tport_name_is_resolved(tp_name_t const *);
|
||||||
|
@ -186,18 +186,59 @@ TPORT_DLL extern tag_typedef_t tptag_tls_version;
|
|||||||
TPORT_DLL extern tag_typedef_t tptag_tls_version_ref;
|
TPORT_DLL extern tag_typedef_t tptag_tls_version_ref;
|
||||||
#define TPTAG_TLS_VERSION_REF(x) tptag_tls_version_ref, tag_uint_vr(&(x))
|
#define TPTAG_TLS_VERSION_REF(x) tptag_tls_version_ref, tag_uint_vr(&(x))
|
||||||
|
|
||||||
|
enum tport_tls_verify_policy {
|
||||||
|
TPTLS_VERIFY_NONE = 0x0,
|
||||||
|
TPTLS_VERIFY_INCOMING = 0x1,
|
||||||
|
TPTLS_VERIFY_IN = 0x1,
|
||||||
|
TPTLS_VERIFY_OUTGOING = 0x2,
|
||||||
|
TPTLS_VERIFY_OUT = 0x2,
|
||||||
|
TPTLS_VERIFY_ALL = 0x3,
|
||||||
|
TPTLS_VERIFY_SUBJECTS_IN = 0x5, /* 0x4 | TPTLS_VERIFY_INCOMING */
|
||||||
|
TPTLS_VERIFY_SUBJECTS_OUT = 0xA, /* 0x8 | TPTLS_VERIFY_OUTGOING */
|
||||||
|
TPTLS_VERIFY_SUBJECTS_ALL = 0xF,
|
||||||
|
};
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_policy;
|
||||||
|
#define TPTAG_TLS_VERIFY_POLICY(x) tptag_tls_verify_policy, tag_uint_v((x))
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_policy_ref;
|
||||||
|
#define TPTAG_TLS_VERIFY_POLICY_REF(x) tptag_tls_verify_policy_ref, tag_uint_vr(&(x))
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_depth;
|
||||||
|
#define TPTAG_TLS_VERIFY_DEPTH(x) tptag_tls_verify_depth, tag_uint_v((x))
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_depth_ref;
|
||||||
|
#define TPTAG_TLS_VERIFY_DEPTH_REF(x) \
|
||||||
|
tptag_tls_verify_depth_ref, tag_uint_vr(&(x))
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_date;
|
||||||
|
#define TPTAG_TLS_VERIFY_DATE(x) tptag_tls_verify_date, tag_uint_v((x))
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_date_ref;
|
||||||
|
#define TPTAG_TLS_VERIFY_DATE_REF(x) \
|
||||||
|
tptag_tls_verify_date_ref, tag_uint_vr(&(x))
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_subjects;
|
||||||
|
#define TPTAG_TLS_VERIFY_SUBJECTS(x) tptag_tls_verify_subjects, tag_cptr_v((x))
|
||||||
|
|
||||||
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_subjects_ref;
|
||||||
|
#define TPTAG_TLS_VERIFY_SUBJECTS_REF(x) \
|
||||||
|
tptag_tls_verify_subjects_ref, tag_cptr_vr(&(x), (x))
|
||||||
|
|
||||||
|
/* TPTAG_TLS_VERIFY_PEER is depreciated - Use TPTAG_TLS_VERIFY_POLICY */
|
||||||
TPORT_DLL extern tag_typedef_t tptag_tls_verify_peer;
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_peer;
|
||||||
#define TPTAG_TLS_VERIFY_PEER(x) tptag_tls_verify_peer, tag_uint_v((x))
|
#define TPTAG_TLS_VERIFY_PEER(x) TPTAG_TLS_VERIFY_POLICY( (x) ? \
|
||||||
|
TPTLS_VERIFY_ALL : TPTLS_VERIFY_NONE)
|
||||||
|
|
||||||
TPORT_DLL extern tag_typedef_t tptag_tls_verify_peer_ref;
|
TPORT_DLL extern tag_typedef_t tptag_tls_verify_peer_ref;
|
||||||
#define TPTAG_TLS_VERIFY_PEER_REF(x) tptag_tls_verify_peer_ref, tag_uint_vr(&(x))
|
#define TPTAG_TLS_VERIFY_PEER_REF(x) tptag_tls_verify_peer_ref, tag_uint_vr(&(x))
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
TPORT_DLL extern tag_typedef_t tptag_trusted;
|
TPORT_DLL extern tag_typedef_t tport_x509_subject;
|
||||||
#define TPTAG_TRUSTED(x) tptag_trusted, tag_bool_v((x))
|
#define TPTAG_X509_SUBJECT(x) tptag_x509_subject, tag_str_v((x))
|
||||||
|
|
||||||
TPORT_DLL extern tag_typedef_t tptag_trusted_ref;
|
TPORT_DLL extern tag_typedef_t tptag_x509_subject_ref;
|
||||||
#define TPTAG_TRUSTED_REF(x) tptag_trusted_ref, tag_bool_vr(&(x))
|
#define TPTAG_X509_SUBJECT_REF(x) tptag_x509_subject_ref, tag_str_vr(&(x))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TPORT_DLL extern tag_typedef_t tptag_debug_drop;
|
TPORT_DLL extern tag_typedef_t tptag_debug_drop;
|
||||||
|
@ -273,7 +273,7 @@ int tport_has_tls(tport_t const *self)
|
|||||||
/** Return true if transport certificate verified successfully */
|
/** Return true if transport certificate verified successfully */
|
||||||
int tport_is_verified(tport_t const *self)
|
int tport_is_verified(tport_t const *self)
|
||||||
{
|
{
|
||||||
return tport_has_tls(self) && self->tp_verified;
|
return tport_has_tls(self) && self->tp_is_connected && self->tp_verified;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return true if transport is being updated. */
|
/** Return true if transport is being updated. */
|
||||||
@ -1465,8 +1465,8 @@ int tport_bind_set(tport_master_t *mr,
|
|||||||
*
|
*
|
||||||
* @TAGS
|
* @TAGS
|
||||||
* TPTAG_SERVER(), TPTAG_PUBLIC(), TPTAG_IDENT(), TPTAG_HTTP_CONNECT(),
|
* TPTAG_SERVER(), TPTAG_PUBLIC(), TPTAG_IDENT(), TPTAG_HTTP_CONNECT(),
|
||||||
* TPTAG_CERTIFICATE(), TPTAG_TLS_VERSION(), TPTAG_TLS_VERIFY_PEER, and tags used with
|
* TPTAG_CERTIFICATE(), TPTAG_TLS_VERSION(), TPTAG_TLS_VERIFY_POLICY, and
|
||||||
* tport_set_params(), especially TPTAG_QUEUESIZE().
|
* tags used with tport_set_params(), especially TPTAG_QUEUESIZE().
|
||||||
*/
|
*/
|
||||||
int tport_tbind(tport_t *self,
|
int tport_tbind(tport_t *self,
|
||||||
tp_name_t const *tpn,
|
tp_name_t const *tpn,
|
||||||
@ -3045,7 +3045,7 @@ int tport_delivered_from(tport_t *tp, msg_t const *msg, tp_name_t name[1])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Return TLS Subjects provided by the source transport */
|
/** Return TLS Subjects provided by the source transport */
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (tp && msg && msg == tp->tp_master->mr_delivery->d_msg) {
|
if (tp && msg && msg == tp->tp_master->mr_delivery->d_msg) {
|
||||||
tport_t *tp_sec = tp->tp_master->mr_delivery->d_tport;
|
tport_t *tp_sec = tp->tp_master->mr_delivery->d_tport;
|
||||||
@ -3069,6 +3069,57 @@ tport_delivered_with_comp(tport_t *tp, msg_t const *msg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Search for subject in list of TLS Certificate subjects */
|
||||||
|
int
|
||||||
|
tport_subject_search(char const *subject, su_strlst_t const *lst)
|
||||||
|
{
|
||||||
|
int idx, ilen;
|
||||||
|
const char *subjuri;
|
||||||
|
|
||||||
|
if (!subject || su_strmatch(tpn_any, subject))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!lst)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check if subject is a URI */
|
||||||
|
if (su_casenmatch(subject,"sip:",4) || su_casenmatch(subject,"sips:",5))
|
||||||
|
subjuri = subject + su_strncspn(subject,5,":") + 1;
|
||||||
|
else
|
||||||
|
subjuri = NULL;
|
||||||
|
|
||||||
|
ilen = su_strlst_len(lst);
|
||||||
|
|
||||||
|
for (idx = 0; idx < ilen; idx++) {
|
||||||
|
const char *lsturi, *lststr;
|
||||||
|
|
||||||
|
lststr = su_strlst_item(lst, idx);
|
||||||
|
|
||||||
|
/* check if lststr is a URI (sips URI is an unacceptable cert subject) */
|
||||||
|
if (su_casenmatch(lststr,"sip:",4))
|
||||||
|
lsturi = lststr + su_strncspn(lststr,4,":") + 1;
|
||||||
|
else
|
||||||
|
lsturi = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Match two SIP Server Identities */
|
||||||
|
if (host_cmp(subjuri ? subjuri : subject, lsturi ? lsturi : lststr) == 0)
|
||||||
|
return 1;
|
||||||
|
#if 0
|
||||||
|
/* XXX - IETF drafts forbid wildcard certs */
|
||||||
|
if (!subjuri && !lsturi && su_strnmatch("*.", lststr, 2)) {
|
||||||
|
size_t urioffset = su_strncspn(subject, 64, ".");
|
||||||
|
if (urioffset) {
|
||||||
|
if (su_casematch(subject + urioffset, lststr+1))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Allocate message for N bytes,
|
/** Allocate message for N bytes,
|
||||||
* return message buffer as a iovec
|
* return message buffer as a iovec
|
||||||
*/
|
*/
|
||||||
@ -3152,7 +3203,7 @@ int tport_recv_error_report(tport_t *self)
|
|||||||
*
|
*
|
||||||
* @TAGS
|
* @TAGS
|
||||||
* TPTAG_MTU(), TPTAG_REUSE(), TPTAG_CLOSE_AFTER(), TPTAG_SDWN_AFTER(),
|
* TPTAG_MTU(), TPTAG_REUSE(), TPTAG_CLOSE_AFTER(), TPTAG_SDWN_AFTER(),
|
||||||
* TPTAG_FRESH(), TPTAG_COMPARTMENT().
|
* TPTAG_FRESH(), TPTAG_COMPARTMENT(), TPTAG_X509_SUBJECT()
|
||||||
*/
|
*/
|
||||||
tport_t *tport_tsend(tport_t *self,
|
tport_t *tport_tsend(tport_t *self,
|
||||||
msg_t *msg,
|
msg_t *msg,
|
||||||
@ -4581,6 +4632,13 @@ tport_t *tport_by_addrinfo(tport_primary_t const *pri,
|
|||||||
if (tport_is_shutdown(sub))
|
if (tport_is_shutdown(sub))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (tport_has_tls(sub) && !su_casematch(tpn->tpn_canon, sub->tp_name->tpn_canon)) {
|
||||||
|
if (!tport_is_verified(sub))
|
||||||
|
continue;
|
||||||
|
if (!tport_subject_search(tpn->tpn_canon, sub->tp_subjects))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (comp != sub->tp_name->tpn_comp)
|
if (comp != sub->tp_name->tpn_comp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -181,8 +181,10 @@ struct tport_s {
|
|||||||
|
|
||||||
su_strlst_t *tp_subjects; /**< Transport Subjects.
|
su_strlst_t *tp_subjects; /**< Transport Subjects.
|
||||||
*
|
*
|
||||||
* Subject Name(s) provided by the
|
* Subject Name(s) provided by the peer
|
||||||
* peer in a TLS connection (if secondary).
|
* in a TLS connection (if secondary).
|
||||||
|
* or matched against incoming
|
||||||
|
* connections (if primary).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define tp_protoname tp_name->tpn_proto
|
#define tp_protoname tp_name->tpn_proto
|
||||||
|
@ -281,21 +281,138 @@ tag_typedef_t tptag_compartment = PTRTAG_TYPEDEF(compartment);
|
|||||||
tag_typedef_t tptag_tls_version = UINTTAG_TYPEDEF(tls_version);
|
tag_typedef_t tptag_tls_version = UINTTAG_TYPEDEF(tls_version);
|
||||||
|
|
||||||
/**@def TPTAG_TLS_VERIFY_PEER(x)
|
/**@def TPTAG_TLS_VERIFY_PEER(x)
|
||||||
*
|
* @par Depreciated:
|
||||||
* The verification of certificates can be controlled:
|
* Alias for TPTAG_TLS_VERIFY_POLICY(TPTLS_VERIFY_IN|TPTLS_VERIFY_OUT)
|
||||||
* 0: no verify certificates;
|
|
||||||
* 1: on server mode, the certificate returned by client is checked
|
|
||||||
* if fail the TLS/SSL handshake is immediately terminated;
|
|
||||||
* 1: on client mode, the server certificate is verified
|
|
||||||
* if fail the TLS/SSL handshake is immediately terminated;
|
|
||||||
*
|
|
||||||
* Use with tport_tbind(), nua_create(), nta_agent_create(),
|
|
||||||
* nta_agent_add_tport(), nth_engine_create(), or initial nth_site_create().
|
|
||||||
*
|
*
|
||||||
* @NEW_1_12_10.
|
* @NEW_1_12_10.
|
||||||
*/
|
*/
|
||||||
tag_typedef_t tptag_tls_verify_peer = UINTTAG_TYPEDEF(tls_verify_peer);
|
tag_typedef_t tptag_tls_verify_peer = UINTTAG_TYPEDEF(tls_verify_peer);
|
||||||
|
|
||||||
|
/**@def TPTAG_TLS_VERIFY_POLICY(x)
|
||||||
|
*
|
||||||
|
* The verification of certificates can be controlled:
|
||||||
|
* @par Values:
|
||||||
|
* - #TPTLS_VERIFY_NONE:
|
||||||
|
* Do not verify Peer Certificates.
|
||||||
|
* - #TPTLS_VERIFY_IN:
|
||||||
|
* Drop incoming connections which fail signature verification
|
||||||
|
* against trusted certificate authorities. Peers must provide a
|
||||||
|
* certificate during the initial TLS Handshake.
|
||||||
|
* - #TPTLS_VERIFY_OUT:
|
||||||
|
* Drop outgoing connections which fail signature verification
|
||||||
|
* against trusted certificate authorities.
|
||||||
|
* - #TPTLS_VERIFY_ALL:
|
||||||
|
* Alias for (TPTLS_VERIFY_IN|TPTLS_VERIFY_OUT)
|
||||||
|
* - #TPTLS_VERIFY_SUBJECTS_IN:
|
||||||
|
* Match the certificate subject on incoming connections against
|
||||||
|
* a provided list. If no match is found, the connection is
|
||||||
|
* rejected. If no list is provided, subject checking is bypassed.
|
||||||
|
* Note: Implies #TPTLS_VERIFY_IN.
|
||||||
|
* - #TPTLS_VERIFY_SUBJECTS_OUT:
|
||||||
|
* Match the certificate subject on outgoing connections against
|
||||||
|
* a provided list. If no match is found, the connection is
|
||||||
|
* rejected.
|
||||||
|
* Note: Implies #TPTLS_VERIFY_OUT.
|
||||||
|
* - #TPTLS_VERIFY_SUBJECTS_ALL:
|
||||||
|
* Alias for (TPTLS_VERIFY_SUBJECTS_IN|TPTLS_VERIFY_SUBJECTS_OUT)
|
||||||
|
*
|
||||||
|
* @par Used with
|
||||||
|
* tport_tbind(), nua_create(), nta_agent_create(), nta_agent_add_tport(),
|
||||||
|
* nth_engine_create(), initial nth_site_create(),
|
||||||
|
* TPTAG_TLS_VERIFY_SUBJECTS(), TPTAG_TLS_VERIFY_DEPTH().
|
||||||
|
*
|
||||||
|
* @NEW_1_12_11.
|
||||||
|
*/
|
||||||
|
tag_typedef_t tptag_tls_verify_policy = UINTTAG_TYPEDEF(tls_verify_policy);
|
||||||
|
|
||||||
|
/**@def TPTAG_TLS_VERIFY_DEPTH(x)
|
||||||
|
*
|
||||||
|
* Define the maximum length of a valid certificate chain.
|
||||||
|
*
|
||||||
|
* @par Default
|
||||||
|
* 2
|
||||||
|
*
|
||||||
|
* @par Used with
|
||||||
|
* tport_tbind(), nua_create(), nta_agent_create(), nta_agent_add_tport(),
|
||||||
|
* nth_engine_create(), or initial nth_site_create().
|
||||||
|
*
|
||||||
|
* @par Parameter Type:
|
||||||
|
* unsigned int
|
||||||
|
*
|
||||||
|
* @NEW_1_12_11.
|
||||||
|
*/
|
||||||
|
tag_typedef_t tptag_tls_verify_depth = UINTTAG_TYPEDEF(tls_verify_depth);
|
||||||
|
|
||||||
|
/**@def TPTAG_TLS_VERIFY_DATE(x)
|
||||||
|
*
|
||||||
|
* Enable/Disable verification of notBefore and notAfter parameters of
|
||||||
|
* X.509 Certificates.
|
||||||
|
*
|
||||||
|
* @par Default
|
||||||
|
* Enabled
|
||||||
|
*
|
||||||
|
* @par Values
|
||||||
|
* - 0 - Disable date verification.
|
||||||
|
* - Non-Zero - Enable date verification.
|
||||||
|
*
|
||||||
|
* @par Used with
|
||||||
|
* tport_tbind(), nua_create(), nta_agent_create(), nta_agent_add_tport(),
|
||||||
|
* nth_engine_create(), or initial nth_site_create().
|
||||||
|
*
|
||||||
|
* @par Parameter Type:
|
||||||
|
* unsigned int
|
||||||
|
*
|
||||||
|
* @par Note
|
||||||
|
* This tag should be only used on devices which lack accurate timekeeping.
|
||||||
|
*
|
||||||
|
* @NEW_1_12_11.
|
||||||
|
*/
|
||||||
|
tag_typedef_t tptag_tls_verify_date = UINTTAG_TYPEDEF(tls_verify_date);
|
||||||
|
|
||||||
|
/**@def TPTAG_TLS_VERIFY_SUBJECTS(x)
|
||||||
|
*
|
||||||
|
* Incoming TLS connections must provide a trusted X.509 certificate.
|
||||||
|
* The character strings provided with this tag are matched against
|
||||||
|
* the subjects from the trusted certificate. If a match is not found,
|
||||||
|
* the connection is automatically rejected.
|
||||||
|
*
|
||||||
|
* @par Used with
|
||||||
|
* tport_tbind(), nua_create(), nta_agent_create(), nta_agent_add_tport(),
|
||||||
|
* nth_engine_create(), initial nth_site_create(),
|
||||||
|
* TPTLS_VERIFY_SUBJECTS_IN
|
||||||
|
*
|
||||||
|
* @par Parameter Type:
|
||||||
|
* void const * (actually su_strlst_t const *)
|
||||||
|
*
|
||||||
|
* @par Values
|
||||||
|
* - SIP Identity - sip:example.com or sip:username@example.com
|
||||||
|
* - DNS - sip.example.com
|
||||||
|
* - IP Address - Both IPv4 and IPv6 Supported
|
||||||
|
*
|
||||||
|
* @NEW_1_12_11.
|
||||||
|
*/
|
||||||
|
tag_typedef_t tptag_tls_verify_subjects = PTRTAG_TYPEDEF(tls_verify_subjects);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/**@def TPTAG_X509_SUBJECT(x)
|
||||||
|
*
|
||||||
|
* Requires that a message be sent over a TLS transport with trusted X.509
|
||||||
|
* certificate. The character string provided must match against a subject
|
||||||
|
* from the trusted certificate.
|
||||||
|
*
|
||||||
|
* @par Used with
|
||||||
|
* tport_tsend(), TPTLS_VERIFY_SUBJECTS_OUT
|
||||||
|
*
|
||||||
|
* @par Parameter Type:
|
||||||
|
* char const *
|
||||||
|
*
|
||||||
|
* @par Values
|
||||||
|
* - Refer to TPTAG_TLS_VERIFY_SUBJECTS()
|
||||||
|
*
|
||||||
|
* @note Not Implemented.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
/**@def TPTAG_QUEUESIZE(x)
|
/**@def TPTAG_QUEUESIZE(x)
|
||||||
*
|
*
|
||||||
* Specify the number of messages that can be queued per connection.
|
* Specify the number of messages that can be queued per connection.
|
||||||
|
@ -56,7 +56,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if HAVE_SIGPIPE
|
#if HAVE_SIGPIPE
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -65,6 +64,7 @@
|
|||||||
#include "tport_tls.h"
|
#include "tport_tls.h"
|
||||||
|
|
||||||
char const tls_version[] = OPENSSL_VERSION_TEXT;
|
char const tls_version[] = OPENSSL_VERSION_TEXT;
|
||||||
|
int tls_ex_data_idx = -1; /* see SSL_get_ex_new_index(3ssl) */
|
||||||
|
|
||||||
enum { tls_master = 0, tls_slave = 1};
|
enum { tls_master = 0, tls_slave = 1};
|
||||||
|
|
||||||
@ -75,9 +75,12 @@ struct tls_s {
|
|||||||
BIO *bio_con;
|
BIO *bio_con;
|
||||||
unsigned int type:1,
|
unsigned int type:1,
|
||||||
accept:1,
|
accept:1,
|
||||||
verify_outgoing:1,
|
|
||||||
verify_incoming:1,
|
verify_incoming:1,
|
||||||
verified:1;
|
verify_outgoing:1,
|
||||||
|
verify_subj_in:1,
|
||||||
|
verify_subj_out:1,
|
||||||
|
verify_date:1,
|
||||||
|
x509_verified:1;
|
||||||
|
|
||||||
/* Receiving */
|
/* Receiving */
|
||||||
int read_events;
|
int read_events;
|
||||||
@ -90,7 +93,7 @@ struct tls_s {
|
|||||||
size_t write_buffer_len;
|
size_t write_buffer_len;
|
||||||
|
|
||||||
/* Host names */
|
/* Host names */
|
||||||
su_strlst_t *subject;
|
su_strlst_t *subjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { tls_buffer_size = 16384 };
|
enum { tls_buffer_size = 16384 };
|
||||||
@ -162,13 +165,44 @@ int tls_verify_cb(int ok, X509_STORE_CTX *store)
|
|||||||
X509 *cert = X509_STORE_CTX_get_current_cert(store);
|
X509 *cert = X509_STORE_CTX_get_current_cert(store);
|
||||||
int depth = X509_STORE_CTX_get_error_depth(store);
|
int depth = X509_STORE_CTX_get_error_depth(store);
|
||||||
int err = X509_STORE_CTX_get_error(store);
|
int err = X509_STORE_CTX_get_error(store);
|
||||||
|
int sslidx = SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||||
|
SSL *ssl = X509_STORE_CTX_get_ex_data(store, sslidx);
|
||||||
|
tls_t *tls = SSL_get_ex_data(ssl, tls_ex_data_idx);
|
||||||
|
|
||||||
SU_DEBUG_1(("-Error with certificate at depth: %i\n", depth));
|
assert(tls);
|
||||||
|
|
||||||
|
#define TLS_VERIFY_CB_CLEAR_ERROR(OK,ERR,STORE) \
|
||||||
|
do {\
|
||||||
|
OK = 1;\
|
||||||
|
ERR = X509_V_OK;\
|
||||||
|
X509_STORE_CTX_set_error(STORE,ERR);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
if (tls->accept && !tls->verify_incoming)
|
||||||
|
TLS_VERIFY_CB_CLEAR_ERROR(ok, err, store);
|
||||||
|
else if (!tls->accept && !tls->verify_outgoing)
|
||||||
|
TLS_VERIFY_CB_CLEAR_ERROR(ok, err, store);
|
||||||
|
else switch (err) {
|
||||||
|
case X509_V_ERR_CERT_NOT_YET_VALID:
|
||||||
|
case X509_V_ERR_CERT_HAS_EXPIRED:
|
||||||
|
case X509_V_ERR_CRL_NOT_YET_VALID:
|
||||||
|
case X509_V_ERR_CRL_HAS_EXPIRED:
|
||||||
|
if (!tls->verify_date)
|
||||||
|
TLS_VERIFY_CB_CLEAR_ERROR(ok, err, store);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
SU_DEBUG_3(("-Error with certificate at depth: %i\n", depth));
|
||||||
X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
|
X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
|
||||||
SU_DEBUG_1((" issuer = %s\n", data));
|
SU_DEBUG_3((" issuer = %s\n", data));
|
||||||
X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
|
X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
|
||||||
SU_DEBUG_1((" subject = %s\n", data));
|
SU_DEBUG_3((" subject = %s\n", data));
|
||||||
SU_DEBUG_1((" err %i:%s\n", err, X509_verify_cert_error_string(err)));
|
SU_DEBUG_3((" err %i:%s\n", err, X509_verify_cert_error_string(err)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
@ -178,11 +212,14 @@ static
|
|||||||
int tls_init_context(tls_t *tls, tls_issues_t const *ti)
|
int tls_init_context(tls_t *tls, tls_issues_t const *ti)
|
||||||
{
|
{
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
int verify;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
|
tls_ex_data_idx = SSL_get_ex_new_index(0, \
|
||||||
|
"sofia-sip private data", NULL, NULL, NULL);
|
||||||
|
|
||||||
if (ti->randFile &&
|
if (ti->randFile &&
|
||||||
!RAND_load_file(ti->randFile, 1024 * 1024)) {
|
!RAND_load_file(ti->randFile, 1024 * 1024)) {
|
||||||
@ -267,13 +304,20 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* corresponds to (enum tport_tls_verify_policy) */
|
||||||
|
tls->verify_incoming = (ti->policy & 0x1) ? 1 : 0;
|
||||||
|
tls->verify_outgoing = (ti->policy & 0x2) ? 1 : 0;
|
||||||
|
tls->verify_subj_in = (ti->policy & 0x4) ? tls->verify_incoming : 0;
|
||||||
|
tls->verify_subj_out = (ti->policy & 0x8) ? tls->verify_outgoing : 0;
|
||||||
|
tls->verify_date = (ti->verify_date) ? 1 : 0;
|
||||||
|
|
||||||
|
if (tls->verify_incoming)
|
||||||
|
verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||||
|
else
|
||||||
|
verify = SSL_VERIFY_NONE;
|
||||||
|
|
||||||
SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth);
|
SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth);
|
||||||
|
SSL_CTX_set_verify(tls->ctx, verify, tls_verify_cb);
|
||||||
SSL_CTX_set_verify(tls->ctx,
|
|
||||||
ti->verify_peer == 1 ? SSL_VERIFY_PEER : SSL_VERIFY_NONE,
|
|
||||||
tls_verify_cb);
|
|
||||||
|
|
||||||
tls->verify_incoming = tls->verify_outgoing = ti->verify_peer ? 1 : 0;
|
|
||||||
|
|
||||||
if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) {
|
if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) {
|
||||||
SU_DEBUG_1(("%s: error setting cipher list\n", "tls_init_context"));
|
SU_DEBUG_1(("%s: error setting cipher list\n", "tls_init_context"));
|
||||||
@ -360,13 +404,20 @@ tls_t *tls_init_master(tls_issues_t *ti)
|
|||||||
return tls;
|
return tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_t *tls_clone(tls_t *master, int sock, int accept)
|
tls_t *tls_init_secondary(tls_t *master, int sock, int accept)
|
||||||
{
|
{
|
||||||
tls_t *tls = tls_create(tls_slave);
|
tls_t *tls = tls_create(tls_slave);
|
||||||
|
|
||||||
if (tls) {
|
if (tls) {
|
||||||
tls->ctx = master->ctx;
|
tls->ctx = master->ctx;
|
||||||
|
tls->type = master->type;
|
||||||
tls->accept = accept ? 1 : 0;
|
tls->accept = accept ? 1 : 0;
|
||||||
|
tls->verify_outgoing = master->verify_outgoing;
|
||||||
|
tls->verify_incoming = master->verify_incoming;
|
||||||
|
tls->verify_subj_out = master->verify_subj_out;
|
||||||
|
tls->verify_subj_in = master->verify_subj_in;
|
||||||
|
tls->verify_date = master->verify_date;
|
||||||
|
tls->x509_verified = master->x509_verified;
|
||||||
|
|
||||||
if (!(tls->read_buffer = su_alloc(tls->home, tls_buffer_size)))
|
if (!(tls->read_buffer = su_alloc(tls->home, tls_buffer_size)))
|
||||||
su_home_unref(tls->home), tls = NULL;
|
su_home_unref(tls->home), tls = NULL;
|
||||||
@ -380,7 +431,7 @@ tls_t *tls_clone(tls_t *master, int sock, int accept)
|
|||||||
tls->con = SSL_new(tls->ctx);
|
tls->con = SSL_new(tls->ctx);
|
||||||
|
|
||||||
if (tls->con == NULL) {
|
if (tls->con == NULL) {
|
||||||
tls_log_errors(1, "tls_clone", 0);
|
tls_log_errors(1, "tls_init_secondary", 0);
|
||||||
tls_free(tls);
|
tls_free(tls);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -388,26 +439,15 @@ tls_t *tls_clone(tls_t *master, int sock, int accept)
|
|||||||
|
|
||||||
SSL_set_bio(tls->con, tls->bio_con, tls->bio_con);
|
SSL_set_bio(tls->con, tls->bio_con, tls->bio_con);
|
||||||
SSL_set_mode(tls->con, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
SSL_set_mode(tls->con, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||||
|
SSL_set_ex_data(tls->con, tls_ex_data_idx, tls);
|
||||||
|
|
||||||
su_setblocking(sock, 0);
|
su_setblocking(sock, 0);
|
||||||
|
|
||||||
return tls;
|
return tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_t *tls_init_slave(tls_t *master, int sock)
|
su_inline
|
||||||
{
|
int tls_post_connection_check(tport_t *self, tls_t *tls)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
X509 *cert;
|
X509 *cert;
|
||||||
int extcount;
|
int extcount;
|
||||||
@ -416,14 +456,23 @@ int tls_post_connection_check(tls_t *tls)
|
|||||||
if (!tls) return -1;
|
if (!tls) return -1;
|
||||||
|
|
||||||
cert = SSL_get_peer_certificate(tls->con);
|
cert = SSL_get_peer_certificate(tls->con);
|
||||||
if (!cert)
|
if (!cert) {
|
||||||
|
SU_DEBUG_7(("%s(%p): Peer did not provide X.509 Certificate.\n",
|
||||||
|
__func__, 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;
|
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);
|
extcount = X509_get_ext_count(cert);
|
||||||
|
|
||||||
if (!tls->subject)
|
|
||||||
tls->subject = su_strlst_create(tls->home);
|
|
||||||
|
|
||||||
/* Find matching subjectAltName.DNS */
|
/* Find matching subjectAltName.DNS */
|
||||||
for (i = 0; i < extcount; i++) {
|
for (i = 0; i < extcount; i++) {
|
||||||
X509_EXTENSION *ext;
|
X509_EXTENSION *ext;
|
||||||
@ -446,13 +495,11 @@ int tls_post_connection_check(tls_t *tls)
|
|||||||
for (j = 0; j < sk_CONF_VALUE_num(values); j++) {
|
for (j = 0; j < sk_CONF_VALUE_num(values); j++) {
|
||||||
value = sk_CONF_VALUE_value(values, j);
|
value = sk_CONF_VALUE_value(values, j);
|
||||||
if (strcmp(value->name, "DNS") == 0)
|
if (strcmp(value->name, "DNS") == 0)
|
||||||
su_strlst_dup_append(tls->subject, value->value);
|
su_strlst_dup_append(tls->subjects, value->value);
|
||||||
else if (strcmp(value->name, "URI") == 0) {
|
if (strcmp(value->name, "IP") == 0)
|
||||||
char *uri = su_strlst_dup_append(tls->subject, value->value);
|
su_strlst_dup_append(tls->subjects, value->value);
|
||||||
char const *url = strchr(uri, ':');
|
else if (strcmp(value->name, "URI") == 0)
|
||||||
if (url++)
|
su_strlst_dup_append(tls->subjects, value->value);
|
||||||
su_strlst_append(tls->subject, url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,15 +512,15 @@ int tls_post_connection_check(tls_t *tls)
|
|||||||
if (subject) {
|
if (subject) {
|
||||||
if (X509_NAME_get_text_by_NID(subject, NID_commonName,
|
if (X509_NAME_get_text_by_NID(subject, NID_commonName,
|
||||||
name, sizeof name) > 0) {
|
name, sizeof name) > 0) {
|
||||||
usize_t k, N = su_strlst_len(tls->subject);
|
usize_t k, N = su_strlst_len(tls->subjects);
|
||||||
name[(sizeof name) - 1] = '\0';
|
name[(sizeof name) - 1] = '\0';
|
||||||
|
|
||||||
for (k = 0; k < N; k++)
|
for (k = 0; k < N; k++)
|
||||||
if (strcasecmp(su_strlst_item(tls->subject, k), name) == 0)
|
if (su_casematch(su_strlst_item(tls->subjects, k), name) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (k == N)
|
if (k >= N)
|
||||||
su_strlst_dup_append(tls->subject, name);
|
su_strlst_dup_append(tls->subjects, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -482,13 +529,64 @@ int tls_post_connection_check(tls_t *tls)
|
|||||||
|
|
||||||
error = SSL_get_verify_result(tls->con);
|
error = SSL_get_verify_result(tls->con);
|
||||||
|
|
||||||
if (error == X509_V_OK)
|
if (cert && error == X509_V_OK)
|
||||||
tls->verified = 1;
|
tls->x509_verified = 1;
|
||||||
|
|
||||||
if (tls->accept && !tls->verify_incoming)
|
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__, self, i, su_strlst_item(tls->subjects, i)));
|
||||||
|
if (i == 0)
|
||||||
|
SU_DEBUG_7(("%s(%p): Peer Certificate provided no usable subjects.\n",
|
||||||
|
__func__, self));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify incoming connections */
|
||||||
|
if (self->tp_accepted) {
|
||||||
|
if (!tls->verify_incoming)
|
||||||
return X509_V_OK;
|
return X509_V_OK;
|
||||||
else if (!tls->accept && !tls->verify_outgoing)
|
|
||||||
|
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;
|
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__, 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__, self, subject));
|
||||||
|
|
||||||
|
return X509_V_ERR_CERT_UNTRUSTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +645,7 @@ ssize_t tls_read(tls_t *tls)
|
|||||||
|
|
||||||
if (0)
|
if (0)
|
||||||
SU_DEBUG_1(("tls_read(%p) called on %s (events %u)\n", (void *)tls,
|
SU_DEBUG_1(("tls_read(%p) called on %s (events %u)\n", (void *)tls,
|
||||||
tls->accept ? "server" : "client",
|
tls->type ? "master" : "slave",
|
||||||
tls->read_events));
|
tls->read_events));
|
||||||
|
|
||||||
if (tls->read_buffer_len)
|
if (tls->read_buffer_len)
|
||||||
@ -607,7 +705,7 @@ ssize_t tls_write(tls_t *tls, void *buf, size_t size)
|
|||||||
if (0)
|
if (0)
|
||||||
SU_DEBUG_1(("tls_write(%p, %p, "MOD_ZU") called on %s\n",
|
SU_DEBUG_1(("tls_write(%p, %p, "MOD_ZU") called on %s\n",
|
||||||
(void *)tls, buf, size,
|
(void *)tls, buf, size,
|
||||||
tls && tls->type == tls_slave ? "server" : "client"));
|
tls && tls->type == tls_slave ? "master" : "slave"));
|
||||||
|
|
||||||
if (tls == NULL || buf == NULL) {
|
if (tls == NULL || buf == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@ -731,7 +829,7 @@ int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
|
|||||||
if (self->tp_is_connected == 0) {
|
if (self->tp_is_connected == 0) {
|
||||||
int ret, status;
|
int ret, status;
|
||||||
|
|
||||||
ret = tls->accept ? SSL_accept(tls->con) : SSL_connect(tls->con);
|
ret = self->tp_accepted ? SSL_accept(tls->con) : SSL_connect(tls->con);
|
||||||
status = SSL_get_error(tls->con, ret);
|
status = SSL_get_error(tls->con, ret);
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@ -751,7 +849,8 @@ int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
|
|||||||
|
|
||||||
case SSL_ERROR_NONE:
|
case SSL_ERROR_NONE:
|
||||||
/* TLS Handshake complete */
|
/* TLS Handshake complete */
|
||||||
if ( tls_post_connection_check(tls) == X509_V_OK ) {
|
status = tls_post_connection_check(self, tls);
|
||||||
|
if ( status == X509_V_OK ) {
|
||||||
su_wait_t wait[1] = {SU_WAIT_INIT};
|
su_wait_t wait[1] = {SU_WAIT_INIT};
|
||||||
tport_master_t *mr = self->tp_master;
|
tport_master_t *mr = self->tp_master;
|
||||||
|
|
||||||
@ -770,9 +869,8 @@ int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
|
|||||||
tls->read_events = SU_WAIT_IN;
|
tls->read_events = SU_WAIT_IN;
|
||||||
tls->write_events = 0;
|
tls->write_events = 0;
|
||||||
self->tp_is_connected = 1;
|
self->tp_is_connected = 1;
|
||||||
self->tp_verified = tls->verified;
|
self->tp_verified = tls->x509_verified;
|
||||||
self->tp_subjects = tls->subject == NULL ? NULL :
|
self->tp_subjects = tls->subjects;
|
||||||
su_strlst_dup(self->tp_home, tls->subject);
|
|
||||||
|
|
||||||
if (tport_has_queued(self))
|
if (tport_has_queued(self))
|
||||||
tport_send_event(self);
|
tport_send_event(self);
|
||||||
|
@ -50,9 +50,9 @@ typedef struct tls_s tls_t;
|
|||||||
extern char const tls_version[];
|
extern char const tls_version[];
|
||||||
|
|
||||||
typedef struct tls_issues_s {
|
typedef struct tls_issues_s {
|
||||||
int verify_peer; /* 0: no verify certificate, *
|
unsigned policy; /* refer to tport_tag.h, tport_tls_verify_policy */
|
||||||
* 1: if fail the TLS/SSL handshake is terminated. */
|
unsigned verify_depth;/* if 0, revert to default (2) */
|
||||||
int verify_depth; /* if 0, then do nothing */
|
unsigned verify_date; /* if 0, notBefore and notAfter dates are ignored */
|
||||||
int configured; /* If non-zero, complain about certificate errors */
|
int configured; /* If non-zero, complain about certificate errors */
|
||||||
char *cert; /* CERT file name. File format is PEM */
|
char *cert; /* CERT file name. File format is PEM */
|
||||||
char *key; /* Private key file. PEM format */
|
char *key; /* Private key file. PEM format */
|
||||||
@ -78,8 +78,7 @@ typedef struct tport_tls_primary_s {
|
|||||||
} tport_tls_primary_t;
|
} tport_tls_primary_t;
|
||||||
|
|
||||||
tls_t *tls_init_master(tls_issues_t *tls_issues);
|
tls_t *tls_init_master(tls_issues_t *tls_issues);
|
||||||
tls_t *tls_init_slave(tls_t *tls_master, int sock);
|
tls_t *tls_init_secondary(tls_t *tls_master, int sock, int accept);
|
||||||
tls_t *tls_init_client(tls_t *tls_master, int sock);
|
|
||||||
void tls_free(tls_t *tls);
|
void tls_free(tls_t *tls);
|
||||||
int tls_get_socket(tls_t *tls);
|
int tls_get_socket(tls_t *tls);
|
||||||
ssize_t tls_read(tls_t *tls);
|
ssize_t tls_read(tls_t *tls);
|
||||||
|
@ -95,9 +95,6 @@ static ssize_t tport_tls_send(tport_t const *self, msg_t *msg,
|
|||||||
static int tport_tls_accept(tport_primary_t *pri, int events);
|
static int tport_tls_accept(tport_primary_t *pri, int events);
|
||||||
static tport_t *tport_tls_connect(tport_primary_t *pri, su_addrinfo_t *ai,
|
static tport_t *tport_tls_connect(tport_primary_t *pri, su_addrinfo_t *ai,
|
||||||
tp_name_t const *tpn);
|
tp_name_t const *tpn);
|
||||||
#if notyet
|
|
||||||
static void tport_tls_deliver(tport_t *self, msg_t *msg, su_time_t now);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tport_vtable_t const tport_tls_vtable =
|
tport_vtable_t const tport_tls_vtable =
|
||||||
{
|
{
|
||||||
@ -171,6 +168,10 @@ static int tport_tls_init_master(tport_primary_t *pri,
|
|||||||
char const *path = NULL;
|
char const *path = NULL;
|
||||||
unsigned tls_version = 1;
|
unsigned tls_version = 1;
|
||||||
unsigned tls_verify = 0;
|
unsigned tls_verify = 0;
|
||||||
|
unsigned tls_policy = TPTLS_VERIFY_NONE;
|
||||||
|
unsigned tls_depth = 0;
|
||||||
|
unsigned tls_date = 1;
|
||||||
|
su_strlst_t const *tls_subjects = NULL;
|
||||||
su_home_t autohome[SU_HOME_AUTO_SIZE(1024)];
|
su_home_t autohome[SU_HOME_AUTO_SIZE(1024)];
|
||||||
tls_issues_t ti = {0};
|
tls_issues_t ti = {0};
|
||||||
|
|
||||||
@ -183,6 +184,10 @@ static int tport_tls_init_master(tport_primary_t *pri,
|
|||||||
TPTAG_CERTIFICATE_REF(path),
|
TPTAG_CERTIFICATE_REF(path),
|
||||||
TPTAG_TLS_VERSION_REF(tls_version),
|
TPTAG_TLS_VERSION_REF(tls_version),
|
||||||
TPTAG_TLS_VERIFY_PEER_REF(tls_verify),
|
TPTAG_TLS_VERIFY_PEER_REF(tls_verify),
|
||||||
|
TPTAG_TLS_VERIFY_POLICY_REF(tls_policy),
|
||||||
|
TPTAG_TLS_VERIFY_DEPTH_REF(tls_depth),
|
||||||
|
TPTAG_TLS_VERIFY_DATE_REF(tls_date),
|
||||||
|
TPTAG_TLS_VERIFY_SUBJECTS_REF(tls_subjects),
|
||||||
TAG_END());
|
TAG_END());
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
@ -193,8 +198,9 @@ static int tport_tls_init_master(tport_primary_t *pri,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
ti.verify_peer = tls_verify;
|
ti.policy = tls_policy | (tls_verify ? TPTLS_VERIFY_ALL : 0);
|
||||||
ti.verify_depth = 2;
|
ti.verify_depth = tls_depth;
|
||||||
|
ti.verify_date = tls_date;
|
||||||
ti.configured = path != tbf;
|
ti.configured = path != tbf;
|
||||||
ti.randFile = su_sprintf(autohome, "%s/%s", path, "tls_seed.dat");
|
ti.randFile = su_sprintf(autohome, "%s/%s", path, "tls_seed.dat");
|
||||||
ti.key = su_sprintf(autohome, "%s/%s", path, "agent.pem");
|
ti.key = su_sprintf(autohome, "%s/%s", path, "agent.pem");
|
||||||
@ -225,6 +231,8 @@ static int tport_tls_init_master(tport_primary_t *pri,
|
|||||||
return *return_culprit = "tls_init_master", -1;
|
return *return_culprit = "tls_init_master", -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tls_subjects)
|
||||||
|
pri->pri_primary->tp_subjects = su_strlst_dup(pri->pri_home, tls_subjects);
|
||||||
pri->pri_has_tls = 1;
|
pri->pri_has_tls = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -247,11 +255,9 @@ static int tport_tls_init_secondary(tport_t *self, int socket, int accepted,
|
|||||||
if (tport_tcp_init_secondary(self, socket, accepted, return_reason) < 0)
|
if (tport_tcp_init_secondary(self, socket, accepted, return_reason) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (accepted) {
|
tlstp->tlstp_context = tls_init_secondary(master, socket, accepted);
|
||||||
tlstp->tlstp_context = tls_init_slave(master, socket);
|
|
||||||
if (!tlstp->tlstp_context)
|
if (!tlstp->tlstp_context)
|
||||||
return *return_reason = "tls_init_slave", -1;
|
return *return_reason = "tls_init_slave", -1;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -439,20 +445,12 @@ ssize_t tport_tls_send(tport_t const *self,
|
|||||||
msg_iovec_t iov[],
|
msg_iovec_t iov[],
|
||||||
size_t iovlen)
|
size_t iovlen)
|
||||||
{
|
{
|
||||||
tport_tls_primary_t *tlspri = (tport_tls_primary_t *)self->tp_pri;
|
|
||||||
tport_tls_t *tlstp = (tport_tls_t *)self;
|
tport_tls_t *tlstp = (tport_tls_t *)self;
|
||||||
enum { TLSBUFSIZE = 2048 };
|
enum { TLSBUFSIZE = 2048 };
|
||||||
size_t i, j, n, m, size = 0;
|
size_t i, j, n, m, size = 0;
|
||||||
ssize_t nerror;
|
ssize_t nerror;
|
||||||
int oldmask, mask;
|
int oldmask, mask;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldmask = tls_events(tlstp->tlstp_context, self->tp_events);
|
oldmask = tls_events(tlstp->tlstp_context, self->tp_events);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -560,8 +558,6 @@ int tport_tls_accept(tport_primary_t *pri, int events)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tport_tls_t *tlstp = (tport_tls_t *)self;
|
|
||||||
tport_tls_primary_t *tlspri = (tport_tls_primary_t *)self->tp_pri;
|
|
||||||
int events = SU_WAIT_IN|SU_WAIT_ERR|SU_WAIT_HUP;
|
int events = SU_WAIT_IN|SU_WAIT_ERR|SU_WAIT_HUP;
|
||||||
|
|
||||||
SU_CANONIZE_SOCKADDR(su);
|
SU_CANONIZE_SOCKADDR(su);
|
||||||
@ -575,8 +571,6 @@ int tport_tls_accept(tport_primary_t *pri, int events)
|
|||||||
self->tp_conn_orient = 1;
|
self->tp_conn_orient = 1;
|
||||||
self->tp_is_connected = 0;
|
self->tp_is_connected = 0;
|
||||||
|
|
||||||
tlstp->tlstp_context = tls_init_slave(tlspri->tlspri_master, s);
|
|
||||||
|
|
||||||
SU_DEBUG_5(("%s(%p): new connection from " TPN_FORMAT "\n",
|
SU_DEBUG_5(("%s(%p): new connection from " TPN_FORMAT "\n",
|
||||||
__func__, (void *)self, TPN_ARGS(self->tp_name)));
|
__func__, (void *)self, TPN_ARGS(self->tp_name)));
|
||||||
|
|
||||||
@ -640,14 +634,9 @@ tport_t *tport_tls_connect(tport_primary_t *pri,
|
|||||||
goto sys_error;
|
goto sys_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tport_setname(self, tpn->tpn_proto, ai, tpn->tpn_canon) != -1
|
if (tport_setname(self, tpn->tpn_proto, ai, tpn->tpn_canon) == -1)
|
||||||
&&
|
goto sys_error;
|
||||||
tport_register_secondary(self, tls_connect, events) != -1) {
|
else if (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
|
|
||||||
goto sys_error;
|
goto sys_error;
|
||||||
|
|
||||||
SU_DEBUG_5(("%s(%p): connecting to " TPN_FORMAT "\n",
|
SU_DEBUG_5(("%s(%p): connecting to " TPN_FORMAT "\n",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user