X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/0756eb3cb50d73a77b486e47528f7cb1bffdb299..4730f9424e0addeb902cc842508eea3f47a131ca:/src/src/auths/plaintext.c diff --git a/src/src/auths/plaintext.c b/src/src/auths/plaintext.c index b15a08d51..2aea4a492 100644 --- a/src/src/auths/plaintext.c +++ b/src/src/auths/plaintext.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/auths/plaintext.c,v 1.1 2004/10/07 13:10:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/auths/plaintext.c,v 1.5 2006/02/23 12:41:22 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2006 */ /* See the file NOTICE for conditions of use and distribution. */ #include "../exim.h" @@ -14,6 +14,8 @@ /* Options specific to the plaintext authentication mechanism. */ optionlist auth_plaintext_options[] = { + { "client_ignore_invalid_base64", opt_bool, + (void *)(offsetof(auth_plaintext_options_block, client_ignore_invalid_base64)) }, { "client_send", opt_stringptr, (void *)(offsetof(auth_plaintext_options_block, client_send)) }, { "server_condition", opt_stringptr, @@ -33,7 +35,8 @@ int auth_plaintext_options_count = auth_plaintext_options_block auth_plaintext_option_defaults = { NULL, /* server_condition */ NULL, /* server_prompts */ - NULL /* client_send */ + NULL, /* client_send */ + FALSE /* client_ignore_invalid_base64 */ }; @@ -87,14 +90,16 @@ if (prompts != NULL) } /* If data was supplied on the AUTH command, decode it, and split it up into -multiple items at binary zeros. If the data consists of the string "=" it -indicates a single, empty string. */ +multiple items at binary zeros. The strings are put into $auth1, $auth2, etc, +up to a maximum. To retain backwards compatibility, they are also put int $1, +$2, etc. If the data consists of the string "=" it indicates a single, empty +string. */ if (*data != 0) { if (Ustrcmp(data, "=") == 0) { - expand_nstring[++expand_nmax] = US""; + auth_vars[0] = expand_nstring[++expand_nmax] = US""; expand_nlength[expand_nmax] = 0; } else @@ -103,6 +108,7 @@ if (*data != 0) end = clear + len; while (clear < end && expand_nmax < EXPAND_MAXN) { + if (expand_nmax < AUTH_VARS) auth_vars[expand_nmax] = clear; expand_nstring[++expand_nmax] = clear; while (*clear != 0) clear++; expand_nlength[expand_nmax] = clear++ - expand_nstring[expand_nmax]; @@ -126,6 +132,7 @@ while ((s = string_nextinlist(&prompts, &sep, big_buffer, big_buffer_size)) /* This loop must run at least once, in case the length is zero */ do { + if (expand_nmax < AUTH_VARS) auth_vars[expand_nmax] = clear; expand_nstring[++expand_nmax] = clear; while (*clear != 0) clear++; expand_nlength[expand_nmax] = clear++ - expand_nstring[expand_nmax]; @@ -133,9 +140,9 @@ while ((s = string_nextinlist(&prompts, &sep, big_buffer, big_buffer_size)) while (clear < end && expand_nmax < EXPAND_MAXN); } -/* We now have a number of items of data in $1, $2, etc. Match against the -decoded data by expanding the condition. Also expand the id to set if -authentication succeeds. */ +/* We now have a number of items of data in $auth1, $auth2, etc (and also, for +compatibility, in $1, $2, etc). Match against the decoded data by expanding the +condition. */ cond = expand_string(ob->server_condition); @@ -143,6 +150,11 @@ HDEBUG(D_auth) { int i; debug_printf("%s authenticator:\n", ablock->name); + for (i = 0; i < AUTH_VARS; i++) + { + if (auth_vars[i] != NULL) + debug_printf(" $auth%d = %s\n", i + 1, auth_vars[i]); + } for (i = 1; i <= expand_nmax; i++) debug_printf(" $%d = %.*s\n", i, expand_nlength[i], expand_nstring[i]); debug_print_string(ablock->server_debug_string); /* customized debug */ @@ -207,6 +219,7 @@ uschar *text = ob->client_send; uschar *s; BOOL first = TRUE; int sep = 0; +int auth_var_idx = 0; /* The text is broken up into a number of different data items, which are sent one by one. The first one is sent with the AUTH command; the remainder are @@ -214,8 +227,9 @@ sent in response to subsequent prompts. Each is expanded before being sent. */ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)) != NULL) { - int i, len; + 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 @@ -230,7 +244,11 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)) != NULL if (smtp_write_command(outblock, FALSE, "*\r\n") >= 0) (void) smtp_read_response(inblock, US buffer, buffsize, '2', timeout); } - if (expand_string_forcedfail) return CANCELLED; + 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; @@ -295,6 +313,34 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)) != NULL "authenticator", ablock->name); return ERROR; } + + /* Now that we know we'll continue, we put the received data into $auth, + 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. */ + + 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; + } + + if (auth_var_idx < AUTH_VARS) + auth_vars[auth_var_idx++] = string_copy(clear); } /* Control should never actually get here. */