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