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