netnamer.c revision 74462
1/*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part.  Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user or with the express written consent of
8 * Sun Microsystems, Inc.
9 *
10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 *
14 * Sun RPC is provided with no support and without any obligation on the
15 * part of Sun Microsystems, Inc. to assist in its use, correction,
16 * modification or enhancement.
17 *
18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20 * OR ANY PART THEREOF.
21 *
22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23 * or profits or other special, indirect and consequential damages, even if
24 * Sun has been advised of the possibility of such damages.
25 *
26 * Sun Microsystems, Inc.
27 * 2550 Garcia Avenue
28 * Mountain View, California  94043
29 *
30 * $FreeBSD: head/lib/libc/rpc/netnamer.c 74462 2001-03-19 12:50:13Z alfred $
31 */
32#if !defined(lint) && defined(SCCSIDS)
33static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro";
34#endif
35/*
36 * netname utility routines convert from unix names to network names and
37 * vice-versa This module is operating system dependent! What we define here
38 * will work with any unix system that has adopted the sun NIS domain
39 * architecture.
40 */
41#include "namespace.h"
42#include <sys/param.h>
43#include <rpc/rpc.h>
44#include <rpc/rpc_com.h>
45#ifdef YP
46#include <rpcsvc/yp_prot.h>
47#include <rpcsvc/ypclnt.h>
48#endif
49#include <ctype.h>
50#include <stdio.h>
51#include <grp.h>
52#include <pwd.h>
53#include <string.h>
54#include <stdlib.h>
55#include <unistd.h>
56#include "un-namespace.h"
57
58static char    *OPSYS = "unix";
59static char    *NETID = "netid.byname";
60static char    *NETIDFILE = "/etc/netid";
61
62static int getnetid __P(( char *, char * ));
63static int _getgroups __P(( char *, gid_t * ));
64
65#ifndef NGROUPS
66#define NGROUPS 16
67#endif
68
69/*
70 * Convert network-name into unix credential
71 */
72int
73netname2user(netname, uidp, gidp, gidlenp, gidlist)
74	char            netname[MAXNETNAMELEN + 1];
75	uid_t            *uidp;
76	gid_t            *gidp;
77	int            *gidlenp;
78	gid_t	       *gidlist;
79{
80	char           *p;
81	int             gidlen;
82	uid_t           uid;
83	long		luid;
84	struct passwd  *pwd;
85	char            val[1024];
86	char           *val1, *val2;
87	char           *domain;
88	int             vallen;
89	int             err;
90
91	if (getnetid(netname, val)) {
92		char *res = val;
93
94		p = strsep(&res, ":");
95		if (p == NULL)
96			return (0);
97		*uidp = (uid_t) atol(p);
98		p = strsep(&res, "\n,");
99		if (p == NULL) {
100			return (0);
101		}
102		*gidp = (gid_t) atol(p);
103		gidlen = 0;
104		for (gidlen = 0; gidlen < NGROUPS; gidlen++) {
105			p = strsep(&res, "\n,");
106			if (p == NULL)
107				break;
108			gidlist[gidlen] = (gid_t) atol(p);
109		}
110		*gidlenp = gidlen;
111
112		return (1);
113	}
114	val1 = strchr(netname, '.');
115	if (val1 == NULL)
116		return (0);
117	if (strncmp(netname, OPSYS, (val1-netname)))
118		return (0);
119	val1++;
120	val2 = strchr(val1, '@');
121	if (val2 == NULL)
122		return (0);
123	vallen = val2 - val1;
124	if (vallen > (1024 - 1))
125		vallen = 1024 - 1;
126	(void) strncpy(val, val1, 1024);
127	val[vallen] = 0;
128
129	err = _rpc_get_default_domain(&domain);	/* change to rpc */
130	if (err)
131		return (0);
132
133	if (strcmp(val2 + 1, domain))
134		return (0);	/* wrong domain */
135
136	if (sscanf(val, "%ld", &luid) != 1)
137		return (0);
138	uid = luid;
139
140	/* use initgroups method */
141	pwd = getpwuid(uid);
142	if (pwd == NULL)
143		return (0);
144	*uidp = pwd->pw_uid;
145	*gidp = pwd->pw_gid;
146	*gidlenp = _getgroups(pwd->pw_name, gidlist);
147	return (1);
148}
149
150/*
151 * initgroups
152 */
153
154static int
155_getgroups(uname, groups)
156	char           *uname;
157	gid_t          groups[NGROUPS];
158{
159	gid_t           ngroups = 0;
160	register struct group *grp;
161	register int    i;
162	register int    j;
163	int             filter;
164
165	setgrent();
166	while ((grp = getgrent())) {
167		for (i = 0; grp->gr_mem[i]; i++)
168			if (!strcmp(grp->gr_mem[i], uname)) {
169				if (ngroups == NGROUPS) {
170#ifdef DEBUG
171					fprintf(stderr,
172				"initgroups: %s is in too many groups\n", uname);
173#endif
174					goto toomany;
175				}
176				/* filter out duplicate group entries */
177				filter = 0;
178				for (j = 0; j < ngroups; j++)
179					if (groups[j] == grp->gr_gid) {
180						filter++;
181						break;
182					}
183				if (!filter)
184					groups[ngroups++] = grp->gr_gid;
185			}
186	}
187toomany:
188	endgrent();
189	return (ngroups);
190}
191
192/*
193 * Convert network-name to hostname
194 */
195int
196netname2host(netname, hostname, hostlen)
197	char            netname[MAXNETNAMELEN + 1];
198	char           *hostname;
199	int             hostlen;
200{
201	int             err;
202	char            valbuf[1024];
203	char           *val;
204	char           *val2;
205	int             vallen;
206	char           *domain;
207
208	if (getnetid(netname, valbuf)) {
209		val = valbuf;
210		if ((*val == '0') && (val[1] == ':')) {
211			(void) strncpy(hostname, val + 2, hostlen);
212			return (1);
213		}
214	}
215	val = strchr(netname, '.');
216	if (val == NULL)
217		return (0);
218	if (strncmp(netname, OPSYS, (val - netname)))
219		return (0);
220	val++;
221	val2 = strchr(val, '@');
222	if (val2 == NULL)
223		return (0);
224	vallen = val2 - val;
225	if (vallen > (hostlen - 1))
226		vallen = hostlen - 1;
227	(void) strncpy(hostname, val, vallen);
228	hostname[vallen] = 0;
229
230	err = _rpc_get_default_domain(&domain);	/* change to rpc */
231	if (err)
232		return (0);
233
234	if (strcmp(val2 + 1, domain))
235		return (0);	/* wrong domain */
236	else
237		return (1);
238}
239
240/*
241 * reads the file /etc/netid looking for a + to optionally go to the
242 * network information service.
243 */
244int
245getnetid(key, ret)
246	char           *key, *ret;
247{
248	char            buf[1024];	/* big enough */
249	char           *res;
250	char           *mkey;
251	char           *mval;
252	FILE           *fd;
253#ifdef YP
254	char           *domain;
255	int             err;
256	char           *lookup;
257	int             len;
258#endif
259
260	fd = fopen(NETIDFILE, "r");
261	if (fd == NULL) {
262#ifdef YP
263		res = "+";
264		goto getnetidyp;
265#else
266		return (0);
267#endif
268	}
269	for (;;) {
270		if (fd == NULL)
271			return (0);	/* getnetidyp brings us here */
272		res = fgets(buf, sizeof(buf), fd);
273		if (res == NULL) {
274			fclose(fd);
275			return (0);
276		}
277		if (res[0] == '#')
278			continue;
279		else if (res[0] == '+') {
280#ifdef YP
281	getnetidyp:
282			err = yp_get_default_domain(&domain);
283			if (err) {
284				continue;
285			}
286			lookup = NULL;
287			err = yp_match(domain, NETID, key,
288				strlen(key), &lookup, &len);
289			if (err) {
290#ifdef DEBUG
291				fprintf(stderr, "match failed error %d\n", err);
292#endif
293				continue;
294			}
295			lookup[len] = 0;
296			strcpy(ret, lookup);
297			free(lookup);
298			if (fd != NULL)
299				fclose(fd);
300			return (2);
301#else	/* YP */
302#ifdef DEBUG
303			fprintf(stderr,
304"Bad record in %s '+' -- NIS not supported in this library copy\n",
305				NETIDFILE);
306#endif
307			continue;
308#endif	/* YP */
309		} else {
310			mkey = strsep(&res, "\t ");
311			if (mkey == NULL) {
312				fprintf(stderr,
313		"Bad record in %s -- %s", NETIDFILE, buf);
314				continue;
315			}
316			do {
317				mval = strsep(&res, " \t#\n");
318			} while (mval != NULL && !*mval);
319			if (mval == NULL) {
320				fprintf(stderr,
321		"Bad record in %s val problem - %s", NETIDFILE, buf);
322				continue;
323			}
324			if (strcmp(mkey, key) == 0) {
325				strcpy(ret, mval);
326				fclose(fd);
327				return (1);
328
329			}
330		}
331	}
332}
333