1/* $NetBSD$ */ 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 62typedef struct { 63 DICT dict; /* generic members */ 64} DICT_UNIX; 65 66/* dict_unix_getpwnam - find password table entry */ 67 68static 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 109static 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 155static 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 164DICT *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