X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/29a1ada5b960fbf29d52e0f44911370a6c0c7c5f..9ef6b510ada8a7d3b053ebaef0686570ebf00f63:/sbr/netsec.c?ds=sidebyside diff --git a/sbr/netsec.c b/sbr/netsec.c index 1fe8f1ae..2d70b379 100644 --- a/sbr/netsec.c +++ b/sbr/netsec.c @@ -6,10 +6,13 @@ * complete copyright information. */ -#include -#include -#include -#include +#include "h/mh.h" +#include "credentials.h" +#include "getcpy.h" +#include "brkstring.h" +#include "h/utils.h" +#include "h/netsec.h" +#include "h/oauth.h" #include #include #include "base64.h" @@ -288,7 +291,8 @@ netsec_set_snoop(netsec_context *nsc, int snoop) * Set the snoop callback for this connection. */ -void netsec_set_snoop_callback(netsec_context *nsc, +void +netsec_set_snoop_callback(netsec_context *nsc, netsec_snoop_callback callback, void *context) { nsc->ns_snoop_cb = callback; @@ -319,7 +323,7 @@ netsec_b64_snoop_decoder(netsec_context *nsc, const char *string, size_t len, len -= offset; } - if (decodeBase64(string, &decoded, &decodedlen, 1, NULL) == OK) { + if (decodeBase64(string, &decoded, &decodedlen, 1) == OK) { /* * Some mechanisms produce large binary tokens, which aren't really * readable. So let's do a simple heuristic. If the token is greater @@ -806,6 +810,7 @@ netsec_vprintf(netsec_context *nsc, char **errstr, const char *format, va_list ap) { int rc; + va_list apcopy; /* * Cheat a little. If we can fit the data into our outgoing buffer, @@ -813,8 +818,10 @@ netsec_vprintf(netsec_context *nsc, char **errstr, const char *format, */ retry: + va_copy(apcopy, ap); rc = vsnprintf((char *) nsc->ns_outptr, - nsc->ns_outbufsize - nsc->ns_outbuflen, format, ap); + nsc->ns_outbufsize - nsc->ns_outbuflen, format, apcopy); + va_end(apcopy); if (rc >= (int) (nsc->ns_outbufsize - nsc->ns_outbuflen)) { /* @@ -830,7 +837,7 @@ retry: * At that point, just give up. */ netsec_err(errstr, "Internal error: wanted to printf() a total of " - "%d bytes, but our buffer size was only %d bytes", + "%d bytes, but our buffer size was only %d bytes", rc, nsc->ns_outbufsize); return NOTOK; } @@ -919,7 +926,7 @@ netsec_flush(netsec_context *nsc, char **errstr) if (nsc->ns_snoop_savebuf) { cb_len += strlen(nsc->ns_snoop_savebuf); nsc->ns_snoop_savebuf = mh_xrealloc(nsc->ns_snoop_savebuf, - outlen); + outlen); ptr = nsc->ns_snoop_savebuf; } else { ptr = snoopoutbuf; @@ -1103,7 +1110,8 @@ netsec_set_sasl_params(netsec_context *nsc, const char *service, * library when asked. */ -int netsec_get_user(void *context, int id, const char **result, +int +netsec_get_user(void *context, int id, const char **result, unsigned int *len) { netsec_context *nsc = (netsec_context *) context; @@ -1183,6 +1191,22 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) int rc; #endif /* CYRUS_SASL || OAUTH_SUPPORT */ + /* + * Output some SASL information if snoop is turned on + */ + + if (nsc->ns_snoop) { + fprintf(stderr, "SASL mechanisms supported by server: %s\n", mechlist); + + if (nsc->sasl_mech) { + fprintf(stderr, "User has requested SASL mechanism: %s\n", + nsc->sasl_mech); + } else { + fprintf(stderr, "No SASL mech selected, will pick " + "the best mech supported by SASL library\n"); + } + } + /* * If we've been passed a requested mechanism, check our mechanism * list from the protocol. If it's not supported, return an error. @@ -1221,6 +1245,10 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) * error message. */ + if (nsc->ns_snoop) { + fprintf(stderr, "Using internal XOAUTH2 mechanism\n"); + } + if (! nsc->oauth_service) { netsec_err(errstr, "Internal error: OAuth2 service name not given"); return NOTOK; @@ -1232,7 +1260,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) &xoauth_client_res, &xoauth_client_res_len, nsc->ns_snoop ? stderr : NULL) != OK) { netsec_err(errstr, "Internal error: Unable to get OAuth2 " - "bearer token"); + "bearer token"); return NOTOK; } @@ -1283,6 +1311,21 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) * messages. */ + if (nsc->ns_snoop) { + const char *client_mechlist; + + rc = sasl_listmech(nsc->sasl_conn, NULL, NULL, " ", NULL, + &client_mechlist, NULL, NULL); + + if (rc != SASL_OK) { + fprintf(stderr, "Unable to get client mechlist: %s\n", + sasl_errstring(rc, NULL, NULL)); + } else { + fprintf(stderr, "Client supported SASL mechanisms: %s\n", + client_mechlist); + } + } + ZERO(&secprops); secprops.maxbufsize = SASL_MAXRECVBUF; @@ -1296,6 +1339,12 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) #endif /* TLS_SUPPORT */ UINT_MAX; +#ifdef TLS_SUPPORT + if (nsc->ns_snoop && nsc->tls_active) + fprintf(stderr, "SASL security layers disabled due to the use " + "of TLS\n"); +#endif /* TLS_SUPPORT */ + rc = sasl_setprop(nsc->sasl_conn, SASL_SEC_PROPS, &secprops); if (rc != SASL_OK) { @@ -1310,7 +1359,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) */ rc = sasl_client_start(nsc->sasl_conn, - nsc->sasl_mech ? nsc->sasl_mech : mechlist, NULL, + nsc->sasl_mech ? nsc->sasl_mech : mechlist, NULL, (const char **) &saslbuf, &saslbuflen, &chosen_mech); @@ -1322,6 +1371,9 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) nsc->sasl_chosen_mech = getcpy(chosen_mech); + if (nsc->ns_snoop) + fprintf(stderr, "Chosen sasl mechanism: %s\n", chosen_mech); + if (nsc->sasl_proto_cb(NETSEC_SASL_START, saslbuf, saslbuflen, NULL, 0, nsc->sasl_proto_context, errstr) != OK) return NOTOK; @@ -1331,7 +1383,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) */ while (rc == SASL_CONTINUE) { - /* + /* * Call our SASL callback, which will handle the details of * reading data from the network. */ @@ -1396,6 +1448,10 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) nsc->sasl_ssf = *ssf; if (nsc->sasl_ssf > 0) { + if (nsc->ns_snoop) + fprintf(stderr, "SASL security layer negotiated, SASL will " + "perform encryption\n"); + rc = sasl_getprop(nsc->sasl_conn, SASL_MAXOUTBUF, (const void **) &outbufmax); @@ -1448,6 +1504,15 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) } nsc->sasl_seclayer = 1; + } else if (nsc->ns_snoop) { + fprintf(stderr, "SASL Security layer NOT negotiated, SASL will NOT " + "perform encryption\n"); +#ifdef TLS_SUPPORT + if (nsc->tls_active) { + fprintf(stderr, "Encryption will be handled by TLS\n"); + } else +#endif /* TLS_SUPPORT */ + fprintf(stderr, "Connection will NOT be encrypted, use caution\n"); } return OK; @@ -1489,6 +1554,7 @@ netsec_get_sasl_ssf(netsec_context *nsc) #ifdef CYRUS_SASL return nsc->sasl_ssf; #else /* CYRUS_SASL */ + NMH_UNUSED(nsc); return 0; #endif /* CYRUS_SASL */ } @@ -1558,6 +1624,11 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr) return NOTOK; } + if (!nsc->ns_hostname) { + netsec_err(errstr, "Internal error: hostname not set"); + return NOTOK; + } + /* * Create the SSL structure which holds the data for a single * TLS connection. @@ -1614,6 +1685,12 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr) SSL_set_bio(ssl, rbio, wbio); SSL_set_connect_state(ssl); + /* + * Use the hostname to set the Server Name Indicator extension + */ + + SSL_set_tlsext_host_name(ssl, nsc->ns_hostname); + /* * If noverify is NOT set, then do certificate validation. * Turning on SSL_VERIFY_PEER will verify the certificate chain @@ -1630,12 +1707,6 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr) #endif /* HAVE_X509_VERIFY_PARAM_SET1_HOST */ SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); - if (! nsc->ns_hostname) { - netsec_err(errstr, "Internal error: hostname not set and " - "certification verification enabled"); - SSL_free(ssl); - return NOTOK; - } #ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST param = SSL_get0_param(ssl); @@ -1654,7 +1725,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr) if (! ssl_bio) { netsec_err(errstr, "Unable to create a SSL BIO: %s", - ERR_error_string(ERR_get_error(), NULL)); + ERR_error_string(ERR_get_error(), NULL)); SSL_free(ssl); return NOTOK; } @@ -1779,7 +1850,7 @@ netsec_err(char **errstr, const char *fmt, ...) int rc = 127; if (! errstr) - return; + return; do { errbufsize = rc + 1;