implement certificate verification API for OpenSSL
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
This commit is contained in:
@@ -91,8 +91,10 @@ static void _tls_log_error(xmpp_ctx_t *ctx);
|
|||||||
static void _tls_dump_cert_info(tls_t *tls);
|
static void _tls_dump_cert_info(tls_t *tls);
|
||||||
static X509 *_tls_cert_read(xmpp_conn_t *conn);
|
static X509 *_tls_cert_read(xmpp_conn_t *conn);
|
||||||
static int _tls_xaddr_nid(void);
|
static int _tls_xaddr_nid(void);
|
||||||
static int _tls_name_to_xmppaddr(GENERAL_NAME *name, char **res);
|
static int _tls_xmppaddr_to_string(GENERAL_NAME *name, char **res);
|
||||||
static GENERAL_NAMES *_tls_cert_get_names(xmpp_conn_t *conn);
|
static int _tls_dnsname_to_string(GENERAL_NAME *name, char **res);
|
||||||
|
static GENERAL_NAMES *_tls_conn_get_names(xmpp_conn_t *conn);
|
||||||
|
static GENERAL_NAMES *_tls_cert_get_names(X509 *client_cert);
|
||||||
|
|
||||||
#define TLS_ERROR_STR(error, table) \
|
#define TLS_ERROR_STR(error, table) \
|
||||||
_tls_error_str(error, table, ARRAY_SIZE(table))
|
_tls_error_str(error, table, ARRAY_SIZE(table))
|
||||||
@@ -255,7 +257,7 @@ char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
|
|||||||
{
|
{
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
int i, j;
|
int i, j;
|
||||||
GENERAL_NAMES *names = _tls_cert_get_names(conn);
|
GENERAL_NAMES *names = _tls_conn_get_names(conn);
|
||||||
if (!names)
|
if (!names)
|
||||||
return NULL;
|
return NULL;
|
||||||
int num_names = sk_GENERAL_NAME_num(names);
|
int num_names = sk_GENERAL_NAME_num(names);
|
||||||
@@ -264,7 +266,7 @@ char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
|
|||||||
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
|
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
break;
|
break;
|
||||||
if (_tls_name_to_xmppaddr(name, &res))
|
if (_tls_xmppaddr_to_string(name, &res))
|
||||||
continue;
|
continue;
|
||||||
if (j == (int)n) {
|
if (j == (int)n) {
|
||||||
xmpp_debug(conn->ctx, "tls", "extracted jid %s from id-on-xmppAddr",
|
xmpp_debug(conn->ctx, "tls", "extracted jid %s from id-on-xmppAddr",
|
||||||
@@ -283,13 +285,13 @@ char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
|
|||||||
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
|
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
|
||||||
{
|
{
|
||||||
unsigned int ret = 0;
|
unsigned int ret = 0;
|
||||||
GENERAL_NAMES *names = _tls_cert_get_names(conn);
|
GENERAL_NAMES *names = _tls_conn_get_names(conn);
|
||||||
if (!names)
|
if (!names)
|
||||||
return 0;
|
return 0;
|
||||||
int j, num_names = sk_GENERAL_NAME_num(names);
|
int j, num_names = sk_GENERAL_NAME_num(names);
|
||||||
for (j = 0; j < num_names; ++j) {
|
for (j = 0; j < num_names; ++j) {
|
||||||
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, j);
|
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, j);
|
||||||
if (_tls_name_to_xmppaddr(name, NULL))
|
if (_tls_xmppaddr_to_string(name, NULL))
|
||||||
continue;
|
continue;
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
@@ -297,10 +299,216 @@ unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _convert_ASN1TIME(ASN1_TIME *ansi_time, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
BIO *bio = BIO_new(BIO_s_mem());
|
||||||
|
int rc = ASN1_TIME_print(bio, ansi_time);
|
||||||
|
if (rc <= 0) {
|
||||||
|
BIO_free(bio);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
rc = BIO_gets(bio, buf, len);
|
||||||
|
if (rc <= 0) {
|
||||||
|
BIO_free(bio);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
BIO_free(bio);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *_asn1_time_to_str(const xmpp_ctx_t *ctx, ASN1_TIME *t)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
int res = _convert_ASN1TIME(t, buf, sizeof(buf));
|
||||||
|
if (res) {
|
||||||
|
return xmpp_strdup(ctx, buf);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
_get_fingerprint(const xmpp_ctx_t *ctx, X509 *err_cert, xmpp_cert_element_t el)
|
||||||
|
{
|
||||||
|
unsigned char buf[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned int len;
|
||||||
|
const EVP_MD *digest;
|
||||||
|
switch (el) {
|
||||||
|
case XMPP_CERT_FINGERPRINT_SHA1:
|
||||||
|
digest = EVP_sha1();
|
||||||
|
break;
|
||||||
|
case XMPP_CERT_FINGERPRINT_SHA256:
|
||||||
|
digest = EVP_sha256();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (X509_digest(err_cert, digest, buf, &len) != 0) {
|
||||||
|
char fingerprint[4 * EVP_MAX_MD_SIZE];
|
||||||
|
hex_encode(fingerprint, buf, len);
|
||||||
|
return xmpp_strdup(ctx, fingerprint);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
_get_alg(const xmpp_ctx_t *ctx, X509 *err_cert, xmpp_cert_element_t el)
|
||||||
|
{
|
||||||
|
int rc, alg_nid = NID_undef;
|
||||||
|
|
||||||
|
switch (el) {
|
||||||
|
case XMPP_CERT_KEYALG: {
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
alg_nid = OBJ_obj2nid(err_cert->cert_info->key->algor->algorithm);
|
||||||
|
#else
|
||||||
|
X509_PUBKEY *pubkey = X509_get_X509_PUBKEY(err_cert);
|
||||||
|
ASN1_OBJECT *ppkalg = NULL;
|
||||||
|
rc = X509_PUBKEY_get0_param(&ppkalg, NULL, NULL, NULL, pubkey);
|
||||||
|
if (rc) {
|
||||||
|
alg_nid = OBJ_obj2nid(ppkalg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
|
case XMPP_CERT_SIGALG: {
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
alg_nid = OBJ_obj2nid(err_cert->sig_alg->algorithm);
|
||||||
|
#else
|
||||||
|
const X509_ALGOR *palg;
|
||||||
|
X509_get0_signature(NULL, &palg, err_cert);
|
||||||
|
alg_nid = OBJ_obj2nid(palg->algorithm);
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (alg_nid != NID_undef) {
|
||||||
|
const char *alg = OBJ_nid2ln(alg_nid);
|
||||||
|
if (alg) {
|
||||||
|
return xmpp_strdup(ctx, alg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static xmpp_tlscert_t *_x509_to_tlscert(xmpp_ctx_t *ctx, X509 *cert)
|
||||||
|
{
|
||||||
|
char *subject, *issuer, buf[32];
|
||||||
|
xmpp_tlscert_t *tlscert = tlscert_new(ctx);
|
||||||
|
if (!tlscert)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
BIO *b = BIO_new(BIO_s_mem());
|
||||||
|
if (!b)
|
||||||
|
goto ERR_OUT;
|
||||||
|
PEM_write_bio_X509(b, cert);
|
||||||
|
BUF_MEM *bptr;
|
||||||
|
BIO_get_mem_ptr(b, &bptr);
|
||||||
|
tlscert->pem = xmpp_alloc(ctx, bptr->length + 1);
|
||||||
|
if (!tlscert->pem)
|
||||||
|
goto ERR_OUT;
|
||||||
|
memcpy(tlscert->pem, bptr->data, bptr->length);
|
||||||
|
tlscert->pem[bptr->length] = '\0';
|
||||||
|
BIO_free(b);
|
||||||
|
|
||||||
|
subject = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
|
||||||
|
if (!subject)
|
||||||
|
goto ERR_OUT;
|
||||||
|
tlscert->elements[XMPP_CERT_SUBJECT] = xmpp_strdup(ctx, subject);
|
||||||
|
OPENSSL_free(subject);
|
||||||
|
issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
|
||||||
|
if (!issuer)
|
||||||
|
goto ERR_OUT;
|
||||||
|
tlscert->elements[XMPP_CERT_ISSUER] = xmpp_strdup(ctx, issuer);
|
||||||
|
OPENSSL_free(issuer);
|
||||||
|
|
||||||
|
tlscert->elements[XMPP_CERT_NOTBEFORE] =
|
||||||
|
_asn1_time_to_str(ctx, X509_get_notBefore(cert));
|
||||||
|
tlscert->elements[XMPP_CERT_NOTAFTER] =
|
||||||
|
_asn1_time_to_str(ctx, X509_get_notAfter(cert));
|
||||||
|
|
||||||
|
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA1] =
|
||||||
|
_get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA1);
|
||||||
|
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] =
|
||||||
|
_get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA256);
|
||||||
|
|
||||||
|
xmpp_snprintf(buf, sizeof(buf), "%ld", X509_get_version(cert) + 1);
|
||||||
|
tlscert->elements[XMPP_CERT_VERSION] = xmpp_strdup(ctx, buf);
|
||||||
|
|
||||||
|
tlscert->elements[XMPP_CERT_KEYALG] = _get_alg(ctx, cert, XMPP_CERT_KEYALG);
|
||||||
|
tlscert->elements[XMPP_CERT_SIGALG] = _get_alg(ctx, cert, XMPP_CERT_SIGALG);
|
||||||
|
|
||||||
|
ASN1_INTEGER *serial = X509_get_serialNumber(cert);
|
||||||
|
BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL);
|
||||||
|
if (bn) {
|
||||||
|
char *serialnumber = BN_bn2hex(bn);
|
||||||
|
if (serialnumber) {
|
||||||
|
tlscert->elements[XMPP_CERT_SERIALNUMBER] =
|
||||||
|
xmpp_strdup(ctx, serialnumber);
|
||||||
|
OPENSSL_free(serialnumber);
|
||||||
|
}
|
||||||
|
BN_free(bn);
|
||||||
|
}
|
||||||
|
|
||||||
|
GENERAL_NAMES *names = _tls_cert_get_names(cert);
|
||||||
|
if (names) {
|
||||||
|
int j, num_names = sk_GENERAL_NAME_num(names);
|
||||||
|
size_t n = 0;
|
||||||
|
for (j = 0; j < num_names; ++j) {
|
||||||
|
char *res;
|
||||||
|
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, j);
|
||||||
|
if (_tls_dnsname_to_string(name, &res))
|
||||||
|
continue;
|
||||||
|
if (tlscert_add_dnsname(tlscert, res))
|
||||||
|
xmpp_debug(ctx, "tls", "Can't store dnsName(%zu): %s", n, res);
|
||||||
|
n++;
|
||||||
|
OPENSSL_free(res);
|
||||||
|
}
|
||||||
|
GENERAL_NAMES_free(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlscert;
|
||||||
|
ERR_OUT:
|
||||||
|
xmpp_tlscert_free(tlscert);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _tls_verify(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||||
|
{
|
||||||
|
if (preverify_ok == 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
SSL *ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
|
||||||
|
SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||||
|
xmpp_conn_t *conn = SSL_get_app_data(ssl);
|
||||||
|
|
||||||
|
if (!conn->certfail_handler) {
|
||||||
|
xmpp_error(conn->ctx, "tls",
|
||||||
|
"No certfail handler set, canceling connection attempt");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509 *err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
|
||||||
|
|
||||||
|
xmpp_tlscert_t *tlscert = _x509_to_tlscert(conn->ctx, err_cert);
|
||||||
|
|
||||||
|
if (!tlscert)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
xmpp_debug(conn->ctx, "tls", "preverify_ok:%d\nSubject: %s\nIssuer: %s",
|
||||||
|
preverify_ok, tlscert->elements[XMPP_CERT_SUBJECT],
|
||||||
|
tlscert->elements[XMPP_CERT_ISSUER]);
|
||||||
|
|
||||||
|
int ret = conn->certfail_handler(
|
||||||
|
tlscert,
|
||||||
|
X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509_ctx)));
|
||||||
|
|
||||||
|
xmpp_tlscert_free(tlscert);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
tls_t *tls_new(xmpp_conn_t *conn)
|
tls_t *tls_new(xmpp_conn_t *conn)
|
||||||
{
|
{
|
||||||
tls_t *tls = xmpp_alloc(conn->ctx, sizeof(*tls));
|
tls_t *tls = xmpp_alloc(conn->ctx, sizeof(*tls));
|
||||||
int mode;
|
|
||||||
|
|
||||||
if (tls) {
|
if (tls) {
|
||||||
int ret;
|
int ret;
|
||||||
@@ -359,6 +567,16 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
|||||||
goto err_free_cert;
|
goto err_free_cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn->tls_cafile || conn->tls_capath) {
|
||||||
|
if (SSL_CTX_load_verify_locations(tls->ssl_ctx, conn->tls_cafile,
|
||||||
|
conn->tls_capath) == 0) {
|
||||||
|
xmpp_error(tls->ctx, "tls",
|
||||||
|
"SSL_CTX_load_verify_locations() failed");
|
||||||
|
_tls_log_error(tls->ctx);
|
||||||
|
goto err_free_cert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tls->ssl = SSL_new(tls->ssl_ctx);
|
tls->ssl = SSL_new(tls->ssl_ctx);
|
||||||
if (tls->ssl == NULL)
|
if (tls->ssl == NULL)
|
||||||
goto err_free_cert;
|
goto err_free_cert;
|
||||||
@@ -368,9 +586,13 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
|||||||
SSL_set_tlsext_host_name(tls->ssl, conn->domain);
|
SSL_set_tlsext_host_name(tls->ssl, conn->domain);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Trust server's certificate when user sets the flag explicitly. */
|
/* Trust server's certificate when user sets the flag explicitly.
|
||||||
mode = conn->tls_trust ? SSL_VERIFY_NONE : SSL_VERIFY_PEER;
|
* Otherwise call the verification callback */
|
||||||
SSL_set_verify(tls->ssl, mode, NULL);
|
if (conn->tls_trust)
|
||||||
|
SSL_set_verify(tls->ssl, SSL_VERIFY_NONE, NULL);
|
||||||
|
else
|
||||||
|
SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, _tls_verify);
|
||||||
|
SSL_set_app_data(tls->ssl, conn);
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
/* Hostname verification is supported in OpenSSL 1.0.2 and newer. */
|
/* Hostname verification is supported in OpenSSL 1.0.2 and newer. */
|
||||||
param = SSL_get0_param(tls->ssl);
|
param = SSL_get0_param(tls->ssl);
|
||||||
@@ -414,6 +636,19 @@ void tls_free(tls_t *tls)
|
|||||||
xmpp_free(tls->ctx, tls);
|
xmpp_free(tls->ctx, tls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
|
||||||
|
{
|
||||||
|
if (conn && conn->tls && conn->tls->ssl) {
|
||||||
|
X509 *cert = SSL_get_peer_certificate(conn->tls->ssl);
|
||||||
|
if (cert) {
|
||||||
|
xmpp_tlscert_t *tlscert = _x509_to_tlscert(conn->ctx, cert);
|
||||||
|
X509_free(cert);
|
||||||
|
return tlscert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int tls_set_credentials(tls_t *tls, const char *cafilename)
|
int tls_set_credentials(tls_t *tls, const char *cafilename)
|
||||||
{
|
{
|
||||||
UNUSED(tls);
|
UNUSED(tls);
|
||||||
@@ -450,6 +685,8 @@ int tls_start(tls_t *tls)
|
|||||||
xmpp_debug(tls->ctx, "tls",
|
xmpp_debug(tls->ctx, "tls",
|
||||||
"Certificate verification FAILED, result=%s(%ld)",
|
"Certificate verification FAILED, result=%s(%ld)",
|
||||||
TLS_ERROR_STR((int)x509_res, cert_errors), x509_res);
|
TLS_ERROR_STR((int)x509_res, cert_errors), x509_res);
|
||||||
|
if (ret > 0)
|
||||||
|
xmpp_debug(tls->ctx, "tls", "User decided to connect anyways");
|
||||||
}
|
}
|
||||||
_tls_dump_cert_info(tls);
|
_tls_dump_cert_info(tls);
|
||||||
|
|
||||||
@@ -642,30 +879,34 @@ static int _tls_xaddr_nid(void)
|
|||||||
return xaddr_nid;
|
return xaddr_nid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GENERAL_NAMES *_tls_cert_get_names(xmpp_conn_t *conn)
|
static GENERAL_NAMES *_tls_conn_get_names(xmpp_conn_t *conn)
|
||||||
{
|
{
|
||||||
X509 *client_cert;
|
X509 *client_cert;
|
||||||
GENERAL_NAMES *names = NULL;
|
GENERAL_NAMES *names = NULL;
|
||||||
client_cert = _tls_cert_read(conn);
|
client_cert = _tls_cert_read(conn);
|
||||||
if (!client_cert)
|
if (!client_cert)
|
||||||
return NULL;
|
return NULL;
|
||||||
int san = X509_get_ext_by_NID(client_cert, NID_subject_alt_name, 0);
|
names = _tls_cert_get_names(client_cert);
|
||||||
X509_EXTENSION *san_ext = X509_get_ext(client_cert, san);
|
|
||||||
if (!san_ext)
|
|
||||||
goto OUT;
|
|
||||||
ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(san_ext);
|
|
||||||
if (!data)
|
|
||||||
goto OUT;
|
|
||||||
const unsigned char *d = ASN1_STRING_get0_data(data);
|
|
||||||
if (!d)
|
|
||||||
goto OUT;
|
|
||||||
names = d2i_GENERAL_NAMES(NULL, &d, ASN1_STRING_length(data));
|
|
||||||
OUT:
|
|
||||||
if (!conn->tls || !conn->tls->client_cert)
|
if (!conn->tls || !conn->tls->client_cert)
|
||||||
X509_free(client_cert);
|
X509_free(client_cert);
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GENERAL_NAMES *_tls_cert_get_names(X509 *client_cert)
|
||||||
|
{
|
||||||
|
int san = X509_get_ext_by_NID(client_cert, NID_subject_alt_name, 0);
|
||||||
|
X509_EXTENSION *san_ext = X509_get_ext(client_cert, san);
|
||||||
|
if (!san_ext)
|
||||||
|
return NULL;
|
||||||
|
ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(san_ext);
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
const unsigned char *d = ASN1_STRING_get0_data(data);
|
||||||
|
if (!d)
|
||||||
|
return NULL;
|
||||||
|
return d2i_GENERAL_NAMES(NULL, &d, ASN1_STRING_length(data));
|
||||||
|
}
|
||||||
|
|
||||||
/** Convert GENERAL_NAME* to a string
|
/** Convert GENERAL_NAME* to a string
|
||||||
*
|
*
|
||||||
* This checks whether the GENERAL_NAME* that is given has the
|
* This checks whether the GENERAL_NAME* that is given has the
|
||||||
@@ -680,7 +921,7 @@ OUT:
|
|||||||
*
|
*
|
||||||
* @return classic Unix style - 0=success, 1=error
|
* @return classic Unix style - 0=success, 1=error
|
||||||
*/
|
*/
|
||||||
static int _tls_name_to_xmppaddr(GENERAL_NAME *name, char **res)
|
static int _tls_xmppaddr_to_string(GENERAL_NAME *name, char **res)
|
||||||
{
|
{
|
||||||
ASN1_OBJECT *oid;
|
ASN1_OBJECT *oid;
|
||||||
ASN1_TYPE *val;
|
ASN1_TYPE *val;
|
||||||
@@ -696,3 +937,18 @@ static int _tls_name_to_xmppaddr(GENERAL_NAME *name, char **res)
|
|||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _tls_dnsname_to_string(GENERAL_NAME *name, char **res)
|
||||||
|
{
|
||||||
|
ASN1_STRING *str;
|
||||||
|
if (!name || name->type != GEN_DNS)
|
||||||
|
return 1;
|
||||||
|
str = GENERAL_NAME_get0_value(name, NULL);
|
||||||
|
if (str == NULL)
|
||||||
|
return 1;
|
||||||
|
if (!res)
|
||||||
|
return 0;
|
||||||
|
if (ASN1_STRING_to_UTF8((unsigned char **)res, str) < 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -160,3 +160,12 @@ void disconnect_mem_error(xmpp_conn_t *conn)
|
|||||||
xmpp_error(conn->ctx, "xmpp", "Memory allocation error");
|
xmpp_error(conn->ctx, "xmpp", "Memory allocation error");
|
||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hex_encode(char *writebuf, void *readbuf, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
sprintf(writebuf, "%02x", ((unsigned char *)readbuf)[i]);
|
||||||
|
writebuf += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,4 +32,7 @@ char *xmpp_strtok_r(char *s, const char *delim, char **saveptr);
|
|||||||
uint64_t time_stamp(void);
|
uint64_t time_stamp(void);
|
||||||
uint64_t time_elapsed(uint64_t t1, uint64_t t2);
|
uint64_t time_elapsed(uint64_t t1, uint64_t t2);
|
||||||
|
|
||||||
|
/* misc functions */
|
||||||
|
void hex_encode(char *writebuf, void *readbuf, size_t len);
|
||||||
|
|
||||||
#endif /* __LIBSTROPHE_UTIL_H__ */
|
#endif /* __LIBSTROPHE_UTIL_H__ */
|
||||||
|
|||||||
Reference in New Issue
Block a user