pcnfsd_v2.c revision 1.10 1 /* $NetBSD: pcnfsd_v2.c,v 1.10 2009/04/18 13:02:36 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 /*
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 == (struct passwd *) 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]);
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 char *r;
337 r = (char *) grab(strlen(s) + 1);
338 strlcpy(r, s, strlen(s) + 1);
339 return (r);
340 }
341
342 v2_mapid_results *
343 pcnfsd2_mapid_2_svc(arg, req)
344 v2_mapid_args *arg;
345 struct svc_req *req;
346 {
347 static v2_mapid_results res;
348 struct passwd *p_passwd;
349 struct group *p_group;
350
351 mapreq_arg a;
352 mapreq_res next_r;
353 mapreq_res last_r = NULL;
354
355
356 if (res.res_list) {
357 free_mapreq_results(res.res_list);
358 res.res_list = NULL;
359 }
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;
369
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;
381 }
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;
388 }
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;
396 }
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;
404 }
405 break;
406 }
407 if (next_r->name == NULL)
408 next_r->name = my_strdup("");
409 a = a->mapreq_next;
410 }
411
412 res.cm = &no_comment[0];
413
414 return (&res);
415 }
416
417
418 /*ARGSUSED*/
419 v2_alert_results *
420 pcnfsd2_alert_2_svc(arg, req)
421 v2_alert_args *arg;
422 struct svc_req *req;
423 {
424 static v2_alert_results res;
425
426 res.stat = ALERT_RES_FAIL;
427 res.cm = ¬_supported[0];
428
429 return (&res);
430 }
431 /*ARGSUSED*/
432 v2_info_results *
433 pcnfsd2_info_2_svc(arg, req)
434 v2_info_args *arg;
435 struct svc_req *req;
436 {
437 static v2_info_results res;
438 static int facilities[FACILITIESMAX];
439 static int onetime = 1;
440
441 #define UNSUPPORTED -1
442 #define QUICK 100
443 #define SLOW 2000
444
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;
462 }
463 res.facilities.facilities_len = PCNFSD2_ALERT + 1;
464 res.facilities.facilities_val = facilities;
465
466 res.vers = &pcnfsd_version[0];
467 res.cm = &no_comment[0];
468
469 return (&res);
470 }
471
472
473
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];
480 {
481 struct group *grp;
482 __aconst char *__aconst *members;
483 int n = 0;
484
485 setgrent();
486
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;
497 }
498 }
499 }
500 endgrent();
501 *len = n;
502 }
503
504 #ifdef USE_YP
505 /* the following is from rpcsvc/yp_prot.h */
506 #define YPMAXDOMAIN 64
507
508 /*
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.
512 */
513 char *
514 find_entry(key, map)
515 const char *key;
516 const char *map;
517 {
518 int err;
519 char *val = NULL;
520 char *cp;
521 int len = 0;
522 static char domain[YPMAXDOMAIN + 1];
523
524 if (getdomainname(domain, YPMAXDOMAIN)) {
525 msg_out("rpc.pcnfsd: getdomainname failed");
526 return (NULL);
527 }
528 if ((err = yp_bind(domain)) != 0) {
529 #ifdef DEBUG
530 msg_out("rpc.pcnfsd: yp_bind failed");
531 #endif
532 return (NULL);
533 }
534 err = yp_match(domain, map, key, strlen(key), &val, &len);
535
536 if (err) {
537 msg_out("rpc.pcnfsd: yp_match failed");
538 if (val)
539 free(val);
540 return (NULL);
541 }
542 if ((cp = strchr(val, '\n')) != NULL)
543 *cp = '\0'; /* in case we get an extra NL at the end */
544 return (val);
545 }
546 #endif
547