]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20000418
authorWietse Venema <wietse@porcupine.org>
Tue, 18 Apr 2000 00:00:00 +0000 (00:00 +0000)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 23:10:24 +0000 (18:10 -0500)
postfix/HISTORY
postfix/SASL_README
postfix/global/mail_version.h
postfix/smtp/smtp_sasl_proto.c
postfix/smtpd/smtpd_sasl_glue.c
postfix/smtpstone/smtp-sink.c
postfix/smtpstone/smtp-source.c

index bab37d87a7cd596a939f3c7d6a340d1775436360..5f17ecb36b989965d706c611a6d6000ccaefe028 100644 (file)
@@ -3819,4 +3819,11 @@ Apologies for any names omitted.
 20000417
 
        The SASL authentication in the SMTP server and client works,
-       but only on Linux and Solaris.
+       but only on Linux and Solaris, neither of which I wish to
+       run on my laptop.
+
+20000418
+
+       Added LMTP support to the smtp-source and smtp-sink utilities
+       so that I don't have to install Cyrus IMAP just to test
+       LMTP.
index 7a9926c99474ec476c704120f27c4530be59757e..767a13cfe7dd336a2661282a2a625ff5d30d869d 100644 (file)
@@ -2,14 +2,16 @@ WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 ===============================================================
 
 Do not use this code.  The Postfix SASL support is based on the
-Cyrus SASL library, which is light years away from production
-quality. There is not enough documentation to figure out how the
-software is supposed to work.
+Cyrus SASL library, which has not enough documentation about how
+the software is supposed to work.
 
-The SASL library code works only on LINUX and Solaris.  If you
-build Postfix+SASL on other systems, the software builds without
-trouble but fails at runtime due to no available authentication
-mechanisms. It can be made to work with considerable tweaking.
+Postfix+SASL 1.5.5 appears to work on RedHat 6.1 (pwcheck_method
+of shadow or sasldb), Solaris 2.7 (pwcheck_method of shadow or
+sasldb), and FreeBSD 3.4 (pwcheck_method of sasldb).  On RedHat
+6.1, SASL 1.5.5 needed write access to the sasldb file.
+
+SASL is a lot of complex code. In a future version the Postfix SASL
+code is likely to be put outside the SMTP server.
 
 Introduction
 ============
@@ -18,16 +20,17 @@ The Postfix SASL support (RFC 2554) was originally implemented by
 Till Franke of SuSE Rhein/Main AG.  The present code is a trimmed-down
 version with only the bare necessities.  
 
-When receiving mail, Postfix logs the client-provided username and
-sender address to the maillog file, and optionally grants mail
-relay access to authenticated clients. SASL authentication information
-is not passed on via message headers or via SMTP.  It is no-one's
-business what username and authentication method the poster was
-using in order to access the mail server.
+When receiving mail, Postfix logs the client-provided username,
+authentication method, and sender address to the maillog file, and
+optionally grants mail access via the permit_sasl_authenticated
+UCE restriction.  SASL authentication information is not passed on
+via message headers or via SMTP.  It is no-one's business what
+username and authentication method the poster was using in order
+to access the mail server.
 
-When sending mail, Postfix looks up the server hostname and if
-a username/password is known, it will use that to authenticate
-to the server.
+When sending mail, Postfix looks up the server hostname in a table,
+and if a username/password is found, it will use that username and
+password to authenticate to the server.
 
 Building the SASL library
 =========================
@@ -80,15 +83,13 @@ In order to allow mail relaying by authenticated clients:
 In /usr/local/lib/sasl/smtpd.conf you need to specify what authentication
 mechanism the server will support, for example:
 
-    pwcheck_method:  shadow
-
-This will use the Linux or Solaris shadow passwd file, which is
-the only way that I was able to test, but which is undesirable
-because it uses plaintext passwords.
+    pwcheck_method:  sasldb
 
-If you wish to use the system shadow password file, the Postfix
-SMTP server can't run chrooted (see master.cf), and the postfix
-user or group needs read access to the shadow passwd file.
+This will use the SASL password file (default: /etc/sasldb), which
+is maintained with the saslpasswd command. On some systems the
+saslpasswd command needs to be run multiple times before it stops
+complaining.  The Postfix SMTP server needs read access to the
+sasldb file - you have to play games with group access permissions.
 
 To run chrooted with SASL support is an interesting exercise.
 
@@ -121,8 +122,8 @@ per-host username and password information.
        smtp_sasl_passwd_maps = hash:/etc/postfix/sasl_passwd
 
     /etc/postfix/sasl_passwd:
-       host.domain     username:password
-       host.domain     username
+       foo.com         username:password
+       bar.com         username
 
 The SASL password file is opened before the SMTP server enters the
 optional chroot jail, so there is no need to copy the sasl_passwd
index 3be0516b4fe777cb3455c0aac96ce49cb47caf93..4999f7b1c1ef667afc3dd2adaaca3cac0629ceff 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20000417"
+#define DEF_MAIL_VERSION       "Snapshot-20000418"
 extern char *var_mail_version;
 
 /* LICENSE
index 2b17e47fc1d69e48eae1cd0732620c39fe86b6bf..f3818236520b70b9f9ddc280624be4aae0e4be7d 100644 (file)
@@ -14,7 +14,7 @@
 /*     SMTP_STATE *state;
 /* DESCRIPTION
 /*     This module contains random chunks of code that implement
-/*     the SMTP protocol interface for SASL negotiation. The goal 
+/*     the SMTP protocol interface for SASL negotiation. The goal
 /*     is to reduce clutter in the main SMTP client source code.
 /*
 /*     smtp_sasl_helo_auth() processes the AUTH option in the
@@ -71,7 +71,7 @@
 
 /* smtp_sasl_helo_auth - handle AUTH option in EHLO reply */
 
-void smtp_sasl_helo_auth(SMTP_STATE *state, const char *words)
+void    smtp_sasl_helo_auth(SMTP_STATE *state, const char *words)
 {
 
     /*
@@ -88,20 +88,24 @@ void smtp_sasl_helo_auth(SMTP_STATE *state, const char *words)
     if (strlen(words) > 0) {
        state->sasl_mechanism_list = mystrdup(words);
        state->features |= SMTP_FEATURE_AUTH;
+    } else {
+       msg_warn("%s offered null AUTH mechanism list",
+                state->session->namaddr);
     }
 }
 
 /* smtp_sasl_helo_login - perform SASL login */
 
-int smtp_sasl_helo_login(SMTP_STATE *state)
+int     smtp_sasl_helo_login(SMTP_STATE *state)
 {
     VSTRING *why = vstring_alloc(10);
     int     ret = 0;
 
     /*
-     * Skip authentication when we have no authentication info for this
-     * server. In that case it should simply treat us like any stranger.
-     * Otherwise, if authentication fails assume the error is recoverable.
+     * Skip authentication when no authentication info exists for this
+     * server, so that we talk to each other like strangers. Otherwise, if
+     * authentication information exists, assume that authentication is
+     * required, and assume that an authentication error is recoverable.
      */
     if (smtp_sasl_passwd_lookup(state) != 0) {
        smtp_sasl_start(state);
index 2c8ed540f53b5f21d4f25b385e3a54a926e6a84d..5372e5c315d34c5034319e4f55b55c6f8a5809ab 100644 (file)
@@ -47,7 +47,7 @@
 /*     This member is a null pointer in the absence of successful
 /*     authentication.
 /* .PP
-/*     smtpd_sasl_logout() cleant up after smtpd_sasl_authenticate().
+/*     smtpd_sasl_logout() cleans up after smtpd_sasl_authenticate().
 /*     This routine exists for the sake of symmetry.
 /*
 /*     smtpd_sasl_disconnect() performs per-connection cleanup.
@@ -186,12 +186,10 @@ void    smtpd_sasl_connect(SMTPD_STATE *state)
        msg_fatal("SASL per-connection server initialization");
 
     /*
-     * Security options. XXX What exactly is this supposed to be doing? The
-     * cyrus-sasl-1.5.15 source code has no documentation at all about this
-     * routine.
-     * 
-     * Disallow anonymous authentication. The permit_sasl_authenticated feature
-     * is restricted to authenticated clients only.
+     * Security options. Some information can be found in the sasl.h include
+     * file. Disallow anonymous authentication; this is because the
+     * permit_sasl_authenticated feature is restricted to authenticated
+     * clients only.
      */
     memset(&sec_props, 0, sizeof(sec_props));
     sec_props.min_ssf = 0;
@@ -277,7 +275,7 @@ char   *smtpd_sasl_authenticate(SMTPD_STATE *state,
        dec_buffer = STR(state->sasl_decoded);
        if (sasl_decode64(init_response, reply_len,
                          dec_buffer, &dec_length) != SASL_OK)
-           return ("501 AUTH failed: malformed initial response");
+           return ("501 Authentication failed: malformed initial response");
        if (msg_verbose)
            msg_info("%s: decoded initial response %s", myname, dec_buffer);
     } else {
@@ -302,6 +300,9 @@ char   *smtpd_sasl_authenticate(SMTPD_STATE *state,
         * comes in multiples of four bytes for each triple of input bytes,
         * plus four bytes for any incomplete last triple, plus one byte for
         * the null terminator.
+        * 
+        * XXX Replace the klunky sasl_encode64() interface by something that
+        * uses VSTRING buffers.
         */
        if (msg_verbose)
            msg_info("%s: uncoded challenge: %.*s",
@@ -337,7 +338,7 @@ char   *smtpd_sasl_authenticate(SMTPD_STATE *state,
     }
 
     /*
-     * Cleanup. What a horrible interface.
+     * Cleanup. What an awful interface.
      */
     if (serverout)
        free(serverout);
index 5619f0b104940459f14bd37dcf7506b23f4895cc..7cd5e65e5e074bafbcddf17a849a8326d8d22394 100644 (file)
@@ -2,9 +2,9 @@
 /* NAME
 /*     smtp-sink 8
 /* SUMMARY
-/*     multi-threaded smtp test server
+/*     multi-threaded SMTP/LMTP test server
 /* SYNOPSIS
-/*     smtp-sink [-c] [-p] [-v] [-w delay] [host]:port backlog
+/*     smtp-sink [-cLpv] [-w delay] [host]:port backlog
 /* DESCRIPTION
 /*     \fIsmtp-sink\fR listens on the named host (or address) and port.
 /*     It takes SMTP messages from the network and throws them away.
@@ -14,6 +14,8 @@
 /* .IP -c
 /*     Display a running counter that is updated whenever an SMTP
 /*     QUIT command is executed.
+/* .IP -L
+/*     Speak LMTP rather than SMTP.
 /* .IP -p
 /*     Disable ESMTP command pipelining.
 /* .IP -v
@@ -21,7 +23,7 @@
 /* .IP "-w delay"
 /*     Wait \fIdelay\fR seconds before responding to a DATA command.
 /* SEE ALSO
-/*     smtp-source, SMTP test message generator
+/*     smtp-source, SMTP/LMTP test message generator
 /* LICENSE
 /* .ad
 /* .fi
@@ -71,6 +73,7 @@ typedef struct SINK_STATE {
     VSTREAM *stream;
     int     data_state;
     int     (*read) (struct SINK_STATE *);
+    int     rcpts;
 } SINK_STATE;
 
 #define ST_ANY                 0
@@ -91,6 +94,7 @@ static int count;
 static int counter;
 static int disable_pipelining;
 static int fixed_delay;
+static int enable_lmtp;
 
 /* ehlo_response - respond to EHLO command */
 
@@ -109,6 +113,22 @@ static void ok_response(SINK_STATE *state)
     smtp_printf(state->stream, "250 Ok");
 }
 
+/* mail_response - reset recipient count, send 250 OK */
+
+static void mail_response(SINK_STATE *state)
+{
+    state->rcpts = 0;
+    ok_response(state);
+}
+
+/* rcpt_response - bump recipient count, send 250 OK */
+
+static void rcpt_response(SINK_STATE *state)
+{
+    state->rcpts++;
+    ok_response(state);
+}
+
 /* data_response - respond to DATA command */
 
 static void data_response(SINK_STATE *state)
@@ -127,6 +147,18 @@ static void data_event(int unused_event, char *context)
     data_response(state);
 }
 
+/* dot_response - response to . command */
+
+static void dot_response(SINK_STATE *state)
+{
+    if (enable_lmtp) {
+       while (state->rcpts-- > 0)      /* XXX this could block */
+           ok_response(state);
+    } else {
+       ok_response(state);
+    }
+}
+
 /* quit_response - respond to QUIT command */
 
 static void quit_response(SINK_STATE *state)
@@ -184,7 +216,7 @@ static int data_read(SINK_STATE *state)
        if (state->data_state == ST_CR_LF_DOT_CR_LF) {
            if (msg_verbose)
                msg_info(".");
-           ok_response(state);
+           dot_response(state);
            state->read = command_read;
            break;
        }
@@ -203,8 +235,9 @@ typedef struct SINK_COMMAND {
 static SINK_COMMAND command_table[] = {
     "helo", ok_response,
     "ehlo", ehlo_response,
-    "mail", ok_response,
-    "rcpt", ok_response,
+    "lhlo", ehlo_response,
+    "mail", mail_response,
+    "rcpt", rcpt_response,
     "data", data_response,
     "rset", ok_response,
     "noop", ok_response,
@@ -311,7 +344,7 @@ static void connect_event(int unused_event, char *context)
 
 static void usage(char *myname)
 {
-    msg_fatal("usage: %s [-c] [-p] [-v] [host]:port backlog", myname);
+    msg_fatal("usage: %s [-cLpv] [host]:port backlog", myname);
 }
 
 int     main(int argc, char **argv)
@@ -328,11 +361,14 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "cpvw:")) > 0) {
+    while ((ch = GETOPT(argc, argv, "cLpvw:")) > 0) {
        switch (ch) {
        case 'c':
            count++;
            break;
+       case 'L':
+           enable_lmtp = 1;
+           break;
        case 'p':
            disable_pipelining = 1;
            break;
index 5968acf5e4ed3dbca553707a4c1156b24edcaa9f..1181ffaff3191dee7de5e6880651257f9cb6e5ee 100644 (file)
@@ -28,6 +28,8 @@
 /*     Old mode: don't send HELO, and don't send message headers.
 /* .IP "-l length"
 /*     Send \fIlength\fR bytes as message payload.
+/* .IP -L
+/*     Speak LMTP rather than SMTP.
 /* .IP "-m message_count"
 /*     Send the specified number of messages (default: 1).
 /* .IP "-r recipient_count"
   */
 typedef struct SESSION {
     int     xfer_count;                        /* # of xfers in session */
+    int     rcpt_done;                 /* # of recipients done */
     int     rcpt_count;                        /* # of recipients to go */
     VSTREAM *stream;                   /* open connection */
     int     connect_count;             /* # of connect()s to retry */
@@ -142,6 +145,7 @@ static int send_headers = 1;
 static int connect_count = 1;
 static int random_delay = 0;
 static int fixed_delay = 0;
+static int talk_lmtp = 0;
 
 static void enqueue_connect(SESSION *);
 static void start_connect(SESSION *);
@@ -445,6 +449,7 @@ static void read_banner(int unused_event, char *context)
 static void send_helo(SESSION *session)
 {
     int     except;
+    char   *protocol = (talk_lmtp ? "LHLO" : "EHLO");
 
     /*
      * Send the standard greeting with our hostname
@@ -452,7 +457,7 @@ static void send_helo(SESSION *session)
     if ((except = setjmp(smtp_timeout_buf)) != 0)
        msg_fatal("%s while sending HELO", exception_text(except));
 
-    command(session->stream, "HELO %s", var_myhostname);
+    command(session->stream, "%s %s", protocol, var_myhostname);
 
     /*
      * Prepare for the next event.
@@ -520,6 +525,7 @@ static void mail_done(int unused, char *context)
        msg_fatal("sender rejected: %d %s", resp->code, resp->str);
 
     session->rcpt_count = recipients;
+    session->rcpt_done = 0;
     send_rcpt(unused, context);
 }
 
@@ -542,6 +548,7 @@ static void send_rcpt(int unused_event, char *context)
     else
        command(session->stream, "RCPT TO:<%s>", recipient);
     session->rcpt_count--;
+    session->rcpt_done++;
 
     /*
      * Prepare for the next event.
@@ -679,8 +686,10 @@ static void dot_done(int unused_event, char *context)
      */
     if ((except = setjmp(smtp_timeout_buf)) != 0)
        msg_fatal("%s while sending message", exception_text(except));
-    if ((resp = response(session->stream, buffer))->code / 100 != 2)
-       msg_fatal("data %d %s", resp->code, resp->str);
+    do {                                       /* XXX this could block */
+       if ((resp = response(session->stream, buffer))->code / 100 != 2)
+           msg_fatal("data %d %s", resp->code, resp->str);
+    } while (talk_lmtp && --session->rcpt_done > 0);
     session->xfer_count++;
 
     /*
@@ -740,7 +749,7 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "cC:df:l:m:or:R:s:t:vw:")) > 0) {
+    while ((ch = GETOPT(argc, argv, "cC:df:l:Lm:or:R:s:t:vw:")) > 0) {
        switch (ch) {
        case 'c':
            count++;
@@ -765,6 +774,9 @@ int     main(int argc, char **argv)
                message_data[i - 1] = '\n';
            }
            break;
+       case 'L':
+           talk_lmtp = 1;
+           break;
        case 'm':
            if ((message_count = atoi(optarg)) <= 0)
                usage(argv[0]);