On 10/9/20 1:06 PM, Demi M. Obenour wrote:
> On 10/8/20 3:19 PM, Wietse Venema wrote:
>> Demi M. Obenour:
>>> On 10/8/20 8:25 AM, Wietse Venema wrote:
>>>> Demi M. Obenour:
>>>>> On 10/6/20 4:23 PM, Wietse Venema wrote:
>>>>>> If the feature is turned on then there should probably be a
>>>>>> default action for users not listed in the table (deny or allow).
>>>>>> Its not going to be pretty when only the numerical UID is avaialble
>>>>>> (a 1:1 mapping username->sender would not make sense).
>>>>>
>>>>> What about defaulting to allow if local_sender_login_maps has its
>>>>> default value, and deny otherwise?  That keeps the current default
>>>>> behavior, while still allowing administrators to lock it down.
>>>>
>>>> The action (deny) for unmatched users should not depend on the
>>>> (non-empty) local_sender_login_maps value.
>>>
>>> Should this be a configuration option?
>>
>> It is not needed. If someone wants unmatched users to allow all,
>> just say so:
>>
>>      local_sender_login_maps = <real login->address map> static:*
>>
>> This still enforces the allowed email addressesfor users that have
>> an entry.
>>
>> If local_sender_login_maps is turned on, indexing with "#" plus the
>> UID as a string would do the job. It is not like users can arbitrarily
>> remove their login name from the password file.
> 
> Here is an updated diff which implements this idea.  It also splits out
> the FROM access check into its own function, and uses var_rcpt_delim
> instead of hard-coding "+".  $mail_owner is now allowed to send mail
> as any user.

Looks like Thunderbird mangled the whitespace.  Here is another attempt:

diff -ur ../postfix-3.5.7-old/src/global/mail_params.h 
../postfix-3.5.7/src/global/mail_params.h
--- ../postfix-3.5.7-old/src/global/mail_params.h       2020-10-05 
18:52:49.518000000 -0400
+++ ../postfix-3.5.7/src/global/mail_params.h   2020-10-05 18:10:32.641000000 
-0400
@@ -1667,6 +1667,10 @@
 #define DEF_SMTPD_SASL_TYPE    DEF_SERVER_SASL_TYPE
 extern char *var_smtpd_sasl_type;
 
+#define VAR_LOCAL_SND_AUTH_MAPS        "local_sender_login_maps"
+#define DEF_LOCAL_SND_AUTH_MAPS        "static:*"
+extern char *var_local_snd_auth_maps;
+
 #define VAR_SMTPD_SND_AUTH_MAPS        "smtpd_sender_login_maps"
 #define DEF_SMTPD_SND_AUTH_MAPS        ""
 extern char *var_smtpd_snd_auth_maps;
diff -ur ../postfix-3.5.7-old/src/postdrop/postdrop.c 
../postfix-3.5.7/src/postdrop/postdrop.c
--- ../postfix-3.5.7-old/src/postdrop/postdrop.c        2020-10-05 
18:52:49.518000000 -0400
+++ ../postfix-3.5.7/src/postdrop/postdrop.c    2020-10-09 12:53:43.249000000 
-0400
@@ -114,6 +114,7 @@
 #include <stdio.h>                     /* remove() */
 #include <string.h>
 #include <stdlib.h>
+#include <inttypes.h>
 #include <signal.h>
 #include <errno.h>
 #include <warn_stat.h>
@@ -147,6 +148,10 @@
 #include <rec_attr_map.h>
 #include <mail_parm_split.h>
 #include <maillog_client.h>
+#include <maps.h>
+#include <mail_addr_find.h>
+#include <strip_addr.h>
+#include <mypwd.h>
 
 /* Application-specific. */
 
@@ -167,9 +172,13 @@
   * Local mail submission access list.
   */
 char   *var_submit_acl;
+char   *var_local_snd_auth_maps;
+char   *var_rcpt_delim;
 
 static const CONFIG_STR_TABLE str_table[] = {
     VAR_SUBMIT_ACL, DEF_SUBMIT_ACL, &var_submit_acl, 0, 0,
+    VAR_LOCAL_SND_AUTH_MAPS, DEF_LOCAL_SND_AUTH_MAPS, 
&var_local_snd_auth_maps, 0, 0,
+    VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 0,
     0,
 };
 
@@ -220,6 +229,65 @@
     postdrop_sig(0);
 }
 
+/*
+ * postdrop_check_access - check if a user is authorized to send mail as
+ * the envelope sender
+ */
+static void postdrop_check_access(VSTRING *const buf, uid_t const uid) {
+    MAPS    *local_sender_login_maps;
+    struct mypasswd *username;
+    const char *owners;
+    char   *saved_owners, *cp, *name, *stripped, *stripped_copy, 
username_buf[22];
+    char   *pw_name;
+    int     found = 0;
+
+    /* Root and $mail_owner are always allowed to send as anyone. */
+    if (uid == 0 || uid == var_owner_uid)
+       return;
+
+    /*
+     * Get the username.
+     */
+    if ((username = mypwuid(uid)) != NULL)
+       pw_name = username->pw_name;
+    else {
+       int status = snprintf(username_buf, sizeof username_buf, "#%"PRIu64, 
(uint64_t)uid);
+       if (status < 0 || status >= sizeof username_buf)
+           msg_fatal("snprintf");
+       pw_name = username_buf;
+    }
+
+    local_sender_login_maps = maps_create(VAR_SMTPD_SND_AUTH_MAPS,
+                                         var_local_snd_auth_maps,
+                                         DICT_FLAG_FOLD_FIX |
+                                         DICT_FLAG_UTF8_REQUEST |
+                                         DICT_FLAG_NO_PROXY |
+                                         DICT_FLAG_NO_UNAUTH);
+
+    if (vstring_memchr(buf, '\0') != NULL)
+       msg_fatal("uid=%ld: NUL in FROM", (long) uid);
+    if ((owners = maps_find(local_sender_login_maps, pw_name, 0)) == NULL)
+       msg_fatal("uid=%ld: not found in local_sender_login_maps", (long) uid);
+    if (local_sender_login_maps->error != 0)
+       msg_fatal("map lookup succeeded, but error set");
+    if (strcmp(owners, "*") == 0)
+       return;
+    if ((stripped = stripped_copy = strip_addr_internal(vstring_str(buf), 
NULL, var_rcpt_delim)) == NULL)
+       stripped = vstring_str(buf);
+    cp = saved_owners = mystrdup(owners);
+    while ((name = mystrtok(&saved_owners, CHARS_COMMA_SP)) != 0) {
+       if (strcmp(stripped, name) == 0) {
+           found = 1;
+           break;
+       }
+    }
+    if (!found)
+       msg_fatal("uid=%ld: does not own address %s", (long) uid, 
vstring_str(buf));
+    if (stripped_copy != NULL)
+       myfree(stripped_copy);
+    myfree(cp);
+}
+
 MAIL_VERSION_STAMP_DECLARE;
 
 /* main - the main program */
@@ -316,16 +384,6 @@
     get_mail_conf_str_table(str_table);
 
     /*
-     * Mail submission access control. Should this be in the user-land gate,
-     * or in the daemon process?
-     */
-    mail_dict_init();
-    if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, var_submit_acl,
-                                      uid)) != 0)
-       msg_fatal("User %s(%ld) is not allowed to submit mail",
-                 errstr, (long) uid);
-
-    /*
      * Stop run-away process accidents by limiting the queue file size. This
      * is not a defense against DOS attack.
      */
@@ -369,6 +427,16 @@
     /* End of initializations. */
 
     /*
+     * Mail submission access control. Should this be in the user-land gate,
+     * or in the daemon process?
+     */
+    mail_dict_init();
+    if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, var_submit_acl,
+                                      uid)) != 0)
+       msg_fatal("User %s(%ld) is not allowed to submit mail",
+                 errstr, (long) uid);
+
+    /*
      * Don't trust the caller's time information.
      */
     GETTIMEOFDAY(&start);
@@ -429,8 +497,10 @@
        if (rec_type == REC_TYPE_TIME)
            continue;
        /* Check these at submission time instead of pickup time. */
-       if (rec_type == REC_TYPE_FROM)
+       if (rec_type == REC_TYPE_FROM) {
+           postdrop_check_access(buf, uid);
            from_count++;
+       }
        if (rec_type == REC_TYPE_RCPT)
            rcpt_count++;
        /* Limit the attribute types that users may specify. */
@@ -477,7 +547,7 @@
        if (rec_type == REC_TYPE_END)
            break;
     }
-    vstring_free(buf);
+    buf = vstring_free(buf);
 
     /*
      * As of Postfix 2.7 the pickup daemon discards mail without recipients.

Attachment: OpenPGP_0xB288B55FFF9C22C1.asc
Description: application/pgp-keys

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

Reply via email to