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