pcnfsd_v2.c revision 1.12 1 /* $NetBSD: pcnfsd_v2.c,v 1.12 2011/10/07 10:46:29 joerg 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]);
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