5 Commits

Author SHA1 Message Date
Dmitry Podgorny
85da4145aa conn: add xmpp_conn_tls_cafile()
This function adds an external CAfile in PEM format as trusted
certificates.
2020-10-07 20:05:57 +03:00
Dmitry Podgorny
c07ac0a68d conn: don't crash when user sets password to NULL
Make it possible to reset password to NULL. It is not required for
ANONYMOUS authentication. Also, report an error and disconnect if
password is not set and libstrophe should try authentication mechanisms
other than ANONYMOUS.
2020-09-30 20:56:52 +03:00
Dmitry Podgorny
60ce94c267 auth: add missed space in log message 2020-09-30 20:43:32 +03:00
Dmitry Podgorny
99f2d4fe54 travis-ci: build libstrophe against LibreSSL 2020-09-24 15:07:15 +03:00
Dmitry Podgorny
acced31192 tls/openssl: Fix undefined error codes for LibreSSL
LibreSSL doesn't define all error codes which OpenSSL defines. Wrap them
with #ifndef.

Reference: https://bugs.gentoo.org/744127
2020-09-24 13:34:49 +03:00
9 changed files with 85 additions and 13 deletions

View File

@@ -6,18 +6,20 @@ stages:
- style
- test
before_script:
- ./bootstrap.sh
- ./travis/before_script.sh
env:
- CONFIGURE_OPT="--without-libxml2"
- CONFIGURE_OPT="--with-libxml2"
- CONFIGURE_OPT="--disable-tls"
- CONFIGURE_OPT="--enable-cares"
script: ./configure ${CONFIGURE_OPT} CFLAGS="-Werror" && make && make check
- CONFIGURE_OPT="PKG_CONFIG_PATH=${HOME}/libressl/lib/pkgconfig" LIBRESSL=yes LIBRESSL_COMMIT="v3.1.4"
- CONFIGURE_OPT="PKG_CONFIG_PATH=${HOME}/libressl/lib/pkgconfig" LIBRESSL=yes LIBRESSL_COMMIT="v2.1.7"
script: ./bootstrap.sh && ./configure ${CONFIGURE_OPT} CFLAGS="-Werror" && make && make check
jobs:
include:
- stage: style
name: "Check code style"
script: ./configure && make format && git diff --exit-code
script: ./bootstrap.sh && ./configure && make format && git diff --exit-code
env:
- CONFIGURE_OPT=""
matrix:

View File

@@ -1,3 +1,6 @@
0.10.1
- Fixed compilation error when LibreSSL is used
0.10.0
- Coding style has been unified
- SCRAM-SHA-256 and SCRAM-SHA-512 support

View File

@@ -49,6 +49,7 @@ int main(int argc, char **argv)
xmpp_conn_t *conn;
xmpp_log_t *log;
char *jid, *pass, *host = NULL;
const char *cafile = NULL;
long flags = 0;
int tcp_keepalive = 0;
int i;
@@ -67,12 +68,15 @@ int main(int argc, char **argv)
flags |= XMPP_CONN_FLAG_LEGACY_AUTH;
else if (strcmp(argv[i], "--tcp-keepalive") == 0)
tcp_keepalive = 1;
else if (strncmp(argv[i], "--cafile=", strlen("--cafile=")) == 0)
cafile = argv[i] + strlen("--cafile=");
else
break;
}
if ((argc - i) < 2 || (argc - i) > 3) {
fprintf(stderr, "Usage: basic [options] <jid> <pass> [<host>]\n\n"
"Options:\n"
" --cafile=<PATH> CAfile for cert verification.\n"
" --disable-tls Disable TLS.\n"
" --mandatory-tls Deny plaintext connection.\n"
" --trust-tls Trust TLS certificate.\n"
@@ -111,6 +115,10 @@ int main(int argc, char **argv)
if (tcp_keepalive)
xmpp_conn_set_keepalive(conn, KA_TIMEOUT, KA_INTERVAL);
/* add external CAfile if needed */
if (cafile)
xmpp_conn_tls_cafile(conn, cafile);
/* setup authentication information */
xmpp_conn_set_jid(conn, jid);
xmpp_conn_set_pass(conn, pass);

View File

@@ -346,8 +346,7 @@ static int _handle_sasl_result(xmpp_conn_t *const conn,
} else {
/* got unexpected reply */
xmpp_error(conn->ctx, "xmpp",
"Got unexpected reply to SASL %s"
"authentication.",
"Got unexpected reply to SASL %s authentication.",
(char *)userdata);
xmpp_disconnect(conn);
}
@@ -668,6 +667,10 @@ static void _auth(xmpp_conn_t *const conn)
xmpp_error(conn->ctx, "auth",
"No node in JID, and SASL ANONYMOUS unsupported.");
xmpp_disconnect(conn);
} else if (conn->pass == NULL) {
xmpp_error(conn->ctx, "auth",
"Password hasn't been set, and SASL ANONYMOUS unsupported.");
xmpp_disconnect(conn);
} else if (conn->sasl_support & SASL_MASK_SCRAM) {
scram_ctx = xmpp_alloc(conn->ctx, sizeof(*scram_ctx));
if (conn->sasl_support & SASL_MASK_SCRAMSHA512)

View File

@@ -171,6 +171,7 @@ struct _xmpp_conn_t {
int ka_interval; /* TCP keepalive interval */
tls_t *tls;
char *tls_cafile;
int tls_support;
int tls_disabled;
int tls_mandatory;

View File

@@ -137,6 +137,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *const ctx)
conn->bound_jid = NULL;
conn->is_raw = 0;
conn->tls_cafile = NULL;
conn->tls_support = 0;
conn->tls_disabled = 0;
conn->tls_mandatory = 0;
@@ -338,6 +339,8 @@ int xmpp_conn_release(xmpp_conn_t *const conn)
xmpp_free(ctx, conn->pass);
if (conn->lang)
xmpp_free(ctx, conn->lang);
if (conn->tls_cafile)
xmpp_free(ctx, conn->tls_cafile);
xmpp_free(ctx, conn);
released = 1;
}
@@ -420,7 +423,7 @@ void xmpp_conn_set_pass(xmpp_conn_t *const conn, const char *const pass)
{
if (conn->pass)
xmpp_free(conn->ctx, conn->pass);
conn->pass = xmpp_strdup(conn->ctx, pass);
conn->pass = pass ? xmpp_strdup(conn->ctx, pass) : NULL;
}
/** Get the strophe context that the connection is associated with.
@@ -686,6 +689,28 @@ int xmpp_conn_tls_start(xmpp_conn_t *const conn)
return conn_tls_start(conn);
}
/** Set external CAfile which will be used for TLS cert verification.
*
* @return XMPP_EOK (0) on success a number less than 0 on failure
*
* @ingroup Connections
*/
int xmpp_conn_tls_cafile(xmpp_conn_t *const conn, const char *cafile)
{
FILE *f;
f = fopen(cafile, "r");
if (f == NULL) {
xmpp_debug(conn->ctx, "conn", "CAfile '%s' is not readable. errno=%d",
cafile, errno);
return XMPP_EINVOP;
}
fclose(f);
conn->tls_cafile = xmpp_strdup(conn->ctx, cafile);
return conn->tls_cafile == NULL ? XMPP_EMEM : XMPP_EOK;
}
/** Cleanly disconnect the connection.
* This function is only called by the stream parser when </stream:stream>
* is received, and it not intended to be called by code outside of Strophe.
@@ -915,6 +940,10 @@ int conn_tls_start(xmpp_conn_t *const conn)
}
if (conn->tls != NULL) {
if (conn->tls_cafile != NULL) {
(void)tls_set_credentials(conn->tls, conn->tls_cafile);
}
if (tls_start(conn->tls)) {
conn->secured = 1;
} else {

View File

@@ -81,6 +81,7 @@ const char *tls_errors[] = {
TLS_ERROR_FIELD(SSL_ERROR_ZERO_RETURN),
TLS_ERROR_FIELD(SSL_ERROR_WANT_CONNECT),
TLS_ERROR_FIELD(SSL_ERROR_WANT_ACCEPT),
#ifndef LIBRESSL_VERSION_NUMBER
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC),
TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC_JOB),
@@ -88,6 +89,7 @@ const char *tls_errors[] = {
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
TLS_ERROR_FIELD(SSL_ERROR_WANT_CLIENT_HELLO_CB),
#endif
#endif /* !LIBRESSL_VERSION_NUMBER */
};
const char *cert_errors[] = {
TLS_ERROR_FIELD(X509_V_OK),
@@ -148,30 +150,34 @@ const char *cert_errors[] = {
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX),
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX),
TLS_ERROR_FIELD(X509_V_ERR_CRL_PATH_VALIDATION_ERROR),
#ifndef LIBRESSL_VERSION_NUMBER
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_VERSION),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_ALGORITHM),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_CURVE),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256),
#endif /* !LIBRESSL_VERSION_NUMBER */
TLS_ERROR_FIELD(X509_V_ERR_HOSTNAME_MISMATCH),
TLS_ERROR_FIELD(X509_V_ERR_EMAIL_MISMATCH),
TLS_ERROR_FIELD(X509_V_ERR_IP_ADDRESS_MISMATCH),
#endif
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
TLS_ERROR_FIELD(X509_V_ERR_INVALID_CALL),
TLS_ERROR_FIELD(X509_V_ERR_STORE_LOOKUP),
#ifndef LIBRESSL_VERSION_NUMBER
TLS_ERROR_FIELD(X509_V_ERR_PATH_LOOP),
TLS_ERROR_FIELD(X509_V_ERR_DANE_NO_MATCH),
TLS_ERROR_FIELD(X509_V_ERR_EE_KEY_TOO_SMALL),
TLS_ERROR_FIELD(X509_V_ERR_CA_KEY_TOO_SMALL),
TLS_ERROR_FIELD(X509_V_ERR_CA_MD_TOO_WEAK),
TLS_ERROR_FIELD(X509_V_ERR_INVALID_CALL),
TLS_ERROR_FIELD(X509_V_ERR_STORE_LOOKUP),
TLS_ERROR_FIELD(X509_V_ERR_NO_VALID_SCTS),
TLS_ERROR_FIELD(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION),
TLS_ERROR_FIELD(X509_V_ERR_OCSP_VERIFY_NEEDED),
TLS_ERROR_FIELD(X509_V_ERR_OCSP_VERIFY_FAILED),
TLS_ERROR_FIELD(X509_V_ERR_OCSP_CERT_UNKNOWN),
#endif
#endif /* !LIBRESSL_VERSION_NUMBER */
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
};
#undef TLS_ERROR_FIELD
@@ -312,9 +318,14 @@ void tls_free(tls_t *tls)
int tls_set_credentials(tls_t *tls, const char *cafilename)
{
UNUSED(tls);
UNUSED(cafilename);
return -1;
int ret;
ret = SSL_CTX_load_verify_locations(tls->ssl_ctx, cafilename, NULL);
if (ret != 1) {
xmpp_error(tls->ctx, "tls", "Failed to process CAfile: %s", cafilename);
_tls_log_error(tls->ctx);
}
return ret;
}
int tls_start(tls_t *tls)

View File

@@ -271,6 +271,7 @@ int xmpp_conn_open_stream(xmpp_conn_t *const conn,
char **attributes,
size_t attributes_len);
int xmpp_conn_tls_start(xmpp_conn_t *const conn);
int xmpp_conn_tls_cafile(xmpp_conn_t *const conn, const char *cafile);
void xmpp_disconnect(xmpp_conn_t *const conn);

14
travis/before_script.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/sh
if [ "x$LIBRESSL" = "xyes" ]; then
cd "$HOME"
git clone https://github.com/libressl-portable/portable.git libressl-git
cd libressl-git
if [ -n "$LIBRESSL_COMMIT" ]; then
git checkout "$LIBRESSL_COMMIT"
fi
./autogen.sh
./configure --prefix="$HOME/libressl"
make -j"$(nproc)"
make install
fi