blob: 04f27f2bda424cd7d7edfc42842e916025b2f1a5 [file] [log] [blame]
Guido van Rossum9de7a011992-08-12 14:57:12 +00001/***********************************************************
2 Written by:
3 Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
Guido van Rossum61b705a2000-02-29 15:52:40 +00004 B&O group,
Guido van Rossum9de7a011992-08-12 14:57:12 +00005 Faculteit der Informatica,
6 Universiteit Twente,
7 Enschede,
8 the Netherlands.
9******************************************************************/
10
11/* NIS module implementation */
12
Barry Warsawadbf4e61996-12-11 00:15:58 +000013#include "Python.h"
Guido van Rossum9de7a011992-08-12 14:57:12 +000014
Guido van Rossum9de7a011992-08-12 14:57:12 +000015#include <sys/time.h>
16#include <sys/types.h>
17#include <rpc/rpc.h>
18#include <rpcsvc/yp_prot.h>
Guido van Rossum8a170cb1996-08-08 19:11:41 +000019#include <rpcsvc/ypclnt.h>
Guido van Rossum9de7a011992-08-12 14:57:12 +000020
Guido van Rossum259552d1996-12-09 18:46:28 +000021#ifdef __sgi
22/* This is missing from rpcsvc/ypclnt.h */
23extern int yp_get_default_domain();
24#endif
25
Barry Warsawadbf4e61996-12-11 00:15:58 +000026static PyObject *NisError;
Guido van Rossum3562d521992-08-12 15:26:16 +000027
Barry Warsawadbf4e61996-12-11 00:15:58 +000028static PyObject *
Guido van Rossum3562d521992-08-12 15:26:16 +000029nis_error (err)
30 int err;
31{
Barry Warsawadbf4e61996-12-11 00:15:58 +000032 PyErr_SetString(NisError, yperr_string(err));
Guido van Rossum3562d521992-08-12 15:26:16 +000033 return NULL;
34}
35
Guido van Rossum9de7a011992-08-12 14:57:12 +000036static struct nis_map {
37 char *alias;
38 char *map;
Guido van Rossum61b705a2000-02-29 15:52:40 +000039 int fix;
Guido van Rossum9de7a011992-08-12 14:57:12 +000040} aliases [] = {
Guido van Rossum61b705a2000-02-29 15:52:40 +000041 {"passwd", "passwd.byname", 0},
42 {"group", "group.byname", 0},
43 {"networks", "networks.byaddr", 0},
44 {"hosts", "hosts.byname", 0},
45 {"protocols", "protocols.bynumber", 0},
46 {"services", "services.byname", 0},
47 {"aliases", "mail.aliases", 1}, /* created with 'makedbm -a' */
48 {"ethers", "ethers.byname", 0},
49 {0L, 0L, 0}
Guido van Rossum9de7a011992-08-12 14:57:12 +000050};
51
52static char *
Guido van Rossum61b705a2000-02-29 15:52:40 +000053nis_mapname (map, pfix)
Guido van Rossum3562d521992-08-12 15:26:16 +000054 char *map;
Guido van Rossum61b705a2000-02-29 15:52:40 +000055 int *pfix;
Guido van Rossum9de7a011992-08-12 14:57:12 +000056{
Guido van Rossum3562d521992-08-12 15:26:16 +000057 int i;
Guido van Rossum9de7a011992-08-12 14:57:12 +000058
Guido van Rossum61b705a2000-02-29 15:52:40 +000059 *pfix = 0;
60 for (i=0; aliases[i].alias != 0L; i++) {
61 if (!strcmp (aliases[i].alias, map)) {
62 *pfix = aliases[i].fix;
63 return aliases[i].map;
64 }
65 if (!strcmp (aliases[i].map, map)) {
66 *pfix = aliases[i].fix;
67 return aliases[i].map;
68 }
69 }
70
Guido van Rossum9de7a011992-08-12 14:57:12 +000071 return map;
72}
73
Barry Warsawadbf4e61996-12-11 00:15:58 +000074typedef int (*foreachfunc) Py_PROTO((int, char *, int, char *, int, char *));
Guido van Rossumb6775db1994-08-01 11:34:53 +000075
Guido van Rossum61b705a2000-02-29 15:52:40 +000076struct ypcallback_data {
77 PyObject *dict;
78 int fix;
79};
80
Guido van Rossum9de7a011992-08-12 14:57:12 +000081static int
Guido van Rossum3562d521992-08-12 15:26:16 +000082nis_foreach (instatus, inkey, inkeylen, inval, invallen, indata)
83 int instatus;
84 char *inkey;
85 int inkeylen;
86 char *inval;
87 int invallen;
Guido van Rossum61b705a2000-02-29 15:52:40 +000088 struct ypcallback_data *indata;
Guido van Rossum9de7a011992-08-12 14:57:12 +000089{
90 if (instatus == YP_TRUE) {
Guido van Rossum61b705a2000-02-29 15:52:40 +000091 PyObject *key;
92 PyObject *val;
Guido van Rossume77a7571993-11-03 15:01:26 +000093 int err;
Guido van Rossum61b705a2000-02-29 15:52:40 +000094
95 if (indata->fix) {
96 inkeylen--;
97 invallen--;
98 }
99 key = PyString_FromStringAndSize(inkey, inkeylen);
100 val = PyString_FromStringAndSize(inval, invallen);
Guido van Rossume77a7571993-11-03 15:01:26 +0000101 if (key == NULL || val == NULL) {
102 /* XXX error -- don't know how to handle */
Barry Warsawadbf4e61996-12-11 00:15:58 +0000103 PyErr_Clear();
104 Py_XDECREF(key);
105 Py_XDECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +0000106 return 1;
107 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000108 err = PyDict_SetItem(indata->dict, key, val);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000109 Py_DECREF(key);
110 Py_DECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +0000111 if (err != 0) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000112 PyErr_Clear();
Guido van Rossume77a7571993-11-03 15:01:26 +0000113 return 1;
114 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000115 return 0;
116 }
117 return 1;
118}
119
Barry Warsawadbf4e61996-12-11 00:15:58 +0000120static PyObject *
Guido van Rossum9de7a011992-08-12 14:57:12 +0000121nis_match (self, args)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000122 PyObject *self;
123 PyObject *args;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000124{
Guido van Rossum3562d521992-08-12 15:26:16 +0000125 char *match;
126 char *domain;
Guido van Rossume77a7571993-11-03 15:01:26 +0000127 int keylen, len;
Guido van Rossum3562d521992-08-12 15:26:16 +0000128 char *key, *map;
129 int err;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000130 PyObject *res;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000131 int fix;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000132
Guido van Rossum7e488981998-10-08 02:25:24 +0000133 if (!PyArg_Parse(args, "(t#s)", &key, &keylen, &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000134 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000135 if ((err = yp_get_default_domain(&domain)) != 0)
136 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000137 map = nis_mapname (map, &fix);
138 if (fix)
139 keylen++;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000140 Py_BEGIN_ALLOW_THREADS
Guido van Rossume77a7571993-11-03 15:01:26 +0000141 err = yp_match (domain, map, key, keylen, &match, &len);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000142 Py_END_ALLOW_THREADS
Guido van Rossum61b705a2000-02-29 15:52:40 +0000143 if (fix)
144 len--;
Guido van Rossum3562d521992-08-12 15:26:16 +0000145 if (err != 0)
146 return nis_error(err);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000147 res = PyString_FromStringAndSize (match, len);
Guido van Rossum3562d521992-08-12 15:26:16 +0000148 free (match);
149 return res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000150}
151
Barry Warsawadbf4e61996-12-11 00:15:58 +0000152static PyObject *
Guido van Rossum9de7a011992-08-12 14:57:12 +0000153nis_cat (self, args)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000154 PyObject *self;
155 PyObject *args;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000156{
Guido van Rossum3562d521992-08-12 15:26:16 +0000157 char *domain;
158 char *map;
159 struct ypall_callback cb;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000160 struct ypcallback_data data;
161 PyObject *dict;
Guido van Rossum3562d521992-08-12 15:26:16 +0000162 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000163
Barry Warsawadbf4e61996-12-11 00:15:58 +0000164 if (!PyArg_Parse(args, "s", &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000165 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000166 if ((err = yp_get_default_domain(&domain)) != 0)
167 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000168 dict = PyDict_New ();
169 if (dict == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000170 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000171 cb.foreach = (foreachfunc)nis_foreach;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000172 data.dict = dict;
173 map = nis_mapname (map, &data.fix);
174 cb.data = (char *)&data;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000175 Py_BEGIN_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000176 err = yp_all (domain, map, &cb);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000177 Py_END_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000178 if (err != 0) {
Guido van Rossum61b705a2000-02-29 15:52:40 +0000179 Py_DECREF(dict);
Guido van Rossum3562d521992-08-12 15:26:16 +0000180 return nis_error(err);
181 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000182 return dict;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000183}
184
Guido van Rossumb6775db1994-08-01 11:34:53 +0000185/* These should be u_long on Sun h/w but not on 64-bit h/w.
186 This is not portable to machines with 16-bit ints and no prototypes */
187#ifndef YPPROC_MAPLIST
188#define YPPROC_MAPLIST 11
189#endif
190#ifndef YPPROG
191#define YPPROG 100004
192#endif
193#ifndef YPVERS
194#define YPVERS 2
195#endif
Guido van Rossum9de7a011992-08-12 14:57:12 +0000196
197typedef char *domainname;
198typedef char *mapname;
199
200enum nisstat {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000201 NIS_TRUE = 1,
202 NIS_NOMORE = 2,
203 NIS_FALSE = 0,
204 NIS_NOMAP = -1,
205 NIS_NODOM = -2,
206 NIS_NOKEY = -3,
207 NIS_BADOP = -4,
208 NIS_BADDB = -5,
209 NIS_YPERR = -6,
210 NIS_BADARGS = -7,
211 NIS_VERS = -8
Guido van Rossum9de7a011992-08-12 14:57:12 +0000212};
213typedef enum nisstat nisstat;
214
215struct nismaplist {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000216 mapname map;
217 struct nismaplist *next;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000218};
219typedef struct nismaplist nismaplist;
220
221struct nisresp_maplist {
222 nisstat stat;
223 nismaplist *maps;
224};
225typedef struct nisresp_maplist nisresp_maplist;
226
227static struct timeval TIMEOUT = { 25, 0 };
228
229static
230bool_t
231nis_xdr_domainname(xdrs, objp)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000232 XDR *xdrs;
233 domainname *objp;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000234{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000235 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
236 return (FALSE);
237 }
238 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000239}
240
241static
242bool_t
243nis_xdr_mapname(xdrs, objp)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000244 XDR *xdrs;
245 mapname *objp;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000246{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000247 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
248 return (FALSE);
249 }
250 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000251}
252
253static
254bool_t
255nis_xdr_ypmaplist(xdrs, objp)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000256 XDR *xdrs;
257 nismaplist *objp;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000258{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000259 if (!nis_xdr_mapname(xdrs, &objp->map)) {
260 return (FALSE);
261 }
262 if (!xdr_pointer(xdrs, (char **)&objp->next,
Guido van Rossumc5015831998-10-07 16:36:14 +0000263 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000264 {
265 return (FALSE);
266 }
267 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000268}
269
270static
271bool_t
272nis_xdr_ypstat(xdrs, objp)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000273 XDR *xdrs;
274 nisstat *objp;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000275{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000276 if (!xdr_enum(xdrs, (enum_t *)objp)) {
277 return (FALSE);
278 }
279 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000280}
281
282
283static
284bool_t
285nis_xdr_ypresp_maplist(xdrs, objp)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000286 XDR *xdrs;
287 nisresp_maplist *objp;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000288{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000289 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
290 return (FALSE);
291 }
292 if (!xdr_pointer(xdrs, (char **)&objp->maps,
Guido van Rossumc5015831998-10-07 16:36:14 +0000293 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000294 {
295 return (FALSE);
296 }
297 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000298}
299
300
301static
302nisresp_maplist *
303nisproc_maplist_2(argp, clnt)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000304 domainname *argp;
305 CLIENT *clnt;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000306{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000307 static nisresp_maplist res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000308
Barry Warsawadbf4e61996-12-11 00:15:58 +0000309 memset(&res, 0, sizeof(res));
Guido van Rossumc5015831998-10-07 16:36:14 +0000310 if (clnt_call(clnt, YPPROC_MAPLIST,
311 (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
312 (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
313 TIMEOUT) != RPC_SUCCESS)
314 {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000315 return (NULL);
316 }
317 return (&res);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000318}
319
320static
321nismaplist *
322nis_maplist ()
323{
Guido van Rossum3562d521992-08-12 15:26:16 +0000324 nisresp_maplist *list;
325 char *dom;
326 CLIENT *cl, *clnt_create();
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000327 char *server = NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000328 int mapi = 0;
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000329 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000330
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000331 if ((err = yp_get_default_domain (&dom)) != 0) {
332 nis_error(err);
333 return NULL;
334 }
Barry Warsaw3696c521996-12-11 00:29:14 +0000335
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000336 while (!server && aliases[mapi].map != 0L) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000337 yp_master (dom, aliases[mapi].map, &server);
338 mapi++;
339 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000340 if (!server) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000341 PyErr_SetString(NisError, "No NIS master found for any map");
342 return NULL;
343 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000344 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
345 if (cl == NULL) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000346 PyErr_SetString(NisError, clnt_spcreateerror(server));
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000347 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000348 }
349 list = nisproc_maplist_2 (&dom, cl);
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000350 clnt_destroy(cl);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000351 if (list == NULL)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000352 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000353 if (list->stat != NIS_TRUE)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000354 goto finally;
355
356 PyMem_DEL(server);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000357 return list->maps;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000358
359 finally:
360 PyMem_DEL(server);
361 return NULL;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000362}
363
Barry Warsawadbf4e61996-12-11 00:15:58 +0000364static PyObject *
Guido van Rossum9de7a011992-08-12 14:57:12 +0000365nis_maps (self, args)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000366 PyObject *self;
367 PyObject *args;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000368{
Guido van Rossum3562d521992-08-12 15:26:16 +0000369 nismaplist *maps;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000370 PyObject *list;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000371
Barry Warsaw3696c521996-12-11 00:29:14 +0000372 if (!PyArg_NoArgs(args))
373 return NULL;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000374 if ((maps = nis_maplist ()) == NULL)
375 return NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000376 if ((list = PyList_New(0)) == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000377 return NULL;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000378 for (maps = maps; maps; maps = maps->next) {
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000379 PyObject *str = PyString_FromString(maps->map);
380 if (!str || PyList_Append(list, str) < 0)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000381 {
382 Py_DECREF(list);
Guido van Rossum3562d521992-08-12 15:26:16 +0000383 list = NULL;
384 break;
385 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000386 Py_DECREF(str);
Guido van Rossum3562d521992-08-12 15:26:16 +0000387 }
388 /* XXX Shouldn't we free the list of maps now? */
Guido van Rossum9de7a011992-08-12 14:57:12 +0000389 return list;
390}
391
Barry Warsawadbf4e61996-12-11 00:15:58 +0000392static PyMethodDef nis_methods[] = {
Guido van Rossum9de7a011992-08-12 14:57:12 +0000393 {"match", nis_match},
394 {"cat", nis_cat},
395 {"maps", nis_maps},
396 {NULL, NULL} /* Sentinel */
397};
398
399void
400initnis ()
401{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000402 PyObject *m, *d;
403 m = Py_InitModule("nis", nis_methods);
404 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000405 NisError = PyErr_NewException("nis.error", NULL, NULL);
406 if (NisError != NULL)
407 PyDict_SetItemString(d, "error", NisError);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000408}