unsigned int ns_outbuflen; /* Output buffer data length */
unsigned int ns_outbufsize; /* Output buffer size */
char *sasl_mech; /* User-requested mechanism */
+ char *sasl_chosen_mech; /* Mechanism chosen by SASL */
+ netsec_sasl_callback sasl_proto_cb; /* SASL callback we use */
#ifdef OAUTH_SUPPORT
char *oauth_service; /* OAuth2 service name */
#endif /* OAUTH_SUPPORT */
char *sasl_hostname; /* Hostname we've connected to */
sasl_conn_t *sasl_conn; /* SASL connection context */
sasl_ssf_t sasl_ssf; /* SASL Security Strength Factor */
- netsec_sasl_callback sasl_proto_cb; /* SASL callback we use */
sasl_callback_t *sasl_cbs; /* Callbacks used by SASL */
nmh_creds_t sasl_creds; /* Credentials (username/password) */
sasl_secret_t *sasl_secret; /* SASL password structure */
- char *sasl_chosen_mech; /* Mechanism chosen by SASL */
int sasl_seclayer; /* If true, SASL security layer is enabled */
char *sasl_tmpbuf; /* Temporary read buffer for decodes */
size_t sasl_maxbufsize; /* Maximum negotiated SASL buffer size */
nsc->ns_outptr = nsc->ns_outbuffer;
nsc->ns_outbuflen = 0;
nsc->sasl_mech = NULL;
+ nsc->sasl_chosen_mech = NULL;
+ nsc->sasl_proto_cb = NULL;
#ifdef OAUTH_SUPPORT
nsc->oauth_service = NULL;
#endif /* OAUTH_SUPPORT */
nsc->sasl_cbs = NULL;
nsc->sasl_creds = NULL;
nsc->sasl_secret = NULL;
- nsc->sasl_chosen_mech = NULL;
nsc->sasl_ssf = 0;
nsc->sasl_seclayer = 0;
nsc->sasl_tmpbuf = NULL;
free(nsc->ns_outbuffer);
if (nsc->sasl_mech)
free(nsc->sasl_mech);
+ if (nsc->sasl_chosen_mech)
+ free(nsc->sasl_chosen_mech);
#ifdef OAUTH_SERVICE
if (nsc->oauth_service)
free(nsc->oauth_service);
}
free(nsc->sasl_secret);
}
- if (nsc->sasl_chosen_mech)
- free(nsc->sasl_chosen_mech);
if (nsc->sasl_tmpbuf)
free(nsc->sasl_tmpbuf);
#endif /* CYRUS_SASL */
netsec_b64_snoop_decoder(netsec_context *nsc, const char *string, size_t len,
void *context)
{
- const char *decoded;
+ unsigned char *decoded;
size_t decodedlen;
int offset;
NMH_UNUSED(nsc);
*
* - Unlike every other function, we return a pointer to the
* existing buffer. This pointer is valid until you call another
- * read functiona again.
- * - We NUL-terminated the buffer right at the end, before the terminator.
+ * read function again.
+ * - We NUL-terminate the buffer right at the end, before the CR-LF terminator.
* - Technically we look for a LF; if we find a CR right before it, then
* we back up one.
- * - If your data may contain embedded NULs, this won't work.
+ * - If your data may contain embedded NULs, this won't work. You should
+ * be using netsec_read() in that case.
*/
char *
nsc->ns_inptr = nsc->ns_inbuffer;
}
+#ifdef CYRUS_SASL
retry:
+#endif /* CYRUS_SASL */
/*
* If we are using TLS and there's anything pending, then skip the
* select call
return NOTOK;
}
+ nsc->sasl_hostname = getcpy(hostname);
+#else /* CYRUS_SASL */
+ NMH_UNUSED(hostname);
+ NMH_UNUSED(service);
+ NMH_UNUSED(errstr);
+#endif /* CYRUS_SASL */
+
/*
* According to the RFC, mechanisms can only be uppercase letter, numbers,
* and a hypen or underscore. So make sure we uppercase any letters
}
nsc->sasl_proto_cb = callback;
- nsc->sasl_hostname = getcpy(hostname);
return OK;
-#else /* CYRUS_SASL */
- netsec_err(errstr, "SASL is not supported");
-
- return NOTOK;
-#endif /* CYRUS_SASL */
}
#ifdef CYRUS_SASL
unsigned char *xoauth_client_res;
size_t xoauth_client_res_len;
#endif /* OAUTH_SUPPORT */
+#if defined CYRUS_SASL || defined OAUTH_SUPPORT
int rc;
+#endif /* CYRUS_SASL || OAUTH_SUPPORT */
/*
* If we've been passed a requested mechanism, check our mechanism
/*
* We're going to assume the error here is a JSON response;
* we ignore it and send a blank message in response. We should
- * then get either an +OK or -ERR
+ * then get a failure messages with a useful error. We should
+ * NOT get a success message at this point.
*/
free(*errstr);
nsc->sasl_proto_cb(NETSEC_SASL_WRITE, NULL, 0, NULL, 0, NULL);
return OK;
#else
- netsec_err(errstr, "SASL not supported");
+ /*
+ * If we're at this point, then either we have NEITHER OAuth2 or
+ * Cyrus-SASL compiled in, or have OAuth2 but didn't give the XOAUTH2
+ * mechanism on the command line.
+ */
+
+ if (! nsc->sasl_mech)
+ netsec_err(errstr, "SASL library support not available; please "
+ "specify a SASL mechanism to use");
+ else
+ netsec_err(errstr, "No support for the %s SASL mechanism",
+ nsc->sasl_mech);
return NOTOK;
#endif /* CYRUS_SASL */
char *
netsec_get_sasl_mechanism(netsec_context *nsc)
{
-#ifdef CYRUS_SASL
return nsc->sasl_chosen_mech;
-#else /* CYRUS_SASL */
- return NULL;
-#endif /* CYRUS_SASL */
}
/*
nsc->oauth_service = getcpy(service);
return OK;
#else /* OAUTH_SUPPORT */
+ NMH_UNUSED(nsc);
+ NMH_UNUSED(service);
return NOTOK;
#endif /* OAUTH_SUPPORT */
}
* supplied socket.
*
* Then we create an SSL BIO, and assign our current SSL connection
- * to it. We then create a buffer BIO and push it in front of our
- * SSL BIO. So the chain looks like:
- *
- * buffer BIO -> SSL BIO -> socket BIO.
+ * to it. This is done so our code stays simple if we want to use
+ * any buffering BIOs (right now we do our own buffering).
+ * So the chain looks like:
*
- * So writes and reads are buffered (we mostly care about writes).
+ * SSL BIO -> socket BIO.
*/
rbio = BIO_new_socket(nsc->ns_readfd, BIO_NOCLOSE);