blob: 2494adbbedad622d2ca7c5f96fc1cbfa553c8025 [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
Brett Cannonf6067ec2004-07-10 00:57:37 +000071#ifdef __APPLE__
72typedef int (*foreachfunc)(unsigned long, char *, int, char *, int, void *);
73#else
Tim Petersdbd9ba62000-07-09 03:09:57 +000074typedef int (*foreachfunc)(int, char *, int, char *, int, char *);
Brett Cannonf6067ec2004-07-10 00:57:37 +000075#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +000076
Guido van Rossum61b705a2000-02-29 15:52:40 +000077struct ypcallback_data {
78 PyObject *dict;
79 int fix;
80};
81
Guido van Rossum9de7a011992-08-12 14:57:12 +000082static int
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +000083nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
84 int invallen, struct ypcallback_data *indata)
Guido van Rossum9de7a011992-08-12 14:57:12 +000085{
86 if (instatus == YP_TRUE) {
Guido van Rossum61b705a2000-02-29 15:52:40 +000087 PyObject *key;
88 PyObject *val;
Guido van Rossume77a7571993-11-03 15:01:26 +000089 int err;
Guido van Rossum61b705a2000-02-29 15:52:40 +000090
91 if (indata->fix) {
Neal Norwitz66239062002-11-04 23:21:09 +000092 if (inkeylen > 0 && inkey[inkeylen-1] == '\0')
93 inkeylen--;
94 if (invallen > 0 && inval[invallen-1] == '\0')
95 invallen--;
Guido van Rossum61b705a2000-02-29 15:52:40 +000096 }
97 key = PyString_FromStringAndSize(inkey, inkeylen);
98 val = PyString_FromStringAndSize(inval, invallen);
Guido van Rossume77a7571993-11-03 15:01:26 +000099 if (key == NULL || val == NULL) {
100 /* XXX error -- don't know how to handle */
Barry Warsawadbf4e61996-12-11 00:15:58 +0000101 PyErr_Clear();
102 Py_XDECREF(key);
103 Py_XDECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +0000104 return 1;
105 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000106 err = PyDict_SetItem(indata->dict, key, val);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000107 Py_DECREF(key);
108 Py_DECREF(val);
Guido van Rossume77a7571993-11-03 15:01:26 +0000109 if (err != 0) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000110 PyErr_Clear();
Guido van Rossume77a7571993-11-03 15:01:26 +0000111 return 1;
112 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000113 return 0;
114 }
115 return 1;
116}
117
Barry Warsawadbf4e61996-12-11 00:15:58 +0000118static PyObject *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000119nis_match (PyObject *self, PyObject *args)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000120{
Guido van Rossum3562d521992-08-12 15:26:16 +0000121 char *match;
122 char *domain;
Guido van Rossume77a7571993-11-03 15:01:26 +0000123 int keylen, len;
Guido van Rossum3562d521992-08-12 15:26:16 +0000124 char *key, *map;
125 int err;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000126 PyObject *res;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000127 int fix;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000128
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000129 if (!PyArg_ParseTuple(args, "t#s:match", &key, &keylen, &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000130 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000131 if ((err = yp_get_default_domain(&domain)) != 0)
132 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000133 map = nis_mapname (map, &fix);
134 if (fix)
135 keylen++;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000136 Py_BEGIN_ALLOW_THREADS
Guido van Rossume77a7571993-11-03 15:01:26 +0000137 err = yp_match (domain, map, key, keylen, &match, &len);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000138 Py_END_ALLOW_THREADS
Guido van Rossum61b705a2000-02-29 15:52:40 +0000139 if (fix)
140 len--;
Guido van Rossum3562d521992-08-12 15:26:16 +0000141 if (err != 0)
142 return nis_error(err);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000143 res = PyString_FromStringAndSize (match, len);
Guido van Rossum3562d521992-08-12 15:26:16 +0000144 free (match);
145 return res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000146}
147
Barry Warsawadbf4e61996-12-11 00:15:58 +0000148static PyObject *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000149nis_cat (PyObject *self, PyObject *args)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000150{
Guido van Rossum3562d521992-08-12 15:26:16 +0000151 char *domain;
152 char *map;
153 struct ypall_callback cb;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000154 struct ypcallback_data data;
155 PyObject *dict;
Guido van Rossum3562d521992-08-12 15:26:16 +0000156 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000157
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000158 if (!PyArg_ParseTuple(args, "s:cat", &map))
Guido van Rossum9de7a011992-08-12 14:57:12 +0000159 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +0000160 if ((err = yp_get_default_domain(&domain)) != 0)
161 return nis_error(err);
Guido van Rossum61b705a2000-02-29 15:52:40 +0000162 dict = PyDict_New ();
163 if (dict == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000164 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000165 cb.foreach = (foreachfunc)nis_foreach;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000166 data.dict = dict;
167 map = nis_mapname (map, &data.fix);
168 cb.data = (char *)&data;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000169 Py_BEGIN_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000170 err = yp_all (domain, map, &cb);
Barry Warsawadbf4e61996-12-11 00:15:58 +0000171 Py_END_ALLOW_THREADS
Guido van Rossum3562d521992-08-12 15:26:16 +0000172 if (err != 0) {
Guido van Rossum61b705a2000-02-29 15:52:40 +0000173 Py_DECREF(dict);
Guido van Rossum3562d521992-08-12 15:26:16 +0000174 return nis_error(err);
175 }
Guido van Rossum61b705a2000-02-29 15:52:40 +0000176 return dict;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000177}
178
Guido van Rossumb6775db1994-08-01 11:34:53 +0000179/* These should be u_long on Sun h/w but not on 64-bit h/w.
180 This is not portable to machines with 16-bit ints and no prototypes */
181#ifndef YPPROC_MAPLIST
182#define YPPROC_MAPLIST 11
183#endif
184#ifndef YPPROG
185#define YPPROG 100004
186#endif
187#ifndef YPVERS
188#define YPVERS 2
189#endif
Guido van Rossum9de7a011992-08-12 14:57:12 +0000190
191typedef char *domainname;
192typedef char *mapname;
193
194enum nisstat {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000195 NIS_TRUE = 1,
196 NIS_NOMORE = 2,
197 NIS_FALSE = 0,
198 NIS_NOMAP = -1,
199 NIS_NODOM = -2,
200 NIS_NOKEY = -3,
201 NIS_BADOP = -4,
202 NIS_BADDB = -5,
203 NIS_YPERR = -6,
204 NIS_BADARGS = -7,
205 NIS_VERS = -8
Guido van Rossum9de7a011992-08-12 14:57:12 +0000206};
207typedef enum nisstat nisstat;
208
209struct nismaplist {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000210 mapname map;
211 struct nismaplist *next;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000212};
213typedef struct nismaplist nismaplist;
214
215struct nisresp_maplist {
216 nisstat stat;
217 nismaplist *maps;
218};
219typedef struct nisresp_maplist nisresp_maplist;
220
221static struct timeval TIMEOUT = { 25, 0 };
222
223static
224bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000225nis_xdr_domainname(XDR *xdrs, domainname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000226{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000227 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
228 return (FALSE);
229 }
230 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000231}
232
233static
234bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000235nis_xdr_mapname(XDR *xdrs, mapname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000236{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000237 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
238 return (FALSE);
239 }
240 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000241}
242
243static
244bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000245nis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000246{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000247 if (!nis_xdr_mapname(xdrs, &objp->map)) {
248 return (FALSE);
249 }
250 if (!xdr_pointer(xdrs, (char **)&objp->next,
Guido van Rossumc5015831998-10-07 16:36:14 +0000251 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000252 {
253 return (FALSE);
254 }
255 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000256}
257
258static
259bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000260nis_xdr_ypstat(XDR *xdrs, nisstat *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000261{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000262 if (!xdr_enum(xdrs, (enum_t *)objp)) {
263 return (FALSE);
264 }
265 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000266}
267
268
269static
270bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000271nis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000272{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000273 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
274 return (FALSE);
275 }
276 if (!xdr_pointer(xdrs, (char **)&objp->maps,
Guido van Rossumc5015831998-10-07 16:36:14 +0000277 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
Barry Warsawadbf4e61996-12-11 00:15:58 +0000278 {
279 return (FALSE);
280 }
281 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000282}
283
284
285static
286nisresp_maplist *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000287nisproc_maplist_2(domainname *argp, CLIENT *clnt)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000288{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000289 static nisresp_maplist res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000290
Barry Warsawadbf4e61996-12-11 00:15:58 +0000291 memset(&res, 0, sizeof(res));
Guido van Rossumc5015831998-10-07 16:36:14 +0000292 if (clnt_call(clnt, YPPROC_MAPLIST,
293 (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
294 (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
295 TIMEOUT) != RPC_SUCCESS)
296 {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000297 return (NULL);
298 }
299 return (&res);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000300}
301
302static
303nismaplist *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000304nis_maplist (void)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000305{
Guido van Rossum3562d521992-08-12 15:26:16 +0000306 nisresp_maplist *list;
307 char *dom;
Thomas Wouterse75e6d02001-01-21 23:34:12 +0000308 CLIENT *cl;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000309 char *server = NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000310 int mapi = 0;
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000311 int err;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000312
Barry Warsaw1abda0f1996-12-11 01:00:46 +0000313 if ((err = yp_get_default_domain (&dom)) != 0) {
314 nis_error(err);
315 return NULL;
316 }
Barry Warsaw3696c521996-12-11 00:29:14 +0000317
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000318 while (!server && aliases[mapi].map != 0L) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000319 yp_master (dom, aliases[mapi].map, &server);
320 mapi++;
321 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000322 if (!server) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000323 PyErr_SetString(NisError, "No NIS master found for any map");
324 return NULL;
325 }
Guido van Rossum9de7a011992-08-12 14:57:12 +0000326 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
327 if (cl == NULL) {
Barry Warsawadbf4e61996-12-11 00:15:58 +0000328 PyErr_SetString(NisError, clnt_spcreateerror(server));
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000329 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000330 }
331 list = nisproc_maplist_2 (&dom, cl);
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000332 clnt_destroy(cl);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000333 if (list == NULL)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000334 goto finally;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000335 if (list->stat != NIS_TRUE)
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000336 goto finally;
337
Guido van Rossumb18618d2000-05-03 23:44:39 +0000338 free(server);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000339 return list->maps;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000340
341 finally:
Guido van Rossumb18618d2000-05-03 23:44:39 +0000342 free(server);
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000343 return NULL;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000344}
345
Barry Warsawadbf4e61996-12-11 00:15:58 +0000346static PyObject *
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000347nis_maps (PyObject *self)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000348{
Guido van Rossum3562d521992-08-12 15:26:16 +0000349 nismaplist *maps;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000350 PyObject *list;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000351
352 if ((maps = nis_maplist ()) == NULL)
353 return NULL;
Barry Warsawadbf4e61996-12-11 00:15:58 +0000354 if ((list = PyList_New(0)) == NULL)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000355 return NULL;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000356 for (maps = maps; maps; maps = maps->next) {
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000357 PyObject *str = PyString_FromString(maps->map);
358 if (!str || PyList_Append(list, str) < 0)
Barry Warsawadbf4e61996-12-11 00:15:58 +0000359 {
360 Py_DECREF(list);
Guido van Rossum3562d521992-08-12 15:26:16 +0000361 list = NULL;
362 break;
363 }
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000364 Py_DECREF(str);
Guido van Rossum3562d521992-08-12 15:26:16 +0000365 }
366 /* XXX Shouldn't we free the list of maps now? */
Guido van Rossum9de7a011992-08-12 14:57:12 +0000367 return list;
368}
369
Barry Warsawadbf4e61996-12-11 00:15:58 +0000370static PyMethodDef nis_methods[] = {
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000371 {"match", nis_match, METH_VARARGS},
372 {"cat", nis_cat, METH_VARARGS},
373 {"maps", (PyCFunction)nis_maps, METH_NOARGS},
Guido van Rossum9de7a011992-08-12 14:57:12 +0000374 {NULL, NULL} /* Sentinel */
375};
376
377void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000378initnis (void)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000379{
Barry Warsawadbf4e61996-12-11 00:15:58 +0000380 PyObject *m, *d;
381 m = Py_InitModule("nis", nis_methods);
382 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000383 NisError = PyErr_NewException("nis.error", NULL, NULL);
384 if (NisError != NULL)
385 PyDict_SetItemString(d, "error", NisError);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000386}