nmh-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nmh-commits] nmh aclocal.m4 configure.in docs/README.SASL h/...


From: Ken Hornstein
Subject: [Nmh-commits] nmh aclocal.m4 configure.in docs/README.SASL h/...
Date: Fri, 16 Jan 2009 02:28:56 +0000

CVSROOT:        /sources/nmh
Module name:    nmh
Changes by:     Ken Hornstein <kenh>    09/01/16 02:28:56

Modified files:
        .              : aclocal.m4 configure.in 
        docs           : README.SASL 
        h              : prototypes.h 
        man            : mh-tailor.man post.man send.man 
        mts/smtp       : hosts.c smtp.c smtp.h 
        sbr            : client.c mts.c 
        uip            : ftpsbr.c mhlsbr.c popsbr.c post.c send.c 
                         whatnowsbr.c 
Added files:
        docs           : pending-release-notes 
Removed files:
        h              : netdb.h 

Log message:
        Massive overhaul of networking code.  Changes:
        
        - All networking interfaces now converted to new APIs (getaddrinfo() and
          the like).  All networking now supports IPv6 (with the exception of
          the built-in FTP client).
        - SASL security layers are now supported for SMTP.
        - Command-line and profile-based selection of the SMTP server and port.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/nmh/aclocal.m4?cvsroot=nmh&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/nmh/configure.in?cvsroot=nmh&r1=1.85&r2=1.86
http://cvs.savannah.gnu.org/viewcvs/nmh/docs/README.SASL?cvsroot=nmh&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/nmh/docs/pending-release-notes?cvsroot=nmh&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/nmh/h/prototypes.h?cvsroot=nmh&r1=1.25&r2=1.26
http://cvs.savannah.gnu.org/viewcvs/nmh/h/netdb.h?cvsroot=nmh&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/nmh/man/mh-tailor.man?cvsroot=nmh&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/nmh/man/post.man?cvsroot=nmh&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/nmh/man/send.man?cvsroot=nmh&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/nmh/mts/smtp/hosts.c?cvsroot=nmh&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/nmh/mts/smtp/smtp.c?cvsroot=nmh&r1=1.24&r2=1.25
http://cvs.savannah.gnu.org/viewcvs/nmh/mts/smtp/smtp.h?cvsroot=nmh&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/nmh/sbr/client.c?cvsroot=nmh&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/nmh/sbr/mts.c?cvsroot=nmh&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/nmh/uip/ftpsbr.c?cvsroot=nmh&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/nmh/uip/mhlsbr.c?cvsroot=nmh&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/nmh/uip/popsbr.c?cvsroot=nmh&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/nmh/uip/post.c?cvsroot=nmh&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/nmh/uip/send.c?cvsroot=nmh&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/nmh/uip/whatnowsbr.c?cvsroot=nmh&r1=1.11&r2=1.12

Patches:
Index: aclocal.m4
===================================================================
RCS file: /sources/nmh/nmh/aclocal.m4,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- aclocal.m4  5 Aug 2008 21:06:00 -0000       1.6
+++ aclocal.m4  16 Jan 2009 02:28:54 -0000      1.7
@@ -13,9 +13,9 @@
 # BIND 4.9.5 installed.
 
 AC_DEFUN(AC_CHECK_NETLIBS,
-[AC_CHECK_FUNC(gethostbyname, ,
-  AC_CHECK_LIB(nsl, gethostbyname, ,
-    AC_CHECK_LIB(resolv, gethostbyname)))
+[AC_CHECK_FUNC(getaddrinfo, ,
+  AC_CHECK_LIB(nsl, getaddrinfo, ,
+    AC_CHECK_LIB(resolv, getaddrinfo)))
 AC_CHECK_FUNC(socket, ,
   AC_CHECK_LIB(socket, socket))
 ])

Index: configure.in
===================================================================
RCS file: /sources/nmh/nmh/configure.in,v
retrieving revision 1.85
retrieving revision 1.86
diff -u -b -r1.85 -r1.86
--- configure.in        5 Aug 2008 21:06:00 -0000       1.85
+++ configure.in        16 Jan 2009 02:28:54 -0000      1.86
@@ -1,7 +1,7 @@
 dnl
 dnl configure.in -- autoconf template for nmh
 dnl
-dnl $Id: configure.in,v 1.85 2008/08/05 21:06:00 pm215 Exp $
+dnl $Id: configure.in,v 1.86 2009/01/16 02:28:54 kenh Exp $
 dnl
 
 dnl 2.13 definitely chokes; 2.53 is the earliest version I've tested.
@@ -521,12 +521,9 @@
                getutent nl_langinfo mbtowc wcwidth)
 
 dnl solaris has these in the nsl library
-AC_SEARCH_LIBS(gethostbyname, nsl,
-  [AC_DEFINE(HAVE_GETHOSTBYNAME,1,
-    [Define to 1 if you have the `gethostbyname' function.])])
-AC_SEARCH_LIBS(sethostent, nsl,
-  [AC_DEFINE(HAVE_SETHOSTENT,1,
-    [Define to 1 if you have the `sethostent' function.])])
+AC_SEARCH_LIBS(getaddrinfo, nsl,
+  [AC_DEFINE(HAVE_GETADDRINFO,1,
+    [Define to 1 if you have the `getaddrinfo' function.])])
 
 dnl sigsetjmp may be a macro
 AC_MSG_CHECKING(for sigsetjmp)

Index: docs/README.SASL
===================================================================
RCS file: /sources/nmh/nmh/docs/README.SASL,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- docs/README.SASL    5 Sep 2003 21:07:49 -0000       1.2
+++ docs/README.SASL    16 Jan 2009 02:28:54 -0000      1.3
@@ -1,7 +1,7 @@
 #
 # README.SASL - Readme about SASL support in nmh
 #
-# $Id: README.SASL,v 1.2 2003/09/05 21:07:49 kenh Exp $
+# $Id: README.SASL,v 1.3 2009/01/16 02:28:54 kenh Exp $
 #
 
 SASL is short for the Simple Authentication and Security Layer.  Is is
@@ -15,18 +15,22 @@
 
 This release of NMH only supports "Version 2" of the Cyrus SASL library.
 It should work with any newer Cyrus SASL release, but it was tested with
-Cyrus SASL 2.1.12.  In particular, the CRAM-MD5 and GSSAPI (Kerberos 5)
-mechanisms were tested.
-
-Currently, security layers ("encryption" in SASL-speak) are only supported
-for POP.  This means that if your POP server _and_ the selected GSSAPI
-mechanism supports it, POP communications will be encrypted.  Currently
-SMTP does NOT support security layers; this may be added in a future
-release.
+Cyrus SASL 2.1.22.  In particular, the CRAM-MD5 and GSSAPI (Kerberos 5)
+mechanisms were tested.  Older versions of Cyrus-SASL had a bug which
+could manifest when negotiating encrypting depending on the encryption
+type you used, so a newer version of Cyrus-SASL is recommended.
+
+Currently, security layers ("encryption" in SASL-speak) are supported
+for both POP and SMTP.  This means that if your POP or SMTP server
+_and_ the selected SASL mechanism supports it, client-server
+communications will be encrypted.  In theory this should work with
+any SASL mechanism that supports security layers; it has only been
+tested with the GSSAPI mechanism.
 
 If you are curious as to whether or not your communications are actually
-encrypted or not, you can use the -snoop flag to the POP utilities.
-Communication that is encrypted is preceeded by an (*).
+encrypted or not, you can use the -snoop flag to the POP or SMTP utilities.
+Communication that is encrypted is preceeded by an (encrypted) or
+(decrypted), depending on the direction of communication.
 
 If you would like to use the GSSAPI SASL mechanism (Kerberos V), you
 should read very carefully the documentation that comes with

Index: h/prototypes.h
===================================================================
RCS file: /sources/nmh/nmh/h/prototypes.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -b -r1.25 -r1.26
--- h/prototypes.h      14 Aug 2008 01:50:45 -0000      1.25
+++ h/prototypes.h      16 Jan 2009 02:28:54 -0000      1.26
@@ -2,7 +2,7 @@
 /*
  * prototypes.h -- various prototypes
  *
- * $Id: prototypes.h,v 1.25 2008/08/14 01:50:45 epg Exp $
+ * $Id: prototypes.h,v 1.26 2009/01/16 02:28:54 kenh Exp $
  */
 
 /*
@@ -33,6 +33,7 @@
 int atooi(char *);
 char **brkstring (char *, char *, char *);
 int check_charset (char *, int);
+int client(char *, char *, char *, int, int);
 void closefds(int);
 char *concat (char *, ...);
 int context_del (char *);

Index: man/mh-tailor.man
===================================================================
RCS file: /sources/nmh/nmh/man/mh-tailor.man,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- man/mh-tailor.man   25 Jan 2001 21:15:56 -0000      1.11
+++ man/mh-tailor.man   16 Jan 2009 02:28:54 -0000      1.12
@@ -1,6 +1,6 @@
 .\"
 .\" %nmhwarning%
-.\" $Id: mh-tailor.man,v 1.11 2001/01/25 21:15:56 ssen Exp $
+.\" $Id: mh-tailor.man,v 1.12 2009/01/16 02:28:54 kenh Exp $
 .\"
 .TH MH-TAILOR %manext5% "%nmhdate%" MH.6.8 [%nmhversion%]
 .SH NAME
@@ -288,19 +288,14 @@
 .RE
 .PP
 .BR servers :
-localhost \\01localnet
+localhost
 .RS 5
 A lists of hosts and networks which to look for SMTP servers when
 posting local mail.  It turns out this is a major win for hosts which
 don't run an message transport system.  The value of
 .B servers
-should be one or more items.  Each item is the name of either a host
-or a net (in the latter case, precede the name of the net by a \\01).
-This list is searched when looking for a smtp server to post mail.
-If a host is present, the SMTP port on that host is tried.  If a net
-is present, the SMTP port on each host in that net is tried.  Note that
-if you are running with the BIND code, then any networks specified are
-ignored (sorry, the interface went away under BIND).
+should be one or more items.  Each item is the name of a host which
+is (hopefully) running a SMTP server.
 .SS "SendMail"
 This option is only available if you set
 .B mts

Index: man/post.man
===================================================================
RCS file: /sources/nmh/nmh/man/post.man,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- man/post.man        10 Apr 2007 22:12:26 -0000      1.11
+++ man/post.man        16 Jan 2009 02:28:55 -0000      1.12
@@ -1,6 +1,6 @@
 .\"
 .\" %nmhwarning%
-.\" $Id: post.man,v 1.11 2007/04/10 22:12:26 jjr Exp $
+.\" $Id: post.man,v 1.12 2009/01/16 02:28:55 kenh Exp $
 .\"
 .TH POST %manext8% "%nmhdate%" MH.6.8 [%nmhversion%]
 .SH NAME
@@ -181,6 +181,16 @@
 .BR sendmail 's
 \*(lqX\-Authentication\-Warning:\*(rq header). 
 .PP
+If nmh is using the SMTP MTA, the
+.B \-server
+and the
+.B \-port
+switches can be used to override the default mail server (defined by the
+.RI servers
+entry in
+.I %etcdir%/mts.conf
+).
+.PP
 If
 .B nmh
 has been compiled with SASL support, the
@@ -198,15 +208,13 @@
 switch can be used to select a authorization userid
 to provide to SASL other than the default.
 .PP
-Currently SASL security layers are not supported for SMTP.
-.BR nmh 's
-SMTP SASL code
-will always negotiate an unencrypted connection.  This means that while the 
SMTP
-authentication can be encrypted, the subsequent data stream can not.  This is 
in
-contrast to
-.BR nmh 's
-POP3 SASL support, where encryption is supported for both the
-authentication and the data stream.
+If SASL authentication is successful, 
+.BR nmh
+will attempt to negotiate a security layer for session encryption.
+Encrypted data is labelled with `(encrypted)' and `(decrypted)' when
+viewing the SMTP transaction with the
+.B \-snoop
+switch.
 
 .SH FILES
 .fc ^ ~

Index: man/send.man
===================================================================
RCS file: /sources/nmh/nmh/man/send.man,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- man/send.man        21 Feb 2006 04:13:06 -0000      1.11
+++ man/send.man        16 Jan 2009 02:28:55 -0000      1.12
@@ -1,6 +1,6 @@
 .\"
 .\" %nmhwarning%
-.\" $Id: send.man,v 1.11 2006/02/21 04:13:06 levine Exp $
+.\" $Id: send.man,v 1.12 2009/01/16 02:28:55 kenh Exp $
 .\"
 .TH SEND %manext1% "%nmhdate%" MH.6.8 [%nmhversion%]
 .SH NAME
@@ -29,6 +29,10 @@
 .IR seconds ]
 .RB [ \-verbose " | " \-noverbose ]
 .RB [ \-watch " | " \-nowatch ]
+.RB [ \-server
+.IR servername ]
+.RB [ \-port
+.IR port-name/number ]
 .RB [ \-sasl ]
 .RB [ \-saslmech
 .IR mechanism ]
@@ -315,6 +319,16 @@
 .B send
 as to how long it should make header lines containing addresses.
 .PP
+If nmh is using the SMTP MTA, the
+.B \-server
+and the
+.B \-port
+switches can be used to override the default mail server (defined by the
+.RI servers
+entry in
+.I %etcdir%/mts.conf
+).
+.PP
 If
 .B nmh
 has been compiled with SASL support, the
@@ -332,15 +346,13 @@
 switch can be used to select a authorization userid
 to provide to SASL other than the default.
 .PP
-Currently SASL security layers are not supported for SMTP.
-.BR nmh 's
-SMTP SASL code
-will always negotiate an unencrypted connection.  This means that while the 
SMTP
-authentication can be encrypted, the subsequent data stream can not.  This is 
in
-contrast to
-.BR nmh 's
-POP3 SASL support, where encryption is supported for both the
-authentication and the data stream.
+If SASL authentication is successful, 
+.BR nmh
+will attempt to negotiate a security layer for session encryption.
+Encrypted data is labelled with `(encrypted)' and `(decrypted)' when
+viewing the SMTP transaction with the
+.B \-snoop
+switch.
 .PP
 The files specified by the profile entry \*(lqAliasfile:\*(rq and any
 additional alias files given by the

Index: mts/smtp/hosts.c
===================================================================
RCS file: /sources/nmh/nmh/mts/smtp/hosts.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- mts/smtp/hosts.c    13 Apr 2007 11:53:08 -0000      1.8
+++ mts/smtp/hosts.c    16 Jan 2009 02:28:55 -0000      1.9
@@ -2,7 +2,7 @@
 /*
  * hosts.c -- find out the official name of a host
  *
- * $Id: hosts.c,v 1.8 2007/04/13 11:53:08 jjr Exp $
+ * $Id: hosts.c,v 1.9 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -38,7 +38,7 @@
 {
     unsigned char *p;
     char *q, site[BUFSIZ];
-    struct hostent *hp;
+    struct addrinfo hints, *res;
 
     static char buffer[BUFSIZ];
     char **r;
@@ -52,12 +52,14 @@
     if (!mh_strcasecmp (LocalName(), site))
        return LocalName();
 
-#ifdef HAVE_SETHOSTENT
-    sethostent (1);
-#endif
-
-    if ((hp = gethostbyname (q))) {
-       strncpy (buffer, hp->h_name, sizeof(buffer));
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_flags = AI_CANONNAME;
+    hints.ai_family = PF_UNSPEC;
+
+    if (getaddrinfo(q, NULL, &hints, &res) == 0) {
+       strncpy (buffer, res->ai_canonname, sizeof(buffer));
+       buffer[sizeof(buffer) - 1] = '\0';
+       freeaddrinfo(res);
        return buffer;
     }
     if (hosts.h_name || init_hs ()) {

Index: mts/smtp/smtp.c
===================================================================
RCS file: /sources/nmh/nmh/mts/smtp/smtp.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- mts/smtp/smtp.c     30 Apr 2008 18:47:02 -0000      1.24
+++ mts/smtp/smtp.c     16 Jan 2009 02:28:55 -0000      1.25
@@ -1,7 +1,7 @@
 /*
  * smtp.c -- nmh SMTP interface
  *
- * $Id: smtp.c,v 1.24 2008/04/30 18:47:02 pm215 Exp $
+ * $Id: smtp.c,v 1.25 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -13,9 +13,6 @@
 #include <h/mts.h>
 #include <signal.h>
 #include <h/signals.h>
-#ifdef MPOP
-#include <errno.h>
-#endif
 
 #ifdef CYRUS_SASL
 #include <sasl/sasl.h>
@@ -82,11 +79,6 @@
 static FILE *sm_rfp = NULL;
 static FILE *sm_wfp = NULL;
 
-#ifdef MPOP
-static int sm_ispool = 0;
-static char sm_tmpfil[BUFSIZ];
-#endif /* MPOP */
-
 #ifdef CYRUS_SASL
 /*
  * Some globals needed by SASL
@@ -97,8 +89,14 @@
 static sasl_ssf_t sasl_ssf;            /* Our security strength factor */
 static char *sasl_pw_context[2];       /* Context to pass into sm_get_pass */
 static int maxoutbuf;                  /* Maximum crypto output buffer */
+static char *sasl_outbuffer;           /* SASL output buffer for encryption */
+static int sasl_outbuflen;             /* Current length of data in outbuf */
+static char *sasl_inbuffer;            /* SASL input buffer for encryption */
+static char *sasl_inptr;               /* Pointer to current inbuf position */
+static int sasl_inbuflen;              /* Current length of data in inbuf */
 static int sm_get_user(void *, int, const char **, unsigned *);
 static int sm_get_pass(sasl_conn_t *, void *, int, sasl_secret_t **);
+static int sm_fgetc(FILE *);
 
 static sasl_callback_t callbacks[] = {
     { SASL_CB_USER, sm_get_user, NULL },
@@ -109,6 +107,10 @@
 #define SM_SASL_N_CB_AUTHNAME 2
     { SASL_CB_LIST_END, NULL, NULL },
 };
+
+#define SASL_MAXRECVBUF 65536
+#else /* CYRUS_SASL */
+#define sm_fgetc fgetc
 #endif /* CYRUS_SASL */
 
 static char *sm_noreply = "No reply text given";
@@ -124,11 +126,11 @@
 /*
  * static prototypes
  */
-static int smtp_init (char *, char *, int, int, int, int, int, int,
+static int smtp_init (char *, char *, char *, int, int, int, int, int, int,
                      char *, char *);
 static int sendmail_init (char *, char *, int, int, int, int, int);
 
-static int rclient (char *, char *, char *);
+static int rclient (char *, char *);
 static int sm_ierror (char *fmt, ...);
 static int smtalk (int time, char *fmt, ...);
 static int sm_wrecord (char *, int);
@@ -136,19 +138,15 @@
 static int sm_werror (void);
 static int smhear (void);
 static int sm_rrecord (char *, int *);
-static int sm_rerror (void);
+static int sm_rerror (int);
 static RETSIGTYPE alrmser (int);
 static char *EHLOset (char *);
-
-#ifdef MPOP
-static int sm_perror (char *fmt, ...);
-/*
- * smtp.c's own static copy of several nmh library subroutines
- */
-static char **smail_brkstring (char *, char *, char *);
-static int smail_brkany (char, char *);
-char **smail_copyip (char **, char **, int);
-#endif
+static int sm_fwrite(char *, int);
+static int sm_fputs(char *);
+static int sm_fputc(int);
+static int sm_getc(void);
+static void sm_fflush(void);
+static int sm_fgets(char *, int, FILE *);
 
 #ifdef CYRUS_SASL
 /*
@@ -158,16 +156,13 @@
 static int sm_auth_sasl(char *, char *, char *);
 #endif /* CYRUS_SASL */
 
-/* from mts/generic/client.c */
-int client (char *, char *, char *, int, char *, int);
-
 int
-sm_init (char *client, char *server, int watch, int verbose,
+sm_init (char *client, char *server, char *port, int watch, int verbose,
          int debug, int onex, int queued, int sasl, char *saslmech,
          char *user)
 {
     if (sm_mts == MTS_SMTP)
-       return smtp_init (client, server, watch, verbose,
+       return smtp_init (client, server, port, watch, verbose,
                          debug, onex, queued, sasl, saslmech, user);
     else
        return sendmail_init (client, server, watch, verbose,
@@ -175,7 +170,7 @@
 }
 
 static int
-smtp_init (char *client, char *server, int watch, int verbose,
+smtp_init (char *client, char *server, char *port, int watch, int verbose,
           int debug, int onex, int queued, int sasl, char *saslmech,
           char *user)
 {
@@ -190,11 +185,6 @@
     sm_verbose = verbose;
     sm_debug = debug;
 
-#ifdef MPOP
-    if (sm_ispool)
-       goto all_done;
-#endif
-
     if (sm_rfp != NULL && sm_wfp != NULL)
        goto send_options;
 
@@ -211,27 +201,15 @@
        client = "localhost";
 #endif
 
-    if ((sd1 = rclient (server, "tcp", "smtp")) == NOTOK)
-       return RP_BHST;
+#ifdef CYRUS_SASL
+    sasl_inbuffer = malloc(SASL_MAXRECVBUF);
+    if (!sasl_inbuffer)
+       return sm_ierror("Unable to allocate %d bytes for read buffer",
+                        SASL_MAXRECVBUF);
+#endif /* CYRUS_SASL */
 
-#ifdef MPOP
-    if (sm_ispool) {
-       if (sm_rfp) {
-           alarm (SM_CLOS);
-           fclose (sm_rfp);
-           alarm (0);
-           sm_rfp = NULL;
-       }
-       if ((sm_wfp = fdopen (sd1, "w")) == NULL) {
-           unlink (sm_tmpfil);
-           close (sd1);
-           return sm_ierror ("unable to fdopen");
-       }
-all_done: ;
-       sm_reply.text[sm_reply.length = 0] = NULL;
-       return (sm_reply.code = RP_OK);
-    }
-#endif /* MPOP */
+    if ((sd1 = rclient (server, port)) == NOTOK)
+       return RP_BHST;
 
     if ((sd2 = dup (sd1)) == NOTOK) {
        close (sd1);
@@ -453,54 +431,16 @@
     }
 }
 
-#ifdef MPOP
-# define MAXARGS  1000
-#endif /* MPOP */
-
 static int
-rclient (char *server, char *protocol, char *service)
+rclient (char *server, char *service)
 {
     int sd;
     char response[BUFSIZ];
-#ifdef MPOP
-    char *cp;
-#endif /* MPOP */
 
-    if ((sd = client (server, protocol, service, FALSE, response, 
sizeof(response))) != NOTOK)
+    if ((sd = client (server, service, response, sizeof(response),
+                     sm_debug)) != NOTOK)
        return sd;
 
-#ifdef MPOP
-    if (!server && servers && (cp = strchr(servers, '/'))) {
-       char **ap;
-       char *arguments[MAXARGS];
-
-       smail_copyip (smail_brkstring (cp = getcpy (servers), " ", "\n"), 
arguments, MAXARGS);
-
-       for (ap = arguments; *ap; ap++)
-           if (**ap == '/') {
-               char *dp;
-
-               if ((dp = strrchr(*ap, '/')) && *++dp == NULL)
-                   *--dp = NULL;
-               snprintf (sm_tmpfil, sizeof(sm_tmpfil), "%s/smtpXXXXXX", *ap);
-#ifdef HAVE_MKSTEMP
-               sd = mkstemp (sm_tmpfil);
-#else
-               mktemp (sm_tmpfil);
-
-               if ((sd = creat (sm_tmpfil, 0600)) != NOTOK) {
-                   sm_ispool = 1;
-                   break;
-               }
-#endif
-           }
-
-       free (cp);
-       if (sd != NOTOK)
-           return sd;
-    }
-#endif /* MPOP */
-
     sm_ierror ("%s", response);
     return NOTOK;
 }
@@ -510,14 +450,6 @@
 {
     char *smtpcom;
 
-#ifdef MPOP
-    if (sm_ispool && !sm_wfp) {
-       sm_reply.length = strlen (strcpy (sm_reply.text, "unable to create new 
spool file"));
-       sm_reply.code = NOTOK;
-       return RP_BHST;
-    }
-#endif /* MPOP */
-
     switch (mode) {
        case S_MAIL:
            smtpcom = "MAIL";
@@ -704,18 +636,6 @@
            break;
     }
 
-#ifdef MPOP
-    if (sm_ispool) {
-       sm_ispool = 0;
-
-       if (sm_wfp) {
-           unlink (sm_tmpfil);
-           fclose (sm_wfp);
-           sm_wfp = NULL;
-       }
-    }
-#endif /* MPOP */
-
     if (sm_rfp != NULL) {
        alarm (SM_CLOS);
        fclose (sm_rfp);
@@ -730,8 +650,14 @@
     if (sm_mts == MTS_SMTP) {
        status = 0;
 #ifdef CYRUS_SASL
-       if (conn)
+       if (conn) {
            sasl_dispose(&conn);
+           if (sasl_outbuffer) {
+               free(sasl_outbuffer);
+           }
+       }
+       if (sasl_inbuffer)
+           free(sasl_inbuffer);
 #endif /* CYRUS_SASL */
     } else {
        status = pidwait (sm_child, OK);
@@ -742,337 +668,18 @@
     return (status ? RP_BHST : RP_OK);
 }
 
-
-#ifdef MPOP
-
-int
-sm_bulk (char *file)
-{
-    int        cc, i, j, k, result;
-    long pos;
-    char *dp, *bp, *cp, s;
-    char buffer[BUFSIZ], sender[BUFSIZ];
-    FILE *fp, *gp;
-
-    gp = NULL;
-    k = strlen (file) - sizeof(".bulk");
-    if ((fp = fopen (file, "r")) == NULL) {
-       return sm_perror("unable to read %s: ", file);
-    }
-    if (sm_debug) {
-       printf ("reading file %s\n", file);
-       fflush (stdout);
-    }
-
-    i = j = 0;
-    while (fgets (buffer, sizeof(buffer), fp)) {
-       if (j++ == 0)
-           strncpy (sender, buffer + sizeof("MAIL FROM:") - 1, sizeof(sender));
-       if (strcmp (buffer, "DATA\r\n") == 0) {
-           i = 1;
-           break;
-       }
-    }
-    if (i == 0) {
-       if (sm_debug) {
-           printf ("no DATA...\n");
-           fflush (stdout);
-       }
-losing0:
-       snprintf (buffer, sizeof(buffer), "%s.bad", file);
-       rename (file, buffer);
-       if (gp) {
-           snprintf (buffer, sizeof(buffer), "%*.*sA.bulk", k, k, file);
-           unlink (buffer);
-           fclose (gp);
-       }
-       fclose (fp);
-       return RP_OK;
-    }
-    if (j < 3) {
-       if (sm_debug) {
-           printf ("no %srecipients...\n", j < 1 ? "sender or " : "");
-           fflush (stdout);
-       }
-       goto losing0;
-    }
-
-    if ((cp = malloc ((size_t) (cc = (pos = ftell (fp)) + 1))) == NULL) {
-       sm_reply.length = strlen (strcpy (sm_reply.text, "out of memory"));
-losing1: ;
-       sm_reply.code = NOTOK;
-       fclose (fp);
-       return RP_BHST;
-    }
-    fseek (fp, 0L, SEEK_SET);
-    for (dp = cp, i = 0; i++ < j; dp += strlen (dp))
-       if (fgets (dp, cc - (dp - cp), fp) == NULL) {
-           sm_reply.length = strlen (strcpy (sm_reply.text, "premature eof"));
-losing2:
-           free (cp);
-           goto losing1;
-       }
-    *dp = NULL;
-
-    for (dp = cp, i = cc - 1; i > 0; dp += cc, i -= cc)
-       if ((cc = write (fileno (sm_wfp), dp, i)) == NOTOK) {
-           int len;
-losing3:
-           sm_perror("error writing to server: ");
-           goto losing2;
-       }
-       else
-           if (sm_debug) {
-               printf ("wrote %d octets to server\n", cc);
-               fflush (stdout);
-           }
-
-    for (dp = cp, i = 0; i++ < j; dp = strchr(dp, '\n'), dp++) {
-       if (sm_debug) {
-           if (bp = strchr(dp, '\r'))
-               *bp = NULL;
-           printf ("=> %s\n", dp);
-           fflush (stdout);
-           if (bp)
-               *bp = '\r';
-       }
-
-       switch (smhear () + (i == 1 ? 1000 : i != j ? 2000 : 3000)) {
-           case 1000 + 250:
-               sm_addrs = 0;
-               result = RP_OK;
-               break;
-
-           case 1000 + 500: 
-           case 1000 + 501: 
-           case 1000 + 552: 
-           case 2000 + 500: 
-           case 2000 + 501:
-               result = RP_PARM;
-               smtalk (SM_RSET, "RSET");
-               free (cp);
-               goto losing0;
-
-           case 2000 + 250:
-           case 2000 + 251:
-               sm_addrs++;
-               result = RP_OK;
-               break;
-
-           case 2000 + 451: 
-#ifdef SENDMAILBUG
-               sm_addrs++;
-               result = RP_OK;
-               break;
-#endif
-           case 2000 + 421: 
-           case 2000 + 450: 
-           case 2000 + 452: 
-               result = RP_NO;
-               goto bad_addr;
-
-           case 2000 + 550: 
-           case 2000 + 551: 
-           case 2000 + 552: 
-           case 2000 + 553: 
-               result = RP_USER;
-bad_addr:
-               if (k <= 0 || strcmp (sender, "<>\r\n") == 0)
-                   break;
-               if (gp == NULL) {
-                   int     l;
-                   snprintf (buffer, sizeof(buffer), "%*.*sA.bulk", k, k, 
file);
-                   if ((gp = fopen (buffer, "w+")) == NULL)
-                       goto bad_data;
-                   fprintf (gp, "MAIL FROM:<>\r\nRCPT TO:%sDATA\r\n", sender);
-                   l = strlen (sender);
-                   fprintf (gp,
-                            "To: %*.*s\r\nSubject: Invalid addresses (%s)\r\n",
-                            l - 4, l - 4, sender + 1, file);
-                   fprintf (gp, "Date: %s\r\nFrom: address@hidden",
-                            dtimenow (0), LocalName ());
-               }
-               if (bp = strchr(dp, '\r'))
-                   *bp = NULL;
-               fprintf (gp, "=>        %s\r\n", dp);
-               if (bp)
-                   *bp = '\r';
-               fprintf (gp, "<= %s\r\n", rp_string (result));
-               fflush (gp);
-               break;
-
-           case 3000 + 354: 
-#ifdef SENDMAILBUG
-ok_data:
-#endif
-               result = RP_OK;
-               break;
-
-           case 3000 + 451: 
-#ifdef SENDMAILBUG
-               goto ok_data;
-#endif
-           case 3000 + 421:
-               result = RP_NO;
-bad_data:
-               smtalk (SM_RSET, "RSET");
-               free (cp);
-               if (gp) {
-                   snprintf (buffer, sizeof(buffer), "%*.*sA.bulk", k, k, 
file);
-                   unlink (buffer);
-                   fclose (gp);
-               }
-               fclose (fp);
-               return result;
-
-           case 3000 + 500: 
-           case 3000 + 501: 
-           case 3000 + 503: 
-           case 3000 + 554: 
-               smtalk (SM_RSET, "RSET");
-               free (cp);
-               goto no_dice;
-
-           default:
-               result = RP_RPLY;
-               goto bad_data;
-       }
-    }
-    free (cp);
-
-    {
-#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
-       struct stat st;
-
-       if (fstat (fileno (sm_wfp), &st) == NOTOK || (cc = st.st_blksize) < 
BUFSIZ)
-           cc = BUFSIZ;
-#else
-       cc = BUFSIZ;
-#endif
-       if ((cp = malloc ((size_t) cc)) == NULL) {
-           smtalk (SM_RSET, "RSET");
-           sm_reply.length = strlen (strcpy (sm_reply.text, "out of memory"));
-           goto losing1;
-       }
-    }
-
-    fseek (fp, pos, SEEK_SET);
-    for (;;) {
-       int eof = 0;
-
-       for (dp = cp, i = cc; i > 0; dp += j, i -= j)
-           if ((j = fread (cp, sizeof(*cp), i, fp)) == OK) {
-               if (ferror (fp)) {
-                   sm_perror("error reading %s: ", file);
-                   goto losing2;
-               }
-               cc = dp - cp;
-               eof = 1;
-               break;
-           }
-
-       for (dp = cp, i = cc; i > 0; dp += j, i -= j)
-           if ((j = write (fileno (sm_wfp), dp, i)) == NOTOK)
-               goto losing3;
-           else
-               if (sm_debug) {
-                   printf ("wrote %d octets to server\n", j);
-                   fflush (stdout);
-               }
-
-       if (eof)
-           break;
-    }
-    free (cp);
-
-    switch (smhear ()) {
-       case 250: 
-       case 251: 
-#ifdef SENDMAILBUG
-ok_dot:
-#endif
-           result = RP_OK;
-           unlink (file);
-           break;
-
-       case 451: 
-#ifdef SENDMAILBUG
-           goto ok_dot;
-#endif
-       case 452: 
-       default: 
-           result = RP_NO;
-           if (gp) {
-               snprintf (buffer, sizeof(buffer), "%*.*sA.bulk", k, k, file);
-               unlink (buffer);
-               fclose (gp);
-               gp = NULL;
-           }
-           break;
-
-       case 552: 
-       case 554: 
-no_dice:
-           result = RP_NDEL;
-           if (k <= 0 || strcmp (sender, "<>\r\n") == 0) {
-               unlink (file);
-               break;
-           }
-           if (gp) {
-               fflush (gp);
-               ftruncate (fileno (gp), 0L);
-               fseek (gp, 0L, SEEK_SET);
-           }
-           else {
-               snprintf (buffer, sizeof(buffer), "%*.*sA.bulk", k, k, file);
-               if ((gp = fopen (buffer, "w")) == NULL)
-                   break;
-           }
-           fprintf (gp, "MAIL FROM:<>\r\nRCPT TO:%sDATA\r\n", sender);
-           i = strlen (sender);
-           fprintf (gp, "To: %*.*s\r\nSubject: Failed mail (%s)\r\n",
-                    i - 4, i - 4, sender + 1, file);
-            fprintf (gp, "Date: %s\r\nFrom: address@hidden",
-                    dtimenow (0), LocalName ());
-           break;
-    }
-
-    if (gp) {
-       fputs ("\r\n------- Begin Returned message\r\n\r\n", gp);
-       fseek (fp, pos, SEEK_SET);
-       while (fgets (buffer, sizeof(buffer), fp)) {
-           if (buffer[0] == '-')
-               fputs ("- ", gp);
-           if (strcmp (buffer, ".\r\n"))
-               fputs (buffer, gp);
-       }
-       fputs ("\r\n------- End Returned Message\r\n\r\n.\r\n", gp);
-       fflush (gp);
-       if (!ferror (gp))
-           unlink (file);
-       fclose (gp);
-    }
-    fclose (fp);
-
-    return result;
-}
-#endif /* MPOP */
-
-
 #ifdef CYRUS_SASL
 /*
  * This function implements SASL authentication for SMTP.  If this function
  * completes successfully, then authentication is successful and we've
  * (optionally) negotiated a security layer.
- *
- * Right now we don't support session encryption.
  */
 static int
-sm_auth_sasl(char *user, char *mechlist, char *host)
+sm_auth_sasl(char *user, char *mechlist, char *inhost)
 {
     int result, status;
     unsigned int buflen, outlen;
-    char *buf, outbuf[BUFSIZ];
+    char *buf, outbuf[BUFSIZ], host[NI_MAXHOST];
     const char *chosen_mech;
     sasl_security_properties_t secprops;
     sasl_ssf_t *ssf;
@@ -1094,10 +701,12 @@
      * reverse-address lookup on the IP address to get the name.
      */
 
-    if (!host) {
-       struct sockaddr_in sin;
-       int len = sizeof(sin);
-       struct hostent *hp;
+    memset(host, 0, sizeof(host));
+
+    if (!inhost) {
+       struct sockaddr_storage sin;
+       socklen_t len = sizeof(sin);
+       int result;
 
        if (getpeername(fileno(sm_wfp), (struct sockaddr *) &sin, &len) < 0) {
            sm_ierror("getpeername on SMTP socket failed: %s",
@@ -1105,14 +714,15 @@
            return NOTOK;
        }
 
-       if ((hp = gethostbyaddr((void *) &sin.sin_addr, sizeof(sin.sin_addr),
-                               sin.sin_family)) == NULL) {
-           sm_ierror("DNS lookup on IP address %s failed",
-                     inet_ntoa(sin.sin_addr));
+       result = getnameinfo((struct sockaddr *) &sin, len, host, sizeof(host),
+                            NULL, 0, NI_NAMEREQD);
+       if (result != 0) {
+           sm_ierror("Unable to look up name of connected host: %s",
+                     gai_strerror(result));
            return NOTOK;
        }
-
-       host = strdup(hp->h_name);
+    } else {
+       strncpy(host, inhost, sizeof(host) - 1);
     }
 
     sasl_pw_context[0] = host;
@@ -1141,8 +751,8 @@
      */
 
     memset(&secprops, 0, sizeof(secprops));
-    secprops.maxbufsize = BUFSIZ;
-    secprops.max_ssf = 0;      /* XXX change this when we do encryption */
+    secprops.maxbufsize = SASL_MAXRECVBUF;
+    secprops.max_ssf = UINT_MAX;
 
     result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
 
@@ -1161,8 +771,7 @@
                               &buflen, (const char **) &chosen_mech);
 
     if (result != SASL_OK && result != SASL_CONTINUE) {
-       sm_ierror("SASL client start failed: %s",
-                 sasl_errstring(result, NULL, NULL));
+       sm_ierror("SASL client start failed: %s", sasl_errdetail(conn));
        return NOTOK;
     }
 
@@ -1279,8 +888,30 @@
        return NOTOK;
     }
 
-    if (maxoutbuf == 0 || maxoutbuf > BUFSIZ)
-       maxoutbuf = BUFSIZ;
+    if (sasl_ssf > 0) {
+       sasl_outbuffer = malloc(maxoutbuf);
+
+       if (sasl_outbuffer == NULL) {
+               sm_ierror("Unable to allocate %d bytes for SASL output "
+                         "buffer", maxoutbuf);
+               return NOTOK;
+       }
+       sasl_outbuflen = 0;
+
+       sasl_inbuffer = malloc(SASL_MAXRECVBUF);
+
+       if (sasl_inbuffer == NULL) {
+               sm_ierror("Unable to allocate %d bytes for SASL input "
+                         "buffer", SASL_MAXRECVBUF);
+               free(sasl_outbuffer);
+               return NOTOK;
+       }
+       sasl_inbuflen = 0;
+       sasl_inptr = sasl_inbuffer;
+    } else {
+       sasl_outbuffer = NULL;
+       sasl_inbuffer = NULL;
+    }
 
     sasl_complete = 1;
 
@@ -1351,37 +982,6 @@
     return RP_BHST;
 }
 
-#ifdef MPOP
-static int
-sm_perror (char *fmt, ...)
-{
-    /* Fill in sm_reply with a suitable error string based on errno.
-     * This isn't particularly MPOP specific, it just happens that that's
-     * the only code that uses it currently.
-     */
-    char *bp, *s;
-    int len, eno = errno;
-
-    va_list ap;
-    va_start(ap,fmt);
-    vsnprintf (sm_reply.text, sizeof(sm_reply.text), fmt, ap);
-    va_end(ap);
-
-    bp = sm_reply.text;
-    len = strlen(bp);
-    bp += len;
-    if ((s = strerror(eno)))
-       snprintf(bp, sizeof(sm_reply.text) - len, "%s", s);
-    else
-       snprintf(bp, sizeof(sm_reply.text) - len, "unknown error %d", eno);
-    
-    sm_reply.length = strlen (sm_reply.text);
-    sm_reply.code = NOTOK;
-
-    return RP_BHST;
-}
-#endif
-
 static int
 smtalk (int time, char *fmt, ...)
 {
@@ -1394,69 +994,14 @@
     va_end(ap);
 
     if (sm_debug) {
+#ifdef CYRUS_SASL
+       if (sasl_ssf)
+               printf("(encrypted) ");
+#endif /* CYRUS_SASL */
        printf ("=> %s\n", buffer);
        fflush (stdout);
     }
 
-#ifdef MPOP
-    if (sm_ispool) {
-       char file[BUFSIZ];
-
-       if (strcmp (buffer, ".") == 0)
-           time = SM_DOT;
-       fprintf (sm_wfp, "%s\r\n", buffer);
-       switch (time) {
-           case SM_DOT:
-               fflush (sm_wfp);
-               if (ferror (sm_wfp))
-                   return sm_werror ();
-               snprintf (file, sizeof(file), "%s%c.bulk", sm_tmpfil,
-                               (char) (sm_ispool + 'a' - 1));
-               if (rename (sm_tmpfil, file) == NOTOK) {
-                   return sm_perror("error renaming %s to %s: ", sm_tmpfil, 
file);
-               }
-               fclose (sm_wfp);
-               if (sm_wfp = fopen (sm_tmpfil, "w"))
-                   chmod (sm_tmpfil, 0600);
-               sm_ispool++;
-               /* and fall... */
-
-           case SM_MAIL:
-           case SM_RCPT:
-               result = 250;
-               break;
-
-           case SM_RSET:
-               fflush (sm_wfp);
-               ftruncate (fileno (sm_wfp), 0L);
-               fseek (sm_wfp, 0L, SEEK_SET);
-               result = 250;
-               break;
-
-           case SM_DATA:
-               result = 354;
-               break;
-
-           case SM_QUIT:
-               unlink (sm_tmpfil);
-               sm_ispool = 0;
-               result = 221;
-               break;
-
-           default:
-               result = 500;
-               break;
-       }
-       if (sm_debug) {
-           printf ("<= %d\n", result);
-           fflush (stdout);
-       }
-
-       sm_reply.text[sm_reply.length = 0] = NULL;
-       return (sm_reply.code = result);
-    }
-#endif /* MPOP */
-
     sm_alarmed = 0;
     alarm ((unsigned) time);
     if ((result = sm_wrecord (buffer, strlen (buffer))) != NOTOK)
@@ -1477,9 +1022,9 @@
     if (sm_wfp == NULL)
        return sm_werror ();
 
-    fwrite (buffer, sizeof(*buffer), len, sm_wfp);
-    fputs ("\r\n", sm_wfp);
-    fflush (sm_wfp);
+    sm_fwrite (buffer, len);
+    sm_fputs ("\r\n");
+    sm_fflush ();
 
     return (ferror (sm_wfp) ? sm_werror () : OK);
 }
@@ -1496,7 +1041,7 @@
 
     if (buffer == NULL && len == 0) {
        if (lc != '\n')
-           fputs ("\r\n", sm_wfp);
+           sm_fputs ("\r\n");
        lc = '\0';
        return (ferror (sm_wfp) ? sm_werror () : OK);
     }
@@ -1505,16 +1050,16 @@
        switch (*bp) {
            case '\n': 
                sm_nl = TRUE;
-               fputc ('\r', sm_wfp);
+               sm_fputc ('\r');
                break;
 
            case '.': 
                if (sm_nl)
-                   fputc ('.', sm_wfp);/* FALL THROUGH */
+                   sm_fputc ('.');/* FALL THROUGH */
            default: 
                sm_nl = FALSE;
        }
-       fputc (*bp, sm_wfp);
+       sm_fputc (*bp);
        if (ferror (sm_wfp))
            return sm_werror ();
     }
@@ -1524,18 +1069,93 @@
     return (ferror (sm_wfp) ? sm_werror () : OK);
 }
 
+/*
+ * Write out to the network, but do buffering for SASL (if enabled)
+ */
+
+static int
+sm_fwrite(char *buffer, int len)
+{
+#ifdef CYRUS_SASL
+    const char *output;
+    unsigned int outputlen;
+
+    if (sasl_complete == 0 || sasl_ssf == 0)
+#endif /* CYRUS_SASL */
+       fwrite(buffer, sizeof(*buffer), len, sm_wfp);
+#ifdef CYRUS_SASL
+    else {
+       while (len >= maxoutbuf - sasl_outbuflen) {
+           memcpy(sasl_outbuffer + sasl_outbuflen, buffer,
+                  maxoutbuf - sasl_outbuflen);
+           len -= maxoutbuf - sasl_outbuflen;
+           sasl_outbuflen = 0;
+
+           if (sasl_encode(conn, sasl_outbuffer, maxoutbuf,
+                           &output, &outputlen) != SASL_OK) {
+               sm_ierror("Unable to SASL encode connection data: %s",
+                         sasl_errdetail(conn));
+               return NOTOK;
+           }
+
+           fwrite(output, sizeof(*output), outputlen, sm_wfp);
+       }
+
+       if (len > 0) {
+           memcpy(sasl_outbuffer + sasl_outbuflen, buffer, len);
+           sasl_outbuflen += len;
+       }
+    }
+#endif /* CYRUS_SASL */
+    return ferror(sm_wfp) ? NOTOK : RP_OK;
+}
 
 /*
- * On some systems, strlen and strcpy are defined as preprocessor macros.  This
- * causes compile problems with the #ifdef MPOP in the middle.  Should the
- * #ifdef MPOP be removed, remove these #undefs.
+ * Convenience functions to replace occurences of fputs() and fputc()
  */
-#ifdef strlen
-# undef strlen
-#endif
-#ifdef strcpy
-# undef strcpy
-#endif
+
+static int
+sm_fputs(char *buffer)
+{
+    return sm_fwrite(buffer, strlen(buffer));
+}
+
+static int
+sm_fputc(int c)
+{
+    char h = c;
+
+    return sm_fwrite(&h, 1);
+}
+
+/*
+ * Flush out any pending data on the connection
+ */
+
+static void
+sm_fflush(void)
+{
+#ifdef CYRUS_SASL
+    const char *output;
+    unsigned int outputlen;
+    int result;
+
+    if (sasl_complete == 1 && sasl_ssf > 0 && sasl_outbuflen > 0) {
+       result = sasl_encode(conn, sasl_outbuffer, sasl_outbuflen,
+                            &output, &outputlen);
+       if (result != SASL_OK) {
+           sm_ierror("Unable to SASL encode connection data: %s",
+                     sasl_errdetail(conn));
+           return;
+       }
+
+       fwrite(output, sizeof(*output), outputlen, sm_wfp);
+       sasl_outbuflen = 0;
+    }
+#endif /* CYRUS_SASL */
+
+    fflush(sm_wfp);
+}
 
 static int
 sm_werror (void)
@@ -1543,9 +1163,6 @@
     sm_reply.length =
        strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no socket opened"
            : sm_alarmed ? "write to socket timed out"
-#ifdef MPOP
-           : sm_ispool ? "error writing to spool file"
-#endif
            : "error writing to socket"));
 
     return (sm_reply.code = NOTOK);
@@ -1585,8 +1202,13 @@
     rp = sm_reply.text;
     rc = sizeof(sm_reply.text) - 1;
 
-    for (more = FALSE; sm_rrecord (bp = buffer, &bc) != NOTOK;) {
+    for (more = FALSE; sm_rrecord ((char *) (bp = (unsigned char *) buffer),
+                                  &bc) != NOTOK ; ) {
        if (sm_debug) {
+#ifdef CYRUS_SASL
+           if (sasl_ssf > 0)
+               printf("(decrypted) ");
+#endif /* CYRUS_SASL */
            printf ("<= %s\n", buffer);
            fflush (stdout);
        }
@@ -1613,7 +1235,7 @@
            continue;
 
        cont = FALSE;
-       code = atoi (bp);
+       code = atoi ((char *) bp);
        bp += 3, bc -= 3;
        for (; bc > 0 && isspace (*bp); bp++, bc--)
            continue;
@@ -1634,7 +1256,7 @@
            if (bc <= 0) {
                /* can never fail to 0-terminate because of size of buffer vs 
fixed string */
                strncpy (buffer, sm_noreply, sizeof(buffer));
-               bp = buffer;
+               bp = (unsigned char *) buffer;
                bc = strlen (sm_noreply);
            }
        }
@@ -1671,18 +1293,22 @@
 static int
 sm_rrecord (char *buffer, int *len)
 {
+    int retval;
+
     if (sm_rfp == NULL)
-       return sm_rerror ();
+       return sm_rerror(0);
 
     buffer[*len = 0] = 0;
 
-    fgets (buffer, BUFSIZ, sm_rfp);
+    if ((retval = sm_fgets (buffer, BUFSIZ, sm_rfp)) != RP_OK)
+       return retval;
     *len = strlen (buffer);
     /* *len should be >0 except on EOF, but check for safety's sake */
-    if (ferror (sm_rfp) || feof (sm_rfp) || (*len == 0))
-       return sm_rerror ();
+    if (*len == 0)
+       return sm_rerror (RP_EOF);
     if (buffer[*len - 1] != '\n')
-       while (getc (sm_rfp) != '\n' && !ferror (sm_rfp) && !feof (sm_rfp))
+       while ((retval = sm_fgetc (sm_rfp)) != '\n' && retval != EOF &&
+              retval != -2)
            continue;
     else
        if ((*len > 1) && (buffer[*len - 2] == '\r'))
@@ -1693,21 +1319,118 @@
     return OK;
 }
 
+/*
+ * Our version of fgets, which calls our private fgetc function
+ */
+
+static int
+sm_fgets(char *buffer, int size, FILE *f)
+{
+    int c;
+
+     do {
+       c = sm_fgetc(f);
+
+       if (c == EOF)
+           return RP_EOF;
+
+       if (c == -2)
+           return NOTOK;
+
+       *buffer++ = c;
+     } while (size > 1 && c != '\n');
+
+     *buffer = '\0';
+
+     return RP_OK;
+}
+
+
+#ifdef CYRUS_SASL
+/*
+ * Read from the network, but do SASL encryption
+ */
+
+static int
+sm_fgetc(FILE *f)
+{
+    char tmpbuf[BUFSIZ], *retbuf;
+    unsigned int retbufsize = 0;
+    int cc, result;
+
+    /*
+     * If we have leftover data, return it
+     */
+
+    if (sasl_inbuflen) {
+       sasl_inbuflen--;
+       return (int) *sasl_inptr++;
+    }
+
+    /*
+     * If not, read from the network until we have some data to return
+     */
+
+    while (retbufsize == 0) {
+
+       cc = read(fileno(f), tmpbuf, sizeof(tmpbuf));
+
+       if (cc == 0)
+           return EOF;
+
+       if (cc < 0) {
+           sm_ierror("Unable to read from network: %s", strerror(errno));
+           return -2;
+       }
+
+       /*
+        * Don't call sasl_decode unless sasl is complete and we have
+        * encryption working
+        */
+
+       if (sasl_complete == 0 || sasl_ssf == 0) {
+           retbuf = tmpbuf;
+           retbufsize = cc;
+       } else {
+           result = sasl_decode(conn, tmpbuf, cc, (const char **) &retbuf,
+                                &retbufsize);
+
+           if (result != SASL_OK) {
+               sm_ierror("Unable to decode SASL network data: %s",
+                         sasl_errdetail(conn));
+               return -2;
+           }
+       }
+    }
+
+    if (retbufsize > SASL_MAXRECVBUF) {
+       sm_ierror("Received data (%d bytes) is larger than the buffer "
+                 "size (%d bytes)", retbufsize, SASL_MAXRECVBUF);
+       return -2;
+    }
+
+    memcpy(sasl_inbuffer, retbuf, retbufsize);
+    sasl_inptr = sasl_inbuffer + 1;
+    sasl_inbuflen = retbufsize - 1;
+
+    return (int) sasl_inbuffer[0];
+}
+#endif /* CYRUS_SASL */
 
 static int
-sm_rerror (void)
+sm_rerror (int rc)
 {
     if (sm_mts == MTS_SMTP)
        sm_reply.length =
            strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no socket opened"
                : sm_alarmed ? "read from socket timed out"
-               : feof (sm_rfp) ? "premature end-of-file on socket"
+               : rc == RP_EOF ? "premature end-of-file on socket"
                : "error reading from socket"));
     else
        sm_reply.length =
            strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no pipe opened"
                : sm_alarmed ? "read from pipe timed out"
-               : feof (sm_rfp) ? "premature end-of-file on pipe"
+               : rc == RP_EOF ? "premature end-of-file on pipe"
                : "error reading from pipe"));
 
     return (sm_reply.code = NOTOK);
@@ -1780,70 +1503,6 @@
     return buffer;
 }
 
-
-#ifdef MPOP
-
-static char *broken[MAXARGS + 1];
-
-static char **
-smail_brkstring (char *strg, char *brksep, char *brkterm)
-{
-    int bi;
-    char c, *sp;
-
-    sp = strg;
-
-    for (bi = 0; bi < MAXARGS; bi++) {
-       while (smail_brkany (c = *sp, brksep))
-           *sp++ = 0;
-       if (!c || smail_brkany (c, brkterm)) {
-           *sp = 0;
-           broken[bi] = 0;
-           return broken;
-       }
-
-       broken[bi] = sp;
-       while ((c = *++sp) && !smail_brkany (c, brksep) && !smail_brkany (c, 
brkterm))
-           continue;
-    }
-    broken[MAXARGS] = 0;
-
-    return broken;
-}
-
-
-/*
- * returns 1 if chr in strg, 0 otherwise
- */
-static int
-smail_brkany (char chr, char *strg)
-{
-    char *sp;
- 
-    if (strg)
-       for (sp = strg; *sp; sp++)
-           if (chr == *sp)
-               return 1;
-    return 0;
-}
-
-/*
- * copy a string array and return pointer to end
- */
-char **
-smail_copyip (char **p, char **q, int len_q)
-{
-    while (*p && --len_q > 0)
-       *q++ = *p++;
-
-    *q = NULL;
- 
-    return q;
-}
-
-#endif /* MPOP */
-
-
 static char *
 EHLOset (char *s)
 {

Index: mts/smtp/smtp.h
===================================================================
RCS file: /sources/nmh/nmh/mts/smtp/smtp.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- mts/smtp/smtp.h     29 Apr 2008 21:05:30 -0000      1.3
+++ mts/smtp/smtp.h     16 Jan 2009 02:28:55 -0000      1.4
@@ -2,7 +2,7 @@
 /*
  * smtp.h -- definitions for the nmh SMTP Interface
  *
- * $Id: smtp.h,v 1.3 2008/04/29 21:05:30 pm215 Exp $
+ * $Id: smtp.h,v 1.4 2009/01/16 02:28:55 kenh Exp $
  */
 
 /* various modes for SMTP */
@@ -24,7 +24,7 @@
  * prototypes
  */
 /* int client (); */
-int sm_init (char *, char *, int, int, int, int, int, int, char *, char *);
+int sm_init (char *, char *, char *, int, int, int, int, int, int, char *, 
char *);
 int sm_winit (int, char *);
 int sm_wadr (char *, char *, char *);
 int sm_waend (void);
@@ -33,11 +33,6 @@
 int sm_end (int);
 char *rp_string (int);
 
-#ifdef MPOP
-int sm_bulk (char *);
-#endif
-
-
 /* The remainder of this file is derived from "mmdf.h" */
 
 /*

Index: sbr/client.c
===================================================================
RCS file: /sources/nmh/nmh/sbr/client.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- sbr/client.c        2 Jan 2006 03:17:42 -0000       1.3
+++ sbr/client.c        16 Jan 2009 02:28:55 -0000      1.4
@@ -2,7 +2,7 @@
 /*
  * client.c -- connect to a server
  *
- * $Id: client.c,v 1.3 2006/01/02 03:17:42 bress Exp $
+ * $Id: client.c,v 1.4 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -21,110 +21,29 @@
 # include <arpa/inet.h>
 #endif
 
-#ifdef HESIOD
-# include <hesiod.h>
-#endif
-
-#ifdef KPOP
-# include <krb.h>
-# include <ctype.h>
-#endif /* KPOP */
-
 #define        TRUE         1
 #define        FALSE        0
 
-#define        OOPS1      (-2)
-#define        OOPS2      (-3)
-
 #define        MAXARGS   1000
-#define        MAXNETS      5
-#define        MAXHOSTS    25
-
-struct addrent {
-    int a_addrtype;            /* assumes AF_INET for inet_netof () */
-    union {
-       int un_net;
-       char un_addr[14];
-    } un;
-};
-
-#define        a_net  un.un_net
-#define        a_addr un.un_addr
-
-static struct addrent *n1, *n2;
-static struct addrent nets[MAXNETS];
-static struct addrent *h1, *h2;
-static struct addrent hosts[MAXHOSTS];
-
-#ifdef KPOP
-static CREDENTIALS cred;
-static MSG_DAT msg_data;
-static KTEXT ticket = (KTEXT) NULL;
-static Key_schedule schedule;
-static char *kservice;                 /* "pop" if using kpop */
-char krb_realm[REALM_SZ];
-char *PrincipalHostname();
-#endif /* KPOP */
-
-#if !defined(h_addr)
-# define h_addr h_addr_list[0]
-#endif
-
-#define        inaddr_copy(hp,sin) \
-    memcpy(&((sin)->sin_addr), (hp)->h_addr, (hp)->h_length)
 
 /*
  * static prototypes
  */
-static int rcaux (struct servent *, struct hostent *, int, char *, int);
-static int getport (int, int, char *, int);
-static int inet (struct hostent *, int);
-struct hostent *gethostbystring (char *s);
 
 /* client's own static version of several nmh subroutines */
 static char **client_brkstring (char *, char *, char *);
 static int client_brkany (char, char *);
 static char **client_copyip (char **, char **, int);
 static char *client_getcpy (char *);
+static void client_freelist(char **);
 
 
 int
-client (char *args, char *protocol, char *service, int rproto,
-               char *response, int len_response)
+client (char *args, char *service, char *response, int len_response, int debug)
 {
-    int sd;
-    register char **ap;
-    char *arguments[MAXARGS];
-    register struct hostent *hp;
-    register struct servent *sp;
-#ifndef        HAVE_GETHOSTBYNAME
-    register struct netent *np;
-#endif
-
-#ifdef KPOP
-    char *cp;
-
-    kservice = service;
-    if (cp = strchr (service, '/')) {  /* "pop/kpop" */
-       *cp++ = '\0';           /* kservice = "pop" */
-       service = cp;           /* service  = "kpop" */
-    } else {
-       kservice = NULL;        /* not using KERBEROS */
-    }
-#endif /* KPOP */
-    
-
-    if ((sp = getservbyname (service, protocol)) == NULL) {
-#ifdef HESIOD
-       if ((sp = hes_getservbyname (service, protocol)) == NULL) {
-           snprintf (response, len_response, "%s/%s: unknown service", 
protocol, service);
-           return NOTOK;
-       }
-#else
-       snprintf (response, len_response, "%s/%s: unknown service", protocol, 
service);
-       return NOTOK;
-#endif
-    }
+    int sd, rc;
+    char **ap, *arguments[MAXARGS];
+    struct addrinfo hints, *res, *ai;
 
     ap = arguments;
     if (args != NULL && *args != 0) {
@@ -140,267 +59,76 @@
        *ap = NULL;
     }
 
-    n1 = nets;
-    n2 = nets + sizeof(nets) / sizeof(nets[0]);
-
-    h1 = hosts;
-    h2 = hosts + sizeof(hosts) / sizeof(hosts[0]);
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_flags = AI_ADDRCONFIG;
+    hints.ai_family = PF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
 
     for (ap = arguments; *ap; ap++) {
-       if (**ap == '\01') {
-/*
- * the assumption here is that if the system doesn't have a
- * gethostbyname() function, it must not use DNS. So we need to look
- * into the /etc/hosts using gethostent(). There probablly aren't any
- * systems still like this, but you never know. On every system I have
- * access to, this section is ignored.
- */
-#ifndef        HAVE_GETHOSTBYNAME
-           if ((np = getnetbyname (*ap + 1))) {
-#ifdef HAVE_SETHOSTENT
-               sethostent (1);
-#endif /* HAVE_SETHOSTENT */
-               while ((hp = gethostent()))
-                   if (np->n_addrtype == hp->h_addrtype
-                           && inet (hp, np->n_net)) {
-                       switch (sd = rcaux (sp, hp, rproto, response, 
len_response)) {
-                           case NOTOK: 
-                               continue;
-                           case OOPS1: 
-                               break;
-                           case OOPS2: 
-                               return NOTOK;
 
-                           default: 
-                               return sd;
-                       }
-                       break;
-                   }
-           }
-#endif /* don't HAVE_GETHOSTBYNAME */
-           continue;
+       if (debug) {
+           fprintf(stderr, "Trying to connect to \"%s\" ...\n", *ap);
        }
 
-       if ((hp = gethostbystring (*ap))) {
-           switch (sd = rcaux (sp, hp, rproto, response, len_response)) {
-               case NOTOK: 
-               case OOPS1: 
-                   break;
-               case OOPS2: 
-                   return NOTOK;
+       rc = getaddrinfo(*ap, service, &hints, &res);
 
-               default: 
-                   return sd;
+       if (rc) {
+           if (debug) {
+               fprintf(stderr, "Lookup of \"%s\" failed: %s\n", *ap,
+                       gai_strerror(rc));
            }
            continue;
        }
-    }
-
-    strncpy (response, "no servers available", len_response);
-    return NOTOK;
-}
-
-
-static int
-rcaux (struct servent *sp, struct hostent *hp, int rproto,
-               char *response, int len_response)
-{
-    int sd;
-    struct in_addr in;
-    register struct addrent *ap;
-    struct sockaddr_in in_socket;
-    register struct sockaddr_in *isock = &in_socket;
-
-#ifdef KPOP
-    int rem;
-    struct hostent *hp2;
-#endif /* KPOP */
 
-    for (ap = nets; ap < n1; ap++)
-       if (ap->a_addrtype == hp->h_addrtype && inet (hp, ap->a_net))
-           return NOTOK;
-
-    for (ap = hosts; ap < h1; ap++)
-       if (ap->a_addrtype == hp->h_addrtype
-               && memcmp(ap->a_addr, hp->h_addr, hp->h_length) == 0)
-           return NOTOK;
+       for (ai = res; ai != NULL; ai = ai->ai_next) {
+           if (debug) {
+               char address[NI_MAXHOST];
 
-    if ((sd = getport (rproto, hp->h_addrtype, response, len_response)) == 
NOTOK)
-       return OOPS2;
+               rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, address,
+                                sizeof(address), NULL, NULL, NI_NUMERICHOST);
 
-    memset (isock, 0, sizeof(*isock));
-    isock->sin_family = hp->h_addrtype;
-    inaddr_copy (hp, isock);
-    isock->sin_port = sp->s_port;
-
-    if (connect (sd, (struct sockaddr *) isock, sizeof(*isock)) == NOTOK)
-       switch (errno) {
-           case ENETDOWN: 
-           case ENETUNREACH: 
-               close (sd);
-               if (n1 < n2) {
-                   n1->a_addrtype = hp->h_addrtype;
-                   memcpy(&in, hp->h_addr, sizeof(in));
-                   n1->a_net = inet_netof (in);
-                   n1++;
-               }
-               return OOPS1;
-
-           case ETIMEDOUT: 
-           case ECONNREFUSED: 
-           default: 
-               close (sd);
-               if (h1 < h2) {
-                   h1->a_addrtype = hp->h_addrtype;
-                   memcpy(h1->a_addr, hp->h_addr, hp->h_length);
-                   h1++;
-               }
-               return NOTOK;
+               fprintf(stderr, "Connecting to %s...\n",
+                       rc ? "unknown" : address);
        }
 
-#ifdef KPOP
-    if (kservice) {    /* "pop" */
-       char *instance;
+           sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 
-       if (( hp2 = gethostbyaddr( hp->h_addr, hp->h_length, hp->h_addrtype ))
-               == NULL ) {
-           return NOTOK;
-       }
-       if ((instance = strdup (hp2->h_name)) == NULL) {
-           close (sd);
-           strncpy (response, "Out of memory.", len_response);
-           return OOPS2;
-       }
-       ticket = (KTEXT) mh_xmalloc (sizeof(KTEXT_ST));
-       rem = krb_sendauth (0L, sd, ticket, kservice, instance,
-                          (char *) krb_realmofhost (instance),
-                          (unsigned long) 0, &msg_data, &cred, schedule,
-                          (struct sockaddr_in *) NULL,
-                          (struct sockaddr_in *) NULL,
-                          "KPOPV0.1");
-       free (instance);
-       if (rem != KSUCCESS) {
-           close (sd);
-           strncpy (response, "Post office refused connection: ", 
len_response);
-           strncat (response, krb_err_txt[rem], len_response - 
strlen(response));
-           return OOPS2;
-       }
+           if (sd < 0) {
+               if (debug)
+                   fprintf(stderr, "socket() failed: %s\n", strerror(errno));
+               continue;
     }
-#endif /* KPOP */
 
+           if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) {
+               freeaddrinfo(res);
+               client_freelist(ap);
     return sd;
-}
-
-
-static int
-getport (int rproto, int addrtype, char *response, int len_response)
-{
-    int sd, port;
-    struct sockaddr_in in_socket, *isock;
-
-    isock = &in_socket;
-    if (rproto && addrtype != AF_INET) {
-       snprintf (response, len_response, "reserved ports not supported for 
af=%d", addrtype);
-       errno = ENOPROTOOPT;
-       return NOTOK;
     }
 
-    if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) {
-       char *s;
-
-       if ((s = strerror (errno)))
-           snprintf (response, len_response, "unable to create socket: %s", s);
-       else
-           snprintf (response, len_response, "unable to create socket: unknown 
error");
-       return NOTOK;
-    }
-#ifdef KPOP
-    if (kservice)      /* "pop" */
-       return(sd);
-#endif /* KPOP */
-    if (!rproto)
-       return sd;
-
-    memset(isock, 0, sizeof(*isock));
-    isock->sin_family = addrtype;
-    for (port = IPPORT_RESERVED - 1;;) {
-       isock->sin_port = htons ((unsigned short) port);
-       if (bind (sd, (struct sockaddr *) isock, sizeof(*isock)) != NOTOK)
-           return sd;
-
-       switch (errno) {
-           char *s;
-
-           case EADDRINUSE: 
-           case EADDRNOTAVAIL: 
-               if (--port <= IPPORT_RESERVED / 2) {
-                   strncpy (response, "ports available", len_response);
-                   return NOTOK;
+           if (debug) {
+               fprintf(stderr, "Connection failed: %s\n", strerror(errno));
                }
-               break;
 
-           default: 
-               if ((s = strerror (errno)))
-                   snprintf (response, len_response, "unable to bind socket: 
%s", s);
-               else
-                   snprintf (response, len_response, "unable to bind socket: 
unknown error");
-               return NOTOK;
+           close(sd);
        }
     }
-}
 
-
-static int
-inet (struct hostent *hp, int net)
-{
-    struct in_addr in;
-
-    memcpy(&in, hp->h_addr, sizeof(in));
-    return (inet_netof (in) == net);
+    freeaddrinfo(res);
+    client_freelist(ap);
+    strncpy (response, "no servers available", len_response);
+    return NOTOK;
 }
 
 
 /*
- * taken from ISODE's compat/internet.c
+ * Free a list of strings
  */
 
-static char *empty = NULL;
-
-#ifdef h_addr
-static char *addrs[2] = { NULL };
-#endif
-
-struct hostent *
-gethostbystring (char *s)
+static void
+client_freelist(char **list)
 {
-    register struct hostent *h;
-    static struct hostent hs;
-#ifdef DG
-    static struct in_addr iaddr;
-#else
-    static unsigned long iaddr;
-#endif
-
-    iaddr = inet_addr (s);
-#ifdef DG
-    if (iaddr.s_addr == NOTOK && strcmp (s, "255.255.255.255"))
-#else
-    if (((int) iaddr == NOTOK) && strcmp (s, "255.255.255.255"))
-#endif
-       return gethostbyname (s);
-
-    h = &hs;
-    h->h_name = s;
-    h->h_aliases = &empty;
-    h->h_addrtype = AF_INET;
-    h->h_length = sizeof(iaddr);
-#ifdef h_addr
-    h->h_addr_list = addrs;
-    memset(addrs, 0, sizeof(addrs));
-#endif
-    h->h_addr = (char *) &iaddr;
-
-    return h;
+    while (*list++ != NULL)
+       free(*list);
 }
 
 

Index: sbr/mts.c
===================================================================
RCS file: /sources/nmh/nmh/sbr/mts.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- sbr/mts.c   13 Apr 2007 11:53:08 -0000      1.5
+++ sbr/mts.c   16 Jan 2009 02:28:55 -0000      1.6
@@ -2,7 +2,7 @@
 /*
  * mts.c -- definitions for the mail transport system
  *
- * $Id: mts.c,v 1.5 2007/04/13 11:53:08 jjr Exp $
+ * $Id: mts.c,v 1.6 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -287,8 +287,7 @@
 LocalName (void)
 {
     static char buffer[BUFSIZ] = "";
-    struct hostent *hp;
-
+    struct addrinfo hints, *res;
 #ifdef HAVE_UNAME
     struct utsname name;
 #endif
@@ -303,20 +302,24 @@
     if (*localname) {
        strncpy (buffer, localname, sizeof(buffer));
     } else {
+       memset(buffer, 0, sizeof(buffer));
 #ifdef HAVE_UNAME
        /* first get our local name */
        uname (&name);
-       strncpy (buffer, name.nodename, sizeof(buffer));
+       strncpy (buffer, name.nodename, sizeof(buffer) - 1);
 #else
        /* first get our local name */
-       gethostname (buffer, sizeof(buffer));
-#endif
-#ifdef HAVE_SETHOSTENT
-       sethostent (1);
+       gethostname (buffer, sizeof(buffer) - 1);
 #endif 
        /* now fully qualify our name */
-       if ((hp = gethostbyname (buffer)))
-           strncpy (buffer, hp->h_name, sizeof(buffer));
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_flags = AI_CANONNAME;
+       hints.ai_family = PF_UNSPEC;
+       if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
+           strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
+           freeaddrinfo(res);
+       }
     }
 
     /*

Index: uip/ftpsbr.c
===================================================================
RCS file: /sources/nmh/nmh/uip/ftpsbr.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- uip/ftpsbr.c        13 Apr 2007 11:53:08 -0000      1.5
+++ uip/ftpsbr.c        16 Jan 2009 02:28:55 -0000      1.6
@@ -1,8 +1,7 @@
-
 /*
  * ftpsbr.c -- simple FTP client library
  *
- * $Id: ftpsbr.c,v 1.5 2007/04/13 11:53:08 jjr Exp $
+ * $Id: ftpsbr.c,v 1.6 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -33,23 +32,15 @@
 #include <netdb.h>
 #include <errno.h>
 
-#if !defined(h_addr)
-# define h_addr        h_addr_list[0]
-#endif
-
-#define        inaddr_copy(hp,sin) \
-    memcpy((char *) &((sin)->sin_addr), (hp)->h_addr, (hp)->h_length)
+#define        start_tcp_client(res) \
+       socket (res->ai_family, res->ai_socktype, res->ai_protocol)
 
-#define        start_tcp_client(sock,priv) \
-       socket (AF_INET, SOCK_STREAM, 0)
-
-#define        join_tcp_server(fd, sock) \
-       connect ((fd), (struct sockaddr *) (sock), sizeof *(sock))
+#define        join_tcp_server(fd, sock, len) \
+       connect ((fd), (struct sockaddr *) (sock), len)
 
 /*
  * prototypes
  */
-struct hostent *gethostbystring ();
 int ftp_get (char *, char *, char *, char *, char *, char *, int, int);
 int ftp_trans (char *, char *, char *, char *, char *, char *, char *, int, 
int);
 
@@ -157,32 +148,32 @@
     }
 
     if (ftp_fd == NOTOK) {
-       struct sockaddr_in in_socket;
-       register struct hostent *hp;
-       register struct servent *sp;
+       struct addrinfo hints, *res;
 
-       if ((sp = getservbyname ("ftp", "tcp")) == NULL) {
-           fprintf (stderr, "tcp/ftp: unknown service");
-           return NOTOK;
-       }
-       if ((hp = gethostbystring (host)) == NULL) {
-           fprintf (stderr, "%s: unknown host\n", host);
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_flags = AI_ADDRCONFIG;
+       hints.ai_family = PF_INET;
+       hints.ai_socktype = SOCK_STREAM;
+
+       result = getaddrinfo(host, "ftp", &hints, &res);
+
+       if (result) {
+           fprintf(stderr, "%s/ftp: %s\n", host, gai_strerror(result));
            return NOTOK;
        }
-       in_socket.sin_family = hp->h_addrtype;
-       inaddr_copy (hp, &in_socket);
-       in_socket.sin_port = sp->s_port;
 
-       if ((ftp_fd = start_tcp_client ((struct sockaddr_in *) NULL, 0))
-               == NOTOK) {
+       if ((ftp_fd = start_tcp_client (res)) == NOTOK) {
            perror (host);
+           freeaddrinfo(res);
            return NOTOK;
        }
-       if (join_tcp_server (ftp_fd, &in_socket) == NOTOK) {
+       if (join_tcp_server (ftp_fd, res->ai_addr, res->ai_addrlen) == NOTOK) {
            perror (host);
+           freeaddrinfo(res);
            close_tcp_socket (ftp_fd), ftp_fd = NOTOK;
            return NOTOK;
        }
+       freeaddrinfo(res);
        getreply (1, 0);
 
        if (v_verbose) {

Index: uip/mhlsbr.c
===================================================================
RCS file: /sources/nmh/nmh/uip/mhlsbr.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- uip/mhlsbr.c        13 Apr 2007 11:53:08 -0000      1.12
+++ uip/mhlsbr.c        16 Jan 2009 02:28:55 -0000      1.13
@@ -2,7 +2,7 @@
 /*
  * mhlsbr.c -- main routines for nmh message lister
  *
- * $Id: mhlsbr.c,v 1.12 2007/04/13 11:53:08 jjr Exp $
+ * $Id: mhlsbr.c,v 1.13 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -291,7 +291,6 @@
 int sc_width (void);                  /* from termsbr.c */
 int sc_length (void);                 /* from termsbr.c */
 int sc_hardcopy (void);               /* from termsbr.c */
-struct hostent *gethostbystring ();
 
 
 int
@@ -1526,17 +1525,16 @@
 doface (struct mcomp *c1)
 {
     int        result, sd;
-    struct sockaddr_in in_socket;
-    struct sockaddr_in *isock = &in_socket;
     static int inited = OK;
-    static int addrlen;
-    static struct in_addr addr;
-    static unsigned short portno;
+    static struct sockaddr_storage ss;
+    static socklen_t socklen;
+    static int socktype;
+    static int protocol;
 
     if (inited == OK) {
        char *cp;
        char **ap = brkstring (cp = getcpy (faceproc), " ", "\n");
-       struct hostent *hp;
+       struct addrinfo hints, *res;
 
        if (ap[0] == NULL || ap[1] == NULL) {
 bad_faceproc: ;
@@ -1544,27 +1542,30 @@
            return (inited = NOTOK);
        }
 
-       if (!(hp = gethostbystring (ap[0])))
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_flags = AI_ADDRCONFIG;
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_DGRAM;
+
+       if (getaddrinfo(ap[0], ap[1], &hints, &res) != 0)
            goto bad_faceproc;
-       memcpy((char *) &addr, hp->h_addr, addrlen = hp->h_length);
 
-       portno = htons ((unsigned short) atoi (ap[1]));
-       free (cp);
+       memcpy(&ss, res->ai_addr, res->ai_addrlen);
+       socklen = res->ai_addrlen;
+       socktype = res->ai_socktype;
+       protocol = res->ai_protocol;
+       freeaddrinfo(res);
 
        inited = DONE;
     }
     if (inited == NOTOK)
        return NOTOK;
 
-    isock->sin_family = AF_INET;
-    isock->sin_port = portno;
-    memcpy((char *) &isock->sin_addr, (char *) &addr, addrlen);
-
-    if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK)
+    if ((sd = socket (ss.ss_family, socktype, protocol)) == NOTOK)
        return NOTOK;
 
     result = sendto (sd, c1->c_text, strlen (c1->c_text), 0,
-               (struct sockaddr *) isock, sizeof(*isock));
+               (struct sockaddr *) &ss, socklen);
 
     close (sd);
 

Index: uip/popsbr.c
===================================================================
RCS file: /sources/nmh/nmh/uip/popsbr.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- uip/popsbr.c        8 Nov 2007 02:28:39 -0000       1.19
+++ uip/popsbr.c        16 Jan 2009 02:28:55 -0000      1.20
@@ -1,7 +1,7 @@
 /*
  * popsbr.c -- POP client subroutines
  *
- * $Id: popsbr.c,v 1.19 2007/11/08 02:28:39 jjr Exp $
+ * $Id: popsbr.c,v 1.20 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -11,9 +11,6 @@
 #include <h/mh.h>
 #include <h/utils.h>
 
-extern int  client(char *args, char *protocol, char *service, int rproto,
-                  char *response, int len_response);
-
 #if defined(NNTP) && !defined(PSHSBR)
 # undef NNTP
 #endif
@@ -81,6 +78,8 @@
 #define POP_SASL_CB_N_PASS 1
     { SASL_CB_LOG, NULL, NULL },
     { SASL_CB_LIST_END, NULL, NULL },
+
+#define SASL_BUFFER_SIZE 262144
 };
 #else /* CYRUS_SASL */
 # define sasl_fgetc fgetc
@@ -255,7 +254,7 @@
      */
 
     memset(&secprops, 0, sizeof(secprops));
-    secprops.maxbufsize = BUFSIZ;
+    secprops.maxbufsize = SASL_BUFFER_SIZE;
     secprops.max_ssf = UINT_MAX;
 
     result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
@@ -384,7 +383,8 @@
     }
 
     /*
-     * Limit this to what we can deal with.
+     * Limit this to what we can deal with.  Shouldn't matter much because
+     * this is only outgoing data (which should be small)
      */
 
     if (maxoutbuf == 0 || maxoutbuf > BUFSIZ)
@@ -459,7 +459,7 @@
     char *c;
     
     /* skip any initial space */
-    for (pro = proxy; isspace(*pro); pro++)
+    for (pro = (unsigned char *) proxy; isspace(*pro); pro++)
         continue;
     
     /* calculate required size for argument array */
@@ -566,12 +566,12 @@
            return NOTOK;
 # endif /* KPOP */
        } else {
-           if ((fd1 = client (host, "tcp", POPSERVICE, rpop, response, 
sizeof(response))) == NOTOK) {
+           if ((fd1 = client (host, POPSERVICE, response, sizeof(response), 
snoop)) == NOTOK) {
                return NOTOK;
            }
        }
 #else  /* NNTP */
-       if ((fd1 = client (host, "tcp", "nntp", rpop, response, 
sizeof(response))) == NOTOK)
+       if ((fd1 = client (host, "nntp", response, sizeof(response), snoop)) == 
NOTOK)
            return NOTOK;
 #endif
 
@@ -1186,7 +1186,7 @@
     static int cnt = 0;
     unsigned int retbufsize = 0;
     int cc, result;
-    char *retbuf, tmpbuf[BUFSIZ];
+    char *retbuf, tmpbuf[SASL_BUFFER_SIZE];
 
     /*
      * If we have some leftover data, return that

Index: uip/post.c
===================================================================
RCS file: /sources/nmh/nmh/uip/post.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- uip/post.c  4 Nov 2007 11:54:35 -0000       1.22
+++ uip/post.c  16 Jan 2009 02:28:55 -0000      1.23
@@ -2,7 +2,7 @@
 /*
  * post.c -- enter messages into the mail transport system
  *
- * $Id: post.c,v 1.22 2007/11/04 11:54:35 jjr Exp $
+ * $Id: post.c,v 1.23 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -138,6 +138,8 @@
     { "saslmech", SASLminc(-5) },
 #define USERSW                   39
     { "user", SASLminc(-4) },
+#define PORTSW                  40
+    { "port server port name/number", 4 },
     { NULL, 0 }
 };
 
@@ -236,6 +238,7 @@
 static int sasl=0;             /* Use SASL auth for SMTP                */
 static char *saslmech=NULL;    /* Force use of particular SASL mech     */
 static char *user=NULL;                /* Authenticate as this user            
 */
+static char *port="smtp";      /* Name of server port for SMTP          */
 
 static unsigned msgflags = 0;  /* what we've seen */
 
@@ -518,6 +521,11 @@
                    if (!(user = *argp++) || *user == '-')
                        adios (NULL, "missing argument to %s", argp[-2]);
                    continue;
+
+               case PORTSW:
+                   if (!(port = *argp++) || *port == '-')
+                       adios (NULL, "missing argument to %s", argp[-2]);
+                   continue;
            }
        }
        if (msg)
@@ -1403,7 +1411,7 @@
 
     sigon ();
 
-    if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose,
+    if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, verbose,
                                    snoop, onex, queued, sasl, saslmech,
                                    user))
            || rp_isbad (retval = sm_winit (smtpmode, from)))
@@ -1442,8 +1450,9 @@
     sigon ();
 
     if (!whomsw || checksw)
-       if (rp_isbad (retval = sm_init (clientsw, serversw, watch, verbose, 
snoop, 0,
-                                       queued, sasl, saslmech, user))
+       if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch,
+                                       verbose, snoop, 0, queued, sasl,
+                                       saslmech, user))
                || rp_isbad (retval = sm_winit (smtpmode, from)))
            die (NULL, "problem initializing server; %s", rp_string (retval));
 

Index: uip/send.c
===================================================================
RCS file: /sources/nmh/nmh/uip/send.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- uip/send.c  4 Nov 2007 11:54:36 -0000       1.9
+++ uip/send.c  16 Jan 2009 02:28:55 -0000      1.10
@@ -2,7 +2,7 @@
 /*
  * send.c -- send a composed message
  *
- * $Id: send.c,v 1.9 2007/11/04 11:54:36 jjr Exp $
+ * $Id: send.c,v 1.10 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -93,19 +93,21 @@
 #define        CLIESW                34
     { "client host", -6 },
 #define        SERVSW                35
-    { "server host", -6 },
+    { "server host", 6 },
 #define        SNOOPSW               36
-    { "snoop", -5 },
+    { "snoop", 5 },
 #define SASLSW                37
-    { "sasl", SASLminc(-4) },
+    { "sasl", SASLminc(4) },
 #define SASLMECHSW            38
-    { "saslmech", SASLminc(-5) },
+    { "saslmech mechanism", SASLminc(-5) },
 #define USERSW                39
-    { "user", SASLminc(-4) },
+    { "user username", SASLminc(-4) },
 #define ATTACHSW              40
     { "attach", 6 },
 #define ATTACHFORMATSW        41
     { "attachformat", 7 },
+#define PORTSW               42
+    { "port server-port-name/number" , 4 },
     { NULL, 0 }
 };
 
@@ -273,6 +275,7 @@
                case SERVSW: 
                case SASLMECHSW:
                case USERSW:
+               case PORTSW:
                    vec[vecp++] = --cp;
                    if (!(cp = *argp++) || *cp == '-')
                        adios (NULL, "missing argument to %s", argp[-2]);

Index: uip/whatnowsbr.c
===================================================================
RCS file: /sources/nmh/nmh/uip/whatnowsbr.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- uip/whatnowsbr.c    3 Aug 2008 18:47:56 -0000       1.11
+++ uip/whatnowsbr.c    16 Jan 2009 02:28:55 -0000      1.12
@@ -2,7 +2,7 @@
 /*
  * whatnowsbr.c -- the WhatNow shell
  *
- * $Id: whatnowsbr.c,v 1.11 2008/08/03 18:47:56 pm215 Exp $
+ * $Id: whatnowsbr.c,v 1.12 2009/01/16 02:28:55 kenh Exp $
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
@@ -1044,7 +1044,7 @@
 #define        CLIESW           30
     { "client host", -6 },
 #define        SERVSW           31
-    { "server host", -6 },
+    { "server host", 6 },
 #define        SNOOPSW          32
     { "snoop", -5 },
 #define SDRFSW           33
@@ -1058,11 +1058,13 @@
 #define SASLMECHSW       37
     { "saslmech", SASLminc(-5) },
 #define USERSW           38
-    { "user", SASLminc(-4) },
+    { "user", SASLminc(4) },
 #define SNDATTACHSW       39
     { "attach file", 6 },
 #define SNDATTACHFORMAT   40
     { "attachformat", 7 },
+#define PORTSW           41
+    { "port server-port-name/number", 4 },
     { NULL, 0 }
 };
 

Index: docs/pending-release-notes
===================================================================
RCS file: docs/pending-release-notes
diff -N docs/pending-release-notes
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ docs/pending-release-notes  16 Jan 2009 02:28:54 -0000      1.1
@@ -0,0 +1,11 @@
+Things to add to the release notes for the next full release:
+
+- SASL security layers (encryption) are now supported for the SMTP MTA.
+- You can now select the SMTP server and port from either "send" or a
+  user's mh_profile (you could always select the server; that option is
+  now documented).  These are available via the -server and -port switches.
+- All networking code has been modified to use the new networking APIs
+  (getaddrinfo and friends).  All networking code (with the exception of
+  the ftp client) now supports IPv6.
+- Support for prefixing a \01 in the "servers" entry in mts.conf to
+  connect to all servers on a particular named net has been removed.

Index: h/netdb.h
===================================================================
RCS file: h/netdb.h
diff -N h/netdb.h
--- h/netdb.h   30 Apr 1999 18:08:34 -0000      1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,71 +0,0 @@
-/*
- * netdb.h
- *
- * Copyright (c) 1980,1983,1988 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- *
- * $Id: netdb.h,v 1.1.1.1 1999/04/30 18:08:34 doug Exp $
- */
-
-/*
- * Structures returned by network
- * data base library.  All addresses
- * are supplied in host order, and
- * returned in network order (suitable
- * for use in system calls).
- */
-struct hostent {
-       char    *h_name;        /* official name of host */
-       char    **h_aliases;    /* alias list */
-       int     h_addrtype;     /* host address type */
-       int     h_length;       /* length of address */
-       char    **h_addr_list;  /* list of addresses from name server */
-#define        h_addr  h_addr_list[0]  /* address, for backward compatiblity */
-};
-
-/*
- * Assumption here is that a network number
- * fits in 32 bits -- probably a poor one.
- */
-struct netent {
-       char            *n_name;        /* official name of net */
-       char            **n_aliases;    /* alias list */
-       int             n_addrtype;     /* net address type */
-       unsigned long   n_net;          /* network # */
-};
-
-struct servent {
-       char    *s_name;        /* official service name */
-       char    **s_aliases;    /* alias list */
-       int     s_port;         /* port # */
-       char    *s_proto;       /* protocol to use */
-};
-
-struct protoent {
-       char    *p_name;        /* official protocol name */
-       char    **p_aliases;    /* alias list */
-       int     p_proto;        /* protocol # */
-};
-
-struct hostent *gethostbyname(), *gethostbyaddr(), *gethostent();
-struct netent  *getnetbyname(), *getnetbyaddr(), *getnetent();
-struct servent *getservbyname(), *getservbyport(), *getservent();
-struct protoent        *getprotobyname(), *getprotobynumber(), *getprotoent();
-
-/*
- * Error return codes from gethostbyname() and gethostbyaddr()
- * (left in extern int h_errno).
- */
-
-#define        HOST_NOT_FOUND  1 /* Authoritative Answer Host not found */
-#define        TRY_AGAIN       2 /* Non-Authoritive Host not found, or 
SERVERFAIL */
-#define        NO_RECOVERY     3 /* Non recoverable errors, FORMERR, REFUSED, 
NOTIMP */
-#define        NO_DATA         4 /* Valid name, no data record of requested 
type */
-#define        NO_ADDRESS      NO_DATA         /* no address, look for MX 
record */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]