blob: f66e9a1cc67f1ee05caad14239de0cdaa7f5ed21 [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 */
Thomas Woutersbd4bc4e2000-07-22 23:57:55 +000023extern int yp_get_default_domain(char **);
Guido van Rossum259552d1996-12-09 18:46:28 +000024#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 *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +000029nis_error (int err)
Guido van Rossum3562d521992-08-12 15:26:16 +000030{
Barry Warsawadbf4e61996-12-11 00:15:58 +000031 PyErr_SetString(NisError, yperr_string(err));
Guido van Rossum3562d521992-08-12 15:26:16 +000032 return NULL;
33}
34
Guido van Rossum9de7a011992-08-12 14:57:12 +000035static struct nis_map {
36 char *alias;
37 char *map;
Guido van Rossum61b705a2000-02-29 15:52:40 +000038 int fix;
Guido van Rossum9de7a011992-08-12 14:57:12 +000039} aliases [] = {
Guido van Rossum61b705a2000-02-29 15:52:40 +000040 {"passwd", "passwd.byname", 0},
41 {"group", "group.byname", 0},
42 {"networks", "networks.byaddr", 0},
43 {"hosts", "hosts.byname", 0},
44 {"protocols", "protocols.bynumber", 0},
45 {"services", "services.byname", 0},
46 {"aliases", "mail.aliases", 1}, /* created with 'makedbm -a' */
47 {"ethers", "ethers.byname", 0},
48 {0L, 0L, 0}
Guido van Rossum9de7a011992-08-12 14:57:12 +000049};
50
51static char *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +000052nis_mapname (char *map, int *pfix)
Guido van Rossum9de7a011992-08-12 14:57:12 +000053{
Guido van Rossum3562d521992-08-12 15:26:16 +000054 int i;
Guido van Rossum9de7a011992-08-12 14:57:12 +000055
Guido van Rossum61b705a2000-02-29 15:52:40 +000056 *pfix = 0;
57 for (i=0; aliases[i].alias != 0L; i++) {
58 if (!strcmp (aliases[i].alias, map)) {
59 *pfix = aliases[i].fix;
60 return aliases[i].map;
61 }
62 if (!strcmp (aliases[i].map, map)) {
63 *pfix = aliases[i].fix;
64 return aliases[i].map;
65 }
66 }
67
Guido van Rossum9de7a011992-08-12 14:57:12 +000068 return map;
69}
70
Tim Petersdbd9ba62000-07-09 03:09:57 +000071typedef int (*foreachfunc)(int, char *, int, char *, int, char *);
Guido van Rossumb6775db1994-08-01 11:34:53 +000072
Guido van Rossum61b705a2000-02-29 15:52:40 +000073struct ypcallback_data {
74 PyObject *dict;
75 int fix;
76};
77
Guido van Rossum9de7a011992-08-12 14:57:12 +000078static int
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +000079nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
80 int invallen, struct ypcallback_data *indata)
Guido van Rossum9de7a011992-08-12 14:57:12 +000081{
82 if (instatus == YP_TRUE) {
Guido van Rossum61b705a2000-02-29 15:52:40 +000083 PyObject *key;
84 PyObject *val;
Guido van Rossume77a7571993-11-03 15:01:26 +000085 int err;
Guido van Rossum61b705a2000-02-29 15:52:40 +000086
87 if (indata->fix) {
88 inkeylen--;
89 invallen--;
90 }
91 key = PyString_FromStringAndSize(inkey, inkeylen);
92 val = PyString_FromStringAndSize(inval, invallen);
Guido van Rossume77a7571993-11-03 15:01:26 +000093 if (key == NULL || val == NULL) {
94 /* XXX error -- don't know how to handle */
Barry Warsawadbf4e61996-12-11 00:15:58 +000095 PyErr_Clear();
96 Py_XDECREF(key);
97 Py_XDECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +000098 return 1;
99 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000100 err = PyDict_SetItem(indata->dict, key, val);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000101 Py_DECREF(key);
102 Py_DECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +0000103 if (err != 0) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000104 PyErr_Clear();
Guido van Rossume77a7571993-11-03 15:01:26 +0000105 return 1;
106 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000107 return 0;
108 }
109 return 1;
110}
111
Barry Warsawadbf4e61996-12-11 00:15:58 +0000112static PyObject *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000113nis_match (PyObject *self, PyObject *args)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000114{
Guido van Rossum3562d521992-08-12 15:26:16 +0000115 char *match;
116 char *domain;
Guido van Rossume77a7571993-11-03 15:01:26 +0000117 int keylen, len;
Guido van Rossum3562d521992-08-12 15:26:16 +0000118 char *key, *map;
119 int err;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000120 PyObject *res;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000121 int fix;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000122
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000123 if (!PyArg_ParseTuple(args, "t#s:match", &key, &keylen, &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000124 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000125 if ((err = yp_get_default_domain(&domain)) != 0)
126 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000127 map = nis_mapname (map, &fix);
128 if (fix)
129 keylen++;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000130 Py_BEGIN_ALLOW_THREADS
Guido van Rossume77a7571993-11-03 15:01:26 +0000131 err = yp_match (domain, map, key, keylen, &match, &len);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000132 Py_END_ALLOW_THREADS
Guido van Rossum61b705a2000-02-29 15:52:40 +0000133 if (fix)
134 len--;
Guido van Rossum3562d521992-08-12 15:26:16 +0000135 if (err != 0)
136 return nis_error(err);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000137 res = PyString_FromStringAndSize (match, len);
Guido van Rossum3562d521992-08-12 15:26:16 +0000138 free (match);
139 return res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000140}
141
Barry Warsawadbf4e61996-12-11 00:15:58 +0000142static PyObject *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000143nis_cat (PyObject *self, PyObject *args)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000144{
Guido van Rossum3562d521992-08-12 15:26:16 +0000145 char *domain;
146 char *map;
147 struct ypall_callback cb;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000148 struct ypcallback_data data;
149 PyObject *dict;
Guido van Rossum3562d521992-08-12 15:26:16 +0000150 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000151
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000152 if (!PyArg_ParseTuple(args, "s:cat", &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000153 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000154 if ((err = yp_get_default_domain(&domain)) != 0)
155 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000156 dict = PyDict_New ();
157 if (dict == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000158 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000159 cb.foreach = (foreachfunc)nis_foreach;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000160 data.dict = dict;
161 map = nis_mapname (map, &data.fix);
162 cb.data = (char *)&data;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000163 Py_BEGIN_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000164 err = yp_all (domain, map, &cb);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000165 Py_END_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000166 if (err != 0) {
Guido van Rossum61b705a2000-02-29 15:52:40 +0000167 Py_DECREF(dict);
Guido van Rossum3562d521992-08-12 15:26:16 +0000168 return nis_error(err);
169 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000170 return dict;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000171}
172
Guido van Rossumb6775db1994-08-01 11:34:53 +0000173/* These should be u_long on Sun h/w but not on 64-bit h/w.
174 This is not portable to machines with 16-bit ints and no prototypes */
175#ifndef YPPROC_MAPLIST
176#define YPPROC_MAPLIST 11
177#endif
178#ifndef YPPROG
179#define YPPROG 100004
180#endif
181#ifndef YPVERS
182#define YPVERS 2
183#endif
Guido van Rossum9de7a011992-08-12 14:57:12 +0000184
185typedef char *domainname;
186typedef char *mapname;
187
188enum nisstat {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000189 NIS_TRUE = 1,
190 NIS_NOMORE = 2,
191 NIS_FALSE = 0,
192 NIS_NOMAP = -1,
193 NIS_NODOM = -2,
194 NIS_NOKEY = -3,
195 NIS_BADOP = -4,
196 NIS_BADDB = -5,
197 NIS_YPERR = -6,
198 NIS_BADARGS = -7,
199 NIS_VERS = -8
Guido van Rossum9de7a011992-08-12 14:57:12 +0000200};
201typedef enum nisstat nisstat;
202
203struct nismaplist {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000204 mapname map;
205 struct nismaplist *next;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000206};
207typedef struct nismaplist nismaplist;
208
209struct nisresp_maplist {
210 nisstat stat;
211 nismaplist *maps;
212};
213typedef struct nisresp_maplist nisresp_maplist;
214
215static struct timeval TIMEOUT = { 25, 0 };
216
217static
218bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000219nis_xdr_domainname(XDR *xdrs, domainname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000220{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000221 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
222 return (FALSE);
223 }
224 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000225}
226
227static
228bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000229nis_xdr_mapname(XDR *xdrs, mapname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000230{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000231 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
232 return (FALSE);
233 }
234 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000235}
236
237static
238bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000239nis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000240{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000241 if (!nis_xdr_mapname(xdrs, &objp->map)) {
242 return (FALSE);
243 }
244 if (!xdr_pointer(xdrs, (char **)&objp->next,
Guido van Rossumc5015831998-10-07 16:36:14 +0000245 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000246 {
247 return (FALSE);
248 }
249 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000250}
251
252static
253bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000254nis_xdr_ypstat(XDR *xdrs, nisstat *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000255{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000256 if (!xdr_enum(xdrs, (enum_t *)objp)) {
257 return (FALSE);
258 }
259 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000260}
261
262
263static
264bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000265nis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000266{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000267 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
268 return (FALSE);
269 }
270 if (!xdr_pointer(xdrs, (char **)&objp->maps,
Guido van Rossumc5015831998-10-07 16:36:14 +0000271 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000272 {
273 return (FALSE);
274 }
275 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000276}
277
278
279static
280nisresp_maplist *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000281nisproc_maplist_2(domainname *argp, CLIENT *clnt)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000282{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000283 static nisresp_maplist res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000284
Barry Warsawadbf4e61996-12-11 00:15:58 +0000285 memset(&res, 0, sizeof(res));
Guido van Rossumc5015831998-10-07 16:36:14 +0000286 if (clnt_call(clnt, YPPROC_MAPLIST,
287 (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
288 (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
289 TIMEOUT) != RPC_SUCCESS)
290 {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000291 return (NULL);
292 }
293 return (&res);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000294}
295
296static
297nismaplist *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000298nis_maplist (void)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000299{
Guido van Rossum3562d521992-08-12 15:26:16 +0000300 nisresp_maplist *list;
301 char *dom;
Thomas Wouterse75e6d02001-01-21 23:34:12 +0000302 CLIENT *cl;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000303 char *server = NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000304 int mapi = 0;
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000305 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000306
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000307 if ((err = yp_get_default_domain (&dom)) != 0) {
308 nis_error(err);
309 return NULL;
310 }
Barry Warsaw3696c521996-12-11 00:29:14 +0000311
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000312 while (!server && aliases[mapi].map != 0L) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000313 yp_master (dom, aliases[mapi].map, &server);
314 mapi++;
315 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000316 if (!server) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000317 PyErr_SetString(NisError, "No NIS master found for any map");
318 return NULL;
319 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000320 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
321 if (cl == NULL) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000322 PyErr_SetString(NisError, clnt_spcreateerror(server));
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000323 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000324 }
325 list = nisproc_maplist_2 (&dom, cl);
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000326 clnt_destroy(cl);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000327 if (list == NULL)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000328 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000329 if (list->stat != NIS_TRUE)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000330 goto finally;
331
Guido van Rossumb18618d2000-05-03 23:44:39 +0000332 free(server);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000333 return list->maps;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000334
335 finally:
Guido van Rossumb18618d2000-05-03 23:44:39 +0000336 free(server);
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000337 return NULL;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000338}
339
Barry Warsawadbf4e61996-12-11 00:15:58 +0000340static PyObject *
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000341nis_maps (PyObject *self)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000342{
Guido van Rossum3562d521992-08-12 15:26:16 +0000343 nismaplist *maps;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000344 PyObject *list;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000345
346 if ((maps = nis_maplist ()) == NULL)
347 return NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000348 if ((list = PyList_New(0)) == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000349 return NULL;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000350 for (maps = maps; maps; maps = maps->next) {
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000351 PyObject *str = PyString_FromString(maps->map);
352 if (!str || PyList_Append(list, str) < 0)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000353 {
354 Py_DECREF(list);
Guido van Rossum3562d521992-08-12 15:26:16 +0000355 list = NULL;
356 break;
357 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000358 Py_DECREF(str);
Guido van Rossum3562d521992-08-12 15:26:16 +0000359 }
360 /* XXX Shouldn't we free the list of maps now? */
Guido van Rossum9de7a011992-08-12 14:57:12 +0000361 return list;
362}
363
Barry Warsawadbf4e61996-12-11 00:15:58 +0000364static PyMethodDef nis_methods[] = {
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000365 {"match", nis_match, METH_VARARGS},
366 {"cat", nis_cat, METH_VARARGS},
367 {"maps", (PyCFunction)nis_maps, METH_NOARGS},
Guido van Rossum9de7a011992-08-12 14:57:12 +0000368 {NULL, NULL} /* Sentinel */
369};
370
371void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000372initnis (void)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000373{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000374 PyObject *m, *d;
375 m = Py_InitModule("nis", nis_methods);
376 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000377 NisError = PyErr_NewException("nis.error", NULL, NULL);
378 if (NisError != NULL)
379 PyDict_SetItemString(d, "error", NisError);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000380}