build: use pkg-config for i18n
[exim.git] / src / src / auths / auth-spa.c
index 8d886b6b6b650ec353eac7438e044317dcd143bc..96e7148ab4d10bbc8b46c5eabdf2d0d0ebf4a568 100644 (file)
@@ -9,7 +9,8 @@
  * All the original code used here was torn by Marc Prud'hommeaux out of the
  * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
  *
  * All the original code used here was torn by Marc Prud'hommeaux out of the
  * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
  *
- * Copyright (c) The Exim Maintainers 2021
+ * Copyright (c) The Exim Maintainers 2021 - 2023
+ * SPDX-License-Identifier: GPL-2.0-or-later
 
  * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
  * support server authentication mode.
 
  * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
  * support server authentication mode.
@@ -155,6 +156,9 @@ int main (int argc, char ** argv)
    up with a different answer to the one above)
 */
 
    up with a different answer to the one above)
 */
 
+#ifndef MACRO_PREDEF
+
+
 #define DEBUG_X(a,b) ;
 
 extern int DEBUGLEVEL;
 #define DEBUG_X(a,b) ;
 
 extern int DEBUGLEVEL;
@@ -1199,65 +1203,74 @@ char versionString[] = "libntlm version 0.21";
 /* Utility routines that handle NTLM auth structures. */
 
 /* The [IS]VAL macros are to take care of byte order for non-Intel
 /* Utility routines that handle NTLM auth structures. */
 
 /* The [IS]VAL macros are to take care of byte order for non-Intel
- * Machines -- I think this file is OK, but it hasn't been tested.
- * The other files (the ones stolen from Samba) should be OK.
- */
+Machines -- I think this file is OK, but it hasn't been tested.
+The other files (the ones stolen from Samba) should be OK.  */
 
 
 
 
-/* I am not crazy about these macros -- they seem to have gotten
- * a bit complex.  A new scheme for handling string/buffer fields
- * in the structures probably needs to be designed
- */
+/* Append a string to the buffer and point the header struct at that. */
 
 
-#define spa_bytes_add(ptr, header, buf, count) \
-{ \
-if (buf && (count) != 0) /* we hate -Wint-in-bool-contex */ \
-  { \
-  SSVAL(&ptr->header.len,0,count); \
-  SSVAL(&ptr->header.maxlen,0,count); \
-  SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
-  memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
-  ptr->bufIndex += count; \
-  } \
-else \
-  { \
-  ptr->header.len = \
-  ptr->header.maxlen = 0; \
-  SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
-  } \
+static void
+spa_bytes_add(SPAbuf * buffer, size_t off, SPAStrHeader * header,
+  const uschar * src, int count)
+{
+off += buffer->bufIndex;
+if (  src && count != 0                        /* we hate -Wint-in-bool-contex */
+   && buffer->bufIndex + count < sizeof(buffer->buffer)        
+   )
+  {
+  SSVAL(&header->len, 0, count);
+  SSVAL(&header->maxlen, 0, count);
+  SIVAL(&header->offset, 0, off);
+  memcpy(buffer->buffer + buffer->bufIndex, src, count);
+  buffer->bufIndex += count;
+  }
+else
+  {
+  header->len = header->maxlen = 0;
+  SIVAL(&header->offset, 0, off);
+  }
 }
 
 }
 
-#define spa_string_add(ptr, header, string) \
-{ \
-char *p = string; \
-int len = 0; \
-if (p) len = strlen(p); \
-spa_bytes_add(ptr, header, (US p), len); \
+static void
+spa_string_add(SPAbuf * buffer, size_t off, SPAStrHeader * header,
+  const uschar * string)
+{
+int len = string ? Ustrlen(string) : 0;
+spa_bytes_add(buffer, off, header, string, len);
 }
 
 }
 
-#define spa_unicode_add_string(ptr, header, string) \
-{ \
-char *p = string; \
-uschar *b = NULL; \
-int len = 0; \
-if (p) \
-  { \
-  len = strlen(p); \
-  b = strToUnicode(p); \
-  } \
-spa_bytes_add(ptr, header, b, len*2); \
+static uschar *
+strToUnicode(const uschar * p)
+{
+static uschar buf[1024];
+size_t l = Ustrlen(p);
+
+assert (l * 2 < sizeof buf);
+
+for (int i = 0; l--; ) { buf[i++] = *p++; buf[i++] = 0; }
+return buf;
 }
 
 }
 
+static void
+spa_unicode_add_string(SPAbuf * buffer, size_t off, SPAStrHeader * header,
+  const uschar * string)
+{
+const uschar * p = string;
+uschar * b = NULL;
+int len = 0;
+if (p)
+  {
+  len = Ustrlen(p);
+  b = US strToUnicode(p);
+  }
+spa_bytes_add(buffer, off, header, b, len*2);
+}
 
 
-#define GetUnicodeString(structPtr, header) \
-unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
-#define GetString(structPtr, header) \
-toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
 
 #ifdef notdef
 
 #define DumpBuffer(fp, structPtr, header) \
 
 #ifdef notdef
 
 #define DumpBuffer(fp, structPtr, header) \
-dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
+ dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
 
 
 static void
 
 
 static void
@@ -1291,24 +1304,6 @@ buf[i] = '\0';
 return buf;
 }
 
 return buf;
 }
 
-static uschar *
-strToUnicode (char *p)
-{
-static uschar buf[1024];
-size_t l = strlen (p);
-int i = 0;
-
-assert (l * 2 < sizeof buf);
-
-while (l--)
-  {
-  buf[i++] = *p++;
-  buf[i++] = 0;
-  }
-
-return buf;
-}
-
 static uschar *
 toString (char *p, size_t len)
 {
 static uschar *
 toString (char *p, size_t len)
 {
@@ -1321,8 +1316,33 @@ buf[len] = 0;
 return buf;
 }
 
 return buf;
 }
 
+static inline uschar *
+get_challenge_unistr(SPAAuthChallenge * challenge, SPAStrHeader * hdr)
+{
+int off = IVAL(&hdr->offset, 0);
+int len = SVAL(&hdr->len, 0);
+return off + len < sizeof(SPAAuthChallenge)
+  ? US unicodeToString(CS challenge + off, len/2) : US"";
+}
+
+static inline uschar *
+get_challenge_str(SPAAuthChallenge * challenge, SPAStrHeader * hdr)
+{
+int off = IVAL(&hdr->offset, 0);
+int len = SVAL(&hdr->len, 0);
+return off + len < sizeof(SPAAuthChallenge)
+  ? US toString(CS challenge + off, len) : US"";
+}
+
 #ifdef notdef
 
 #ifdef notdef
 
+#define GetUnicodeString(structPtr, header) \
+ unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
+
+#define GetString(structPtr, header) \
+ toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
+
+
 void
 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
 {
 void
 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
 {
@@ -1366,25 +1386,26 @@ fprintf (fp, "      Flags = %08x\n", IVAL (&response->flags, 0));
 #endif
 
 void
 #endif
 
 void
-spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
+spa_build_auth_request (SPAAuthRequest * request, uschar * user, uschar * domain)
 {
 {
-char *u = strdup (user);
-char *p = strchr (u, '@');
+uschar * u = string_copy(user);
+uschar * p = Ustrchr(u, '@');
 
 if (p)
   {
   if (!domain)
 
 if (p)
   {
   if (!domain)
-   domain = p + 1;
+    domain = p + 1;
   *p = '\0';
   }
 
   *p = '\0';
   }
 
-request->bufIndex = 0;
+request->buf.bufIndex = 0;
 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
 SIVAL (&request->msgType, 0, 1);
 SIVAL (&request->flags, 0, 0x0000b207);      /* have to figure out what these mean */
 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
 SIVAL (&request->msgType, 0, 1);
 SIVAL (&request->flags, 0, 0x0000b207);      /* have to figure out what these mean */
-spa_string_add (request, user, u);
-spa_string_add (request, domain, domain);
-free (u);
+spa_string_add(&request->buf, offsetof(SPAAuthRequest, buf), &request->user,
+               u);
+spa_string_add(&request->buf, offsetof(SPAAuthRequest, buf), &request->domain,
+               domain);
 }
 
 
 }
 
 
@@ -1402,7 +1423,7 @@ patch added by PH on suggestion of Russell King */
 
 memset(challenge, 0, sizeof(SPAAuthChallenge));
 
 
 memset(challenge, 0, sizeof(SPAAuthChallenge));
 
-challenge->bufIndex = 0;
+challenge->buf.bufIndex = 0;
 memcpy (challenge->ident, "NTLMSSP\0", 8);
 SIVAL (&challenge->msgType, 0, 2);
 SIVAL (&challenge->flags, 0, 0x00008201);
 memcpy (challenge->ident, "NTLMSSP\0", 8);
 SIVAL (&challenge->msgType, 0, 2);
 SIVAL (&challenge->flags, 0, 0x00008201);
@@ -1424,24 +1445,27 @@ memcpy(challenge->challengeData,chalstr,8);
 
 
 
 
 
 
-/* This is the original source of this function, preserved here for reference.
+/* The original version of this function is available in git.
 The new version below was re-organized by PH following a patch and some further
 suggestions from Mark Lyda to fix the problem that is described at the head of
 this module. At the same time, I removed the untidiness in the code below that
 The new version below was re-organized by PH following a patch and some further
 suggestions from Mark Lyda to fix the problem that is described at the head of
 this module. At the same time, I removed the untidiness in the code below that
-involves the "d" and "domain" variables. */
+involves the "d" and "domain" variables.
+Further modified by JGH to replace complex macro "functions" with real ones. */
 
 
-#ifdef NEVER
 void
 spa_build_auth_response (SPAAuthChallenge * challenge,
 void
 spa_build_auth_response (SPAAuthChallenge * challenge,
-                        SPAAuthResponse * response, char *user,
-                        char *password)
+                        SPAAuthResponse * response, uschar * user,
+                        uschar * password)
 {
 uint8x lmRespData[24];
 uint8x ntRespData[24];
 {
 uint8x lmRespData[24];
 uint8x ntRespData[24];
-char *d = strdup (GetUnicodeString (challenge, uDomain));
-char *domain = d;
-char *u = strdup (user);
-char *p = strchr (u, '@');
+uint32x cf = IVAL(&challenge->flags, 0);
+uschar * u = string_copy(user);
+uschar * p = Ustrchr(u, '@');
+uschar * d = NULL;
+uschar * domain;
+SPAbuf * buf = &response->buf;
+const size_t off = offsetof(SPAAuthResponse, buf);
 
 if (p)
   {
 
 if (p)
   {
@@ -1449,76 +1473,36 @@ if (p)
   *p = '\0';
   }
 
   *p = '\0';
   }
 
-spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
-spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
+else domain = d = string_copy(cf & 0x1
+  ? CUS get_challenge_unistr(challenge, &challenge->uDomain)
+  : CUS get_challenge_str(challenge, &challenge->uDomain));
+
+spa_smb_encrypt(password, challenge->challengeData, lmRespData);
+spa_smb_nt_encrypt(password, challenge->challengeData, ntRespData);
 
 
-response->bufIndex = 0;
+buf->bufIndex = 0;
 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
 SIVAL (&response->msgType, 0, 3);
 
 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
 SIVAL (&response->msgType, 0, 3);
 
-spa_bytes_add (response, lmResponse, lmRespData, 24);
-spa_bytes_add (response, ntResponse, ntRespData, 24);
-spa_unicode_add_string (response, uDomain, domain);
-spa_unicode_add_string (response, uUser, u);
-spa_unicode_add_string (response, uWks, u);
-spa_string_add (response, sessionKey, NULL);
-
-response->flags = challenge->flags;
-
-free (d);
-free (u);
-}
-#endif
-
-
-/* This is the re-organized version (see comments above) */
+spa_bytes_add(buf, off, &response->lmResponse, lmRespData, cf & 0x200 ? 24 : 0);
+spa_bytes_add(buf, off, &response->ntResponse, ntRespData, cf & 0x8000 ? 24 : 0);
 
 
-void
-spa_build_auth_response (SPAAuthChallenge * challenge,
-                        SPAAuthResponse * response, char *user,
-                        char *password)
-{
-uint8x lmRespData[24];
-uint8x ntRespData[24];
-uint32x cf = IVAL(&challenge->flags, 0);
-char *u = strdup (user);
-char *p = strchr (u, '@');
-char *d = NULL;
-char *domain;
-
-if (p)
+if (cf & 0x1)          /* Unicode Text */
   {
   {
-  domain = p + 1;
-  *p = '\0';
+  spa_unicode_add_string(buf, off, &response->uDomain, domain);
+  spa_unicode_add_string(buf, off, &response->uUser, u);
+  spa_unicode_add_string(buf, off, &response->uWks, u);
+  }
+else
+  {                    /* OEM Text */
+  spa_string_add(buf, off, &response->uDomain, domain);
+  spa_string_add(buf, off, &response->uUser, u);
+  spa_string_add(buf, off, &response->uWks, u);
   }
 
   }
 
-else domain = d = strdup((cf & 0x1)?
-  CCS GetUnicodeString(challenge, uDomain) :
-  CCS GetString(challenge, uDomain));
-
-spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
-spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
-
-response->bufIndex = 0;
-memcpy (response->ident, "NTLMSSP\0\0\0", 8);
-SIVAL (&response->msgType, 0, 3);
-
-spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
-spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
-
-if (cf & 0x1) {      /* Unicode Text */
-     spa_unicode_add_string (response, uDomain, domain);
-     spa_unicode_add_string (response, uUser, u);
-     spa_unicode_add_string (response, uWks, u);
-} else {             /* OEM Text */
-     spa_string_add (response, uDomain, domain);
-     spa_string_add (response, uUser, u);
-     spa_string_add (response, uWks, u);
+spa_string_add(buf, off, &response->sessionKey, NULL);
+response->flags = challenge->flags;
 }
 
 }
 
-spa_string_add (response, sessionKey, NULL);
-response->flags = challenge->flags;
 
 
-if (d != NULL) free (d);
-free (u);
-}
+#endif   /*!MACRO_PREDEF*/