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 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 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 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 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