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