From: Wietse Venema Date: Sat, 24 Feb 2001 05:00:00 +0000 (-0500) Subject: snapshot-20010224 X-Git-Tag: v1.1.0~74 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e53f2b72eec3681f3a290ae0c1d464fa795a6029;p=thirdparty%2Fpostfix.git snapshot-20010224 --- diff --git a/postfix/BEWARE b/postfix/BEWARE new file mode 100644 index 000000000..1b0c41829 --- /dev/null +++ b/postfix/BEWARE @@ -0,0 +1,11 @@ +LINUX SYSLOGD PERFORMANCE +========================= + +LINUX syslogd uses synchronous writes by default, which is very +expensive. For services such as mail it is recommended that you +disable synchronous logfile writes by editing /etc/syslog.conf and +by prepending a - to the logfile name: + + mail.* -/var/log/mail.log + +Send a "kill -HUP" to the syslogd to make the change effective. diff --git a/postfix/HISTORY b/postfix/HISTORY index 4613ef2c2..813c90c65 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -4870,13 +4870,6 @@ Apologies for any names omitted. will give more insight into how Postfix uses its lookup tables. User interface comes later. File: util/dict_debug.c. -20010215 - - The showq output format assumes queue IDs of up to 10 - characters. It can be more with large file systems. - Workaround for 11 character queue IDs by Lamont Jones. - File: showq/showq.c. - 20010216 Bugfix: the pipe delivery agent expanded $size as if it @@ -4889,12 +4882,13 @@ Apologies for any names omitted. in $mydestination, because Postfix would send one recipient at a time, with multiple deliveries of recipients of the same message in parallel; a similar problem could exist - with firewall relay hosts that forward mail for $mydestination - to an inside machine. This behavior is now changed to depend - on the transport-specific xxx_destination_recipient_limit - parameter. This also means that you can now get qmail behavior - for SMTP deliveries by setting smtp_destination_recipient_limit=1. - File: {qmgr,nqmgr}/qmgr_message.c. + with virus scanning and with firewall relay hosts that + forward mail for $mydestination to an inside machine. This + behavior is now changed to depend on the transport-specific + xxx_destination_recipient_limit parameter. This also means + that you can now get qmail behavior for SMTP deliveries by + setting smtp_destination_recipient_limit=1. File: + {qmgr,nqmgr}/qmgr_message.c. Workaround: Solaris socketpair() can fail with EINTR. Added a sane_socketpair.c module that joins the ranks of the other @@ -4912,3 +4906,29 @@ Apologies for any names omitted. configuration file edits" has a section that explains that mynetworks should be properly configured in order to reject unauthorized mail relay requests from strangers. + +20010223 + + Documentation: the basic.html document has a section that + explains that mynetworks should be properly configured in + order to reject unauthorized mail relay requests from + strangers. + + Feature: new "mynetworks_style" parameter that controls + how mynetworks (trusted networks) is derived from the + inet_interfaces (machine interfaces) setting. Specify + "class" for entire class A, B, C networks; "subnet" for + the local subnets only; or "host" for maximal privacy. + Files: util/inet_addr_local.[hc], global/own_inet_addr.[hc], + global/mynetworks.[hc], postconf/postconf.c. + + Portability: MACOSX patches by Gerben Wierda. + + Portability: Solaris /dev/null is a symlink, which tripped + up the code to safely open a file before delivery. We now + grudgingly allow symlinks owned by root. File: util/safe_open.c. + +20010224 + + Bugfix: "postconf mynetworks" ignored the inet_interfaces + setting. That was a very old one. File: postconf/postconf.c. diff --git a/postfix/INSTALL b/postfix/INSTALL index c56c93055..20d58268c 100644 --- a/postfix/INSTALL +++ b/postfix/INSTALL @@ -74,6 +74,7 @@ If your system is supported, it is one of Linux SuSE 6.x Linux SuSE 7.x Mac OS X server + Mac OS X Public Beta NEXTSTEP 3.x NetBSD 1.x OPENSTEP 4.x @@ -416,10 +417,10 @@ Finally, if you haven't used Sendmail prior to using Postfix, you will have to build the alias database (with: sendmail -bi, or: newaliases). Be sure to set up aliases for root and postmaster that forward mail to a real person. Postfix has a sample aliases file -the conf/aliases. +conf/aliases that you can adapt to local conditions. 11 - To chroot or not to chroot -============================== +=============================== Postfix can run most daemon processes in a chroot jail, that is, the processes run at a fixed low privilege and with access only to diff --git a/postfix/INSTALL.sh b/postfix/INSTALL.sh index 2dfbfcbe6..1ad76e988 100644 --- a/postfix/INSTALL.sh +++ b/postfix/INSTALL.sh @@ -345,14 +345,18 @@ no) ;; ) esac -test "$need_config" = 1 && cat <&2 +test "$need_config" = 1 || exit 0 + +ALIASES=`bin/postconf -h alias_database | sed 's/^[^:]*://'` +cat <&2 - Warning: you still need to edit myorigin/mydestination in - $CONFIG_DIRECTORY/main.cf. See also html/faq.html for dialup + Warning: you still need to edit myorigin/mydestination/mynetworks + in $CONFIG_DIRECTORY/main.cf. See also html/faq.html for dialup sites or for sites inside a firewalled network. - BTW: Edit your alias database and be sure to set up aliases - for root and postmaster, then run $NEWALIASES_PATH. + BTW: Check your $ALIASES file and be sure to set up aliases + for root and postmaster that direct mail to a real person, then + run $NEWALIASES_PATH. EOF diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 2b58ef711..1cfc98c8e 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -8,9 +8,9 @@ load, at the cost of a small but noticeable slowdown when one runs Postfix no longer automatically delivers recipients one at a time when their domain is listed in $mydestination. This change solves -delivery performance problems with delivery via LMTP, and with -firewall relays that forward all mail for $mydestination to an -inside host. +delivery performance problems with delivery via LMTP, with virus +scanning, and with firewall relays that forward all mail for +$mydestination to an inside host. The "one recipient at a time" delivery behavior is now controlled by the per-transport recipient limit (xxx_destination_recipient_limit, diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf index b170c6c54..b6476b6c5 100644 --- a/postfix/conf/main.cf +++ b/postfix/conf/main.cf @@ -123,21 +123,34 @@ mail_owner = postfix # RELAY CONTROL # The mynetworks parameter specifies the list of networks that make -# up the local neighborhood. The list is used by the anti-UCE software -# to distinguish local clients from strangers. See permit_mynetworks -# and smtpd_recipient_restrictions in the file sample-smtpd.cf file. +# up the local neighborhood. The list is used by the anti-UCE +# software to relay authorize clients. See the check_relay_domains +# and and smtpd_recipient_restrictions in the sample-smtpd.cf file. # -# The default is a list of all networks attached to the machine: a -# complete class A network (X.0.0.0/8), a complete class B network -# (X.X.0.0/16), and so on. +# By default, Postfix derives the mynetworks setting from the local +# machine network addresses. + +# The mynetworks_style parameter specifies how Postfix computes the +# mynetworks default value from the local machine network addresses. +# +# By default (mynetworks_style = subnet), Postfix relay authorizes +# all clients in the subnets that are attached to this machine. # -# YOU MUST CHANGE THIS DEFAULT SETTING IF YOUR ADDRESS BLOCK IS PART -# OF A LARGER ADDRESS RANGE THAT IS OWNED BY YOUR PROVIDER - IT WOULD -# CAUSE POSTFIX TO RELAY MAIL FROM ALL THEIR CUSTOMERS. +# Specify "mynetworks_style = class" when you want to relay authorize +# all clients in the class A, B or C networks that are attached to +# to this machine. +# +# Specify "mynetworks_style = host" if you do not want to relay +# authorize clients other than the local machine. # -# If you need stricter control than the default, specify a list of -# network/mask patterns, where the mask specifies the number of bits -# in the network part of a host address. +# mynetworks_style = class +# mynetworks_style = subnet +# mynetworks_style = host + +# Instead of implicitly deriving the mynetworks value from local +# machine addresses, you can specify an explicit list of network/mask +# patterns, where the mask specifies the number of bits in the network +# part of a host address. # # You can also specify the absolute pathname of a pattern file instead # of listing the patterns here. diff --git a/postfix/html/basic.html b/postfix/html/basic.html index 19635f6f9..a769d5619 100644 --- a/postfix/html/basic.html +++ b/postfix/html/basic.html @@ -32,6 +32,9 @@ three parameters before you can use the Postfix mail system:
  • What domains to receive mail for +

    + +

  • What clients to relay mail for @@ -158,6 +161,32 @@ hostnames of the machine, including $myhostname, and localhost.$mydomain. +

    What clients to relay mail for

    + +By default, Postfix will relay mail for clients in relay authorized +networks and in relay authorized domains. + +

    + +Relay authorized client networks are defined by the mynetworks parameter. The default is to +relay authorize all clients in all class A, B or C networks that +are attached to the machine. + +

    + +YOU MUST CHANGE THIS DEFAULT SETTING +IF YOUR ADDRESS BLOCK IS PART OF A LARGER ADDRESS RANGE THAT IS +OWNED BY YOUR PROVIDER - IT WOULD CAUSE POSTFIX TO RELAY MAIL FROM +ALL THEIR CUSTOMERS. + +

    + +Relay authorized client domains are by defined by the relay_domains comfiguration +parameter. The default setting trusts clients with hostnames below +the domain(s) listed in mydestination. +

    What trouble to report to the postmaster

    @@ -287,8 +316,8 @@ top-level domain). The mynetworks parameter lists all networks that this machine is attached to. This information can be used by the -anti-UCE features to distinguish between local systems and -strangers. +anti-UCE features to distinguish between relay authorized +clients and relay unauthorized strangers.

    @@ -296,7 +325,8 @@ By default, mynetworks is set to the class A, B or C networks that the machine is attached to. For example, for my machines at home, the result is: 168.100.0.0/16 127.0.0.0/8. However, network 168.100 is owned by my ISP. Of course I do not want -to consider all their customer systems as local, so I use instead: +to consider all their customer systems as relay authorized clients, +so I use instead:

    diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 99b16fc42..43d75aed0 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -781,7 +781,9 @@ mynetworks.o: ../../include/msg.h mynetworks.o: ../../include/vstring.h mynetworks.o: ../../include/vbuf.h mynetworks.o: ../../include/inet_addr_list.h +mynetworks.o: ../../include/name_mask.h mynetworks.o: own_inet_addr.h +mynetworks.o: mail_params.h mynetworks.o: mynetworks.h mypwd.o: mypwd.c mypwd.o: ../../include/sys_defs.h diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index d300ece4d..52cf7e61b 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -60,6 +60,7 @@ /* char *var_relay_domains; /* char *var_fflush_domains; /* char *var_def_transport; +/* char *var_mynetworks_style; /* /* char *var_import_environ; /* char *var_export_environ; @@ -172,6 +173,7 @@ char *var_syslog_facility; char *var_relay_domains; char *var_fflush_domains; char *var_def_transport; +char *var_mynetworks_style; char *var_import_environ; char *var_export_environ; @@ -290,6 +292,7 @@ void mail_params_init() VAR_EXPORT_ENVIRON, DEF_EXPORT_ENVIRON, &var_export_environ, 0, 0, VAR_IMPORT_ENVIRON, DEF_IMPORT_ENVIRON, &var_import_environ, 0, 0, VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport, 0, 0, + VAR_MYNETWORKS_STYLE, DEF_MYNETWORKS_STYLE, &var_mynetworks_style, 1, 0, 0, }; static CONFIG_STR_FN_TABLE function_str_defaults_2[] = { diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index cf789375e..02eb7fd6a 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -990,6 +990,14 @@ extern int var_trigger_timeout; #define VAR_MYNETWORKS "mynetworks" extern char *var_mynetworks; +#define VAR_MYNETWORKS_STYLE "mynetworks_style" +#define DEF_MYNETWORKS_STYLE MYNETWORKS_STYLE_SUBNET +extern char *var_mynetworks_style; + +#define MYNETWORKS_STYLE_CLASS "class" +#define MYNETWORKS_STYLE_SUBNET "subnet" +#define MYNETWORKS_STYLE_HOST "host" + #define VAR_RELAY_DOMAINS "relay_domains" #define DEF_RELAY_DOMAINS "$mydestination" extern char *var_relay_domains; diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 7482f815e..291dc89bd 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20010222" +#define DEF_MAIL_VERSION "Snapshot-20010224" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/global/mynetworks.c b/postfix/src/global/mynetworks.c index cd1f54f67..5eb649ba3 100644 --- a/postfix/src/global/mynetworks.c +++ b/postfix/src/global/mynetworks.c @@ -10,9 +10,15 @@ /* DESCRIPTION /* This routine uses the address list built by own_inet_addr() /* to produce a list of patterns that match the corresponding -/* networks. The patterns are conservative: they match whole -/* class A, B, C or D networks. This is usually sufficient to -/* distinguish between organizations. +/* networks. +/* +/* The interface list is specified with the "inet_interfaces" +/* configuration parameter. +/* +/* The address to netblock conversion style is specified with +/* the "mynetworks_style" parameter: one of "class" (match +/* whole class A, B, C or D networks), "subnet" (match local +/* subnets), or "host" (match local interfaces only). /* LICENSE /* .ad /* .fi @@ -43,12 +49,27 @@ #include #include #include +#include /* Global library. */ #include +#include #include +/* Application-specific. */ + +#define MASK_STYLE_CLASS (1 << 0) +#define MASK_STYLE_SUBNET (1 << 1) +#define MASK_STYLE_HOST (1 << 2) + +static NAME_MASK mask_styles[] = { + MYNETWORKS_STYLE_CLASS, MASK_STYLE_CLASS, + MYNETWORKS_STYLE_SUBNET, MASK_STYLE_SUBNET, + MYNETWORKS_STYLE_HOST, MASK_STYLE_HOST, + 0, +}; + /* mynetworks - return patterns that match my own networks */ const char *mynetworks(void) @@ -58,32 +79,71 @@ const char *mynetworks(void) if (result == 0) { char *myname = "mynetworks"; INET_ADDR_LIST *my_addr_list; + INET_ADDR_LIST *my_mask_list; unsigned long addr; unsigned long mask; struct in_addr net; int shift; + int junk; int i; + int mask_style; + + mask_style = name_mask("mynetworks mask style", mask_styles, + var_mynetworks_style); result = vstring_alloc(20); my_addr_list = own_inet_addr_list(); + my_mask_list = own_inet_mask_list(); for (i = 0; i < my_addr_list->used; i++) { addr = ntohl(my_addr_list->addrs[i].s_addr); - if (IN_CLASSA(addr)) { - mask = IN_CLASSA_NET; - shift = IN_CLASSA_NSHIFT; - } else if (IN_CLASSB(addr)) { - mask = IN_CLASSB_NET; - shift = IN_CLASSB_NSHIFT; - } else if (IN_CLASSC(addr)) { - mask = IN_CLASSC_NET; - shift = IN_CLASSC_NSHIFT; - } else if (IN_CLASSD(addr)) { - mask = IN_CLASSD_NET; - shift = IN_CLASSD_NSHIFT; - } else { - msg_fatal("%s: bad address class: %s", - myname, inet_ntoa(my_addr_list->addrs[i])); + mask = ntohl(my_mask_list->addrs[i].s_addr); + + switch (mask_style) { + + /* + * Natural mask. This is dangerous if you're customer of an + * ISP who gave you a small portion of their network. + */ + case MASK_STYLE_CLASS: + if (IN_CLASSA(addr)) { + mask = IN_CLASSA_NET; + shift = IN_CLASSA_NSHIFT; + } else if (IN_CLASSB(addr)) { + mask = IN_CLASSB_NET; + shift = IN_CLASSB_NSHIFT; + } else if (IN_CLASSC(addr)) { + mask = IN_CLASSC_NET; + shift = IN_CLASSC_NSHIFT; + } else if (IN_CLASSD(addr)) { + mask = IN_CLASSD_NET; + shift = IN_CLASSD_NSHIFT; + } else { + msg_fatal("%s: bad address class: %s", + myname, inet_ntoa(my_addr_list->addrs[i])); + } + break; + + /* + * Subnet mask. This is safe, but breaks backwards + * compatibility when used as default setting. + */ + case MASK_STYLE_SUBNET: + for (junk = mask, shift = BITS_PER_ADDR; junk != 0; shift--, (junk <<= 1)) + /* void */ ; + break; + + /* + * Host only. Do not relay authorize other hosts. + */ + case MASK_STYLE_HOST: + mask = ~0; + shift = 0; + break; + + default: + msg_panic("unknown mynetworks mask style: %s", + var_mynetworks_style); } net.s_addr = htonl(addr & mask); vstring_sprintf_append(result, "%s/%d ", @@ -98,13 +158,15 @@ const char *mynetworks(void) #ifdef TEST char *var_inet_interfaces; +char *var_mynetworks_style; -main(int argc, char **argv) +int main(int argc, char **argv) { - if (argc != 2) - msg_fatal("usage: %s interface_list", argv[0]); + if (argc != 3) + msg_fatal("usage: %s mask_style interface_list", argv[0]); msg_verbose = 10; - var_inet_interfaces = argv[1]; + var_inet_interfaces = argv[2]; + var_mynetworks_style = argv[1]; mynetworks(); } diff --git a/postfix/src/global/own_inet_addr.c b/postfix/src/global/own_inet_addr.c index d33a25009..f06232989 100644 --- a/postfix/src/global/own_inet_addr.c +++ b/postfix/src/global/own_inet_addr.c @@ -10,6 +10,8 @@ /* struct in_addr *addr; /* /* INET_ADDR_LIST *own_inet_addr_list() +/* +/* INET_ADDR_LIST *own_inet_mask_list() /* DESCRIPTION /* own_inet_addr() determines if the specified IP address belongs /* to this mail system instance, i.e. if this mail system instance @@ -17,6 +19,9 @@ /* /* own_inet_addr_list() returns the list of all addresses that /* belong to this mail system instance. +/* +/* own_inet_mask_list() returns the list of all corresponding +/* netmasks. /* LICENSE /* .ad /* .fi @@ -56,24 +61,31 @@ /* Application-specific. */ static INET_ADDR_LIST addr_list; +static INET_ADDR_LIST mask_list; /* own_inet_addr_init - initialize my own address list */ -static void own_inet_addr_init(INET_ADDR_LIST *addr_list) +static void own_inet_addr_init(INET_ADDR_LIST *addr_list, + INET_ADDR_LIST *mask_list) { + INET_ADDR_LIST local_addrs; + INET_ADDR_LIST local_masks; char *hosts; char *host; char *sep = " \t,"; char *bufp; + int nvirtual; + int nlocal; inet_addr_list_init(addr_list); + inet_addr_list_init(mask_list); /* * If we are listening on all interfaces (default), ask the system what * the interfaces are. */ if (strcasecmp(var_inet_interfaces, DEF_INET_INTERFACES) == 0) { - if (inet_addr_local(addr_list) == 0) + if (inet_addr_local(addr_list, mask_list) == 0) msg_fatal("could not find any active network interfaces"); #if 0 if (addr_list->used == 1) @@ -94,6 +106,26 @@ static void own_inet_addr_init(INET_ADDR_LIST *addr_list) msg_fatal("config variable %s: host not found: %s", VAR_INET_INTERFACES, host); myfree(hosts); + + inet_addr_list_init(&local_addrs); + inet_addr_list_init(&local_masks); + if (inet_addr_local(&local_addrs, &local_masks) == 0) + msg_fatal("could not find any active network interfaces"); + for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) { + for (nlocal = 0; /* see below */ ; nlocal++) { + if (nlocal >= local_addrs.used) + msg_fatal("parameter %s: no local interface found for %s", + VAR_INET_INTERFACES, + inet_ntoa(addr_list->addrs[nvirtual])); + if (addr_list->addrs[nvirtual].s_addr + == local_addrs.addrs[nlocal].s_addr) { + inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]); + break; + } + } + } + inet_addr_list_free(&local_addrs); + inet_addr_list_free(&local_masks); } } @@ -104,7 +136,7 @@ int own_inet_addr(struct in_addr * addr) int i; if (addr_list.used == 0) - own_inet_addr_init(&addr_list); + own_inet_addr_init(&addr_list, &mask_list); for (i = 0; i < addr_list.used; i++) if (addr->s_addr == addr_list.addrs[i].s_addr) @@ -117,7 +149,17 @@ int own_inet_addr(struct in_addr * addr) INET_ADDR_LIST *own_inet_addr_list(void) { if (addr_list.used == 0) - own_inet_addr_init(&addr_list); + own_inet_addr_init(&addr_list, &mask_list); return (&addr_list); } + +/* own_inet_mask_list - return list of addresses */ + +INET_ADDR_LIST *own_inet_mask_list(void) +{ + if (addr_list.used == 0) + own_inet_addr_init(&addr_list, &mask_list); + + return (&mask_list); +} diff --git a/postfix/src/global/own_inet_addr.h b/postfix/src/global/own_inet_addr.h index ad984c818..5a38b58f7 100644 --- a/postfix/src/global/own_inet_addr.h +++ b/postfix/src/global/own_inet_addr.h @@ -21,6 +21,7 @@ */ extern int own_inet_addr(struct in_addr *); extern struct INET_ADDR_LIST *own_inet_addr_list(void); +extern struct INET_ADDR_LIST *own_inet_mask_list(void); /* LICENSE /* .ad diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index c40200727..512ed8ed9 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -253,8 +253,20 @@ static const char *check_mydomainname(void) static const char *check_mynetworks(void) { - if (var_inet_interfaces == 0) - var_inet_interfaces = mystrdup(DEF_INET_INTERFACES); + const char *junk; + + if (var_inet_interfaces == 0) { + if ((mode & SHOW_DEFS) + || !(junk = mail_conf_lookup(VAR_INET_INTERFACES))) + junk = DEF_INET_INTERFACES; + var_inet_interfaces = mystrdup(junk); + } + if (var_mynetworks_style == 0) { + if ((mode & SHOW_DEFS) + || !(junk = mail_conf_lookup(VAR_MYNETWORKS_STYLE))) + junk = DEF_MYNETWORKS_STYLE; + var_mynetworks_style = mystrdup(junk); + } return (mynetworks()); } diff --git a/postfix/src/util/inet_addr_local.c b/postfix/src/util/inet_addr_local.c index 9a53d8d6f..5eca34397 100644 --- a/postfix/src/util/inet_addr_local.c +++ b/postfix/src/util/inet_addr_local.c @@ -6,13 +6,17 @@ /* SYNOPSIS /* #include /* -/* int inet_addr_local(list) -/* INET_ADDR_LIST *list; +/* int inet_addr_local(addr_list, mask_list) +/* INET_ADDR_LIST *addr_list; +/* INET_ADDR_LIST *mask_list; /* DESCRIPTION /* inet_addr_local() determines all active IP interface addresses /* of the local system. Any address found is appended to the /* specified address list. The result value is the number of /* active interfaces found. +/* +/* The mask_list is either a null pointer, or it is an list +/* that receives the netmasks corresponding to the address list. /* DIAGNOSTICS /* Fatal errors: out of memory. /* SEE ALSO @@ -68,7 +72,7 @@ /* inet_addr_local - find all IP addresses for this host */ -int inet_addr_local(INET_ADDR_LIST *addr_list) +int inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list) { char *myname = "inet_addr_local"; struct ifconf ifc; @@ -119,8 +123,15 @@ int inet_addr_local(INET_ADDR_LIST *addr_list) for (ifr = ifc.ifc_req; ifr < the_end;) { if (ifr->ifr_addr.sa_family == AF_INET) { /* IP interface */ addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr; - if (addr.s_addr != INADDR_ANY) /* has IP address */ + if (addr.s_addr != INADDR_ANY) { /* has IP address */ inet_addr_list_append(addr_list, &addr); + if (mask_list) { + if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0) + msg_fatal("%s: ioctl SIOCGIFNETMASK: %m", myname); + addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr; + inet_addr_list_append(mask_list, &addr); + } + } } ifr = NEXT_INTERFACE(ifr); } @@ -137,12 +148,14 @@ int inet_addr_local(INET_ADDR_LIST *addr_list) int main(int unused_argc, char **argv) { INET_ADDR_LIST addr_list; + INET_ADDR_LIST mask_list; int i; msg_vstream_init(argv[0], VSTREAM_ERR); inet_addr_list_init(&addr_list); - inet_addr_local(&addr_list); + inet_addr_list_init(&mask_list); + inet_addr_local(&addr_list, &mask_list); if (addr_list.used == 0) msg_fatal("cannot find any active network interfaces"); @@ -150,10 +163,13 @@ int main(int unused_argc, char **argv) if (addr_list.used == 1) msg_warn("found only one active network interface"); - for (i = 0; i < addr_list.used; i++) - vstream_printf("%s\n", inet_ntoa(addr_list.addrs[i])); + for (i = 0; i < addr_list.used; i++) { + vstream_printf("%s/", inet_ntoa(addr_list.addrs[i])); + vstream_printf("%s\n", inet_ntoa(mask_list.addrs[i])); + } vstream_fflush(VSTREAM_OUT); inet_addr_list_free(&addr_list); + inet_addr_list_free(&mask_list); } #endif diff --git a/postfix/src/util/inet_addr_local.h b/postfix/src/util/inet_addr_local.h index f48ca1eb0..969264fe2 100644 --- a/postfix/src/util/inet_addr_local.h +++ b/postfix/src/util/inet_addr_local.h @@ -19,7 +19,7 @@ /* * External interface. */ -extern int inet_addr_local(INET_ADDR_LIST *); +extern int inet_addr_local(INET_ADDR_LIST *, INET_ADDR_LIST *); /* LICENSE /* .ad diff --git a/postfix/src/util/safe_open.c b/postfix/src/util/safe_open.c index f582cc1f0..e1e88f8b4 100644 --- a/postfix/src/util/safe_open.c +++ b/postfix/src/util/safe_open.c @@ -87,7 +87,7 @@ /* safe_open_exist - open existing file */ static VSTREAM *safe_open_exist(const char *path, int flags, - struct stat * fstat_st, VSTRING * why) + struct stat * fstat_st, VSTRING *why) { struct stat local_statbuf; struct stat lstat_st; @@ -127,17 +127,26 @@ static VSTREAM *safe_open_exist(const char *path, int flags, * slowed down by arbitrary amounts, and there it would make sense to * compare even more file attributes, such as the inode generation number * on systems that have one. + * + * Grr. Solaris /dev/whatever is a symlink. We'll have to make an exception + * for symlinks owned by root. NEVER, NEVER, make exceptions for symlinks + * owned by a non-root user. This would open a security hole when + * delivering mail to a world-writable mailbox directory. */ - else if (lstat(path, &lstat_st) < 0 - || fstat_st->st_dev != lstat_st.st_dev - || fstat_st->st_ino != lstat_st.st_ino + else if (lstat(path, &lstat_st) < 0) { + vstring_sprintf(why, "file status changed unexpectedly: %m"); + } else if (S_ISLNK(lstat_st.st_mode)) { + if (lstat_st.st_uid == 0) + return (fp); + vstring_sprintf(why, "file is a symbolic link"); + } else if (fstat_st->st_dev != lstat_st.st_dev + || fstat_st->st_ino != lstat_st.st_ino #ifdef HAS_ST_GEN - || fstat_st->st_gen != lstat_st.st_gen + || fstat_st->st_gen != lstat_st.st_gen #endif - || fstat_st->st_nlink != lstat_st.st_nlink - || fstat_st->st_mode != lstat_st.st_mode) { - vstring_sprintf(why, "%s", S_ISLNK(lstat_st.st_mode) ? - "file is a symbolic link" : "file status changed unexpectedly"); + || fstat_st->st_nlink != lstat_st.st_nlink + || fstat_st->st_mode != lstat_st.st_mode) { + vstring_sprintf(why, "file status changed unexpectedly"); } /* @@ -159,7 +168,7 @@ static VSTREAM *safe_open_exist(const char *path, int flags, /* safe_open_create - create new file */ static VSTREAM *safe_open_create(const char *path, int flags, int mode, - struct stat * st, uid_t user, uid_t group, VSTRING * why) + struct stat * st, uid_t user, uid_t group, VSTRING *why) { VSTREAM *fp; @@ -207,7 +216,7 @@ static VSTREAM *safe_open_create(const char *path, int flags, int mode, /* safe_open - safely open or create file */ VSTREAM *safe_open(const char *path, int flags, int mode, - struct stat * st, uid_t user, gid_t group, VSTRING * why) + struct stat * st, uid_t user, gid_t group, VSTRING *why) { VSTREAM *fp; diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index f7c118624..1b1d3df54 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -853,6 +853,7 @@ typedef int pid_t; #define S_ISSOCK(mode) (((mode) & (_S_IFMT)) == (_S_IFSOCK)) #define S_ISFIFO(mode) (((mode) & (_S_IFMT)) == (_S_IFIFO)) #define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG)) +#define S_ISLNK(mode) (((mode) & (_S_IFMT)) == (_S_IFLNK)) #endif #ifdef MISSING_POSIX_S_MODES