+ switch (mtype) {
+ case NETSEC_SASL_START:
+ /*
+ * Generate our AUTH message, but there is a wrinkle.
+ *
+ * Technically, according to RFC 5034, if your command INCLUDING
+ * an initial response exceeds 255 octets (including CRLF), you
+ * can't issue this all in one go, but have to just issue the
+ * AUTH command, wait for a blank initial response, and then
+ * send your data.
+ */
+
+ mech = netsec_get_sasl_mechanism(nsc);
+
+ if (indatalen) {
+ char *b64data;
+ b64data = mh_xmalloc(BASE64SIZE(indatalen));
+ writeBase64raw(indata, indatalen, (unsigned char *) b64data);
+ b64len = strlen(b64data);
+
+ /* Formula here is AUTH + SP + mech + SP + out + CR + LF */
+ len = b64len + 8 + strlen(mech);
+ if (len > 255) {
+ rc = netsec_printf(nsc, errstr, "AUTH %s\r\n", mech);
+ if (rc)
+ return NOTOK;
+ if (netsec_flush(nsc, errstr) != OK)
+ return NOTOK;
+ line = netsec_readline(nsc, &len, errstr);
+ if (! line)
+ return NOTOK;
+ /*
+ * If the protocol is being followed correctly, should just
+ * be a "+ ", nothing else.
+ */
+ if (len != 2 || strcmp(line, "+ ") != 0) {
+ netsec_err(errstr, "Did not get expected blank response "
+ "for initial challenge response");
+ return NOTOK;
+ }
+ rc = netsec_printf(nsc, errstr, "%s\r\n", b64data);
+ free(b64data);
+ if (rc != OK)
+ return NOTOK;
+ netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL);
+ rc = netsec_flush(nsc, errstr);
+ netsec_set_snoop_callback(nsc, NULL, NULL);
+ if (rc != OK)
+ return NOTOK;
+ } else {
+ rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech,
+ b64data);
+ free(b64data);
+ if (rc != OK)
+ return NOTOK;
+ netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder,
+ &snoopoffset);
+ snoopoffset = 6 + strlen(mech);
+ rc = netsec_flush(nsc, errstr);
+ netsec_set_snoop_callback(nsc, NULL, NULL);
+ if (rc != OK)
+ return NOTOK;
+ }
+ } else {
+ if (netsec_printf(nsc, errstr, "AUTH %s\r\n", mech) != OK)
+ return NOTOK;
+ if (netsec_flush(nsc, errstr) != OK)
+ return NOTOK;
+ }