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