xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_unix.c (revision a30b880ed60a24c405edba78187a04247f4d9d33)
1*a30b880eStron /*	$NetBSD: dict_unix.c,v 1.1.1.2 2013/01/02 18:59:12 tron Exp $	*/
241fbaed0Stron 
341fbaed0Stron /*++
441fbaed0Stron /* NAME
541fbaed0Stron /*	dict_unix 3
641fbaed0Stron /* SUMMARY
741fbaed0Stron /*	dictionary manager interface to UNIX tables
841fbaed0Stron /* SYNOPSIS
941fbaed0Stron /*	#include <dict_unix.h>
1041fbaed0Stron /*
1141fbaed0Stron /*	DICT	*dict_unix_open(map, dummy, dict_flags)
1241fbaed0Stron /*	const char *map;
1341fbaed0Stron /*	int	dummy;
1441fbaed0Stron /*	int	dict_flags;
1541fbaed0Stron /* DESCRIPTION
1641fbaed0Stron /*	dict_unix_open() makes the specified UNIX table accessible via
1741fbaed0Stron /*	the generic dictionary operations described in dict_open(3).
1841fbaed0Stron /*	The \fIdummy\fR argument is not used.
1941fbaed0Stron /*
2041fbaed0Stron /*	Known map names:
2141fbaed0Stron /* .IP passwd.byname
2241fbaed0Stron /*	The table is the UNIX password database. The key is a login name.
2341fbaed0Stron /*	The result is a password file entry in passwd(5) format.
2441fbaed0Stron /* .IP group.byname
2541fbaed0Stron /*	The table is the UNIX group database. The key is a group name.
2641fbaed0Stron /*	The result is a group file entry in group(5) format.
2741fbaed0Stron /* SEE ALSO
2841fbaed0Stron /*	dict(3) generic dictionary manager
2941fbaed0Stron /* DIAGNOSTICS
3041fbaed0Stron /*	Fatal errors: out of memory, unknown map name, attempt to update map.
3141fbaed0Stron /* LICENSE
3241fbaed0Stron /* .ad
3341fbaed0Stron /* .fi
3441fbaed0Stron /*	The Secure Mailer license must be distributed with this software.
3541fbaed0Stron /* AUTHOR(S)
3641fbaed0Stron /*	Wietse Venema
3741fbaed0Stron /*	IBM T.J. Watson Research
3841fbaed0Stron /*	P.O. Box 704
3941fbaed0Stron /*	Yorktown Heights, NY 10598, USA
4041fbaed0Stron /*--*/
4141fbaed0Stron 
4241fbaed0Stron /* System library. */
4341fbaed0Stron 
4441fbaed0Stron #include "sys_defs.h"
4541fbaed0Stron #include <unistd.h>
4641fbaed0Stron #include <errno.h>
4741fbaed0Stron #include <string.h>
4841fbaed0Stron #include <pwd.h>
4941fbaed0Stron #include <grp.h>
5041fbaed0Stron 
5141fbaed0Stron /* Utility library. */
5241fbaed0Stron 
5341fbaed0Stron #include "msg.h"
5441fbaed0Stron #include "mymalloc.h"
5541fbaed0Stron #include "vstring.h"
5641fbaed0Stron #include "stringops.h"
5741fbaed0Stron #include "dict.h"
5841fbaed0Stron #include "dict_unix.h"
5941fbaed0Stron 
6041fbaed0Stron /* Application-specific. */
6141fbaed0Stron 
6241fbaed0Stron typedef struct {
6341fbaed0Stron     DICT    dict;			/* generic members */
6441fbaed0Stron } DICT_UNIX;
6541fbaed0Stron 
6641fbaed0Stron /* dict_unix_getpwnam - find password table entry */
6741fbaed0Stron 
dict_unix_getpwnam(DICT * dict,const char * key)6841fbaed0Stron static const char *dict_unix_getpwnam(DICT *dict, const char *key)
6941fbaed0Stron {
7041fbaed0Stron     struct passwd *pwd;
7141fbaed0Stron     static VSTRING *buf;
7241fbaed0Stron     static int sanity_checked;
7341fbaed0Stron 
74*a30b880eStron     dict->error = 0;
7541fbaed0Stron 
7641fbaed0Stron     /*
7741fbaed0Stron      * Optionally fold the key.
7841fbaed0Stron      */
7941fbaed0Stron     if (dict->flags & DICT_FLAG_FOLD_FIX) {
8041fbaed0Stron 	if (dict->fold_buf == 0)
8141fbaed0Stron 	    dict->fold_buf = vstring_alloc(10);
8241fbaed0Stron 	vstring_strcpy(dict->fold_buf, key);
8341fbaed0Stron 	key = lowercase(vstring_str(dict->fold_buf));
8441fbaed0Stron     }
8541fbaed0Stron     if ((pwd = getpwnam(key)) == 0) {
8641fbaed0Stron 	if (sanity_checked == 0) {
8741fbaed0Stron 	    sanity_checked = 1;
8841fbaed0Stron 	    errno = 0;
8941fbaed0Stron 	    if (getpwuid(0) == 0) {
9041fbaed0Stron 		msg_warn("cannot access UNIX password database: %m");
91*a30b880eStron 		dict->error = DICT_ERR_RETRY;
9241fbaed0Stron 	    }
9341fbaed0Stron 	}
9441fbaed0Stron 	return (0);
9541fbaed0Stron     } else {
9641fbaed0Stron 	if (buf == 0)
9741fbaed0Stron 	    buf = vstring_alloc(10);
9841fbaed0Stron 	sanity_checked = 1;
9941fbaed0Stron 	vstring_sprintf(buf, "%s:%s:%ld:%ld:%s:%s:%s",
10041fbaed0Stron 			pwd->pw_name, pwd->pw_passwd, (long) pwd->pw_uid,
10141fbaed0Stron 			(long) pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,
10241fbaed0Stron 			pwd->pw_shell);
10341fbaed0Stron 	return (vstring_str(buf));
10441fbaed0Stron     }
10541fbaed0Stron }
10641fbaed0Stron 
10741fbaed0Stron /* dict_unix_getgrnam - find group table entry */
10841fbaed0Stron 
dict_unix_getgrnam(DICT * dict,const char * key)10941fbaed0Stron static const char *dict_unix_getgrnam(DICT *dict, const char *key)
11041fbaed0Stron {
11141fbaed0Stron     struct group *grp;
11241fbaed0Stron     static VSTRING *buf;
11341fbaed0Stron     char  **cpp;
11441fbaed0Stron     static int sanity_checked;
11541fbaed0Stron 
116*a30b880eStron     dict->error = 0;
11741fbaed0Stron 
11841fbaed0Stron     /*
11941fbaed0Stron      * Optionally fold the key.
12041fbaed0Stron      */
12141fbaed0Stron     if (dict->flags & DICT_FLAG_FOLD_FIX) {
12241fbaed0Stron 	if (dict->fold_buf == 0)
12341fbaed0Stron 	    dict->fold_buf = vstring_alloc(10);
12441fbaed0Stron 	vstring_strcpy(dict->fold_buf, key);
12541fbaed0Stron 	key = lowercase(vstring_str(dict->fold_buf));
12641fbaed0Stron     }
12741fbaed0Stron     if ((grp = getgrnam(key)) == 0) {
12841fbaed0Stron 	if (sanity_checked == 0) {
12941fbaed0Stron 	    sanity_checked = 1;
13041fbaed0Stron 	    errno = 0;
13141fbaed0Stron 	    if (getgrgid(0) == 0) {
13241fbaed0Stron 		msg_warn("cannot access UNIX group database: %m");
133*a30b880eStron 		dict->error = DICT_ERR_RETRY;
13441fbaed0Stron 	    }
13541fbaed0Stron 	}
13641fbaed0Stron 	return (0);
13741fbaed0Stron     } else {
13841fbaed0Stron 	if (buf == 0)
13941fbaed0Stron 	    buf = vstring_alloc(10);
14041fbaed0Stron 	sanity_checked = 1;
14141fbaed0Stron 	vstring_sprintf(buf, "%s:%s:%ld:",
14241fbaed0Stron 			grp->gr_name, grp->gr_passwd, (long) grp->gr_gid);
14341fbaed0Stron 	for (cpp = grp->gr_mem; *cpp; cpp++) {
14441fbaed0Stron 	    vstring_strcat(buf, *cpp);
14541fbaed0Stron 	    if (cpp[1])
14641fbaed0Stron 		VSTRING_ADDCH(buf, ',');
14741fbaed0Stron 	}
14841fbaed0Stron 	VSTRING_TERMINATE(buf);
14941fbaed0Stron 	return (vstring_str(buf));
15041fbaed0Stron     }
15141fbaed0Stron }
15241fbaed0Stron 
15341fbaed0Stron /* dict_unix_close - close UNIX map */
15441fbaed0Stron 
dict_unix_close(DICT * dict)15541fbaed0Stron static void dict_unix_close(DICT *dict)
15641fbaed0Stron {
15741fbaed0Stron     if (dict->fold_buf)
15841fbaed0Stron 	vstring_free(dict->fold_buf);
15941fbaed0Stron     dict_free(dict);
16041fbaed0Stron }
16141fbaed0Stron 
16241fbaed0Stron /* dict_unix_open - open UNIX map */
16341fbaed0Stron 
dict_unix_open(const char * map,int open_flags,int dict_flags)164*a30b880eStron DICT   *dict_unix_open(const char *map, int open_flags, int dict_flags)
16541fbaed0Stron {
16641fbaed0Stron     DICT_UNIX *dict_unix;
16741fbaed0Stron     struct dict_unix_lookup {
16841fbaed0Stron 	char   *name;
16941fbaed0Stron 	const char *(*lookup) (DICT *, const char *);
17041fbaed0Stron     };
17141fbaed0Stron     static struct dict_unix_lookup dict_unix_lookup[] = {
17241fbaed0Stron 	"passwd.byname", dict_unix_getpwnam,
17341fbaed0Stron 	"group.byname", dict_unix_getgrnam,
17441fbaed0Stron 	0,
17541fbaed0Stron     };
17641fbaed0Stron     struct dict_unix_lookup *lp;
17741fbaed0Stron 
178*a30b880eStron     /*
179*a30b880eStron      * Sanity checks.
180*a30b880eStron      */
181*a30b880eStron     if (open_flags != O_RDONLY)
182*a30b880eStron 	return (dict_surrogate(DICT_TYPE_UNIX, map, open_flags, dict_flags,
183*a30b880eStron 			       "%s:%s map requires O_RDONLY access mode",
184*a30b880eStron 			       DICT_TYPE_UNIX, map));
18541fbaed0Stron 
186*a30b880eStron     /*
187*a30b880eStron      * "Open" the database.
188*a30b880eStron      */
18941fbaed0Stron     for (lp = dict_unix_lookup; /* void */ ; lp++) {
19041fbaed0Stron 	if (lp->name == 0)
191*a30b880eStron 	    return (dict_surrogate(DICT_TYPE_UNIX, map, open_flags, dict_flags,
192*a30b880eStron 			      "unknown table: %s:%s", DICT_TYPE_UNIX, map));
19341fbaed0Stron 	if (strcmp(map, lp->name) == 0)
19441fbaed0Stron 	    break;
19541fbaed0Stron     }
196*a30b880eStron     dict_unix = (DICT_UNIX *) dict_alloc(DICT_TYPE_UNIX, map,
197*a30b880eStron 					 sizeof(*dict_unix));
19841fbaed0Stron     dict_unix->dict.lookup = lp->lookup;
19941fbaed0Stron     dict_unix->dict.close = dict_unix_close;
20041fbaed0Stron     dict_unix->dict.flags = dict_flags | DICT_FLAG_FIXED;
20141fbaed0Stron     if (dict_flags & DICT_FLAG_FOLD_FIX)
20241fbaed0Stron 	dict_unix->dict.fold_buf = vstring_alloc(10);
203*a30b880eStron     dict_unix->dict.owner.status = DICT_OWNER_TRUSTED;
20441fbaed0Stron 
20541fbaed0Stron     return (DICT_DEBUG (&dict_unix->dict));
20641fbaed0Stron }
207