X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f78eb7c6264c5f1a4ec2fb24c39060e0686f7714..184e88237dea64ce48076cdd0184612d057cbafd:/src/src/auths/plaintext.c diff --git a/src/src/auths/plaintext.c b/src/src/auths/plaintext.c index e5f261a16..cacb91f7d 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.4 2006/02/10 14:25:43 ph10 Exp $ */ +/* $Cambridge: exim/src/src/auths/plaintext.c,v 1.7 2007/01/08 10:50:19 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2006 */ +/* Copyright (c) University of Cambridge 1995 - 2007 */ /* See the file NOTICE for conditions of use and distribution. */ #include "../exim.h" @@ -14,10 +14,10 @@ /* 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, - (void *)(offsetof(auth_plaintext_options_block, server_condition)) }, { "server_prompts", opt_stringptr, (void *)(offsetof(auth_plaintext_options_block, server_prompts)) } }; @@ -31,9 +31,9 @@ int auth_plaintext_options_count = /* Default private options block for the plaintext authentication method. */ 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 */ }; @@ -51,7 +51,7 @@ auth_plaintext_init(auth_instance *ablock) auth_plaintext_options_block *ob = (auth_plaintext_options_block *)(ablock->options_block); if (ablock->public_name == NULL) ablock->public_name = ablock->name; -if (ob->server_condition != NULL) ablock->server = TRUE; +if (ablock->server_condition != NULL) ablock->server = TRUE; if (ob->client_send != NULL) ablock->client = TRUE; } @@ -69,7 +69,7 @@ auth_plaintext_server(auth_instance *ablock, uschar *data) auth_plaintext_options_block *ob = (auth_plaintext_options_block *)(ablock->options_block); uschar *prompts = ob->server_prompts; -uschar *clear, *cond, *end, *s; +uschar *clear, *end, *s; int number = 1; int len, rc; int sep = 0; @@ -138,59 +138,12 @@ while ((s = string_nextinlist(&prompts, &sep, big_buffer, big_buffer_size)) } /* 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. */ +compatibility, in $1, $2, etc). Authentication and authorization are handled +together for this authenticator by expanding the server_condition option. Note +that ablock->server_condition is always non-NULL because that's what configures +this authenticator as a server. */ -cond = expand_string(ob->server_condition); - -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 */ - if (cond == NULL) - debug_printf("expansion failed: %s\n", expand_string_message); - else - debug_printf("expanded string: %s\n", cond); - } - -/* A forced expansion failure causes authentication to fail. Other expansion -failures yield DEFER, which will cause a temporary error code to be returned to -the AUTH command. The problem is at the server end, so the client should try -again later. */ - -if (cond == NULL) - { - if (expand_string_forcedfail) return FAIL; - auth_defer_msg = expand_string_message; - return DEFER; - } - -/* Return FAIL for empty string, "0", "no", and "false"; return OK for -"1", "yes", and "true"; return DEFER for anything else, with the string -available as an error text for the user. */ - -if (*cond == 0 || - Ustrcmp(cond, "0") == 0 || - strcmpic(cond, US"no") == 0 || - strcmpic(cond, US"false") == 0) - return FAIL; - -if (Ustrcmp(cond, "1") == 0 || - strcmpic(cond, US"yes") == 0 || - strcmpic(cond, US"true") == 0) - return OK; - -auth_defer_msg = cond; -auth_defer_user_msg = string_sprintf(": %s", cond); -return DEFER; +return auth_check_serv_cond(ablock); } @@ -216,6 +169,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 @@ -223,8 +177,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 @@ -239,7 +194,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; @@ -304,6 +263,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. */