X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/4730f9424e0addeb902cc842508eea3f47a131ca..1d28cc061677bd07d9bed48dd84bd5c590247043:/src/src/auths/cram_md5.c diff --git a/src/src/auths/cram_md5.c b/src/src/auths/cram_md5.c index 26521fbe9..280b5293a 100644 --- a/src/src/auths/cram_md5.c +++ b/src/src/auths/cram_md5.c @@ -1,11 +1,11 @@ -/* $Cambridge: exim/src/src/auths/cram_md5.c,v 1.5 2006/02/23 12:41:22 ph10 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2006 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ +/* Copyright (c) The Exim Maintainers 2020 */ /* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* The stand-alone version just tests the algorithm. We have to drag @@ -27,11 +27,11 @@ program. */ optionlist auth_cram_md5_options[] = { { "client_name", opt_stringptr, - (void *)(offsetof(auth_cram_md5_options_block, client_name)) }, + OPT_OFF(auth_cram_md5_options_block, client_name) }, { "client_secret", opt_stringptr, - (void *)(offsetof(auth_cram_md5_options_block, client_secret)) }, + OPT_OFF(auth_cram_md5_options_block, client_secret) }, { "server_secret", opt_stringptr, - (void *)(offsetof(auth_cram_md5_options_block, server_secret)) } + OPT_OFF(auth_cram_md5_options_block, server_secret) } }; /* Size of the options list. An extern variable has to be used so that its @@ -40,7 +40,7 @@ address can appear in the tables drtables.c. */ int auth_cram_md5_options_count = sizeof(auth_cram_md5_options)/sizeof(optionlist); -/* Default private options block for the contidion authentication method. */ +/* Default private options block for the condition authentication method. */ auth_cram_md5_options_block auth_cram_md5_option_defaults = { NULL, /* server_secret */ @@ -49,6 +49,17 @@ auth_cram_md5_options_block auth_cram_md5_option_defaults = { }; +#ifdef MACRO_PREDEF + +/* Dummy values */ +void auth_cram_md5_init(auth_instance *ablock) {} +int auth_cram_md5_server(auth_instance *ablock, uschar *data) {return 0;} +int auth_cram_md5_client(auth_instance *ablock, void *sx, int timeout, + uschar *buffer, int buffsize) {return 0;} + +#else /*!MACRO_PREDEF*/ + + /************************************************* * Initialization entry point * *************************************************/ @@ -70,12 +81,14 @@ if (ob->client_secret != NULL) } } +#endif /*!MACRO_PREDEF*/ #endif /* STAND_ALONE */ +#ifndef MACRO_PREDEF /************************************************* -* Peform the CRAM-MD5 algorithm * +* Perform the CRAM-MD5 algorithm * *************************************************/ /* The CRAM-MD5 algorithm is described in RFC 2195. It computes @@ -98,7 +111,6 @@ static void compute_cram_md5(uschar *secret, uschar *challenge, uschar *digestptr) { md5 base; -int i; int len = Ustrlen(secret); uschar isecret[64]; uschar osecret[64]; @@ -110,8 +122,8 @@ and use that. */ if (len > 64) { md5_start(&base); - md5_end(&base, (uschar *)secret, len, md5secret); - secret = (uschar *)md5secret; + md5_end(&base, US secret, len, md5secret); + secret = US md5secret; len = 16; } @@ -122,7 +134,7 @@ memcpy(isecret, secret, len); memset(isecret+len, 0, 64-len); memcpy(osecret, isecret, 64); -for (i = 0; i < 64; i++) +for (int i = 0; i < 64; i++) { isecret[i] ^= 0x36; osecret[i] ^= 0x5c; @@ -132,7 +144,7 @@ for (i = 0; i < 64; i++) md5_start(&base); md5_mid(&base, isecret); -md5_end(&base, (uschar *)challenge, Ustrlen(challenge), md5secret); +md5_end(&base, US challenge, Ustrlen(challenge), md5secret); /* Compute the outer MD5 digest */ @@ -155,8 +167,8 @@ auth_cram_md5_server(auth_instance *ablock, uschar *data) { auth_cram_md5_options_block *ob = (auth_cram_md5_options_block *)(ablock->options_block); -uschar *challenge = string_sprintf("<%d.%d@%s>", getpid(), time(NULL), - primary_hostname); +uschar *challenge = string_sprintf("<%d.%ld@%s>", getpid(), + (long int) time(NULL), primary_hostname); uschar *clear, *secret; uschar digest[16]; int i, rc, len; @@ -164,17 +176,17 @@ int i, rc, len; /* If we are running in the test harness, always send the same challenge, an example string taken from the RFC. */ -if (running_in_test_harness) +if (f.running_in_test_harness) challenge = US"<1896.697170952@postoffice.reston.mci.net>"; /* No data should have been sent with the AUTH command */ -if (*data != 0) return UNEXPECTED; +if (*data) return UNEXPECTED; /* Send the challenge, read the return */ if ((rc = auth_get_data(&data, challenge, Ustrlen(challenge))) != OK) return rc; -if ((len = auth_b64decode(data, &clear)) < 0) return BAD64; +if ((len = b64decode(data, &clear)) < 0) return BAD64; /* The return consists of a user name, space-separated from the CRAM-MD5 digest, expressed in hex. Extract the user name and put it in $auth1 and $1. @@ -182,7 +194,7 @@ The former is now the preferred variable; the latter is the original one. Then check that the remaining length is 32. */ auth_vars[0] = expand_nstring[1] = clear; -while (*clear != 0 && !isspace(*clear)) clear++; +while (*clear && !isspace(*clear)) clear++; if (!isspace(*clear)) return FAIL; *clear++ = 0; @@ -201,7 +213,7 @@ the given name. */ if (secret == NULL) { - if (expand_string_forcedfail) return FAIL; + if (f.expand_string_forcedfail) return FAIL; auth_defer_msg = expand_string_message; return DEFER; } @@ -216,7 +228,7 @@ HDEBUG(D_auth) debug_printf("CRAM-MD5: user name = %s\n", auth_vars[0]); debug_printf(" challenge = %s\n", challenge); debug_printf(" received = %s\n", clear); - Ustrcpy(buff," digest = "); + Ustrcpy(buff, US" digest = "); for (i = 0; i < 16; i++) sprintf(CS buff+22+2*i, "%02x", digest[i]); debug_printf("%.54s\n", buff); } @@ -233,7 +245,8 @@ for (i = 0; i < 16; i++) ((b >= 'a')? b - 'a' + 10 : b - '0')) != digest[i]) return FAIL; } -return OK; +/* Expand server_condition as an authorization check */ +return auth_check_serv_cond(ablock); } @@ -247,8 +260,7 @@ return OK; int auth_cram_md5_client( auth_instance *ablock, /* authenticator block */ - smtp_inblock *inblock, /* input connection */ - smtp_outblock *outblock, /* output connection */ + void * sx, /* smtp connextion */ int timeout, /* command timeout */ uschar *buffer, /* for reading response */ int buffsize) /* size of buffer */ @@ -262,18 +274,18 @@ int i; uschar digest[16]; /* If expansion of either the secret or the user name failed, return CANCELLED -or ERROR, as approriate. */ +or ERROR, as appropriate. */ -if (secret == NULL || name == NULL) +if (!secret || !name) { - if (expand_string_forcedfail) + if (f.expand_string_forcedfail) { *buffer = 0; /* No message */ return CANCELLED; } string_format(buffer, buffsize, "expansion of \"%s\" failed in " "%s authenticator: %s", - (secret == NULL)? ob->client_secret : ob->client_name, + !secret ? ob->client_secret : ob->client_name, ablock->name, expand_string_message); return ERROR; } @@ -281,12 +293,12 @@ if (secret == NULL || name == NULL) /* Initiate the authentication exchange and read the challenge, which arrives in base 64. */ -if (smtp_write_command(outblock, FALSE, "AUTH %s\r\n", ablock->public_name) < 0) +if (smtp_write_command(sx, SCMD_FLUSH, "AUTH %s\r\n", ablock->public_name) < 0) return FAIL_SEND; -if (smtp_read_response(inblock, (uschar *)buffer, buffsize, '3', timeout) < 0) +if (!smtp_read_response(sx, buffer, buffsize, '3', timeout)) return FAIL; -if (auth_b64decode(buffer + 4, &challenge) < 0) +if (b64decode(buffer + 4, &challenge) < 0) { string_format(buffer, buffsize, "bad base 64 string in challenge: %s", big_buffer + 4); @@ -300,26 +312,22 @@ compute_cram_md5(secret, challenge, digest); /* Create the response from the user name plus the CRAM-MD5 digest */ string_format(big_buffer, big_buffer_size - 36, "%s", name); -p = big_buffer; -while (*p != 0) p++; +for (p = big_buffer; *p; ) p++; *p++ = ' '; for (i = 0; i < 16; i++) - { - sprintf(CS p, "%02x", digest[i]); - p += 2; - } + p += sprintf(CS p, "%02x", digest[i]); /* Send the response, in base 64, and check the result. The response is -in big_buffer, but auth_b64encode() returns its result in working store, +in big_buffer, but b64encode() returns its result in working store, so calling smtp_write_command(), which uses big_buffer, is OK. */ buffer[0] = 0; -if (smtp_write_command(outblock, FALSE, "%s\r\n", auth_b64encode(big_buffer, +if (smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", b64encode(CUS big_buffer, p - big_buffer)) < 0) return FAIL_SEND; -return smtp_read_response(inblock, (uschar *)buffer, buffsize, '2', timeout)? - OK : FAIL; +return smtp_read_response(sx, US buffer, buffsize, '2', timeout) + ? OK : FAIL; } #endif /* STAND_ALONE */ @@ -349,4 +357,5 @@ return 0; #endif +#endif /*!MACRO_PREDEF*/ /* End of cram_md5.c */