Postfix3.3.1
dict_unix.c
[詳解]
1 /*++
2 /* NAME
3 /* dict_unix 3
4 /* SUMMARY
5 /* dictionary manager interface to UNIX tables
6 /* SYNOPSIS
7 /* #include <dict_unix.h>
8 /*
9 /* DICT *dict_unix_open(map, dummy, dict_flags)
10 /* const char *map;
11 /* int dummy;
12 /* int dict_flags;
13 /* DESCRIPTION
14 /* dict_unix_open() makes the specified UNIX table accessible via
15 /* the generic dictionary operations described in dict_open(3).
16 /* The \fIdummy\fR argument is not used.
17 /*
18 /* Known map names:
19 /* .IP passwd.byname
20 /* The table is the UNIX password database. The key is a login name.
21 /* The result is a password file entry in passwd(5) format.
22 /* .IP group.byname
23 /* The table is the UNIX group database. The key is a group name.
24 /* The result is a group file entry in group(5) format.
25 /* SEE ALSO
26 /* dict(3) generic dictionary manager
27 /* DIAGNOSTICS
28 /* Fatal errors: out of memory, unknown map name, attempt to update map.
29 /* LICENSE
30 /* .ad
31 /* .fi
32 /* The Secure Mailer license must be distributed with this software.
33 /* AUTHOR(S)
34 /* Wietse Venema
35 /* IBM T.J. Watson Research
36 /* P.O. Box 704
37 /* Yorktown Heights, NY 10598, USA
38 /*--*/
39 
40 /* System library. */
41 
42 #include "sys_defs.h"
43 #include <unistd.h>
44 #include <errno.h>
45 #include <string.h>
46 #include <pwd.h>
47 #include <grp.h>
48 
49 /* Utility library. */
50 
51 #include "msg.h"
52 #include "mymalloc.h"
53 #include "vstring.h"
54 #include "stringops.h"
55 #include "dict.h"
56 #include "dict_unix.h"
57 
58 /* Application-specific. */
59 
60 typedef struct {
61  DICT dict; /* generic members */
62 } DICT_UNIX;
63 
64 /* dict_unix_getpwnam - find password table entry */
65 
66 static const char *dict_unix_getpwnam(DICT *dict, const char *key)
67 {
68  struct passwd *pwd;
69  static VSTRING *buf;
70  static int sanity_checked;
71 
72  dict->error = 0;
73 
74  /*
75  * Optionally fold the key.
76  */
77  if (dict->flags & DICT_FLAG_FOLD_FIX) {
78  if (dict->fold_buf == 0)
79  dict->fold_buf = vstring_alloc(10);
80  vstring_strcpy(dict->fold_buf, key);
81  key = lowercase(vstring_str(dict->fold_buf));
82  }
83  if ((pwd = getpwnam(key)) == 0) {
84  if (sanity_checked == 0) {
85  sanity_checked = 1;
86  errno = 0;
87  if (getpwuid(0) == 0) {
88  msg_warn("cannot access UNIX password database: %m");
89  dict->error = DICT_ERR_RETRY;
90  }
91  }
92  return (0);
93  } else {
94  if (buf == 0)
95  buf = vstring_alloc(10);
96  sanity_checked = 1;
97  vstring_sprintf(buf, "%s:%s:%ld:%ld:%s:%s:%s",
98  pwd->pw_name, pwd->pw_passwd, (long) pwd->pw_uid,
99  (long) pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,
100  pwd->pw_shell);
101  return (vstring_str(buf));
102  }
103 }
104 
105 /* dict_unix_getgrnam - find group table entry */
106 
107 static const char *dict_unix_getgrnam(DICT *dict, const char *key)
108 {
109  struct group *grp;
110  static VSTRING *buf;
111  char **cpp;
112  static int sanity_checked;
113 
114  dict->error = 0;
115 
116  /*
117  * Optionally fold the key.
118  */
119  if (dict->flags & DICT_FLAG_FOLD_FIX) {
120  if (dict->fold_buf == 0)
121  dict->fold_buf = vstring_alloc(10);
122  vstring_strcpy(dict->fold_buf, key);
123  key = lowercase(vstring_str(dict->fold_buf));
124  }
125  if ((grp = getgrnam(key)) == 0) {
126  if (sanity_checked == 0) {
127  sanity_checked = 1;
128  errno = 0;
129  if (getgrgid(0) == 0) {
130  msg_warn("cannot access UNIX group database: %m");
131  dict->error = DICT_ERR_RETRY;
132  }
133  }
134  return (0);
135  } else {
136  if (buf == 0)
137  buf = vstring_alloc(10);
138  sanity_checked = 1;
139  vstring_sprintf(buf, "%s:%s:%ld:",
140  grp->gr_name, grp->gr_passwd, (long) grp->gr_gid);
141  for (cpp = grp->gr_mem; *cpp; cpp++) {
142  vstring_strcat(buf, *cpp);
143  if (cpp[1])
144  VSTRING_ADDCH(buf, ',');
145  }
146  VSTRING_TERMINATE(buf);
147  return (vstring_str(buf));
148  }
149 }
150 
151 /* dict_unix_close - close UNIX map */
152 
153 static void dict_unix_close(DICT *dict)
154 {
155  if (dict->fold_buf)
156  vstring_free(dict->fold_buf);
157  dict_free(dict);
158 }
159 
160 /* dict_unix_open - open UNIX map */
161 
162 DICT *dict_unix_open(const char *map, int open_flags, int dict_flags)
163 {
164  DICT_UNIX *dict_unix;
165  struct dict_unix_lookup {
166  char *name;
167  const char *(*lookup) (DICT *, const char *);
168  };
169  static struct dict_unix_lookup dict_unix_lookup[] = {
170  "passwd.byname", dict_unix_getpwnam,
171  "group.byname", dict_unix_getgrnam,
172  0,
173  };
174  struct dict_unix_lookup *lp;
175 
176  /*
177  * Sanity checks.
178  */
179  if (open_flags != O_RDONLY)
180  return (dict_surrogate(DICT_TYPE_UNIX, map, open_flags, dict_flags,
181  "%s:%s map requires O_RDONLY access mode",
182  DICT_TYPE_UNIX, map));
183 
184  /*
185  * "Open" the database.
186  */
187  for (lp = dict_unix_lookup; /* void */ ; lp++) {
188  if (lp->name == 0)
189  return (dict_surrogate(DICT_TYPE_UNIX, map, open_flags, dict_flags,
190  "unknown table: %s:%s", DICT_TYPE_UNIX, map));
191  if (strcmp(map, lp->name) == 0)
192  break;
193  }
194  dict_unix = (DICT_UNIX *) dict_alloc(DICT_TYPE_UNIX, map,
195  sizeof(*dict_unix));
196  dict_unix->dict.lookup = lp->lookup;
197  dict_unix->dict.close = dict_unix_close;
198  dict_unix->dict.flags = dict_flags | DICT_FLAG_FIXED;
199  if (dict_flags & DICT_FLAG_FOLD_FIX)
200  dict_unix->dict.fold_buf = vstring_alloc(10);
201  dict_unix->dict.owner.status = DICT_OWNER_TRUSTED;
202 
203  return (DICT_DEBUG (&dict_unix->dict));
204 }
void(* close)(struct DICT *)
Definition: dict.h:87
#define vstring_str(vp)
Definition: vstring.h:71
#define DICT_FLAG_FIXED
Definition: dict.h:114
int flags
Definition: dict.h:81
#define DICT_ERR_RETRY
Definition: dict.h:178
#define DICT_FLAG_FOLD_FIX
Definition: dict.h:124
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
Definition: dict.h:78
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define DICT_OWNER_TRUSTED
Definition: dict.h:46
DICT dict
Definition: dict_unix.c:61
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
int error
Definition: dict.h:94
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
DICT * dict_unix_open(const char *map, int open_flags, int dict_flags)
Definition: dict_unix.c:162
char * lowercase(char *string)
Definition: lowercase.c:34
const char *(* lookup)(struct DICT *, const char *)
Definition: dict.h:82
int status
Definition: dict.h:38
void dict_free(DICT *)
Definition: dict_alloc.c:163
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
DICT * dict_alloc(const char *, const char *, ssize_t)
Definition: dict_alloc.c:135
VSTRING * fold_buf
Definition: dict.h:92
DICT_OWNER owner
Definition: dict.h:93
#define DICT_TYPE_UNIX
Definition: dict_unix.h:22
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
Definition: vstring.c:459
DICT * dict_surrogate(const char *dict_type, const char *dict_name, int open_flags, int dict_flags, const char *fmt,...)