int tlsops_desc(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { static char buf[128]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { LM_INFO("TLS connection not found in select_desc\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; buf[0] = '\0'; SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, 128); res->rs.s = buf; res->rs.len = strlen(buf); res->flags = PV_VAL_STR; tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return pv_get_null(msg, param, res); }
int tlsops_cipher(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { str cipher; static char buf[1024]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { LM_INFO("TLS connection not found in select_cipher\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; cipher.s = (char*)SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)); cipher.len = cipher.s ? strlen(cipher.s) : 0; if (cipher.len >= 1024) { LM_ERR("cipher name too long\n"); goto err; } memcpy(buf, cipher.s, cipher.len); res->rs.s = buf; res->rs.len = cipher.len; res->flags = PV_VAL_STR; tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return pv_get_null(msg, param, res); }
static int get_desc(str* res, sip_msg_t* msg) { static char buf[128]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { INFO("TLS connection not found in select_desc\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; buf[0] = '\0'; SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, 128); res->s = buf; res->len = strlen(buf); tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return -1; }
static int get_version(str* res, sip_msg_t* msg) { str version; static char buf[1024]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { INFO("TLS connection not found in select_version\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; version.s = (char*)SSL_get_version(ssl); version.len = version.s ? strlen(version.s) : 0; if (version.len >= 1024) { ERR("Version string too long\n"); goto err; } memcpy(buf, version.s, version.len); res->s = buf; res->len = version.len; tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return -1; }
static int get_bits(str* res, int* i, sip_msg_t* msg) { str bits; int b; static char buf[1024]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { INFO("TLS connection not found in select_bits\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; b = SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), 0); bits.s = int2str(b, &bits.len); if (bits.len >= 1024) { ERR("Bits string too long\n"); goto err; } memcpy(buf, bits.s, bits.len); res->s = buf; res->len = bits.len; if (i) *i = b; tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return -1; }
static int get_cipher(str* res, sip_msg_t* msg) { str cipher; static char buf[1024]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { INFO("TLS connection not found in select_cipher\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; cipher.s = (char*)SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)); cipher.len = cipher.s ? strlen(cipher.s) : 0; if (cipher.len >= 1024) { ERR("Cipher name too long\n"); goto err; } memcpy(buf, cipher.s, cipher.len); res->s = buf; res->len = cipher.len; tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return -1; }
static int get_cert(X509** cert, struct tcp_connection** c, struct sip_msg* msg, int my) { SSL* ssl; *cert = 0; *c = get_cur_connection(msg); if (!(*c)) { INFO("TLS connection not found\n"); return -1; } ssl = get_ssl(*c); if (!ssl) goto err; *cert = my ? SSL_get_certificate(ssl) : SSL_get_peer_certificate(ssl); if (!*cert) { if (my) { ERR("Unable to retrieve my TLS certificate from SSL structure\n"); } else { ERR("Unable to retrieve peer TLS certificate from SSL structure\n"); } goto err; } return 0; err: tcpconn_put(*c); return -1; }
static int get_tlsext_sn(str* res, sip_msg_t* msg) { static char buf[1024]; struct tcp_connection* c; str server_name; SSL* ssl; c = get_cur_connection(msg); if (!c) { INFO("TLS connection not found in select_desc\n"); goto error; } ssl = get_ssl(c); if (!ssl) goto error; buf[0] = '\0'; server_name.s = (char*)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (server_name.s) { server_name.len = strlen(server_name.s); DBG("received server_name (TLS extension): '%.*s'\n", STR_FMT(&server_name)); } else { DBG("SSL_get_servername returned NULL\n"); goto error; } /* copy server_name into the buffer. If the buffer is too small copy only * the last bytes as these are the more important ones and prefix with * '+' */ if (server_name.len > sizeof(buf)) { ERR("server_name to big for buffer\n"); buf[0] = '+'; memcpy(buf + 1, server_name.s + 1 + server_name.len - sizeof(buf), sizeof(buf) - 1); res->len = sizeof(buf); } else { memcpy(buf, server_name.s, server_name.len); res->len = server_name.len; } res->s = buf; tcpconn_put(c); return 0; error: if (c) tcpconn_put(c); return -1; }
/* * Check whether peer certificate exists and verify the result * of certificate verification */ int tlsops_check_cert(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { static str succ = str_init("1"); static str fail = str_init("0"); int err; struct tcp_connection* c; SSL* ssl; X509* cert = 0; switch (param->pvn.u.isname.name.n) { case CERT_VERIFIED: err = X509_V_OK; break; case CERT_REVOKED: err = X509_V_ERR_CERT_REVOKED; break; case CERT_EXPIRED: err = X509_V_ERR_CERT_HAS_EXPIRED; break; case CERT_SELFSIGNED: err = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; break; default: LM_CRIT("unexpected parameter value \"%d\"\n", param->pvn.u.isname.name.n); return pv_get_null(msg, param, res); } c = get_cur_connection(msg); if (!c) return -1; ssl = get_ssl(c); if (!ssl) goto err; if ((cert = SSL_get_peer_certificate(ssl)) && SSL_get_verify_result(ssl) == err) { res->rs.s = succ.s; res->rs.len = succ.len; res->ri = 1; } else { res->rs.s = fail.s; res->rs.len = fail.len; res->ri = 0; } res->flags = PV_VAL_STR | PV_VAL_INT; if (cert) X509_free(cert); tcpconn_put(c); return 0; err: if (cert) X509_free(cert); if (c) tcpconn_put(c); return pv_get_null(msg, param, res); }
/* * Check whether peer certificate exists and verify the result * of certificate verification */ static int check_cert(str* res, int* ires, int local, int err, sip_msg_t* msg) { static str succ = STR_STATIC_INIT("1"); static str fail = STR_STATIC_INIT("0"); struct tcp_connection* c; SSL* ssl; X509* cert = 0; c = get_cur_connection(msg); if (!c) return -1; ssl = get_ssl(c); if (!ssl) goto error; if (local) { DBG("Verification of local certificates not supported\n"); goto error; } else { if ((cert = SSL_get_peer_certificate(ssl)) && SSL_get_verify_result(ssl) == err) { *res = succ; if (ires) *ires = 1; } else { *res = fail; if (ires) *ires = 0; } } if (cert) X509_free(cert); tcpconn_put(c); return 0; error: if (cert) X509_free(cert); if (c) tcpconn_put(c); return -1; }
static inline int get_cert(X509** cert, struct tcp_connection** c, struct sip_msg* msg, int my) { SSL* ssl; *cert = 0; *c = get_cur_connection(msg); if (!(*c)) { LM_INFO("TLS connection not found\n"); return -1; } ssl = get_ssl(*c); if (!ssl) goto err; *cert = my ? SSL_get_certificate(ssl) : SSL_get_peer_certificate(ssl); if (!*cert) { LM_ERR("failed to get certificate from SSL structure\n"); goto err; } return 0; err: tcpconn_put(*c); return -1; }
int tlsops_version(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { str version; static char buf[1024]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { LM_INFO("TLS connection not found in select_version\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; version.s = (char*)SSL_get_version(ssl); version.len = version.s ? strlen(version.s) : 0; if (version.len >= 1024) { LM_ERR("version string too long\n"); goto err; } memcpy(buf, version.s, version.len); res->rs.s = buf; res->rs.len = version.len; res->flags = PV_VAL_STR; tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return pv_get_null(msg, param, res); }
int tlsops_bits(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { str bits; int b; static char buf[1024]; struct tcp_connection* c; SSL* ssl; c = get_cur_connection(msg); if (!c) { LM_INFO("TLS connection not found in select_bits\n"); goto err; } ssl = get_ssl(c); if (!ssl) goto err; b = SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), 0); bits.s = int2str(b, &bits.len); if (bits.len >= 1024) { LM_ERR("bits string too long\n"); goto err; } memcpy(buf, bits.s, bits.len); res->rs.s = buf; res->rs.len = bits.len; res->ri = b; res->flags = PV_VAL_STR | PV_VAL_INT; tcpconn_put(c); return 0; err: if (c) tcpconn_put(c); return pv_get_null(msg, param, res); }