Build: avoid compiling code for unused transports, routers, authenticators
[exim.git] / src / src / auths / spa.c
index e7a588dd203e3afb9be8f4bdf5ac21d63e6fd810..51418c4ed1736af57a8e856166fc5410d3507d26 100644 (file)
@@ -2,9 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
 /* 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 */
 
 /* This file, which provides support for Microsoft's Secure Password
 Authentication, was contributed by Marc Prud'hommeaux. Tom Kistner added SPA
@@ -33,6 +34,8 @@ References:
 
 
 #include "../exim.h"
+
+#ifdef AUTH_SPA                /* Remainder of file */
 #include "spa.h"
 
 /* #define DEBUG_SPA */
@@ -140,7 +143,8 @@ SPAAuthChallenge challenge;
 SPAAuthResponse  response;
 SPAAuthResponse  *responseptr = &response;
 uschar msgbuf[2048];
-uschar *clearpass;
+uschar *clearpass, *s;
+unsigned off;
 
 /* send a 334, MS Exchange style, and grab the client's request,
 unless we already have it via an initial response. */
@@ -187,9 +191,19 @@ that causes failure if the size of msgbuf is exceeded. ****/
 
   {
   int i;
-  char * p = (CS responseptr) + IVAL(&responseptr->uUser.offset,0);
+  char * p;
   int len = SVAL(&responseptr->uUser.len,0)/2;
 
+  if (  (off = IVAL(&responseptr->uUser.offset,0)) >= sizeof(SPAAuthResponse)
+     || len >= sizeof(responseptr->buffer)/2
+     || (p = (CS responseptr) + off) + len*2 >= CS (responseptr+1)
+     )
+    {
+    DEBUG(D_auth)
+      debug_printf("auth_spa_server(): bad uUser spec in response\n");
+    return FAIL;
+    }
+
   if (len + 1 >= sizeof(msgbuf)) return FAIL;
   for (i = 0; i < len; ++i)
     {
@@ -235,8 +249,16 @@ spa_smb_nt_encrypt(clearpass, challenge.challengeData, ntRespData);
 
 /* compare NT hash (LM may not be available) */
 
-if (memcmp(ntRespData, (US responseptr)+IVAL(&responseptr->ntResponse.offset,0),
-      24) == 0)
+off = IVAL(&responseptr->ntResponse.offset,0);
+if (off >= sizeof(SPAAuthResponse) - 24)
+  {
+  DEBUG(D_auth)
+    debug_printf("auth_spa_server(): bad ntRespData spec in response\n");
+  return FAIL;
+  }
+s = (US responseptr) + off;
+
+if (memcmp(ntRespData, s, 24) == 0)
   return auth_check_serv_cond(ablock); /* success. we have a winner. */
 
   /* Expand server_condition as an authorization check (PH) */
@@ -265,14 +287,13 @@ SPAAuthRequest   request;
 SPAAuthChallenge challenge;
 SPAAuthResponse  response;
 char msgbuf[2048];
-char *domain = NULL;
-char *username, *password;
+uschar * domain = NULL, * username, * password;
 
 /* Code added by PH to expand the options */
 
 *buffer = 0;    /* Default no message when cancelled */
 
-if (!(username = CS expand_string(ob->spa_username)))
+if (!(username = expand_string(ob->spa_username)))
   {
   if (f.expand_string_forcedfail) return CANCELLED;
   string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
@@ -281,7 +302,7 @@ if (!(username = CS expand_string(ob->spa_username)))
   return ERROR;
   }
 
-if (!(password = CS expand_string(ob->spa_password)))
+if (!(password = expand_string(ob->spa_password)))
   {
   if (f.expand_string_forcedfail) return CANCELLED;
   string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
@@ -291,7 +312,7 @@ if (!(password = CS expand_string(ob->spa_password)))
   }
 
 if (ob->spa_domain)
-  if (!(domain = CS expand_string(ob->spa_domain)))
+  if (!(domain = expand_string(ob->spa_domain)))
     {
     if (f.expand_string_forcedfail) return CANCELLED;
     string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
@@ -311,7 +332,7 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout))
 
 DSPA("\n\n%s authenticator: using domain %s\n\n", ablock->name, domain);
 
-spa_build_auth_request(&request, CS username, domain);
+spa_build_auth_request(&request, username, domain);
 spa_bits_to_base64(US msgbuf, US &request, spa_request_length(&request));
 
 DSPA("\n\n%s authenticator: sending request (%s)\n\n", ablock->name, msgbuf);
@@ -328,7 +349,7 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout))
 DSPA("\n\n%s authenticator: challenge (%s)\n\n", ablock->name, buffer + 4);
 spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4));
 
-spa_build_auth_response(&challenge, &response, CS username, CS password);
+spa_build_auth_response(&challenge, &response, username, password);
 spa_bits_to_base64(US msgbuf, US &response, spa_request_length(&response));
 DSPA("\n\n%s authenticator: challenge response (%s)\n\n", ablock->name, msgbuf);
 
@@ -353,5 +374,6 @@ if (errno != 0 || buffer[0] != '3')
 return FAIL;
 }
 
-#endif   /*!MACRO_PREDEF*/
+#endif /*!MACRO_PREDEF*/
+#endif /*AUTH_SPA*/
 /* End of spa.c */