1 /* $NetBSD: dict_nis.c,v 1.1.1.1 2009/06/23 10:08:59 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 /* 150 * Sanity check. 151 */ 152 if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) 153 msg_panic("dict_nis_lookup: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); 154 155 dict_errno = 0; 156 if (dict_nis_domain == dict_nis_disabled) 157 return (0); 158 159 /* 160 * Optionally fold the key. 161 */ 162 if (dict->flags & DICT_FLAG_FOLD_FIX) { 163 if (dict->fold_buf == 0) 164 dict->fold_buf = vstring_alloc(10); 165 vstring_strcpy(dict->fold_buf, key); 166 key = lowercase(vstring_str(dict->fold_buf)); 167 } 168 169 /* 170 * See if this NIS map was written with one null byte appended to key and 171 * value. 172 */ 173 if (dict->flags & DICT_FLAG_TRY1NULL) { 174 err = yp_match(dict_nis_domain, dict_nis->dict.name, 175 (void *) key, strlen(key) + 1, 176 &result, &result_len); 177 if (err == 0) { 178 dict->flags &= ~DICT_FLAG_TRY0NULL; 179 return (result); 180 } 181 } 182 183 /* 184 * See if this NIS map was written with no null byte appended to key and 185 * value. This should never be the case, but better play safe. 186 */ 187 if (dict->flags & DICT_FLAG_TRY0NULL) { 188 err = yp_match(dict_nis_domain, dict_nis->dict.name, 189 (void *) key, strlen(key), 190 &result, &result_len); 191 if (err == 0) { 192 dict->flags &= ~DICT_FLAG_TRY1NULL; 193 if (buf == 0) 194 buf = vstring_alloc(10); 195 vstring_strncpy(buf, result, result_len); 196 return (vstring_str(buf)); 197 } 198 } 199 200 /* 201 * When the NIS lookup fails for reasons other than "key not found", keep 202 * logging warnings, and hope that someone will eventually notice the 203 * problem and fix it. 204 */ 205 if (err != YPERR_KEY) { 206 msg_warn("lookup %s, NIS domain %s, map %s: %s", 207 key, dict_nis_domain, dict_nis->dict.name, 208 dict_nis_strerror(err)); 209 dict_errno = DICT_ERR_RETRY; 210 } 211 return (0); 212 } 213 214 /* dict_nis_close - close NIS map */ 215 216 static void dict_nis_close(DICT *dict) 217 { 218 if (dict->fold_buf) 219 vstring_free(dict->fold_buf); 220 dict_free(dict); 221 } 222 223 /* dict_nis_open - open NIS map */ 224 225 DICT *dict_nis_open(const char *map, int open_flags, int dict_flags) 226 { 227 DICT_NIS *dict_nis; 228 229 if (open_flags != O_RDONLY) 230 msg_fatal("%s:%s map requires O_RDONLY access mode", 231 DICT_TYPE_NIS, map); 232 233 dict_nis = (DICT_NIS *) dict_alloc(DICT_TYPE_NIS, map, sizeof(*dict_nis)); 234 dict_nis->dict.lookup = dict_nis_lookup; 235 dict_nis->dict.close = dict_nis_close; 236 dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED; 237 if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) 238 dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL); 239 if (dict_flags & DICT_FLAG_FOLD_FIX) 240 dict_nis->dict.fold_buf = vstring_alloc(10); 241 if (dict_nis_domain == 0) 242 dict_nis_init(); 243 return (DICT_DEBUG (&dict_nis->dict)); 244 } 245 246 #endif 247