7 /* scrutinize mail queue file
9 /* #include <mail_open_ok.h>
11 /* int mail_open_ok(queue_name, queue_id, statp, pathp)
12 /* const char *queue_name;
13 /* const char *queue_id;
14 /* struct stat *statp;
17 /* mail_open_ok() determines if it is OK to open the specified
20 /* The queue name and queue id should conform to the syntax
21 /* requirements for these names.
22 /* Unfortunately, on some systems readdir() etc. can return bogus
23 /* file names. For this reason, the code silently ignores invalid
26 /* The file should have mode 0700. Files with other permissions
27 /* are silently ignored.
29 /* The file should be a regular file.
30 /* Files that do not satisfy this requirement are skipped with
33 /* The file link count is not restricted. With a writable maildrop
34 /* directory, refusal to deliver linked files is prone to denial of
35 /* service attack; it's better to deliver mail too often than not.
37 /* Upon return, the \fIstatp\fR argument receives the file
38 /* attributes and \fIpathp\fR a copy of the file name. The file
39 /* name is volatile. Make a copy if it is to be used for any
40 /* appreciable amount of time.
42 /* Warnings: bad file attributes (file type), multiple hard links.
43 /* mail_open_ok() returns MAIL_OPEN_YES for good files, MAIL_OPEN_NO
44 /* for anything else. It is left up to the system administrator to
45 /* deal with non-file objects.
47 /* mail_open_ok() examines a queue file without actually opening
48 /* it, and therefore is susceptible to race conditions.
52 /* The Secure Mailer license must be distributed with this software.
55 /* IBM T.J. Watson Research
57 /* Yorktown Heights, NY 10598, USA
60 /* System libraries. */
67 /* Utility library. */
73 #include "mail_queue.h"
74 #include "mail_open_ok.h"
76 /* mail_open_ok - see if this file is OK to open */
78 int mail_open_ok(const char *queue_name
, const char *queue_id
,
79 struct stat
* statp
, const char **path
)
81 if (mail_queue_name_ok(queue_name
) == 0) {
82 msg_warn("bad mail queue name: %s", queue_name
);
83 return (MAIL_OPEN_NO
);
85 if (mail_queue_id_ok(queue_id
) == 0)
86 return (MAIL_OPEN_NO
);
90 * I really would like to look up the file attributes *after* opening the
91 * file so that we could save one directory traversal on systems without
92 * name-to-inode cache. However, we don't necessarily always want to open
95 *path
= mail_queue_path((VSTRING
*) 0, queue_name
, queue_id
);
97 if (lstat(*path
, statp
) < 0) {
99 msg_warn("%s: %m", *path
);
100 return (MAIL_OPEN_NO
);
102 if (!S_ISREG(statp
->st_mode
)) {
103 msg_warn("%s: uid %ld: not a regular file", *path
, (long) statp
->st_uid
);
104 return (MAIL_OPEN_NO
);
106 if ((statp
->st_mode
& S_IRWXU
) != MAIL_QUEUE_STAT_READY
)
107 return (MAIL_OPEN_NO
);
110 * Workaround for spurious "file has 2 links" warnings in showq. As
111 * kernels have evolved from non-interruptible system calls towards
112 * fine-grained locks, the showq command has become likely to observe a
113 * file while the queue manager is in the middle of renaming it, at a
114 * time when the file has links to both the old and new name. We now log
115 * the warning only when the condition appears to be persistent.
117 #define MINUTE_SECONDS 60 /* XXX should be centralized */
119 if (statp
->st_nlink
> 1) {
121 msg_info("%s: uid %ld: file has %d links", *path
,
122 (long) statp
->st_uid
, (int) statp
->st_nlink
);
123 else if (statp
->st_ctime
< time((time_t *) 0) - MINUTE_SECONDS
)
124 msg_warn("%s: uid %ld: file has %d links", *path
,
125 (long) statp
->st_uid
, (int) statp
->st_nlink
);
127 return (MAIL_OPEN_YES
);