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