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.
Wietse
Demi 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.
OpenPGP_0xB288B55FFF9C22C1.asc
Description: application/pgp-keys
OpenPGP_signature
Description: OpenPGP digital signature