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