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