- /* 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? */
-
- if (smtp_read_response(inblock, 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. */
-
- if (text == NULL)
- {
- if (smtp_write_command(outblock, FALSE, "*\r\n") >= 0)
- (void)smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
- string_format(buffer, buffsize, "Too few items in client_send in %s "
- "authenticator", ablock->name);
- return ERROR;
- }
-
- /* Now that we know we'll continue, we put the received data into $auth<n>,
- if possible. First, decode it: buffer+4 skips over the SMTP status code. */
-
- clear_len = auth_b64decode(buffer+4, &clear);
-
- /* If decoding failed, the default is to terminate the authentication, and
- return FAIL, with the SMTP response still in the buffer. However, if client_
- ignore_invalid_base64 is set, we ignore the error, and put an empty string
- into $auth<n>. */
-
- if (clear_len < 0)
- {
- uschar *save_bad = string_copy(buffer);
- if (!ob->client_ignore_invalid_base64)
- {
- if (smtp_write_command(outblock, FALSE, "*\r\n") >= 0)
- (void)smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
- string_format(buffer, buffsize, "Invalid base64 string in server "
- "response \"%s\"", save_bad);
- return CANCELLED;
- }
- clear = US"";
- clear_len = 0;
- }