diff --git a/postfix/HISTORY b/postfix/HISTORY index 6948b8a2b..4766e1711 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -27157,3 +27157,18 @@ Apologies for any names omitted. versus virtual aliasing, and inet_interfaces. Files: proto/postconf.proto, proto/aliases, proto/virtual, proto/ADDRESS_REWRITING_README.html. + +20230516 + + Bugfix (defect introduced: Postfix 3.4): the postlog(1) + command created a logfile with permissions 0644, but the + postlogd(8) daemon created it with permissions 0600, for + example after "postfix logrotate". The discrepancy is now + eliminated, and the permissions when creating a file are + now configurable with the "maillog_file_permissions" + parameter, default 0600 for backwards compatibility. Files: + mantools/postlink, proto/MAILLOG_README.html, proto/postconf.proto, + global/mail_params.c, global/mail_params.h, global/Makefile.in, + master/master.c, postlog/postlog.c, postlogd/postlogd.c, + util/logwriter.c, util/logwriter.h, util/Makefile.in, + util/vstream.c. diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 15e965f41..9966ea45d 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -1153,6 +1153,7 @@ while (<>) { s;\bmail[-]*\n*[ ]*log_file_compressor\b;$&;g; s;\bmail[-]*\n*[ ]*log_file_prefixes\b;$&;g; s;\bmail[-]*\n*[ ]*log_file_rotate_suffix\b;$&;g; + s;\bmail[-]*\n*[ ]*log_file_permissions\b;$&;g; s;\bpostlog_service_name\b;$&;g; s;\bpostlogd_watchdog_timeout\b;$&;g; diff --git a/postfix/proto/MAILLOG_README.html b/postfix/proto/MAILLOG_README.html index da1c1a8b5..13c1091e8 100644 --- a/postfix/proto/MAILLOG_README.html +++ b/postfix/proto/MAILLOG_README.html @@ -63,10 +63,16 @@ Postfix version.

/var/log/postfix.log. See also the "Logfile rotation" section below for logfile management.

+

In the example below, specifying maillog_file_permissions is +optional (Postfix 3.9 and later). The default value is 0600, i.e., +only the super-user can access the file; the value 0644 also +adds 'group' and 'other' read access.

+
 # postfix stop
 # postconf maillog_file=/var/log/postfix.log
+# postconf maillog_file_permissions=0644 # (Postfix 3.9 and later)
 # postfix start
 
@@ -124,6 +130,10 @@ old logfile.

program is configured with the maillog_file_compressor parameter (default: gzip).

+
  • The next time it logs an event, postlogd(8) will create a +new logfile, with permissions specified with the maillog_file_permissions +parameter (default: 0600).

    +

    Notes:

    diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 0604d2413..0ec06fe49 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -18263,6 +18263,17 @@ default suffix, YYYYMMDD-HHMMSS, allows logs to be rotated frequently.

    This feature is available in Postfix 3.4 and later.

    +%PARAM maillog_file_permissions 0600 + +

    The file access permissions that will be set when the file +$maillog_file is created for the first time, or when the file is +created after an existing file is rotated. Specify one of: 0600 +(only super-user read/write access), 0640 (adds 'group' read +access), or 0644 (also adds 'other' read access). The leading +'0' is optional.

    + +

    This feature is available in Postfix 3.9 and later.

    + %PARAM info_log_address_format external

    The email address form that will be used in non-debug logging diff --git a/postfix/proto/stop b/postfix/proto/stop index 1026d9c4b..238698457 100644 --- a/postfix/proto/stop +++ b/postfix/proto/stop @@ -1580,3 +1580,4 @@ stderr charset latin utf +mb diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history index 0327ec379..60b8572a1 100644 --- a/postfix/proto/stop.double-history +++ b/postfix/proto/stop.double-history @@ -48,3 +48,5 @@ proto proto ADDRESS_REWRITING_README html postfix postfix c aliasing Files proto aliases proto virtual postfix postfix c proto proto aliases proto virtual proto ADDRESS_REWRITING_README html + master master c postlog postlog c postlogd postlogd c + proto postconf proto proto aliases proto virtual diff --git a/postfix/proto/stop.spell-cc b/postfix/proto/stop.spell-cc index 84fcd8758..aa28bee99 100644 --- a/postfix/proto/stop.spell-cc +++ b/postfix/proto/stop.spell-cc @@ -1801,3 +1801,4 @@ bitcount bytecount ipproto cw +uncreate diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 86390ede2..562290232 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -1911,6 +1911,7 @@ mail_params.o: ../../include/htable.h mail_params.o: ../../include/inet_addr_list.h mail_params.o: ../../include/inet_proto.h mail_params.o: ../../include/iostuff.h +mail_params.o: ../../include/logwriter.h mail_params.o: ../../include/midna_domain.h mail_params.o: ../../include/mkmap.h mail_params.o: ../../include/msg.h diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 81aee73cf..1763fd383 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -159,6 +159,7 @@ /* char *var_maillog_file_pfxs; /* char *var_maillog_file_comp; /* char *var_maillog_file_stamp; +/* char *var_maillog_file_perms; /* char *var_postlog_service; /* /* char *var_dnssec_probe; @@ -226,6 +227,7 @@ #include #include #include +#include /* Global library. */ @@ -375,6 +377,7 @@ char *var_maillog_file; char *var_maillog_file_pfxs; char *var_maillog_file_comp; char *var_maillog_file_stamp; +char *var_maillog_file_perms; char *var_postlog_service; char *var_dnssec_probe; @@ -729,6 +732,7 @@ void mail_params_init() VAR_MAILLOG_FILE_PFXS, DEF_MAILLOG_FILE_PFXS, &var_maillog_file_pfxs, 1, 0, VAR_MAILLOG_FILE_COMP, DEF_MAILLOG_FILE_COMP, &var_maillog_file_comp, 1, 0, VAR_MAILLOG_FILE_STAMP, DEF_MAILLOG_FILE_STAMP, &var_maillog_file_stamp, 1, 0, + VAR_MAILLOG_FILE_PERMS, DEF_MAILLOG_FILE_PERMS, &var_maillog_file_perms, 1, 0, VAR_POSTLOG_SERVICE, DEF_POSTLOG_SERVICE, &var_postlog_service, 1, 0, VAR_DNSSEC_PROBE, DEF_DNSSEC_PROBE, &var_dnssec_probe, 0, 0, VAR_KNOWN_TCP_PORTS, DEF_KNOWN_TCP_PORTS, &var_known_tcp_ports, 0, 0, @@ -979,6 +983,9 @@ void mail_params_init() dict_db_cache_size = var_db_read_buf; dict_lmdb_map_size = var_lmdb_map_size; inet_windowsize = var_inet_windowsize; + if (set_logwriter_create_perms(var_maillog_file_perms) < 0) + msg_warn("ignoring bad permissions: %s = %s", + VAR_MAILLOG_FILE_PERMS, var_maillog_file_perms); /* * Variables whose defaults are determined at runtime, after other diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 7c80add97..c008f46f7 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -4349,6 +4349,10 @@ extern char *var_maillog_file_comp; #define DEF_MAILLOG_FILE_STAMP "%Y%m%d-%H%M%S" extern char *var_maillog_file_stamp; +#define VAR_MAILLOG_FILE_PERMS "maillog_file_permissions" +#define DEF_MAILLOG_FILE_PERMS "0600" +extern char *var_maillog_file_perms; + #define VAR_POSTLOG_SERVICE "postlog_service_name" #define DEF_POSTLOG_SERVICE MAIL_SERVICE_POSTLOG extern char *var_postlog_service; diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index aadda2771..4704e0ba6 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20230508" +#define MAIL_RELEASE_DATE "20230516" #define MAIL_VERSION_NUMBER "3.9" #ifdef SNAPSHOT diff --git a/postfix/src/master/master.c b/postfix/src/master/master.c index 1fc3fe9e4..f34df22e9 100644 --- a/postfix/src/master/master.c +++ b/postfix/src/master/master.c @@ -135,13 +135,13 @@ /* The external command to execute when a Postfix daemon program is /* invoked with the -D option. /* .IP "\fBinet_interfaces (all)\fR" -/* The network interface addresses that this mail system receives +/* The local network interface addresses that this mail system receives /* mail on. /* .IP "\fBinet_protocols (see 'postconf -d output')\fR" /* The Internet protocols Postfix will attempt to use when making /* or accepting connections. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a privileged Postfix +/* The list of environment variables that a privileged Postfix /* process will import from a non-Postfix parent process, or name=value /* environment overrides. /* .IP "\fBmail_owner (postfix)\fR" @@ -495,7 +495,7 @@ int main(int argc, char **argv) vstring_sprintf(lock_path, "%s/%s.pid", DEF_PID_DIR, var_procname); if (test_lock && access(vstring_str(lock_path), F_OK) < 0) exit(0); - lock_fp = open_lock(vstring_str(lock_path), O_RDWR | O_CREAT, 0644, why); + lock_fp = open_lock(vstring_str(lock_path), O_RDWR | O_CREAT, 0600, why); if (test_lock) exit(lock_fp ? 0 : 1); if (lock_fp == 0) @@ -513,7 +513,7 @@ int main(int argc, char **argv) vstring_sprintf(data_lock_path, "%s/%s.lock", var_data_dir, var_procname); set_eugid(var_owner_uid, var_owner_gid); data_lock_fp = - open_lock(vstring_str(data_lock_path), O_RDWR | O_CREAT, 0644, why); + open_lock(vstring_str(data_lock_path), O_RDWR | O_CREAT, 0600, why); set_ugid(getuid(), getgid()); if (data_lock_fp == 0) msg_fatal("open lock file %s: %s", diff --git a/postfix/src/postlog/postlog.c b/postfix/src/postlog/postlog.c index 7175f4234..195ebd918 100644 --- a/postfix/src/postlog/postlog.c +++ b/postfix/src/postlog/postlog.c @@ -82,6 +82,12 @@ /* \fBpostlogd\fR(8) service. /* .IP "\fBpostlog_service_name (postlog)\fR" /* The name of the \fBpostlogd\fR(8) service entry in master.cf. +/* .PP +/* Available in Postfix 3.9 and later: +/* .IP "\fBmaillog_file_permissions (0600)\fR" +/* The file access permissions that will be set when the file +/* $maillog_file is created for the first time, or when the file is +/* created after an existing file is rotated. /* SEE ALSO /* postconf(5), configuration parameters /* postlogd(8), Postfix logging diff --git a/postfix/src/postlogd/postlogd.c b/postfix/src/postlogd/postlogd.c index 902cbe5d3..33d7c8b41 100644 --- a/postfix/src/postlogd/postlogd.c +++ b/postfix/src/postlogd/postlogd.c @@ -56,6 +56,12 @@ /* .IP "\fBpostlogd_watchdog_timeout (10s)\fR" /* How much time a \fBpostlogd\fR(8) process may take to process a request /* before it is terminated by a built-in watchdog timer. +/* .PP +/* Available in Postfix 3.9 and later: +/* .IP "\fBmaillog_file_permissions (0600)\fR" +/* The file access permissions that will be set when the file +/* $maillog_file is created for the first time, or when the file is +/* created after an existing file is rotated. /* SEE ALSO /* postconf(5), configuration parameters /* syslogd(8), system logging diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index f69dec58e..d795f69d6 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -2157,6 +2157,7 @@ logwriter.o: logwriter.c logwriter.o: logwriter.h logwriter.o: msg.h logwriter.o: mymalloc.h +logwriter.o: name_code.h logwriter.o: safe_open.h logwriter.o: sys_defs.h logwriter.o: vbuf.h diff --git a/postfix/src/util/logwriter.c b/postfix/src/util/logwriter.c index aea2767f8..4a18be314 100644 --- a/postfix/src/util/logwriter.c +++ b/postfix/src/util/logwriter.c @@ -21,6 +21,9 @@ /* const char *path, /* const char *buffer, /* ssize_t buflen) +/* +/* int set_logwriter_create_perms( +/* const char *mode) /* DESCRIPTION /* This module manages a logfile writer. /* @@ -38,6 +41,15 @@ /* logwriter_one_shot() combines all the above operations. The /* result is zero if successful, VSTREAM_EOF if any operation /* failed. +/* +/* set_logwriter_create_perms() sets the file permissions that +/* will be used when creating a logfile. Valid inputs are +/* "644", "640", and "600". Leading zeros are allowed and +/* ignored. +/* DIAGNOSTICS +/* Fatal error: logfile create error; warning: logfile permission +/* change error. set_logwriter_create_perms() returns the file +/* create permission if the request is valid, -1 otherwise. /* LICENSE /* .ad /* .fi @@ -66,10 +78,12 @@ #include #include #include +#include /* * Application-specific. */ +static int logwriter_perms = 0600; /* logwriter_open_or_die - open logfile */ @@ -82,7 +96,7 @@ VSTREAM *logwriter_open_or_die(const char *path) #define NO_CHOWN (-1) #define NO_CHGRP (-1) - fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, 0644, + fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, logwriter_perms, NO_STATP, NO_CHOWN, NO_CHGRP, why); if (fp == 0) msg_fatal("open logfile '%s': %s", path, vstring_str(why)); @@ -122,3 +136,21 @@ int logwriter_one_shot(const char *path, const char *buf, ssize_t len) err |= logwriter_close(fp); return (err ? VSTREAM_EOF : 0); } + +/* set_logwriter_create_perms - logfile permission control */ + +int set_logwriter_create_perms(const char *mode_str) +{ + static const NAME_CODE sane_perms[] = { + "644", 0644, + "640", 0640, + "600", 0600, + 0, -1, + }; + int perms; + + if ((perms = name_code(sane_perms, NAME_CODE_FLAG_NONE, + mode_str + strspn(mode_str, "0"))) != -1) + logwriter_perms = perms; + return (perms); +} diff --git a/postfix/src/util/logwriter.h b/postfix/src/util/logwriter.h index f5266e4b7..c827d25f5 100644 --- a/postfix/src/util/logwriter.h +++ b/postfix/src/util/logwriter.h @@ -23,6 +23,7 @@ extern VSTREAM *logwriter_open_or_die(const char *); extern int logwriter_write(VSTREAM *, const char *, ssize_t); extern int logwriter_close(VSTREAM *); extern int logwriter_one_shot(const char *, const char *, ssize_t); +extern int set_logwriter_create_perms(const char *); /* LICENSE /* .ad diff --git a/postfix/src/util/vstream.c b/postfix/src/util/vstream.c index b4f9fbb67..affbcc0df 100644 --- a/postfix/src/util/vstream.c +++ b/postfix/src/util/vstream.c @@ -522,6 +522,7 @@ /* System library. */ #include +#include #include /* 44BSD stdarg.h uses abort() */ #include #include @@ -1386,7 +1387,38 @@ VSTREAM *vstream_fopen(const char *path, int flags, mode_t mode) VSTREAM *stream; int fd; - if ((fd = open(path, flags, mode)) < 0) { + /* + * To set permissions on new files only, we need to distinguish between + * creating a new file and opening an existing one. + */ +#define open_create(path, flags, mode) \ + open((path), (flags) | (O_CREAT | O_EXCL), (mode)) +#define open_exist(path, flags, mode) \ + open((path), (flags) & ~(O_CREAT | O_EXCL), (mode)) + + switch (flags & (O_CREAT | O_EXCL)) { + case O_CREAT: + fd = open_exist(path, flags, mode); + if (fd < 0 && errno == ENOENT) { + fd = open_create(path, flags, mode); + if (fd >= 0) { + if (fchmod(fd, mode) < 0) /* can't uncreate */ + msg_warn("fchmod %s 0%o: %m", path, (unsigned) mode); + } else if ( /* fd < 0 && */ errno == EEXIST) + fd = open_exist(path, flags, mode); + } + break; + case O_CREAT | O_EXCL: + fd = open(path, flags, mode); + if (fd >= 0) + if (fchmod(fd, mode) < 0) /* can't uncreate */ + msg_warn("fchmod %s 0%o: %m", path, (unsigned) mode); + break; + default: + fd = open(path, flags, mode); + break; + } + if (fd < 0) { return (0); } else { stream = vstream_fdopen(fd, flags);