- int i, len, clear_len;
- uschar *ss = expand_string(s);
- uschar *clear;
-
- /* Forced expansion failure is not an error; authentication is abandoned. On
- all but the first string, we have to abandon the authentication attempt by
- sending a line containing "*". Save the failed expansion string, because it
- is in big_buffer, and that gets used by the sending function. */
-
- if (ss == NULL)
- {
- uschar *ssave = string_copy(s);
- if (!first)
- {
- if (smtp_write_command(outblock, FALSE, "*\r\n") >= 0)
- (void) smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
- }
- if (expand_string_forcedfail)
- {
- *buffer = 0; /* No message */
- return CANCELLED;
- }
- string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
- "authenticator: %s", ssave, ablock->name, expand_string_message);
- return ERROR;
- }
-
- len = Ustrlen(ss);
-
- /* The character ^ is used as an escape for a binary zero character, which is
- needed for the PLAIN mechanism. It must be doubled if really needed. */
-
- for (i = 0; i < len; i++)
- {
- if (ss[i] == '^')
- {
- if (ss[i+1] != '^') ss[i] = 0; else
- {
- i++;
- len--;
- memmove(ss + i, ss + i + 1, len - i);
- }
- }
- }
-
- /* The first string is attached to the AUTH command; others are sent
- unembelished. */
-
- if (first)
- {
- first = FALSE;
- if (smtp_write_command(outblock, FALSE, "AUTH %s%s%s\r\n",
- ablock->public_name, (len == 0)? "" : " ",
- auth_b64encode(ss, len)) < 0)
- return FAIL_SEND;
- }
- else
- {
- if (smtp_write_command(outblock, FALSE, "%s\r\n",
- auth_b64encode(ss, len)) < 0)
- return FAIL_SEND;
- }
-
- /* If we receive a success response from the server, authentication
- has succeeded. There may be more data to send, but is there any point
- in provoking an error here? */