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 = ¬_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 = ¬_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 = ¬_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 = ¬_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 = ¬_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