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