build: use pkg-config for i18n
[exim.git] / src / src / auths / dovecot.c
index 9b0d437da54ea2924f9bc93028699a10da41b7cc..ee69436becc92cdfb956827fe70da5316e8deddf 100644 (file)
@@ -1,12 +1,13 @@
 /*
 /*
- * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
- * Copyright (c) 2006-2019 The Exim Maintainers
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+Copyright (c) The Exim Maintainers 2006 - 2024
+Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
+SPDX-License-Identifier: GPL-2.0-or-later
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+*/
 
 /* A number of modifications have been made to the original code. Originally I
 commented them specially, but now they are getting quite extensive, so I have
 
 /* A number of modifications have been made to the original code. Originally I
 commented them specially, but now they are getting quite extensive, so I have
@@ -22,6 +23,8 @@ because using C buffered I/O gives problems on some operating systems. PH */
  */
 
 #include "../exim.h"
  */
 
 #include "../exim.h"
+
+#ifdef AUTH_DOVECOT    /* Remainder of file */
 #include "dovecot.h"
 
 #define VERSION_MAJOR  1
 #include "dovecot.h"
 
 #define VERSION_MAJOR  1
@@ -51,8 +54,10 @@ The cost is the length of an array of pointers on the stack.
 
 /* Options specific to the authentication mechanism. */
 optionlist auth_dovecot_options[] = {
 
 /* Options specific to the authentication mechanism. */
 optionlist auth_dovecot_options[] = {
-  { "server_socket", opt_stringptr, OPT_OFF(auth_dovecot_options_block, server_socket) },
-/*{ "server_tls", opt_bool, OPT_OFF(auth_dovecot_options_block, server_tls) },*/
+  { "server_socket", opt_stringptr,
+    OPT_OFF(auth_dovecot_options_block, server_socket) },
+/*{ "server_tls", opt_bool,
+    OPT_OFF(auth_dovecot_options_block, server_tls) },*/
 };
 
 /* Size of the options list. An extern variable has to be used so that its
 };
 
 /* Size of the options list. An extern variable has to be used so that its
@@ -73,7 +78,7 @@ auth_dovecot_options_block auth_dovecot_option_defaults = {
 #ifdef MACRO_PREDEF
 
 /* Dummy values */
 #ifdef MACRO_PREDEF
 
 /* Dummy values */
-void auth_dovecot_init(auth_instance *ablock) {}
+void auth_dovecot_init(driver_instance *ablock) {}
 int auth_dovecot_server(auth_instance *ablock, uschar *data) {return 0;}
 int auth_dovecot_client(auth_instance *ablock, void * sx,
   int timeout, uschar *buffer, int buffsize) {return 0;}
 int auth_dovecot_server(auth_instance *ablock, uschar *data) {return 0;}
 int auth_dovecot_client(auth_instance *ablock, void * sx,
   int timeout, uschar *buffer, int buffsize) {return 0;}
@@ -96,13 +101,20 @@ static int socket_buffer_left;
 enable consistency checks to be done, or anything else that needs
 to be set up. */
 
 enable consistency checks to be done, or anything else that needs
 to be set up. */
 
-void auth_dovecot_init(auth_instance *ablock)
+void
+auth_dovecot_init(driver_instance * a)
 {
 {
-auth_dovecot_options_block *ob =
-       (auth_dovecot_options_block *)(ablock->options_block);
-
-if (!ablock->public_name) ablock->public_name = ablock->name;
-if (ob->server_socket) ablock->server = TRUE;
+auth_instance * ablock = (auth_instance *)a;
+auth_dovecot_options_block * ob =
+       (auth_dovecot_options_block *)(a->options_block);
+
+if (!ablock->public_name)
+  ablock->public_name = a->name;
+if (ob->server_socket)
+  ablock->server = TRUE;
+else DEBUG(D_auth)
+  debug_printf("Dovecot auth driver: no server_socket for %s\n",
+             ablock->public_name);
 ablock->client = FALSE;
 }
 
 ablock->client = FALSE;
 }
 
@@ -245,8 +257,7 @@ return s;
 int
 auth_dovecot_server(auth_instance * ablock, uschar * data)
 {
 int
 auth_dovecot_server(auth_instance * ablock, uschar * data)
 {
-auth_dovecot_options_block *ob =
-       (auth_dovecot_options_block *) ablock->options_block;
+auth_dovecot_options_block * ob = ablock->drinst.options_block;
 uschar buffer[DOVECOT_AUTH_MAXLINELEN];
 uschar *args[DOVECOT_AUTH_MAXFIELDCOUNT];
 uschar *auth_command;
 uschar buffer[DOVECOT_AUTH_MAXLINELEN];
 uschar *args[DOVECOT_AUTH_MAXFIELDCOUNT];
 uschar *auth_command;
@@ -275,11 +286,20 @@ if (cctx.sock < 0)
 # ifndef DISABLE_TLS
 if (ob->server_tls)
   {
 # ifndef DISABLE_TLS
 if (ob->server_tls)
   {
-  uschar * s;
+  union sockaddr_46 interface_sock;
+  EXIM_SOCKLEN_T size = sizeof(interface_sock);
   smtp_connect_args conn_args = { .host = &host };
   smtp_connect_args conn_args = { .host = &host };
-  tls_support tls_dummy = {.sni=NULL};
+  tls_support tls_dummy = { .sni = NULL };
   uschar * errstr;
 
   uschar * errstr;
 
+  if (getsockname(cctx->sock, (struct sockaddr *) &interface_sock, &size) == 0)
+    conn_args.sending_ip_address = host_ntoa(-1, &interface_sock, NULL, NULL);
+  else
+    {
+    *errmsg = string_sprintf("getsockname failed: %s", strerror(errno));
+    goto bad;
+    }
+
   if (!tls_client_start(&cctx, &conn_args, NULL, &tls_dummy, &errstr))
     {
     auth_defer_msg = string_sprintf("TLS connect failed: %s", errstr);
   if (!tls_client_start(&cctx, &conn_args, NULL, &tls_dummy, &errstr))
     {
     auth_defer_msg = string_sprintf("TLS connect failed: %s", errstr);
@@ -294,16 +314,14 @@ auth_defer_msg = US"authentication socket protocol error";
 socket_buffer_left = 0;  /* Global, used to read more than a line but return by line */
 for (;;)
   {
 socket_buffer_left = 0;  /* Global, used to read more than a line but return by line */
 for (;;)
   {
-debug_printf("%s %d\n", __FUNCTION__, __LINE__);
   if (!dc_gets(buffer, sizeof(buffer), &cctx))
     OUT("authentication socket read error or premature eof");
   if (!dc_gets(buffer, sizeof(buffer), &cctx))
     OUT("authentication socket read error or premature eof");
-debug_printf("%s %d\n", __FUNCTION__, __LINE__);
   p = buffer + Ustrlen(buffer) - 1;
   if (*p != '\n')
     OUT("authentication socket protocol line too long");
 
   *p = '\0';
   p = buffer + Ustrlen(buffer) - 1;
   if (*p != '\n')
     OUT("authentication socket protocol line too long");
 
   *p = '\0';
-  HDEBUG(D_auth) debug_printf("received: '%s'\n", buffer);
+  HDEBUG(D_auth) debug_printf("  DOVECOT<< '%s'\n", buffer);
 
   nargs = strcut(buffer, args, nelem(args));
 
 
   nargs = strcut(buffer, args, nelem(args));
 
@@ -413,12 +431,12 @@ if ((
   HDEBUG(D_auth) debug_printf("error sending auth_command: %s\n",
     strerror(errno));
 
   HDEBUG(D_auth) debug_printf("error sending auth_command: %s\n",
     strerror(errno));
 
-HDEBUG(D_auth) debug_printf("sent: '%s'\n", auth_command);
+HDEBUG(D_auth) debug_printf("  DOVECOT>> '%s'\n", auth_command);
 
 while (1)
   {
 
 while (1)
   {
-  uschar *temp;
-  uschar *auth_id_pre = NULL;
+  uschar * temp;
+  uschar * auth_id_pre = NULL;
 
   if (!dc_gets(buffer, sizeof(buffer), &cctx))
     {
 
   if (!dc_gets(buffer, sizeof(buffer), &cctx))
     {
@@ -427,7 +445,7 @@ while (1)
     }
 
   buffer[Ustrlen(buffer) - 1] = 0;
     }
 
   buffer[Ustrlen(buffer) - 1] = 0;
-  HDEBUG(D_auth) debug_printf("received: '%s'\n", buffer);
+  HDEBUG(D_auth) debug_printf("  DOVECOT<< '%s'\n", buffer);
   nargs = strcut(buffer, args, nelem(args));
   HDEBUG(D_auth) debug_strcut(args, nargs, nelem(args));
 
   nargs = strcut(buffer, args, nelem(args));
   HDEBUG(D_auth) debug_strcut(args, nargs, nelem(args));
 
@@ -461,6 +479,8 @@ while (1)
 #endif
          write(cctx.sock, temp, Ustrlen(temp))) < 0)
        OUT("authentication socket write error");
 #endif
          write(cctx.sock, temp, Ustrlen(temp))) < 0)
        OUT("authentication socket write error");
+
+      HDEBUG(D_auth) debug_printf("  DOVECOT>> '%s'\n", temp);
       break;
 
     case 'F':
       break;
 
     case 'F':
@@ -514,8 +534,35 @@ if (cctx.sock >= 0)
   close(cctx.sock);
 
 /* Expand server_condition as an authorization check */
   close(cctx.sock);
 
 /* Expand server_condition as an authorization check */
-return ret == OK ? auth_check_serv_cond(ablock) : ret;
+if (ret == OK) ret = auth_check_serv_cond(ablock);
+
+HDEBUG(D_auth) debug_printf("dovecot auth ret: %s\n", rc_names[ret]);
+return ret;
 }
 
 
 }
 
 
-#endif   /*!MACRO_PREDEF*/
+# ifdef DYNLOOKUP
+#  define dovecot_auth_info _auth_info
+# endif
+
+auth_info dovecot_auth_info = {
+.drinfo = {
+  .driver_name =       US"dovecot",                   /* lookup name */
+  .options =           auth_dovecot_options,
+  .options_count =     &auth_dovecot_options_count,
+  .options_block =     &auth_dovecot_option_defaults,
+  .options_len =       sizeof(auth_dovecot_options_block),
+  .init =              auth_dovecot_init,
+# ifdef DYNLOOKUP
+  .dyn_magic =         AUTH_MAGIC,
+# endif
+  },
+.servercode =          auth_dovecot_server,
+.clientcode =          NULL,
+.version_report =      NULL,
+.macros_create =       NULL,
+};
+
+#endif /*!MACRO_PREDEF*/
+#endif /*AUTH_DOVECOT*/
+/* end of auths/dovecot.c */