* complete copyright information.
*/
-#include <h/mh.h>
-#include <h/utils.h>
-#include <h/netsec.h>
-#include <h/oauth.h>
+#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 <stdarg.h>
#include <sys/select.h>
#include "base64.h"
static int netsec_get_password(sasl_conn_t *conn, void *context, int id,
sasl_secret_t **psecret);
-static int sasl_initialized = 0;
+static bool sasl_initialized;
#define SASL_MAXRECVBUF 65536
#endif /* CYRUS_SASL */
#include <openssl/ssl.h>
#include <openssl/err.h>
-static int tls_initialized = 0;
+static bool tls_initialized;
static SSL_CTX *sslctx = NULL; /* SSL Context */
#endif /* TLS_SUPPORT */
* 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;
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
va_list ap)
{
int rc;
+ va_list apcopy;
/*
* Cheat a little. If we can fit the data into our outgoing buffer,
*/
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)) {
/*
* 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) {
unsigned int snoopoutlen = netoutlen;
- const char *snoopoutbuf = nsc->ns_outbuffer;
+ const char *snoopoutbuf = (const char *) nsc->ns_outbuffer;
while (snoopoutlen > 0) {
const char *end = strpbrk(snoopoutbuf, "\r\n");
#endif /* TLS_SUPPORT */
fprintf(stderr, "=> ");
if (nsc->ns_snoop_cb) {
- char *ptr;
+ const char *ptr;
unsigned int cb_len = outlen;
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;
sasl_errstring(retval, NULL, NULL));
return NOTOK;
}
- sasl_initialized++;
+ sasl_initialized = true;
}
/*
* 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;
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;
return nsc->sasl_chosen_mech;
}
+/*
+ * Return the negotiated SASL strength security factor (SSF)
+ */
+
+int
+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 */
+}
+
/*
* Set an OAuth2 service name, if we support it.
*/
return NOTOK;
}
- tls_initialized++;
+ tls_initialized = true;
}
if (nsc->ns_readfd == -1 || nsc->ns_writefd == -1) {
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;