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