Re: [Exim] SMTP-AUTH via Cyrus-SASL pwcheck daemon

Page principale
Supprimer ce message
Répondre à ce message
Auteur: Alexander Sabourenkov
Date:  
À: Philip Hazel
CC: exim-users
Sujet: Re: [Exim] SMTP-AUTH via Cyrus-SASL pwcheck daemon
>
> The Radius check syntax is done as a condition, like PAM:
>
>       ${if radius{args}{1}{0}}

>
> I think this is more logical than a lookup.



Yes, that's in fact more logical. I think I'll rewrite it that way
some time later for 3.33 Exim.

the patch - attached.



cya.



diff -c -r -N exim-3.33/scripts/MakeLinks exim-3.33.my/scripts/MakeLinks
*** exim-3.33/scripts/MakeLinks    Wed Aug 15 15:09:07 2001
--- exim-3.33.my/scripts/MakeLinks    Wed Sep 19 21:55:17 2001
***************
*** 79,84 ****
--- 79,86 ----
  ln -s ../../src/lookups/pgsql.c          pgsql.c
  ln -s ../../src/lookups/testdb.h         testdb.h
  ln -s ../../src/lookups/testdb.c         testdb.c
+ ln -s ../../src/lookups/pwcheck.c        pwcheck.c
+ ln -s ../../src/lookups/pwcheck.h        pwcheck.h
  cd ..


  # Likewise for the code for the directors
diff -c -r -N exim-3.33/src/EDITME exim-3.33.my/src/EDITME
*** exim-3.33/src/EDITME    Wed Aug 15 15:09:07 2001
--- exim-3.33.my/src/EDITME    Thu Sep 20 10:32:36 2001
***************
*** 335,340 ****
--- 335,341 ----


LOOKUP_DBM=yes
LOOKUP_LSEARCH=yes
+ LOOKUP_PWCHECK=yes

  # LOOKUP_CDB=yes
  # LOOKUP_DNSDB=yes
diff -c -r -N exim-3.33/src/config.h.defaults exim-3.33.my/src/config.h.defaults
*** exim-3.33/src/config.h.defaults    Wed Aug 15 15:09:08 2001
--- exim-3.33.my/src/config.h.defaults    Wed Sep 19 21:32:41 2001
***************
*** 55,60 ****
--- 55,61 ----
  #define LOOKUP_NISPLUS
  #define LOOKUP_PGSQL
  #define LOOKUP_TESTDB
+ #define LOOKUP_PWCHECK


#define LDAP_LIB_TYPE

diff -c -r -N exim-3.33/src/drtables.c exim-3.33.my/src/drtables.c
*** exim-3.33/src/drtables.c    Wed Aug 15 15:09:08 2001
--- exim-3.33.my/src/drtables.c    Wed Sep 19 21:46:11 2001
***************
*** 75,80 ****
--- 75,84 ----
  #include "lookups/testdb.h"
  #endif


+ #ifdef LOOKUP_PWCHECK
+ #include "lookups/pwcheck.h"
+ #endif
+

/* The second field in each item below is a set of bit flags:

***************
*** 288,293 ****
--- 292,314 ----
    NULL,                          /* no close function */
    NULL,                          /* no tidy function */
    nisplus_quote                  /* quoting function */
+ #else
+   NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
+ #endif
+   },
+ 
+ /* sasl pwcheck daemon lookup */
+ 
+   {
+   "pwcheck",                     /* lookup name */
+   lookup_querystyle,             /* query-style lookup */
+ #ifdef LOOKUP_PWCHECK
+   pwcheck_open,                  /* open function */
+   NULL,                          /* check function */
+   pwcheck_find,                  /* find function */
+   NULL,                          /* no close function */
+   NULL,                          /* no tidy function */
+   NULL                           /* quoting function */
  #else
    NULL, NULL, NULL, NULL, NULL, NULL /* lookup not present */
  #endif
diff -c -r -N exim-3.33/src/lookups/Makefile exim-3.33.my/src/lookups/Makefile
*** exim-3.33/src/lookups/Makefile    Wed Aug 15 15:09:10 2001
--- exim-3.33.my/src/lookups/Makefile    Wed Sep 19 21:50:14 2001
***************
*** 3,10 ****
  # to the lookups subdirectory. When the relevant LOOKUP_ macros are not
  # defined, dummy modules get compiled.


! OBJ = cdb.o dbmdb.o dnsdb.o ldap.o lsearch.o mysql.o nis.o nisplus.o pgsql.o \
!       testdb.o


  lookups.a:       $(OBJ)
           /bin/rm -f lookups.a
--- 3,9 ----
  # to the lookups subdirectory. When the relevant LOOKUP_ macros are not
  # defined, dummy modules get compiled.


! OBJ = pwcheck.o cdb.o dbmdb.o dnsdb.o ldap.o lsearch.o mysql.o nis.o nisplus.o pgsql.o testdb.o

  lookups.a:       $(OBJ)
           /bin/rm -f lookups.a
***************
*** 15,20 ****
--- 14,20 ----
  .SUFFIXES:       .o .c
  .c.o:;           $(CC) -c $(CFLAGS) $(INCLUDE) $*.c


+ pwcheck.o:       $(HDRS) pwcheck.c   pwcheck.h
  cdb.o:           $(HDRS) cdb.c       cdb.h
  dbmdb.o:         $(HDRS) dbmdb.c     dbmdb.h
  dnsdb.o:         $(HDRS) dnsdb.c     dnsdb.h
diff -c -r -N exim-3.33/src/lookups/pwcheck.c exim-3.33.my/src/lookups/pwcheck.c
*** exim-3.33/src/lookups/pwcheck.c    Thu Jan  1 03:00:00 1970
--- exim-3.33.my/src/lookups/pwcheck.c    Wed Sep 19 22:55:56 2001
***************
*** 0 ****
--- 1,175 ----
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <ctype.h>
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <strings.h>
+ #include <netdb.h>
+ #include <netinet/in.h>
+ #include <sys/param.h>
+ #include <sys/un.h>
+ #include <sys/uio.h>
+ #include <sys/socket.h>
+ #include "../exim.h"
+ 
+ 
+ void *pwcheck_open(char *a, char **b) {
+     return (void *)(1);
+ }
+ 
+ #define PWCHECK_OK  1
+ #define PWCHECK_BAD 0
+ 
+ /* taken from cyrus-sasl file checkpw.c */
+ /*
+  * Keep calling the writev() system call with 'fd', 'iov', and 'iovcnt'
+  * until all the data is written out or an error occurs.
+  */
+ static int retry_writev(int fd, struct iovec *iov, int iovcnt)
+ {
+     int n;
+     int i;
+     int written = 0;
+     static int iov_max =
+ #ifdef MAXIOV
+     MAXIOV
+ #else
+ #ifdef IOV_MAX
+     IOV_MAX
+ #else
+     8192
+ #endif
+ #endif
+     ;
+     
+     for (;;) {
+     while (iovcnt && iov[0].iov_len == 0) {
+         iov++;
+         iovcnt--;
+     }
+ 
+     if (!iovcnt) return written;
+ 
+     n = writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt);
+     if (n == -1) {
+         if (errno == EINVAL && iov_max > 10) {
+         iov_max /= 2;
+         continue;
+         }
+         if (errno == EINTR) continue;
+         return -1;
+     }
+ 
+     written += n;
+ 
+     for (i = 0; i < iovcnt; i++) {
+         if (iov[i].iov_len > n) {
+         iov[i].iov_base = (char *)iov[i].iov_base + n;
+         iov[i].iov_len -= n;
+         break;
+         }
+         n -= iov[i].iov_len;
+         iov[i].iov_len = 0;
+     }
+ 
+     if (i == iovcnt) return written;
+     }
+ }
+ 
+ 
+ /* taken from cyrus-sasl file checkpw.c */
+ /* pwcheck daemon-authenticated login */
+ static int pwcheck_verify_password(const char *userid,
+                    const char *passwd,
+                    const char **reply)
+ {
+     int s;
+     struct sockaddr_un srvaddr;
+     int r;
+     struct iovec iov[10];
+     static char response[1024];
+     int start, n;
+     char pwpath[1024];
+ 
+     if (reply) { *reply = NULL; }
+ 
+     /*if (strlen(PWCHECKDIR)+8+1 > sizeof(pwpath)) return SASL_FAIL;
+       */
+     strcpy(pwpath, "/var/pwcheck");
+     strcat(pwpath, "/pwcheck");
+ 
+     s = socket(AF_UNIX, SOCK_STREAM, 0);
+     if (s == -1) return errno;
+ 
+     memset((char *)&srvaddr, 0, sizeof(srvaddr));
+     srvaddr.sun_family = AF_UNIX;
+     strncpy(srvaddr.sun_path, pwpath, sizeof(srvaddr.sun_path));
+     r = connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
+     if (r == -1) {
+     if (reply) { *reply = "cannot connect to pwcheck server"; }
+     return PWCHECK_BAD;
+     }
+ 
+     iov[0].iov_base = (char *)userid;
+     iov[0].iov_len = strlen(userid)+1;
+     iov[1].iov_base = (char *)passwd;
+     iov[1].iov_len = strlen(passwd)+1;
+ 
+     retry_writev(s, iov, 2);
+ 
+     start = 0;
+     while (start < sizeof(response) - 1) {
+     n = read(s, response+start, sizeof(response) - 1 - start);
+     if (n < 1) break;
+     start += n;
+     }
+ 
+     close(s);
+ 
+     if (start > 1 && !strncmp(response, "OK", 2)) {
+     return PWCHECK_OK;
+     }
+ 
+     response[start] = '\0';
+     if (reply) { *reply = response; }
+     return PWCHECK_BAD;
+ }
+ 
+ 
+ int pwcheck_find(void *handle, char *filename,char *keyquery,int  length,char **result,char **errmsg) {
+     /* handle, filename unused */
+     /* query of form ${pwcheck {login:password}} */
+     /* parameters used: *keyquery for query, **errmsg for error msg from pwcheck_verify_password*/
+     char userid[1024],passwd[1024],*sp;
+     int rv;
+     //sp = strsep(&keyquery,":");
+     DEBUG(9) debug_printf("PWCHECK lookup : keyquery=%s\n",keyquery);
+     sp = strrchr(keyquery,':');
+     if (sp == NULL)
+         return 0;
+     strncpy(userid,keyquery,sp-keyquery); strcpy(passwd,sp+1);
+     userid[sp-keyquery] = 0;
+     DEBUG(9) debug_printf("PWCHECK lookup : userid=%s passwd=%s\n",userid,passwd);
+     
+     rv = pwcheck_verify_password(userid,passwd,NULL);
+ 
+     DEBUG(9) debug_printf("PWCHECK lookup : pwcheck_verify_password returned %d\n",rv);
+     if ( rv == PWCHECK_OK ) {
+         rv = OK;
+         *result = "OK";
+     }
+     else {
+         rv = FAIL;
+         *errmsg = "Authentication failed";
+     }
+     DEBUG(9) debug_printf("PWCHECK lookup : returning %s\n", (rv==OK)?"OK":"FAIL");
+ 
+     
+     return rv;
+ }
+ 
+ 
+ 
+ 
+ 
diff -c -r -N exim-3.33/src/lookups/pwcheck.h exim-3.33.my/src/lookups/pwcheck.h
*** exim-3.33/src/lookups/pwcheck.h    Thu Jan  1 03:00:00 1970
--- exim-3.33.my/src/lookups/pwcheck.h    Wed Sep 19 21:57:11 2001
***************
*** 0 ****
--- 1,6 ----
+ /* Header for the pwcheck lookup */
+ 
+ extern void *pwcheck_open(char *, char **);
+ extern int   pwcheck_find(void *, char *, char *, int, char **, char **);
+ 
+ /* End of lookups/pwcheck.h */