xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_unix.c (revision a30b880ed60a24c405edba78187a04247f4d9d33)
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