Home | History | Annotate | Line # | Download | only in rpc.pcnfsd
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 
     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 		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