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