Postfix3.3.1
mail_open_ok.c
[詳解]
1 /*++
2 /* NAME
3 /* mail_open_ok 3
4 /* SUMMARY
5 /* scrutinize mail queue file
6 /* SYNOPSIS
7 /* #include <mail_open_ok.h>
8 /*
9 /* int mail_open_ok(queue_name, queue_id, statp, pathp)
10 /* const char *queue_name;
11 /* const char *queue_id;
12 /* struct stat *statp;
13 /* char **pathp
14 /* DESCRIPTION
15 /* mail_open_ok() determines if it is OK to open the specified
16 /* queue file.
17 /*
18 /* The queue name and queue id should conform to the syntax
19 /* requirements for these names.
20 /* Unfortunately, on some systems readdir() etc. can return bogus
21 /* file names. For this reason, the code silently ignores invalid
22 /* queue file names.
23 /*
24 /* The file should have mode 0700. Files with other permissions
25 /* are silently ignored.
26 /*
27 /* The file should be a regular file.
28 /* Files that do not satisfy this requirement are skipped with
29 /* a warning.
30 /*
31 /* The file link count is not restricted. With a writable maildrop
32 /* directory, refusal to deliver linked files is prone to denial of
33 /* service attack; it's better to deliver mail too often than not.
34 /*
35 /* Upon return, the \fIstatp\fR argument receives the file
36 /* attributes and \fIpathp\fR a copy of the file name. The file
37 /* name is volatile. Make a copy if it is to be used for any
38 /* appreciable amount of time.
39 /* DIAGNOSTICS
40 /* Warnings: bad file attributes (file type), multiple hard links.
41 /* mail_open_ok() returns MAIL_OPEN_YES for good files, MAIL_OPEN_NO
42 /* for anything else. It is left up to the system administrator to
43 /* deal with non-file objects.
44 /* BUGS
45 /* mail_open_ok() examines a queue file without actually opening
46 /* it, and therefore is susceptible to race conditions.
47 /* LICENSE
48 /* .ad
49 /* .fi
50 /* The Secure Mailer license must be distributed with this software.
51 /* AUTHOR(S)
52 /* Wietse Venema
53 /* IBM T.J. Watson Research
54 /* P.O. Box 704
55 /* Yorktown Heights, NY 10598, USA
56 /*--*/
57 
58 /* System libraries. */
59 
60 #include <sys_defs.h>
61 #include <sys/stat.h>
62 #include <time.h>
63 #include <errno.h>
64 
65 /* Utility library. */
66 
67 #include <msg.h>
68 #include <warn_stat.h>
69 
70 /* Global library. */
71 
72 #include "mail_queue.h"
73 #include "mail_open_ok.h"
74 
75 /* mail_open_ok - see if this file is OK to open */
76 
77 int mail_open_ok(const char *queue_name, const char *queue_id,
78  struct stat * statp, const char **path)
79 {
80  if (mail_queue_name_ok(queue_name) == 0) {
81  msg_warn("bad mail queue name: %s", queue_name);
82  return (MAIL_OPEN_NO);
83  }
84  if (mail_queue_id_ok(queue_id) == 0)
85  return (MAIL_OPEN_NO);
86 
87 
88  /*
89  * I really would like to look up the file attributes *after* opening the
90  * file so that we could save one directory traversal on systems without
91  * name-to-inode cache. However, we don't necessarily always want to open
92  * the file.
93  */
94  *path = mail_queue_path((VSTRING *) 0, queue_name, queue_id);
95 
96  if (lstat(*path, statp) < 0) {
97  if (errno != ENOENT)
98  msg_warn("%s: %m", *path);
99  return (MAIL_OPEN_NO);
100  }
101  if (!S_ISREG(statp->st_mode)) {
102  msg_warn("%s: uid %ld: not a regular file", *path, (long) statp->st_uid);
103  return (MAIL_OPEN_NO);
104  }
105  if ((statp->st_mode & S_IRWXU) != MAIL_QUEUE_STAT_READY)
106  return (MAIL_OPEN_NO);
107 
108  /*
109  * Workaround for spurious "file has 2 links" warnings in showq. As
110  * kernels have evolved from non-interruptible system calls towards
111  * fine-grained locks, the showq command has become likely to observe a
112  * file while the queue manager is in the middle of renaming it, at a
113  * time when the file has links to both the old and new name. We now log
114  * the warning only when the condition appears to be persistent.
115  */
116 #define MINUTE_SECONDS 60 /* XXX should be centralized */
117 
118  if (statp->st_nlink > 1) {
119  if (msg_verbose)
120  msg_info("%s: uid %ld: file has %d links", *path,
121  (long) statp->st_uid, (int) statp->st_nlink);
122  else if (statp->st_ctime < time((time_t *) 0) - MINUTE_SECONDS)
123  msg_warn("%s: uid %ld: file has %d links", *path,
124  (long) statp->st_uid, (int) statp->st_nlink);
125  }
126  return (MAIL_OPEN_YES);
127 }
int msg_verbose
Definition: msg.c:177
int mail_queue_id_ok(const char *queue_id)
Definition: mail_queue.c:296
#define MAIL_OPEN_YES
Definition: mail_open_ok.h:19
#define lstat(p, s)
Definition: warn_stat.h:19
#define stat(p, s)
Definition: warn_stat.h:18
int mail_queue_name_ok(const char *queue_name)
Definition: mail_queue.c:281
#define MAIL_QUEUE_STAT_READY
Definition: mail_queue.h:48
#define S_IRWXU
Definition: qmgr_active.c:87
const char * mail_queue_path(VSTRING *buf, const char *queue_name, const char *queue_id)
Definition: mail_queue.c:204
int mail_open_ok(const char *queue_name, const char *queue_id, struct stat *statp, const char **path)
Definition: mail_open_ok.c:77
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define MAIL_OPEN_NO
Definition: mail_open_ok.h:20
#define MINUTE_SECONDS
void msg_info(const char *fmt,...)
Definition: msg.c:199