*/
#include "h/mh.h"
+#include "credentials.h"
+#include "getcpy.h"
#include "brkstring.h"
#include "h/utils.h"
#include "h/netsec.h"
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
* 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;
}
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;
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.
* 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;
&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;
}
* 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;
#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) {
*/
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);
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;
*/
while (rc == SASL_CONTINUE) {
- /*
+ /*
* Call our SASL callback, which will handle the details of
* reading data from the network.
*/
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);
}
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;
#ifdef CYRUS_SASL
return nsc->sasl_ssf;
#else /* CYRUS_SASL */
+ NMH_UNUSED(nsc);
return 0;
#endif /* CYRUS_SASL */
}
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.
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
#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);
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;
}
int rc = 127;
if (! errstr)
- return;
+ return;
do {
errbufsize = rc + 1;