pcnfsd_v2.c revision 1.4
1/*	$NetBSD: pcnfsd_v2.c,v 1.4 1995/08/14 19:50:10 gwr Exp $	*/
2
3/* RE_SID: @(%)/usr/dosnfs/shades_SCCS/unix/pcnfsd/v2/src/SCCS/s.pcnfsd_v2.c 1.2 91/12/18 13:26:13 SMI */
4/*
5**=====================================================================
6** Copyright (c) 1986,1987,1988,1989,1990,1991 by Sun Microsystems, Inc.
7**	@(#)pcnfsd_v2.c	1.2	12/18/91
8**=====================================================================
9*/
10#include "common.h"
11/*
12**=====================================================================
13**             I N C L U D E   F I L E   S E C T I O N                *
14**                                                                    *
15** If your port requires different include files, add a suitable      *
16** #define in the customization section, and make the inclusion or    *
17** exclusion of the files conditional on this.                        *
18**=====================================================================
19*/
20#include "pcnfsd.h"
21
22#include <stdio.h>
23#include <pwd.h>
24#include <grp.h>
25#include <sys/file.h>
26#include <signal.h>
27#include <sys/stat.h>
28#include <sys/ioctl.h>
29#include <netdb.h>
30#include <string.h>
31
32#ifdef USE_YP
33#include <rpcsvc/ypclnt.h>
34#endif
35
36#ifndef SYSV
37#include <sys/wait.h>
38#endif
39
40#ifdef ISC_2_0
41#include <sys/fcntl.h>
42#endif
43
44#ifdef SHADOW_SUPPORT
45#include <shadow.h>
46#endif
47
48/*
49**---------------------------------------------------------------------
50** Other #define's
51**---------------------------------------------------------------------
52*/
53
54void            fillin_extra_groups();
55extern void     scramble();
56extern void    *grab();
57extern char    *crypt();
58extern int      build_pr_list();
59extern pirstat  build_pr_queue();
60extern psrstat  pr_start();
61extern psrstat  pr_start2();
62extern pcrstat  pr_cancel();
63extern pirstat  get_pr_status();
64
65extern struct passwd  *get_password();
66
67#ifdef WTMP
68extern void wlogin();
69#endif
70
71#ifdef USE_YP
72char *find_entry();
73#endif
74
75/*
76**---------------------------------------------------------------------
77**                       Misc. variable definitions
78**---------------------------------------------------------------------
79*/
80
81extern pr_list         printers;
82extern pr_queue        queue;
83
84/*
85**=====================================================================
86**                      C O D E   S E C T I O N                       *
87**=====================================================================
88*/
89
90
91static char no_comment[] = "No comment";
92static char not_supported[] = "Not supported";
93static char pcnfsd_version[] = "@(#)pcnfsd_v2.c	1.2 - rpc.pcnfsd V2.0 (c) 1991 Sun Technology Enterprises, Inc.";
94
95/*ARGSUSED*/
96void *pcnfsd2_null_2_svc(arg, req)
97void*arg;
98struct svc_req *req;
99{
100static char dummy;
101return((void *)&dummy);
102}
103
104v2_auth_results *pcnfsd2_auth_2_svc(arg, req)
105v2_auth_args *arg;
106struct svc_req *req;
107{
108static v2_auth_results  r;
109
110char            uname[32];
111char            pw[64];
112int             c1, c2;
113struct passwd  *p;
114static u_int           extra_gids[EXTRAGIDLEN];
115static char     home[256];
116#ifdef USE_YP
117char           *yphome;
118char           *cp;
119#endif /*USE_YP*/
120
121
122	r.stat = AUTH_RES_FAIL;	/* assume failure */
123	r.uid = (int)-2;
124	r.gid = (int)-2;
125	r.cm = &no_comment[0];
126	r.gids.gids_len = 0;
127	r.gids.gids_val = &extra_gids[0];
128	home[0] = '\0';
129	r.home = &home[0];
130	r.def_umask = umask(0);
131	(void)umask(r.def_umask);	/* or use 022 */
132
133	scramble(arg->id, uname);
134	scramble(arg->pw, pw);
135
136#ifdef USER_CACHE
137	if(check_cache(uname, pw, &r.uid, &r.gid)) {
138		 r.stat = AUTH_RES_OK;
139#ifdef WTMP
140		wlogin(uname, req);
141#endif
142                 fillin_extra_groups
143			(uname, r.gid, &r.gids.gids_len, extra_gids);
144#ifdef USE_YP
145		yphome = find_entry(uname, "auto.home");
146		if(yphome) {
147			strcpy(home, yphome);
148			free(yphome);
149			cp = strchr(home, ':');
150			cp++;
151			cp = strchr(cp, ':');
152			if(cp)
153				*cp = '/';
154		}
155#endif
156		 return (&r);
157   }
158#endif
159
160	p = get_password(uname);
161	if (p == (struct passwd *)NULL)
162	   return (&r);
163
164	c1 = strlen(pw);
165	c2 = strlen(p->pw_passwd);
166	if ((c1 && !c2) || (c2 && !c1) ||
167	   (strcmp(p->pw_passwd, crypt(pw, p->pw_passwd))))
168           {
169	   return (&r);
170	   }
171	r.stat = AUTH_RES_OK;
172	r.uid = p->pw_uid;
173	r.gid = p->pw_gid;
174#ifdef WTMP
175	wlogin(uname, req);
176#endif
177        fillin_extra_groups(uname, r.gid, &r.gids.gids_len, extra_gids);
178
179#ifdef USE_YP
180	yphome = find_entry(uname, "auto.home");
181	if(yphome) {
182		strcpy(home, yphome);
183		free(yphome);
184		cp = strchr(home, ':');
185		cp++;
186		cp = strchr(cp, ':');
187		if(cp)
188			*cp = '/';
189	}
190#endif
191
192#ifdef USER_CACHE
193	add_cache_entry(p);
194#endif
195
196return(&r);
197
198}
199
200v2_pr_init_results *pcnfsd2_pr_init_2_svc(arg, req)
201v2_pr_init_args *arg;
202struct svc_req *req;
203{
204static v2_pr_init_results res;
205
206	res.stat =
207	 (pirstat) pr_init(arg->system, arg->pn, &res.dir);
208	res.cm = &no_comment[0];
209
210
211return(&res);
212}
213
214v2_pr_start_results *pcnfsd2_pr_start_2_svc(arg, req)
215v2_pr_start_args *arg;
216struct svc_req *req;
217{
218static v2_pr_start_results res;
219
220	res.stat =
221	  (psrstat) pr_start2(arg->system, arg->pn, arg->user,
222	  arg ->file, arg->opts, &res.id);
223	res.cm = &no_comment[0];
224
225return(&res);
226}
227
228/*ARGSUSED*/
229v2_pr_list_results *pcnfsd2_pr_list_2_svc(arg, req)
230void *arg;
231struct svc_req *req;
232{
233static v2_pr_list_results res;
234
235	if(printers == NULL)
236		(void)build_pr_list();
237	res.cm = &no_comment[0];
238	res.printers = printers;
239
240return(&res);
241}
242
243v2_pr_queue_results *pcnfsd2_pr_queue_2_svc(arg, req)
244v2_pr_queue_args *arg;
245struct svc_req *req;
246{
247static v2_pr_queue_results res;
248
249	res.stat = build_pr_queue(arg->pn, arg->user,
250		arg->just_mine, &res.qlen, &res.qshown);
251	res.cm = &no_comment[0];
252	res.just_yours = arg->just_mine;
253	res.jobs = queue;
254
255
256return(&res);
257}
258
259v2_pr_status_results *pcnfsd2_pr_status_2_svc(arg, req)
260v2_pr_status_args *arg;
261struct svc_req *req;
262{
263static v2_pr_status_results res;
264static char status[128];
265
266	res.stat = get_pr_status(arg->pn, &res.avail, &res.printing,
267		&res.qlen, &res.needs_operator, &status[0]);
268	res.status = &status[0];
269	res.cm = &no_comment[0];
270
271return(&res);
272}
273
274v2_pr_cancel_results *pcnfsd2_pr_cancel_2_svc(arg, req)
275v2_pr_cancel_args *arg;
276struct svc_req *req;
277{
278static v2_pr_cancel_results res;
279
280	res.stat = pr_cancel(arg->pn, arg->user, arg->id);
281	res.cm = &no_comment[0];
282
283return(&res);
284}
285
286/*ARGSUSED*/
287v2_pr_requeue_results *pcnfsd2_pr_requeue_2_svc(arg, req)
288v2_pr_requeue_args *arg;
289struct svc_req *req;
290{
291static v2_pr_requeue_results res;
292	res.stat = PC_RES_FAIL;
293	res.cm = &not_supported[0];
294
295return(&res);
296}
297
298/*ARGSUSED*/
299v2_pr_hold_results *pcnfsd2_pr_hold_2_svc(arg, req)
300v2_pr_hold_args *arg;
301struct svc_req *req;
302{
303static v2_pr_hold_results res;
304
305	res.stat = PC_RES_FAIL;
306	res.cm = &not_supported[0];
307
308return(&res);
309}
310
311/*ARGSUSED*/
312v2_pr_release_results *pcnfsd2_pr_release_2_svc(arg, req)
313v2_pr_release_args *arg;
314struct svc_req *req;
315{
316static v2_pr_release_results res;
317
318	res.stat = PC_RES_FAIL;
319	res.cm = &not_supported[0];
320
321return(&res);
322}
323
324/*ARGSUSED*/
325v2_pr_admin_results *pcnfsd2_pr_admin_2_svc(arg, req)
326v2_pr_admin_args *arg;
327struct svc_req *req;
328{
329static v2_pr_admin_results res;
330/*
331** The default action for admin is to fail.
332** If someone wishes to implement an administration
333** mechanism, and isn't worried about the security
334** holes, go right ahead.
335*/
336
337	res.cm = &not_supported[0];
338	res.stat = PI_RES_FAIL;
339
340return(&res);
341}
342
343void
344free_mapreq_results(p)
345mapreq_res p;
346{
347	if(p->mapreq_next)
348		free_mapreq_results(p->mapreq_next); /* recurse */
349	if(p->name)
350		(void)free(p->name);
351	(void)free(p);
352	return;
353}
354
355static char *
356my_strdup(s)
357char *s;
358{
359char *r;
360	r = (char *)grab(strlen(s)+1);
361	strcpy(r, s);
362	return(r);
363}
364
365v2_mapid_results *pcnfsd2_mapid_2_svc(arg, req)
366v2_mapid_args *arg;
367struct svc_req *req;
368{
369static v2_mapid_results res;
370struct passwd *p_passwd;
371struct group  *p_group;
372
373mapreq_arg a;
374mapreq_res next_r;
375mapreq_res last_r = NULL;
376
377
378	if(res.res_list) {
379		free_mapreq_results(res.res_list);
380		res.res_list = NULL;
381	}
382
383	a = arg->req_list;
384	while(a) {
385		next_r = (struct mapreq_res_item *)
386			grab(sizeof(struct mapreq_res_item));
387		next_r->stat = MAP_RES_UNKNOWN;
388		next_r->req = a->req;
389		next_r->id = a->id;
390		next_r->name = NULL;
391		next_r->mapreq_next = NULL;
392
393		if(last_r == NULL)
394			res.res_list = next_r;
395		else
396			last_r->mapreq_next = next_r;
397		last_r = next_r;
398		switch(a->req) {
399		case MAP_REQ_UID:
400			p_passwd = getpwuid((uid_t)a->id);
401			if(p_passwd) {
402				next_r->name = my_strdup(p_passwd->pw_name);
403				next_r->stat = MAP_RES_OK;
404			}
405			break;
406		case MAP_REQ_GID:
407			p_group = getgrgid((gid_t)a->id);
408			if(p_group) {
409				next_r->name = my_strdup(p_group->gr_name);
410				next_r->stat = MAP_RES_OK;
411			}
412			break;
413		case MAP_REQ_UNAME:
414			next_r->name = my_strdup(a->name);
415			p_passwd = getpwnam(a->name);
416			if(p_passwd) {
417				next_r->id = p_passwd->pw_uid;
418				next_r->stat = MAP_RES_OK;
419			}
420			break;
421		case MAP_REQ_GNAME:
422			next_r->name = my_strdup(a->name);
423			p_group = getgrnam(a->name);
424			if(p_group) {
425				next_r->id = p_group->gr_gid;
426				next_r->stat = MAP_RES_OK;
427			}
428			break;
429		}
430		if(next_r->name == NULL)
431			next_r->name = my_strdup("");
432		a = a->mapreq_next;
433	}
434
435	res.cm = &no_comment[0];
436
437return(&res);
438}
439
440
441/*ARGSUSED*/
442v2_alert_results *pcnfsd2_alert_2_svc(arg, req)
443v2_alert_args *arg;
444struct svc_req *req;
445{
446static v2_alert_results res;
447
448	res.stat = ALERT_RES_FAIL;
449	res.cm = &not_supported[0];
450
451return(&res);
452}
453
454/*ARGSUSED*/
455v2_info_results *pcnfsd2_info_2_svc(arg, req)
456v2_info_args *arg;
457struct svc_req *req;
458{
459static v2_info_results res;
460static int facilities[FACILITIESMAX];
461static int onetime = 1;
462
463#define UNSUPPORTED -1
464#define QUICK 100
465#define SLOW 2000
466
467	if(onetime) {
468		onetime = 0;
469		facilities[PCNFSD2_NULL] = QUICK;
470		facilities[PCNFSD2_INFO] = QUICK;
471		facilities[PCNFSD2_PR_INIT] = QUICK;
472		facilities[PCNFSD2_PR_START] = SLOW;
473		facilities[PCNFSD2_PR_LIST] = QUICK; /* except first time */
474		facilities[PCNFSD2_PR_QUEUE] = SLOW;
475		facilities[PCNFSD2_PR_STATUS] = SLOW;
476		facilities[PCNFSD2_PR_CANCEL] = SLOW;
477		facilities[PCNFSD2_PR_ADMIN] = UNSUPPORTED;
478		facilities[PCNFSD2_PR_REQUEUE] = UNSUPPORTED;
479		facilities[PCNFSD2_PR_HOLD] = UNSUPPORTED;
480		facilities[PCNFSD2_PR_RELEASE] = UNSUPPORTED;
481		facilities[PCNFSD2_MAPID] = QUICK;
482		facilities[PCNFSD2_AUTH] = QUICK;
483		facilities[PCNFSD2_ALERT] = QUICK;
484	}
485	res.facilities.facilities_len = PCNFSD2_ALERT+1;
486	res.facilities.facilities_val = facilities;
487
488	res.vers = &pcnfsd_version[0];
489	res.cm = &no_comment[0];
490
491return(&res);
492}
493
494
495
496void
497fillin_extra_groups(uname, main_gid, len, extra_gids)
498char *uname;
499u_int main_gid;
500int *len;
501u_int extra_gids[EXTRAGIDLEN];
502{
503struct group *grp;
504char **members;
505int n = 0;
506
507	setgrent();
508
509	while(n < EXTRAGIDLEN) {
510		grp = getgrent();
511		if(grp == NULL)
512			break;
513		if(grp->gr_gid == main_gid)
514			continue;
515		for(members = grp->gr_mem; members && *members; members++) {
516			if(!strcmp(*members, uname)) {
517				extra_gids[n++] = grp->gr_gid;
518				break;
519			}
520		}
521	}
522	endgrent();
523	*len = n;
524}
525
526#ifdef USE_YP
527/* the following is from rpcsvc/yp_prot.h */
528#define YPMAXDOMAIN 64
529/*
530 * find_entry returns NULL on any error (printing a message) and
531 * otherwise returns a pointer to the malloc'd result. The caller
532 * is responsible for free()ing the result string.
533 */
534char *
535find_entry(key, map)
536char *key;
537char *map;
538{
539	int err;
540	char *val = NULL;
541	char *cp;
542	int len = 0;
543	static char domain[YPMAXDOMAIN+1];
544
545	if(getdomainname(domain, YPMAXDOMAIN) ) {
546		msg_out("rpc.pcnfsd: getdomainname failed");
547		return(NULL);
548	}
549
550	if (err = yp_bind(domain)) {
551#ifdef	DEBUG
552		msg_out("rpc.pcnfsd: yp_bind failed");
553#endif
554		return(NULL);
555	}
556
557	err = yp_match(domain, map, key, strlen(key), &val, &len);
558
559	if (err) {
560		msg_out("rpc.pcnfsd: yp_match failed");
561		return(NULL);
562	}
563
564	if(cp = strchr(val, '\n'))
565			*cp = '\0';		/* in case we get an extra NL at the end */
566	return(val);
567}
568
569#endif
570