1 /* $NetBSD: dict_nis.c,v 1.1.1.2 2013/01/02 18:59:12 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* dict_nis 3 6 /* SUMMARY 7 /* dictionary manager interface to NIS maps 8 /* SYNOPSIS 9 /* #include <dict_nis.h> 10 /* 11 /* DICT *dict_nis_open(map, open_flags, dict_flags) 12 /* const char *map; 13 /* int open_flags; 14 /* int dict_flags; 15 /* DESCRIPTION 16 /* dict_nis_open() makes the specified NIS map accessible via 17 /* the generic dictionary operations described in dict_open(3). 18 /* SEE ALSO 19 /* dict(3) generic dictionary manager 20 /* DIAGNOSTICS 21 /* Fatal errors: out of memory, attempt to update NIS map. 22 /* LICENSE 23 /* .ad 24 /* .fi 25 /* The Secure Mailer license must be distributed with this software. 26 /* AUTHOR(S) 27 /* Wietse Venema 28 /* IBM T.J. Watson Research 29 /* P.O. Box 704 30 /* Yorktown Heights, NY 10598, USA 31 /*--*/ 32 33 /* System library. */ 34 35 #include "sys_defs.h" 36 #include <string.h> 37 38 #ifdef STRCASECMP_IN_STRINGS_H 39 #include <strings.h> 40 #endif 41 42 #ifdef HAS_NIS 43 44 #include <rpcsvc/ypclnt.h> 45 #ifndef YPERR_BUSY 46 #define YPERR_BUSY 16 47 #endif 48 #ifndef YPERR_ACCESS 49 #define YPERR_ACCESS 15 50 #endif 51 52 #endif 53 54 /* Utility library. */ 55 56 #include "msg.h" 57 #include "mymalloc.h" 58 #include "vstring.h" 59 #include "stringops.h" 60 #include "dict.h" 61 #include "dict_nis.h" 62 63 #ifdef HAS_NIS 64 65 /* Application-specific. */ 66 67 typedef struct { 68 DICT dict; /* generic members */ 69 } DICT_NIS; 70 71 /* 72 * Class variables, so that multiple maps can share this info. 73 */ 74 static char dict_nis_disabled[1]; 75 static char *dict_nis_domain; 76 77 /* dict_nis_init - NIS binding */ 78 79 static void dict_nis_init(void) 80 { 81 const char *myname = "dict_nis_init"; 82 83 if (yp_get_default_domain(&dict_nis_domain) != 0 84 || dict_nis_domain == 0 || *dict_nis_domain == 0 85 || strcasecmp(dict_nis_domain, "(none)") == 0) { 86 dict_nis_domain = dict_nis_disabled; 87 msg_warn("%s: NIS domain name not set - NIS lookups disabled", myname); 88 } 89 if (msg_verbose) 90 msg_info("%s: NIS domain %s", myname, dict_nis_domain); 91 } 92 93 /* dict_nis_strerror - map error number to string */ 94 95 static char *dict_nis_strerror(int err) 96 { 97 98 /* 99 * Grr. There should be a standard function for this. 100 */ 101 switch (err) { 102 case YPERR_BADARGS: 103 return ("args to function are bad"); 104 case YPERR_RPC: 105 return ("RPC failure - domain has been unbound"); 106 case YPERR_DOMAIN: 107 return ("can't bind to server on this domain"); 108 case YPERR_MAP: 109 return ("no such map in server's domain"); 110 case YPERR_KEY: 111 return ("no such key in map"); 112 case YPERR_YPERR: 113 return ("internal yp server or client error"); 114 case YPERR_RESRC: 115 return ("resource allocation failure"); 116 case YPERR_NOMORE: 117 return ("no more records in map database"); 118 case YPERR_PMAP: 119 return ("can't communicate with portmapper"); 120 case YPERR_YPBIND: 121 return ("can't communicate with ypbind"); 122 case YPERR_YPSERV: 123 return ("can't communicate with ypserv"); 124 case YPERR_NODOM: 125 return ("local domain name not set"); 126 case YPERR_BADDB: 127 return ("yp database is bad"); 128 case YPERR_VERS: 129 return ("yp version mismatch"); 130 case YPERR_ACCESS: 131 return ("access violation"); 132 case YPERR_BUSY: 133 return ("database busy"); 134 default: 135 return ("unknown NIS lookup error"); 136 } 137 } 138 139 /* dict_nis_lookup - find table entry */ 140 141 static const char *dict_nis_lookup(DICT *dict, const char *key) 142 { 143 DICT_NIS *dict_nis = (DICT_NIS *) dict; 144 static char *result; 145 int result_len; 146 int err; 147 static VSTRING *buf; 148 149 dict->error = 0; 150 151 /* 152 * Sanity check. 153 */ 154 if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) 155 msg_panic("dict_nis_lookup: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); 156 157 if (dict_nis_domain == dict_nis_disabled) 158 return (0); 159 160 /* 161 * Optionally fold the key. 162 */ 163 if (dict->flags & DICT_FLAG_FOLD_FIX) { 164 if (dict->fold_buf == 0) 165 dict->fold_buf = vstring_alloc(10); 166 vstring_strcpy(dict->fold_buf, key); 167 key = lowercase(vstring_str(dict->fold_buf)); 168 } 169 170 /* 171 * See if this NIS map was written with one null byte appended to key and 172 * value. 173 */ 174 if (dict->flags & DICT_FLAG_TRY1NULL) { 175 err = yp_match(dict_nis_domain, dict_nis->dict.name, 176 (void *) key, strlen(key) + 1, 177 &result, &result_len); 178 if (err == 0) { 179 dict->flags &= ~DICT_FLAG_TRY0NULL; 180 return (result); 181 } 182 } 183 184 /* 185 * See if this NIS map was written with no null byte appended to key and 186 * value. This should never be the case, but better play safe. 187 */ 188 if (dict->flags & DICT_FLAG_TRY0NULL) { 189 err = yp_match(dict_nis_domain, dict_nis->dict.name, 190 (void *) key, strlen(key), 191 &result, &result_len); 192 if (err == 0) { 193 dict->flags &= ~DICT_FLAG_TRY1NULL; 194 if (buf == 0) 195 buf = vstring_alloc(10); 196 vstring_strncpy(buf, result, result_len); 197 return (vstring_str(buf)); 198 } 199 } 200 201 /* 202 * When the NIS lookup fails for reasons other than "key not found", keep 203 * logging warnings, and hope that someone will eventually notice the 204 * problem and fix it. 205 */ 206 if (err != YPERR_KEY) { 207 msg_warn("lookup %s, NIS domain %s, map %s: %s", 208 key, dict_nis_domain, dict_nis->dict.name, 209 dict_nis_strerror(err)); 210 dict->error = DICT_ERR_RETRY; 211 } 212 return (0); 213 } 214 215 /* dict_nis_close - close NIS map */ 216 217 static void dict_nis_close(DICT *dict) 218 { 219 if (dict->fold_buf) 220 vstring_free(dict->fold_buf); 221 dict_free(dict); 222 } 223 224 /* dict_nis_open - open NIS map */ 225 226 DICT *dict_nis_open(const char *map, int open_flags, int dict_flags) 227 { 228 DICT_NIS *dict_nis; 229 230 if (open_flags != O_RDONLY) 231 return (dict_surrogate(DICT_TYPE_NIS, map, open_flags, dict_flags, 232 "%s:%s map requires O_RDONLY access mode", 233 DICT_TYPE_NIS, map)); 234 235 dict_nis = (DICT_NIS *) dict_alloc(DICT_TYPE_NIS, map, sizeof(*dict_nis)); 236 dict_nis->dict.lookup = dict_nis_lookup; 237 dict_nis->dict.close = dict_nis_close; 238 dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED; 239 if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) 240 dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL); 241 if (dict_flags & DICT_FLAG_FOLD_FIX) 242 dict_nis->dict.fold_buf = vstring_alloc(10); 243 if (dict_nis_domain == 0) 244 dict_nis_init(); 245 dict_nis->dict.owner.status = DICT_OWNER_TRUSTED; 246 return (DICT_DEBUG (&dict_nis->dict)); 247 } 248 249 #endif 250