xref: /netbsd-src/usr.sbin/rpc.pcnfsd/pcnfsd_v2.c (revision fdecd6a253f999ae92b139670d9e15cc9df4497c)
1 /*	$NetBSD: pcnfsd_v2.c,v 1.5 1997/05/21 07:20:13 lukem 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 
54 void            fillin_extra_groups();
55 extern void     scramble();
56 extern void    *grab();
57 extern char    *crypt();
58 extern int      build_pr_list();
59 extern pirstat  build_pr_queue();
60 extern psrstat  pr_start();
61 extern psrstat  pr_start2();
62 extern pcrstat  pr_cancel();
63 extern pirstat  get_pr_status();
64 
65 extern struct passwd  *get_password();
66 
67 #ifdef WTMP
68 extern void wlogin();
69 #endif
70 
71 #ifdef USE_YP
72 char *find_entry();
73 #endif
74 
75 /*
76 **---------------------------------------------------------------------
77 **                       Misc. variable definitions
78 **---------------------------------------------------------------------
79 */
80 
81 extern pr_list         printers;
82 extern pr_queue        queue;
83 
84 /*
85 **=====================================================================
86 **                      C O D E   S E C T I O N                       *
87 **=====================================================================
88 */
89 
90 
91 static char no_comment[] = "No comment";
92 static char not_supported[] = "Not supported";
93 static char pcnfsd_version[] = "@(#)pcnfsd_v2.c	1.2 - rpc.pcnfsd V2.0 (c) 1991 Sun Technology Enterprises, Inc.";
94 
95 /*ARGSUSED*/
96 void *pcnfsd2_null_2_svc(arg, req)
97 void*arg;
98 struct svc_req *req;
99 {
100 static char dummy;
101 return((void *)&dummy);
102 }
103 
104 v2_auth_results *pcnfsd2_auth_2_svc(arg, req)
105 v2_auth_args *arg;
106 struct svc_req *req;
107 {
108 static v2_auth_results  r;
109 
110 char            uname[32];
111 char            pw[64];
112 int             c1, c2;
113 struct passwd  *p;
114 static u_int           extra_gids[EXTRAGIDLEN];
115 static char     home[256];
116 #ifdef USE_YP
117 char           *yphome;
118 char           *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 
196 return(&r);
197 
198 }
199 
200 v2_pr_init_results *pcnfsd2_pr_init_2_svc(arg, req)
201 v2_pr_init_args *arg;
202 struct svc_req *req;
203 {
204 static 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 
211 return(&res);
212 }
213 
214 v2_pr_start_results *pcnfsd2_pr_start_2_svc(arg, req)
215 v2_pr_start_args *arg;
216 struct svc_req *req;
217 {
218 static 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 
225 return(&res);
226 }
227 
228 /*ARGSUSED*/
229 v2_pr_list_results *pcnfsd2_pr_list_2_svc(arg, req)
230 void *arg;
231 struct svc_req *req;
232 {
233 static 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 
240 return(&res);
241 }
242 
243 v2_pr_queue_results *pcnfsd2_pr_queue_2_svc(arg, req)
244 v2_pr_queue_args *arg;
245 struct svc_req *req;
246 {
247 static 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 
256 return(&res);
257 }
258 
259 v2_pr_status_results *pcnfsd2_pr_status_2_svc(arg, req)
260 v2_pr_status_args *arg;
261 struct svc_req *req;
262 {
263 static v2_pr_status_results res;
264 static 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 
271 return(&res);
272 }
273 
274 v2_pr_cancel_results *pcnfsd2_pr_cancel_2_svc(arg, req)
275 v2_pr_cancel_args *arg;
276 struct svc_req *req;
277 {
278 static v2_pr_cancel_results res;
279 
280 	res.stat = pr_cancel(arg->pn, arg->user, arg->id);
281 	res.cm = &no_comment[0];
282 
283 return(&res);
284 }
285 
286 /*ARGSUSED*/
287 v2_pr_requeue_results *pcnfsd2_pr_requeue_2_svc(arg, req)
288 v2_pr_requeue_args *arg;
289 struct svc_req *req;
290 {
291 static v2_pr_requeue_results res;
292 	res.stat = PC_RES_FAIL;
293 	res.cm = &not_supported[0];
294 
295 return(&res);
296 }
297 
298 /*ARGSUSED*/
299 v2_pr_hold_results *pcnfsd2_pr_hold_2_svc(arg, req)
300 v2_pr_hold_args *arg;
301 struct svc_req *req;
302 {
303 static v2_pr_hold_results res;
304 
305 	res.stat = PC_RES_FAIL;
306 	res.cm = &not_supported[0];
307 
308 return(&res);
309 }
310 
311 /*ARGSUSED*/
312 v2_pr_release_results *pcnfsd2_pr_release_2_svc(arg, req)
313 v2_pr_release_args *arg;
314 struct svc_req *req;
315 {
316 static v2_pr_release_results res;
317 
318 	res.stat = PC_RES_FAIL;
319 	res.cm = &not_supported[0];
320 
321 return(&res);
322 }
323 
324 /*ARGSUSED*/
325 v2_pr_admin_results *pcnfsd2_pr_admin_2_svc(arg, req)
326 v2_pr_admin_args *arg;
327 struct svc_req *req;
328 {
329 static 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 
340 return(&res);
341 }
342 
343 void
344 free_mapreq_results(p)
345 mapreq_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 
355 static char *
356 my_strdup(s)
357 char *s;
358 {
359 char *r;
360 	r = (char *)grab(strlen(s)+1);
361 	strcpy(r, s);
362 	return(r);
363 }
364 
365 v2_mapid_results *pcnfsd2_mapid_2_svc(arg, req)
366 v2_mapid_args *arg;
367 struct svc_req *req;
368 {
369 static v2_mapid_results res;
370 struct passwd *p_passwd;
371 struct group  *p_group;
372 
373 mapreq_arg a;
374 mapreq_res next_r;
375 mapreq_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 
437 return(&res);
438 }
439 
440 
441 /*ARGSUSED*/
442 v2_alert_results *pcnfsd2_alert_2_svc(arg, req)
443 v2_alert_args *arg;
444 struct svc_req *req;
445 {
446 static v2_alert_results res;
447 
448 	res.stat = ALERT_RES_FAIL;
449 	res.cm = &not_supported[0];
450 
451 return(&res);
452 }
453 
454 /*ARGSUSED*/
455 v2_info_results *pcnfsd2_info_2_svc(arg, req)
456 v2_info_args *arg;
457 struct svc_req *req;
458 {
459 static v2_info_results res;
460 static int facilities[FACILITIESMAX];
461 static 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 
491 return(&res);
492 }
493 
494 
495 
496 void
497 fillin_extra_groups(uname, main_gid, len, extra_gids)
498 char *uname;
499 u_int main_gid;
500 int *len;
501 u_int extra_gids[EXTRAGIDLEN];
502 {
503 struct group *grp;
504 char **members;
505 int 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  */
534 char *
535 find_entry(key, map)
536 char *key;
537 char *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 		if (val)
562 			free(val);
563 		return(NULL);
564 	}
565 
566 	if(cp = strchr(val, '\n'))
567 			*cp = '\0';		/* in case we get an extra NL at the end */
568 	return(val);
569 }
570 
571 #endif
572