blob: 0a38ee85c5a34c70c0be5969e4cb58c9a6fcdbc0 [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) {
Neal Norwitz66239062002-11-04 23:21:09 +000088 if (inkeylen > 0 && inkey[inkeylen-1] == '\0')
89 inkeylen--;
90 if (invallen > 0 && inval[invallen-1] == '\0')
91 invallen--;
Guido van Rossum61b705a2000-02-29 15:52:40 +000092 }
93 key = PyString_FromStringAndSize(inkey, inkeylen);
94 val = PyString_FromStringAndSize(inval, invallen);
Guido van Rossume77a7571993-11-03 15:01:26 +000095 if (key == NULL || val == NULL) {
96 /* XXX error -- don't know how to handle */
Barry Warsawadbf4e61996-12-11 00:15:58 +000097 PyErr_Clear();
98 Py_XDECREF(key);
99 Py_XDECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +0000100 return 1;
101 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000102 err = PyDict_SetItem(indata->dict, key, val);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000103 Py_DECREF(key);
104 Py_DECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +0000105 if (err != 0) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000106 PyErr_Clear();
Guido van Rossume77a7571993-11-03 15:01:26 +0000107 return 1;
108 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000109 return 0;
110 }
111 return 1;
112}
113
Barry Warsawadbf4e61996-12-11 00:15:58 +0000114static PyObject *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000115nis_match (PyObject *self, PyObject *args)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000116{
Guido van Rossum3562d521992-08-12 15:26:16 +0000117 char *match;
118 char *domain;
Guido van Rossume77a7571993-11-03 15:01:26 +0000119 int keylen, len;
Guido van Rossum3562d521992-08-12 15:26:16 +0000120 char *key, *map;
121 int err;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000122 PyObject *res;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000123 int fix;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000124
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000125 if (!PyArg_ParseTuple(args, "t#s:match", &key, &keylen, &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000126 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000127 if ((err = yp_get_default_domain(&domain)) != 0)
128 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000129 map = nis_mapname (map, &fix);
130 if (fix)
131 keylen++;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000132 Py_BEGIN_ALLOW_THREADS
Guido van Rossume77a7571993-11-03 15:01:26 +0000133 err = yp_match (domain, map, key, keylen, &match, &len);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000134 Py_END_ALLOW_THREADS
Guido van Rossum61b705a2000-02-29 15:52:40 +0000135 if (fix)
136 len--;
Guido van Rossum3562d521992-08-12 15:26:16 +0000137 if (err != 0)
138 return nis_error(err);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000139 res = PyString_FromStringAndSize (match, len);
Guido van Rossum3562d521992-08-12 15:26:16 +0000140 free (match);
141 return res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000142}
143
Barry Warsawadbf4e61996-12-11 00:15:58 +0000144static PyObject *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000145nis_cat (PyObject *self, PyObject *args)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000146{
Guido van Rossum3562d521992-08-12 15:26:16 +0000147 char *domain;
148 char *map;
149 struct ypall_callback cb;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000150 struct ypcallback_data data;
151 PyObject *dict;
Guido van Rossum3562d521992-08-12 15:26:16 +0000152 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000153
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000154 if (!PyArg_ParseTuple(args, "s:cat", &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000155 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000156 if ((err = yp_get_default_domain(&domain)) != 0)
157 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000158 dict = PyDict_New ();
159 if (dict == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000160 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000161 cb.foreach = (foreachfunc)nis_foreach;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000162 data.dict = dict;
163 map = nis_mapname (map, &data.fix);
164 cb.data = (char *)&data;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000165 Py_BEGIN_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000166 err = yp_all (domain, map, &cb);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000167 Py_END_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000168 if (err != 0) {
Guido van Rossum61b705a2000-02-29 15:52:40 +0000169 Py_DECREF(dict);
Guido van Rossum3562d521992-08-12 15:26:16 +0000170 return nis_error(err);
171 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000172 return dict;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000173}
174
Guido van Rossumb6775db1994-08-01 11:34:53 +0000175/* These should be u_long on Sun h/w but not on 64-bit h/w.
176 This is not portable to machines with 16-bit ints and no prototypes */
177#ifndef YPPROC_MAPLIST
178#define YPPROC_MAPLIST 11
179#endif
180#ifndef YPPROG
181#define YPPROG 100004
182#endif
183#ifndef YPVERS
184#define YPVERS 2
185#endif
Guido van Rossum9de7a011992-08-12 14:57:12 +0000186
187typedef char *domainname;
188typedef char *mapname;
189
190enum nisstat {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000191 NIS_TRUE = 1,
192 NIS_NOMORE = 2,
193 NIS_FALSE = 0,
194 NIS_NOMAP = -1,
195 NIS_NODOM = -2,
196 NIS_NOKEY = -3,
197 NIS_BADOP = -4,
198 NIS_BADDB = -5,
199 NIS_YPERR = -6,
200 NIS_BADARGS = -7,
201 NIS_VERS = -8
Guido van Rossum9de7a011992-08-12 14:57:12 +0000202};
203typedef enum nisstat nisstat;
204
205struct nismaplist {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000206 mapname map;
207 struct nismaplist *next;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000208};
209typedef struct nismaplist nismaplist;
210
211struct nisresp_maplist {
212 nisstat stat;
213 nismaplist *maps;
214};
215typedef struct nisresp_maplist nisresp_maplist;
216
217static struct timeval TIMEOUT = { 25, 0 };
218
219static
220bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000221nis_xdr_domainname(XDR *xdrs, domainname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000222{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000223 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
224 return (FALSE);
225 }
226 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000227}
228
229static
230bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000231nis_xdr_mapname(XDR *xdrs, mapname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000232{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000233 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
234 return (FALSE);
235 }
236 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000237}
238
239static
240bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000241nis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000242{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000243 if (!nis_xdr_mapname(xdrs, &objp->map)) {
244 return (FALSE);
245 }
246 if (!xdr_pointer(xdrs, (char **)&objp->next,
Guido van Rossumc5015831998-10-07 16:36:14 +0000247 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000248 {
249 return (FALSE);
250 }
251 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000252}
253
254static
255bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000256nis_xdr_ypstat(XDR *xdrs, nisstat *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000257{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000258 if (!xdr_enum(xdrs, (enum_t *)objp)) {
259 return (FALSE);
260 }
261 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000262}
263
264
265static
266bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000267nis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000268{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000269 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
270 return (FALSE);
271 }
272 if (!xdr_pointer(xdrs, (char **)&objp->maps,
Guido van Rossumc5015831998-10-07 16:36:14 +0000273 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000274 {
275 return (FALSE);
276 }
277 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000278}
279
280
281static
282nisresp_maplist *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000283nisproc_maplist_2(domainname *argp, CLIENT *clnt)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000284{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000285 static nisresp_maplist res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000286
Barry Warsawadbf4e61996-12-11 00:15:58 +0000287 memset(&res, 0, sizeof(res));
Guido van Rossumc5015831998-10-07 16:36:14 +0000288 if (clnt_call(clnt, YPPROC_MAPLIST,
289 (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
290 (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
291 TIMEOUT) != RPC_SUCCESS)
292 {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000293 return (NULL);
294 }
295 return (&res);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000296}
297
298static
299nismaplist *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000300nis_maplist (void)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000301{
Guido van Rossum3562d521992-08-12 15:26:16 +0000302 nisresp_maplist *list;
303 char *dom;
Thomas Wouterse75e6d02001-01-21 23:34:12 +0000304 CLIENT *cl;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000305 char *server = NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000306 int mapi = 0;
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000307 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000308
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000309 if ((err = yp_get_default_domain (&dom)) != 0) {
310 nis_error(err);
311 return NULL;
312 }
Barry Warsaw3696c521996-12-11 00:29:14 +0000313
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000314 while (!server && aliases[mapi].map != 0L) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000315 yp_master (dom, aliases[mapi].map, &server);
316 mapi++;
317 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000318 if (!server) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000319 PyErr_SetString(NisError, "No NIS master found for any map");
320 return NULL;
321 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000322 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
323 if (cl == NULL) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000324 PyErr_SetString(NisError, clnt_spcreateerror(server));
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000325 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000326 }
327 list = nisproc_maplist_2 (&dom, cl);
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000328 clnt_destroy(cl);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000329 if (list == NULL)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000330 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000331 if (list->stat != NIS_TRUE)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000332 goto finally;
333
Guido van Rossumb18618d2000-05-03 23:44:39 +0000334 free(server);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000335 return list->maps;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000336
337 finally:
Guido van Rossumb18618d2000-05-03 23:44:39 +0000338 free(server);
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000339 return NULL;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000340}
341
Barry Warsawadbf4e61996-12-11 00:15:58 +0000342static PyObject *
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000343nis_maps (PyObject *self)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000344{
Guido van Rossum3562d521992-08-12 15:26:16 +0000345 nismaplist *maps;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000346 PyObject *list;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000347
348 if ((maps = nis_maplist ()) == NULL)
349 return NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000350 if ((list = PyList_New(0)) == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000351 return NULL;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000352 for (maps = maps; maps; maps = maps->next) {
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000353 PyObject *str = PyString_FromString(maps->map);
354 if (!str || PyList_Append(list, str) < 0)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000355 {
356 Py_DECREF(list);
Guido van Rossum3562d521992-08-12 15:26:16 +0000357 list = NULL;
358 break;
359 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000360 Py_DECREF(str);
Guido van Rossum3562d521992-08-12 15:26:16 +0000361 }
362 /* XXX Shouldn't we free the list of maps now? */
Guido van Rossum9de7a011992-08-12 14:57:12 +0000363 return list;
364}
365
Barry Warsawadbf4e61996-12-11 00:15:58 +0000366static PyMethodDef nis_methods[] = {
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000367 {"match", nis_match, METH_VARARGS},
368 {"cat", nis_cat, METH_VARARGS},
369 {"maps", (PyCFunction)nis_maps, METH_NOARGS},
Guido van Rossum9de7a011992-08-12 14:57:12 +0000370 {NULL, NULL} /* Sentinel */
371};
372
373void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000374initnis (void)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000375{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000376 PyObject *m, *d;
377 m = Py_InitModule("nis", nis_methods);
378 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000379 NisError = PyErr_NewException("nis.error", NULL, NULL);
380 if (NisError != NULL)
381 PyDict_SetItemString(d, "error", NisError);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000382}