- if (start && decodeBase64 (start, &decoded, &decoded_len, 1, NULL) == OK) {
- char *hexified;
- char *prefix = mh_xmalloc(prefix_len + 1);
- char *display_string;
-
- /* prefix is the beginning portion, which isn't base64 encoded. */
- snprintf (prefix, prefix_len + 1, "%*s", prefix_len, string);
- hexify ((const unsigned char *) decoded, decoded_len, &hexified);
- /* Wrap the decoded portion in "b64<>". */
- display_string = concat (prefix, "b64<", hexified, ">", NULL);
- free (hexified);
- free (prefix);
- free ((char *) decoded);
-
- return display_string;
- } else {
- return getcpy (string);
+ switch (mtype) {
+ case NETSEC_SASL_START:
+ /*
+ * Generate an AUTH message; if we were given an input token
+ * then generate a an AUTH message that includes the initial
+ * response.
+ */
+
+ mech = netsec_get_sasl_mechanism(nsc);
+
+ if (indatalen) {
+ char *b64data;
+
+ b64data = mh_xmalloc(BASE64SIZE(indatalen));
+ writeBase64raw(indata, indatalen, (unsigned char *) b64data);
+
+ netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder,
+ &snoopoffset);
+ snoopoffset = 6 + strlen(mech);
+ rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech, b64data);
+ free(b64data);
+ netsec_set_snoop_callback(nsc, NULL, NULL);
+ } else {
+ rc = netsec_printf(nsc, errstr, "AUTH %s\r\n", mech);
+ }
+
+ if (rc != OK)
+ return NOTOK;
+
+ if (netsec_flush(nsc, errstr) != OK)
+ return NOTOK;
+
+ break;
+
+ case NETSEC_SASL_READ:
+ /*
+ * Read in a line that should contain a 334 response code, followed
+ * by base64 response data.
+ */
+
+ netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset);
+ snoopoffset = 4;
+ line = netsec_readline(nsc, &len, errstr);
+ netsec_set_snoop_callback(nsc, NULL, NULL);
+
+ if (line == NULL)
+ return NOTOK;
+
+ if (len < 4) {
+ netsec_err(errstr, "Invalid format for SASL response");
+ return NOTOK;
+ }
+
+ if (strncmp(line, "334 ", 4) != 0) {
+ netsec_err(errstr, "Improper SASL protocol response: %s", line);
+ return NOTOK;
+ }
+
+ if (len == 4) {
+ *outdata = NULL;
+ *outdatalen = 0;
+ } else {
+ rc = decodeBase64(line + 4, (const char **) outdata, &len, 0, NULL);
+ if (rc != OK) {
+ netsec_err(errstr, "Unable to decode base64 response");
+ return NOTOK;
+ }
+ *outdatalen = len;
+ }
+ break;
+
+ case NETSEC_SASL_WRITE:
+ /*
+ * The output encoding is pretty simple, so this is easy.
+ */
+ if (indatalen == 0) {
+ rc = netsec_printf(nsc, errstr, "\r\n");
+ } else {
+ unsigned char *b64data;
+ b64data = mh_xmalloc(BASE64SIZE(indatalen));
+ writeBase64raw(indata, indatalen, b64data);
+ netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL);
+ rc = netsec_printf(nsc, errstr, "%s\r\n", b64data);
+ netsec_set_snoop_callback(nsc, NULL, NULL);
+ free(b64data);
+ }
+
+ if (rc != OK)
+ return NOTOK;
+
+ if (netsec_flush(nsc, errstr) != OK)
+ return NOTOK;
+ break;
+
+ case NETSEC_SASL_FINISH:
+ /*
+ * Finish the protocol; we're looking for a 235 message.
+ */
+ line = netsec_readline(nsc, &len, errstr);
+ if (line == NULL)
+ return NOTOK;
+
+ if (strncmp(line, "235 ", 4) != 0) {
+ if (len > 4)
+ netsec_err(errstr, "Authentication failed: %s", line + 4);
+ else
+ netsec_err(errstr, "Authentication failed: %s", line);
+ return NOTOK;
+ }
+ break;
+
+ case NETSEC_SASL_CANCEL:
+ /*
+ * Cancel the SASL exchange; this is done by sending a single "*".
+ */
+ rc = netsec_printf(nsc, errstr, "*\r\n");
+ if (rc == OK)
+ rc = netsec_flush(nsc, errstr);
+ if (rc != OK)
+ return NOTOK;
+ break;