Hi,
For some experiments with different authentication algorithms I wanted
to implement them in exim -- on the server side this isn't too hard, but
on the client side it doesn't give me what the server said.
The following patch allows the use of $0, $1, ... in the client_send
variable and introduces a new option called client_ignore_invalid_base64
that controls whether base64 decoding errors on server responses are
ignored (current behaviour since it isn't even decoded) or not.
The patch also includes documentation updates, though I'm not sure the
format is correct.
I'd appreciate comments on this.
Thanks,
johannes
[patch follows]
--- exim4-4.60/doc/OptionLists.txt 2005-11-28 11:57:32.000000000 +0100
+++ exim4-4.60.mod/doc/OptionLists.txt 2006-02-20 13:28:35.710453000 +0100
@@ -124,6 +124,7 @@
check_string string "From " appendfile 3.03
unset pipe 3.03
check_srv string* unset dnslookup 4.31
+client_ignore_invalid_base64 boolean true plaintext XXXX
client_name string* + cram_md5 3.10
client_secret string* unset cram_md5 3.10
client_send string* unset plaintext 3.10
--- exim4-4.60/doc/spec.txt 2006-02-20 13:15:43.794457000 +0100
+++ exim4-4.60.mod/doc/spec.txt 2006-02-20 16:22:08.627395000 +0100
@@ -19874,7 +19874,14 @@
34.5 Using plaintext in a client
-The plaintext authenticator has just one client option:
+The plaintext authenticator has two client options:
+
++-----------------------------------------------------------------------------+
+|client_ignore_invalid_base64 | Use: plaintext | Type: boolean | Default: true|
++-----------------------------------------------------------------------------+
+
+If this option is set, the client will not fail when the server sends invalid
+base64 encoded strings during the authentication.
+-----------------------------------------------------------------------------+
|client_send | Use: plaintext | Type: string* | Default: unset|
@@ -19914,6 +19921,12 @@
The initial colon means that the first string is empty, so no data is sent with
the AUTH command itself. The remaining strings are sent in response to prompts.
+Within the strings, the expansion variables $0, $1, ... are available with the
+server responses (only after those are sent, of course, so in the first part
+you cannot use any, in the second part you can use $0, in the third $0 and $1
+etc.). If client_ignore_invalid_base64 is set, a string that could not be
+decoded is empty instead.
+
35. The cram_md5 authenticator
The CRAM-MD5 authentication mechanism is described in RFC 2195. The server
--- exim4-4.60/src/auths/plaintext.c 2005-11-28 11:57:32.000000000 +0100
+++ exim4-4.60.mod/src/auths/plaintext.c 2006-02-20 16:25:45.573393000 +0100
@@ -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 @@
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 */
};
@@ -214,8 +217,11 @@
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, *noclear = "";
+
+ expand_nmax = -1;
/* Forced expansion failure is not an error; authentication is abandoned. On
all but the first string, we have to abandon the authentication attempt by
@@ -295,6 +301,28 @@
"authenticator", ablock->name);
return ERROR;
}
+
+ /* now that we know we'll continue, we put the received data into $n,
+ * if possible */
+ clear_len = auth_b64decode(buffer+4, &clear);
+ if (clear_len < 0) {
+ if (!ob->client_ignore_invalid_base64) {
+ /* the server sent an invalid base64 string...
+ * we should explicitly terminate this AUTH anyway */
+ if (smtp_write_command(outblock, FALSE, "*\r\n") >= 0)
+ (void) smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
+ return FAIL;
+ }
+ /* ignore this and put an empty string into the $n var */
+ clear_len = 0;
+ clear = noclear;
+ }
+ if ((clear_len >= 0) && (expand_nmax < EXPAND_MAXN)) {
+ expand_nmax++;
+ expand_nstring[expand_nmax] = string_copy(clear);
+ expand_nlength[expand_nmax] = Ustrlen(expand_nstring[expand_nmax]);
+ }
+
}
/* Control should never actually get here. */
--- exim4-4.60/src/auths/plaintext.h 2005-11-28 11:57:32.000000000 +0100
+++ exim4-4.60.mod/src/auths/plaintext.h 2006-02-20 12:26:46.000000000 +0100
@@ -13,6 +13,7 @@
uschar *server_condition;
uschar *server_prompts;
uschar *client_send;
+ BOOL client_ignore_invalid_base64;
} auth_plaintext_options_block;
/* Data for reading the private options. */