No empty .Rs/.Re
[netbsd-mini2440.git] / usr.sbin / rpc.pcnfsd / pcnfsd_v2.c
blob63b9845b9fd4e136127ad9741f89bc77758aff49
1 /* $NetBSD: pcnfsd_v2.c,v 1.9 2003/07/16 08:22:01 itojun Exp $ */
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 */
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 **=====================================================================
20 #include <sys/file.h>
21 #include <sys/ioctl.h>
22 #include <sys/stat.h>
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>
33 #ifdef USE_YP
34 #include <rpcsvc/ypclnt.h>
35 #endif
37 #ifndef SYSV
38 #include <sys/wait.h>
39 #endif
41 #ifdef ISC_2_0
42 #include <sys/fcntl.h>
43 #endif
45 #ifdef SHADOW_SUPPORT
46 #include <shadow.h>
47 #endif
49 #include "common.h"
50 #include "pcnfsd.h"
51 #include "extern.h"
54 **=====================================================================
55 ** C O D E S E C T I O N *
56 **=====================================================================
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.";
64 /*ARGSUSED*/
65 void *
66 pcnfsd2_null_2_svc(arg, req)
67 void *arg;
68 struct svc_req *req;
70 static char dummy;
71 return ((void *) &dummy);
74 v2_auth_results *
75 pcnfsd2_auth_2_svc(arg, req)
76 v2_auth_args *arg;
77 struct svc_req *req;
79 static v2_auth_results r;
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 */
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 */
104 scramble(arg->id, uname);
105 scramble(arg->pw, pw);
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 = '/';
126 #endif
127 return (&r);
129 #endif
131 p = get_password(uname);
132 if (p == (struct passwd *) NULL)
133 return (&r);
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);
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);
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 = '/';
160 #endif
162 #ifdef USER_CACHE
163 add_cache_entry(p);
164 #endif
166 return (&r);
170 v2_pr_init_results *
171 pcnfsd2_pr_init_2_svc(arg, req)
172 v2_pr_init_args *arg;
173 struct svc_req *req;
175 static v2_pr_init_results res;
177 res.stat =
178 (pirstat) pr_init(arg->system, arg->pn, &res.dir);
179 res.cm = &no_comment[0];
182 return (&res);
185 v2_pr_start_results *
186 pcnfsd2_pr_start_2_svc(arg, req)
187 v2_pr_start_args *arg;
188 struct svc_req *req;
190 static v2_pr_start_results res;
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];
197 return (&res);
199 /*ARGSUSED*/
200 v2_pr_list_results *
201 pcnfsd2_pr_list_2_svc(arg, req)
202 void *arg;
203 struct svc_req *req;
205 static v2_pr_list_results res;
207 if (printers == NULL)
208 (void) build_pr_list();
209 res.cm = &no_comment[0];
210 res.printers = printers;
212 return (&res);
215 v2_pr_queue_results *
216 pcnfsd2_pr_queue_2_svc(arg, req)
217 v2_pr_queue_args *arg;
218 struct svc_req *req;
220 static v2_pr_queue_results res;
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;
229 return (&res);
232 v2_pr_status_results *
233 pcnfsd2_pr_status_2_svc(arg, req)
234 v2_pr_status_args *arg;
235 struct svc_req *req;
237 static v2_pr_status_results res;
238 static char status[128];
240 res.stat = get_pr_status(arg->pn, &res.avail, &res.printing,
241 &res.qlen, &res.needs_operator, &status[0]);
242 res.status = &status[0];
243 res.cm = &no_comment[0];
245 return (&res);
248 v2_pr_cancel_results *
249 pcnfsd2_pr_cancel_2_svc(arg, req)
250 v2_pr_cancel_args *arg;
251 struct svc_req *req;
253 static v2_pr_cancel_results res;
255 res.stat = pr_cancel(arg->pn, arg->user, arg->id);
256 res.cm = &no_comment[0];
258 return (&res);
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;
266 static v2_pr_requeue_results res;
267 res.stat = PC_RES_FAIL;
268 res.cm = &not_supported[0];
270 return (&res);
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;
278 static v2_pr_hold_results res;
280 res.stat = PC_RES_FAIL;
281 res.cm = &not_supported[0];
283 return (&res);
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;
291 static v2_pr_release_results res;
293 res.stat = PC_RES_FAIL;
294 res.cm = &not_supported[0];
296 return (&res);
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;
304 static v2_pr_admin_results res;
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.
312 res.cm = &not_supported[0];
313 res.stat = PI_RES_FAIL;
315 return (&res);
318 void
319 free_mapreq_results(p)
320 mapreq_res p;
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;
330 static char *my_strdup __P((const char *));
332 static char *
333 my_strdup(s)
334 const char *s;
336 char *r;
337 r = (char *) grab(strlen(s) + 1);
338 strlcpy(r, s, strlen(s) + 1);
339 return (r);
342 v2_mapid_results *
343 pcnfsd2_mapid_2_svc(arg, req)
344 v2_mapid_args *arg;
345 struct svc_req *req;
347 static v2_mapid_results res;
348 struct passwd *p_passwd;
349 struct group *p_group;
351 mapreq_arg a;
352 mapreq_res next_r;
353 mapreq_res last_r = NULL;
356 if (res.res_list) {
357 free_mapreq_results(res.res_list);
358 res.res_list = NULL;
360 a = arg->req_list;
361 while (a) {
362 next_r = (struct mapreq_res_item *)
363 grab(sizeof(struct mapreq_res_item));
364 next_r->stat = MAP_RES_UNKNOWN;
365 next_r->req = a->req;
366 next_r->id = a->id;
367 next_r->name = NULL;
368 next_r->mapreq_next = NULL;
370 if (last_r == NULL)
371 res.res_list = next_r;
372 else
373 last_r->mapreq_next = next_r;
374 last_r = next_r;
375 switch (a->req) {
376 case MAP_REQ_UID:
377 p_passwd = getpwuid((uid_t) a->id);
378 if (p_passwd) {
379 next_r->name = my_strdup(p_passwd->pw_name);
380 next_r->stat = MAP_RES_OK;
382 break;
383 case MAP_REQ_GID:
384 p_group = getgrgid((gid_t) a->id);
385 if (p_group) {
386 next_r->name = my_strdup(p_group->gr_name);
387 next_r->stat = MAP_RES_OK;
389 break;
390 case MAP_REQ_UNAME:
391 next_r->name = my_strdup(a->name);
392 p_passwd = getpwnam(a->name);
393 if (p_passwd) {
394 next_r->id = p_passwd->pw_uid;
395 next_r->stat = MAP_RES_OK;
397 break;
398 case MAP_REQ_GNAME:
399 next_r->name = my_strdup(a->name);
400 p_group = getgrnam(a->name);
401 if (p_group) {
402 next_r->id = p_group->gr_gid;
403 next_r->stat = MAP_RES_OK;
405 break;
407 if (next_r->name == NULL)
408 next_r->name = my_strdup("");
409 a = a->mapreq_next;
412 res.cm = &no_comment[0];
414 return (&res);
418 /*ARGSUSED*/
419 v2_alert_results *
420 pcnfsd2_alert_2_svc(arg, req)
421 v2_alert_args *arg;
422 struct svc_req *req;
424 static v2_alert_results res;
426 res.stat = ALERT_RES_FAIL;
427 res.cm = &not_supported[0];
429 return (&res);
431 /*ARGSUSED*/
432 v2_info_results *
433 pcnfsd2_info_2_svc(arg, req)
434 v2_info_args *arg;
435 struct svc_req *req;
437 static v2_info_results res;
438 static int facilities[FACILITIESMAX];
439 static int onetime = 1;
441 #define UNSUPPORTED -1
442 #define QUICK 100
443 #define SLOW 2000
445 if (onetime) {
446 onetime = 0;
447 facilities[PCNFSD2_NULL] = QUICK;
448 facilities[PCNFSD2_INFO] = QUICK;
449 facilities[PCNFSD2_PR_INIT] = QUICK;
450 facilities[PCNFSD2_PR_START] = SLOW;
451 facilities[PCNFSD2_PR_LIST] = QUICK; /* except first time */
452 facilities[PCNFSD2_PR_QUEUE] = SLOW;
453 facilities[PCNFSD2_PR_STATUS] = SLOW;
454 facilities[PCNFSD2_PR_CANCEL] = SLOW;
455 facilities[PCNFSD2_PR_ADMIN] = UNSUPPORTED;
456 facilities[PCNFSD2_PR_REQUEUE] = UNSUPPORTED;
457 facilities[PCNFSD2_PR_HOLD] = UNSUPPORTED;
458 facilities[PCNFSD2_PR_RELEASE] = UNSUPPORTED;
459 facilities[PCNFSD2_MAPID] = QUICK;
460 facilities[PCNFSD2_AUTH] = QUICK;
461 facilities[PCNFSD2_ALERT] = QUICK;
463 res.facilities.facilities_len = PCNFSD2_ALERT + 1;
464 res.facilities.facilities_val = facilities;
466 res.vers = &pcnfsd_version[0];
467 res.cm = &no_comment[0];
469 return (&res);
474 void
475 fillin_extra_groups(uname, main_gid, len, extra_gids)
476 char *uname;
477 gid_t main_gid;
478 int *len;
479 gid_t extra_gids[EXTRAGIDLEN];
481 struct group *grp;
482 __aconst char *__aconst *members;
483 int n = 0;
485 setgrent();
487 while (n < EXTRAGIDLEN) {
488 grp = getgrent();
489 if (grp == NULL)
490 break;
491 if (grp->gr_gid == main_gid)
492 continue;
493 for (members = grp->gr_mem; members && *members; members++) {
494 if (!strcmp(*members, uname)) {
495 extra_gids[n++] = grp->gr_gid;
496 break;
500 endgrent();
501 *len = n;
504 #ifdef USE_YP
505 /* the following is from rpcsvc/yp_prot.h */
506 #define YPMAXDOMAIN 64
509 * find_entry returns NULL on any error (printing a message) and
510 * otherwise returns a pointer to the malloc'd result. The caller
511 * is responsible for free()ing the result string.
513 char *
514 find_entry(key, map)
515 const char *key;
516 const char *map;
518 int err;
519 char *val = NULL;
520 char *cp;
521 int len = 0;
522 static char domain[YPMAXDOMAIN + 1];
524 if (getdomainname(domain, YPMAXDOMAIN)) {
525 msg_out("rpc.pcnfsd: getdomainname failed");
526 return (NULL);
528 if ((err = yp_bind(domain)) != 0) {
529 #ifdef DEBUG
530 msg_out("rpc.pcnfsd: yp_bind failed");
531 #endif
532 return (NULL);
534 err = yp_match(domain, map, key, strlen(key), &val, &len);
536 if (err) {
537 msg_out("rpc.pcnfsd: yp_match failed");
538 if (val)
539 free(val);
540 return (NULL);
542 if ((cp = strchr(val, '\n')) != NULL)
543 *cp = '\0'; /* in case we get an extra NL at the end */
544 return (val);
546 #endif