- 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)
- {
- uschar *ssave = string_copy(s);
- if (!first)
- {
- if (smtp_write_command(sx, SCMD_FLUSH, "*\r\n") >= 0)
- (void) smtp_read_response(sx, US buffer, buffsize, '2', timeout);
- }
- if (f.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
- unembellished. */
-
- if (first)
- {
- first = FALSE;
- if (smtp_write_command(sx, SCMD_FLUSH, "AUTH %s%s%s\r\n",
- ablock->public_name, len == 0 ? "" : " ", b64encode(ss, len)) < 0)
- return FAIL_SEND;
- }
- else
- {
- if (smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", 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? */
-
- if (smtp_read_response(sx, US buffer, buffsize, '2', timeout)) return OK;
-
- /* Not a success response. If errno != 0 there is some kind of transmission
- error. Otherwise, check the response code in the buffer. If it starts with
- '3', more data is expected. */
-
- if (errno != 0 || buffer[0] != '3') return FAIL;
-
- /* If there is no more data to send, we have to cancel the authentication
- exchange and return ERROR. */
-