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