* krsh.c
[krb5.git] / src / appl / bsd / krshd.c
1 /*
2  *      appl/bsd/krshd.c
3  */
4
5 /*
6  * Copyright (c) 1983 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms are permitted
10  * provided that the above copyright notice and this paragraph are
11  * duplicated in all such forms and that any documentation,
12  * advertising materials, and other materials related to such
13  * distribution and use acknowledge that the software was developed
14  * by the University of California, Berkeley.  The name of the
15  * University may not be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #ifndef lint
23 char copyright[] =
24   "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
25  All rights reserved.\n";
26 #endif /* not lint */
27
28 /* based on @(#)rshd.c  5.12 (Berkeley) 9/12/88 */
29
30      /*
31       * remote shell server:
32       * remuser\0
33       * locuser\0
34       * command\0
35       * data
36       */
37      
38 /*
39  * This is the rshell daemon. The very basic protocol for checking 
40  * authentication and authorization is:
41  * 1) Check authentication.
42  * 2) Check authorization via the access-control files: 
43  *    ~/.k5login (using krb5_kuserok) and/or
44  *    ~/.rhosts  (using ruserok).
45  * Execute command if configured authoriztion checks pass, else deny 
46  * permission.
47  *
48  * The configuration is done either by command-line arguments passed by inetd, 
49  * or by the name of the daemon. If command-line arguments are present, they 
50  * take priority. The options are:
51  * -k and -K means check .k5login (using krb5_kuserok).
52  * -r and -R means check .rhosts  (using ruserok).
53  * The difference between upper and lower case is as follows:
54  *    If lower case -r or -k, then as long as one of krb5_kuserok or ruserok 
55  * passes, allow access. If both fail, no access. The program does not fall
56  * back on password verification.
57  *    If uppercase -R or -K, then those checks must be passed, regardless of 
58  * other checks, else no access.
59  * 
60  *     If no command-line arguments are present, then the presence of the 
61  * letters kKrR in the program-name before "shd" determine the 
62  * behaviour of the program exactly as with the command-line arguments.
63  */
64      
65 /* DEFINES:
66  *   KERBEROS - Define this if application is to be kerberised.
67  *   KRB5_KRB4_COMPAT - Define this if v4 rlogin clients are also to be served.
68  *   ALWAYS_V5_KUSEROK - Define this if you want .k5login to be
69  *              checked even for v4 clients (instead of .klogin).
70  *   LOG_ALL_LOGINS - Define this if you want to log all logins.
71  *   LOG_OTHER_USERS - Define this if you want to log all principals that do
72  *              not map onto the local user.
73  *   LOG_REMOTE_REALM - Define this if you want to log all principals from 
74  *              remote realms.
75  *   LOG_CMD - Define this if you want to log not only the user but also the
76  *             command executed. This only decides the type of information
77  *             logged. Whether or not to log is still decided by the above 
78  *             three DEFINES.
79  *       Note:  Root account access is always logged.
80  */
81      
82 #define SERVE_NON_KRB     
83 #define LOG_REMOTE_REALM
84 #define LOG_CMD
85      
86 #ifdef HAVE_UNISTD_H
87 #include <unistd.h>
88 #endif
89 #ifdef HAVE_STDLIB_H
90 #include <stdlib.h>
91 #endif
92 #ifdef __SCO__
93 #include <sys/unistd.h>
94 #endif
95
96 #include <sys/types.h>
97 #include <sys/ioctl.h>
98 #include <sys/param.h>
99 #include <sys/socket.h>
100 #include <sys/file.h>
101 #include <sys/time.h>
102
103 #include <fcntl.h>
104
105 #ifdef HAVE_SYS_SELECT_H
106 #include <sys/select.h>
107 #endif
108      
109 #include <netinet/in.h>
110 #include <arpa/inet.h>
111      
112 #include <stdio.h>
113 #include <errno.h>
114 #include <pwd.h>
115 #include <ctype.h>
116 #include <string.h>
117      
118 #ifdef HAVE_SYS_LABEL_H
119 /* only SunOS 4? */
120 #include <sys/label.h>
121 #include <sys/audit.h>
122 #include <pwdadj.h>
123 #endif
124      
125 #include <signal.h>
126 #include <netdb.h>
127      
128 #ifdef CRAY
129 #ifndef NO_UDB
130 #include <udb.h>
131 #endif  /* !NO_UDB */
132 #include <sys/category.h>
133 #include <netinet/ip.h>
134 #include <sys/tfm.h>
135 #include <sys/nal.h>
136 #include <sys/secparm.h>
137 #include <sys/usrv.h>
138 #include <sys/utsname.h>
139 #include <sys/sysv.h>
140 #include <sys/slrec.h>
141 #include <sys/unistd.h>
142 #include <path.h>
143 #endif /* CRAY */
144      
145 #include <syslog.h>
146
147 #ifdef POSIX_TERMIOS
148 #include <termios.h>
149 #endif
150      
151 #ifdef HAVE_SYS_FILIO_H
152 /* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
153 #include <sys/filio.h>
154 #endif
155
156 #ifdef KERBEROS
157 #include <krb5/krb5.h>
158 #include <krb5/asn1.h>
159 #include <krb5/crc-32.h>
160 #include <krb5/mit-des.h>
161 #include <krb5/ext-proto.h>
162
163 #include <com_err.h>
164 #include "loginpaths.h"
165
166 #define ARGSTR  "rRxXeEkKD:?"
167
168 #define SECURE_MESSAGE "This rsh session is using DES encryption for all data transmissions.\r\n"
169
170 #ifdef BUFSIZ
171 #undef BUFSIZ
172 #endif
173 #define BUFSIZ 5120
174
175 #define MAXRETRIES 4
176
177 char des_inbuf[2*BUFSIZ];         /* needs to be > largest read size */
178 krb5_encrypt_block eblock;        /* eblock for encrypt/decrypt */
179 char des_outbuf[2*BUFSIZ];        /* needs to be > largest write size */
180 krb5_data desinbuf,desoutbuf;
181
182 void fatal();
183 int v5_des_read();
184 int v5_des_write();
185
186 int (*des_read)() = v5_des_read;
187 int (*des_write)() = v5_des_write;
188
189 int do_encrypt = 0;
190 int netf;
191
192 #else /* !KERBEROS */
193
194 #define ARGSTR  "rRD:?"
195 #define (*des_read)  read
196 #define (*des_write) write
197      
198 #endif /* KERBEROS */
199      
200 #ifndef HAVE_KILLPG
201 #define killpg(pid, sig) kill(-(pid), (sig))
202 #endif
203
204 int must_pass_rhosts = 0, must_pass_k5 = 0, must_pass_one = 0;
205 int failed_k5 = 0;
206 char *progname;
207
208 #define MAX_PROG_NAME 10
209
210 #ifdef CRAY
211 int     secflag;
212 extern
213 #endif /* CRAY */
214 int     errno;
215
216 /*VARARGS1*/
217 int     error();
218
219
220 #ifdef __SCO__
221 /* sco has getgroups and setgroups but no initgroups */
222 int initgroups(char* name, gid_t basegid) {
223   gid_t others[NGROUPS_MAX+1];
224   int ngrps;
225
226   others[0] = basegid;
227   ngrps = getgroups(NGROUPS_MAX, others+1);
228   return setgroups(ngrps+1, others);
229 }
230 #endif
231
232
233 main(argc, argv)
234      int argc;
235      char **argv;
236 {
237 #if defined(BSD) && BSD+0 >= 43
238     struct linger linger;
239 #endif
240     int on = 1, fromlen;
241     struct sockaddr_in from;
242     extern int opterr, optind;
243     extern char *optarg;
244     char *options;
245     int ch;
246     int i;
247     int fd;
248     int debug_port = 0;
249
250 #ifdef CRAY
251     secflag = sysconf(_SC_CRAY_SECURE_SYS);
252 #endif
253     
254     progname = *argv;
255     
256 #ifndef LOG_ODELAY /* 4.2 syslog */
257     openlog(progname, LOG_PID);
258 #else
259 #ifndef LOG_DAEMON
260 #define LOG_DAEMON 0
261 #endif
262     openlog(progname, LOG_PID | LOG_ODELAY, LOG_DAEMON);        
263 #endif /* 4.2 syslog */
264     
265     if (argc == 1) { /* Get parameters from program name. */
266         if (strlen(progname) > MAX_PROG_NAME) {
267             usage();
268             exit(1);
269         }
270         options = (char *) malloc(MAX_PROG_NAME+1);
271         options[0] = '\0';
272         for (i = 0; (progname[i] != '\0') && (i < MAX_PROG_NAME); i++)
273           if (!strcmp(progname+i, "shd")) {
274               strcpy(options, "-");
275               strncat(options, progname, i);
276               options[i+1] = '\0';
277 #if 0
278               /*
279                * Since we are just going to break out afterwards, we'll
280                * re-use the variable "i" to move the command line args.
281                */
282               for (i=argc-1; i>0; i--) argv[i+1] = argv[i];
283 #endif
284               argv[++argc] = NULL;
285
286               argv[1] = options;
287               break;
288           }
289     }
290     
291     /* Analyze parameters. */
292     opterr = 0;
293     while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
294       switch (ch) {
295         case 'r':         
296           must_pass_one = 1; /* If just 'r', any one check must succeed */
297           break;
298         case 'R':         /* If 'R', must pass .rhosts check*/
299           must_pass_rhosts = 1;
300           if (must_pass_one)
301             must_pass_one = 0;
302           break;
303 #ifdef KERBEROS
304         case 'k':
305           must_pass_one = 1; /* If just 'k', any one check must succeed */
306           break;
307         case 'K':         /* If 'K', must pass .k5login check*/
308           must_pass_k5 = 1;
309           if (must_pass_one)
310             must_pass_one = 0;
311           break;
312           
313         case 'x':
314         case 'X':
315         case 'e':
316         case 'E':
317           do_encrypt = 1;
318           break;
319 #endif
320         case 'D':
321           debug_port = atoi(optarg);
322           break;
323         case '?':
324         default:
325           usage();
326           exit(1);
327           break;
328       }
329
330     if (optind == 0) {
331         usage();
332         exit(1);
333     }
334     
335     argc -= optind;
336     argv += optind;
337     
338     fromlen = sizeof (from);
339
340     if (debug_port) {
341         int s;
342         struct sockaddr_in sin;
343         
344         if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
345             fprintf(stderr, "Error in socket: %s\n", strerror(errno));
346             exit(2);
347         }
348         
349         memset((char *) &sin, 0,sizeof(sin));
350         sin.sin_family = AF_INET;
351         sin.sin_port = htons(debug_port);
352         sin.sin_addr.s_addr = INADDR_ANY;
353         
354         if ((bind(s, (struct sockaddr *) &sin, sizeof(sin))) < 0) {
355             fprintf(stderr, "Error in bind: %s\n", strerror(errno));
356             exit(2);
357         }
358         
359         if ((listen(s, 5)) < 0) {
360             fprintf(stderr, "Error in listen: %s\n", strerror(errno));
361             exit(2);
362         }
363         
364         if ((fd = accept(s, &from, &fromlen)) < 0) {
365             fprintf(stderr, "Error in accept: %s\n", strerror(errno));
366             exit(2);
367         }
368         
369         close(s);
370     } else {
371         if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
372             fprintf(stderr, "%s: ", progname);
373             perror("getpeername");
374             _exit(1);
375         }
376         
377         fd = 0;
378     }
379     
380     if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
381                    sizeof (on)) < 0)
382       syslog(LOG_WARNING,
383              "setsockopt (SO_KEEPALIVE): %m");
384 #if defined(BSD) && BSD+0 >= 43
385     linger.l_onoff = 1;
386     linger.l_linger = 60;                       /* XXX */
387     if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&linger,
388                    sizeof (linger)) < 0)
389       syslog(LOG_WARNING , "setsockopt (SO_LINGER): %m");
390 #endif
391     doit(dup(fd), &from);
392 }
393
394 #ifdef CRAY
395 char    username[32] = "LOGNAME=";
396 #include <tmpdir.h>
397 char tmpdir[64] = "TMPDIR=";
398 #else
399 char    username[20] = "USER=";
400 #endif
401
402 char    homedir[64] = "HOME=";
403 char    shell[64] = "SHELL=";
404 char    term[64] = "TERM=network";
405 char    path[128] = "PATH=";
406 char    path_rest[64] = RPATH;
407
408 #ifdef CRAY
409 char    *envinit[] =
410 {homedir, shell, path, username, "TZ=GMT0", tmpdir, term, 0};
411 #define TZENV   4
412 #define TMPDIRENV 5
413 char    *getenv();
414 #else /* CRAY */
415 #ifdef KERBEROS
416 char    *envinit[] =
417 {homedir, shell, path, username, term, 0};
418 #else /* KERBEROS */
419 char    *envinit[] =
420 {homedir, shell, path, username, term, 0};
421 #endif /* KERBEROS */
422 #endif /* CRAY */
423
424 extern char     **environ;
425 char ttyn[12];          /* Line string for wtmp entries */
426
427 #ifdef CRAY
428 #define SIZEOF_INADDR  SIZEOF_in_addr
429 int maxlogs;
430 #else
431 #define SIZEOF_INADDR sizeof(struct in_addr)
432 #endif
433
434 #ifndef NCARGS
435 /* linux doesn't seem to have it... */
436 #define NCARGS 1024
437 #endif
438
439 #define NMAX   16 
440
441 int pid;
442 char locuser[NMAX+1];
443 char remuser[NMAX +1];
444 char cmdbuf[NCARGS+1];
445 char *kremuser;
446 krb5_principal client;
447 krb5_authenticator *kdata;
448
449 #ifdef KRB5_KRB4_COMPAT
450 #include <kerberosIV/krb.h>
451 AUTH_DAT        *v4_kdata;
452 KTEXT           v4_ticket;
453 #endif
454
455 int auth_sys = 0;       /* Which version of Kerberos used to authenticate */
456
457 #define KRB5_RECVAUTH_V4        4
458 #define KRB5_RECVAUTH_V5        5
459
460 doit(f, fromp)
461      int f;
462      struct sockaddr_in *fromp;
463 {
464     char *cp;
465     
466 #ifdef KERBEROS
467     krb5_address peeraddr;
468     krb5_error_code status;
469 #endif
470
471     int tmpint;
472     
473     int ioctlval, cnt;
474     char *salt, *ttynm, *tty;
475     register char *p;
476     char *crypt();
477     struct passwd *pwd;
478     
479 #ifdef CRAY
480 #ifndef NO_UDB
481     struct udb    *ue;
482     struct udb ue_static;
483     extern struct udb *getudbnam();
484 #endif
485     extern struct passwd *getpwnam(), *getpwuid();
486     static int      jid;
487     int error();
488     int paddr;
489     struct  nal nal;
490     int     nal_error;
491     struct usrv usrv;
492     struct  sysv sysv;
493     char    *makejtmp(), *jtmpnam = 0;
494     int packet_level;               /* Packet classification level */
495     long packet_compart;            /* Packet compartments */
496 #endif  /* CRAY */
497     
498     int s;
499     struct hostent *hp;
500     char *hostname;
501     short port;
502     int pv[2], pw[2], px[2], cc;
503     fd_set ready, readfrom;
504     char buf[BUFSIZ], sig;
505     int one = 1;
506     krb5_sigtype     cleanup();
507     int fd;
508     struct sockaddr_in fromaddr;
509     int non_privileged = 0;
510 #ifdef POSIX_SIGNALS
511     struct sigaction sa;
512 #endif
513
514 #ifdef IP_TOS
515 /* solaris has IP_TOS, but only IPTOS_* values */
516 #ifdef HAVE_GETTOSBYNAME
517     struct tosent *tp;
518
519     if ((tp = gettosbyname("interactive", "tcp")) &&
520         (setsockopt(f, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
521 #ifdef  TOS_WARN
522       syslog(LOG_NOTICE, "setsockopt (IP_TOS): %m");
523 #else
524     ;       /* silently ignore TOS errors in 6E */
525 #endif
526 #endif
527 #endif /* IP_TOS */
528     
529     fromaddr = *fromp;
530
531 #ifdef POSIX_SIGNALS
532     (void)sigemptyset(&sa.sa_mask);
533     sa.sa_flags = 0;
534     sa.sa_handler = SIG_DFL;
535     (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
536     (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
537     (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
538 #else
539     signal(SIGINT, SIG_DFL);
540     signal(SIGQUIT, SIG_DFL);
541     signal(SIGTERM, SIG_DFL);
542 #endif
543 #ifdef DEBUG
544     { int t = open("/dev/tty", 2);
545       if (t >= 0) {
546           ioctl(t, TIOCNOTTY, (char *)0);
547           (void) close(t);
548       }
549   }
550 #endif
551     fromp->sin_port = ntohs((u_short)fromp->sin_port);
552     if (fromp->sin_family != AF_INET) {
553         syslog(LOG_ERR , "malformed from address\n");
554         exit(1);
555     }
556 #ifdef KERBEROS
557     krb5_init_ets();
558     netf = f;
559     desinbuf.data = des_inbuf;
560     desoutbuf.data = des_outbuf;
561     if ((must_pass_rhosts || must_pass_one)
562         && (fromp->sin_port >= IPPORT_RESERVED ||
563             fromp->sin_port < IPPORT_RESERVED/2))
564       non_privileged = 1;
565 #else
566     if (fromp->sin_port >= IPPORT_RESERVED ||
567             fromp->sin_port < IPPORT_RESERVED/2) {
568         syslog(LOG_ERR , "connection from bad port\n");
569         exit(1);
570     }
571 #endif /* KERBEROS */
572     
573 #ifdef CRAY
574     
575     /* If this is a secure system then get the packet classification
576        of f.  ( Note IP_SECURITY is checked in get_packet_classification:
577        if it's not set then the user's (root) default
578        classification level and compartments are returned. )
579        Then set this process to that level/compart so that the stderr
580        connection will be labeled appropriately.
581        */
582     if (secflag) {
583         if (get_packet_classification(f,getuid(),
584                                       &packet_level,&packet_compart) < 0) {
585             syslog(LOG_ERR, "cannot get ip packet level\n");
586             exit(1);
587         }
588         if(secflag == TFM_UDB_5) {
589             if(setucmp(packet_compart, C_PROC) != 0) {
590                 error("Unable to setucmp.\n");
591                 exit(1);
592             }
593         } else if(secflag == TFM_UDB_6) {
594             if(setulvl(packet_level,C_PROC) != 0) {
595                 error("Unable to setulvl.\n");
596                 exit(1);
597             }
598             if(setucmp(packet_compart, C_PROC) != 0) {
599                 error("Unable to setucmp.\n");
600                 exit(1);
601             }
602         }
603         
604     }
605 #endif /* CRAY */
606     
607     (void) alarm(60);
608     port = 0;
609     for (;;) {
610         char c;
611         if ((cc = read(f, &c, 1)) != 1) {
612             if (cc < 0)
613               syslog(LOG_NOTICE , "read: %m");
614             shutdown(f, 1+1);
615             exit(1);
616         }
617         if (c == 0)
618           break;
619         port = port * 10 + c - '0';
620     }
621     (void) alarm(0);
622     if (port != 0) {
623         int lport = IPPORT_RESERVED - 1;
624         s = rresvport(&lport);
625         if (s < 0) {
626             syslog(LOG_ERR ,
627                    "can't get stderr port: %m");
628             exit(1);
629         }
630 #ifdef KERBEROS
631         if ((must_pass_rhosts || must_pass_one)
632             && port >= IPPORT_RESERVED)
633           non_privileged = 1;
634 #else
635         if (port >= IPPORT_RESERVED) {
636             syslog(LOG_ERR , "2nd port not reserved\n");
637             exit(1);
638         }
639 #endif /* KERBEROS */
640         fromp->sin_port = htons((u_short)port);
641         if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) {
642             syslog(LOG_INFO ,
643                    "connect second port: %m");
644             exit(1);
645         }
646     }
647     dup2(f, 0);
648     dup2(f, 1);
649     dup2(f, 2);
650     hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
651                        fromp->sin_family);
652     if (hp){
653         hostname = malloc(strlen(hp->h_name) + 1);
654         strcpy(hostname,hp->h_name);
655     }
656     else {
657         hostname = malloc(strlen((char *)inet_ntoa(fromp->sin_addr)) + 1);
658         strcpy(hostname,(char *)inet_ntoa(fromp->sin_addr));
659     }
660     peeraddr.addrtype = fromp->sin_family;
661     peeraddr.length = SIZEOF_INADDR;
662     peeraddr.contents = (krb5_octet *)&fromp->sin_addr;
663
664
665 #ifdef KERBEROS
666     if (status = recvauth(f, fromaddr, peeraddr)) {
667         error("Authentication failed: %s\n", error_message(status));
668         exit(1);
669     }
670     if (!strncmp(cmdbuf, "-x ", 3))
671         do_encrypt = 1;
672 #else
673     getstr(f, remuser, sizeof(remuser), "remuser");
674     getstr(f, locuser, sizeof(locuser), "locuser");
675     getstr(f, cmdbuf, sizeof(cmdbuf), "command");
676 #endif /* KERBEROS */
677     
678 #ifdef CRAY
679     paddr = inet_addr(inet_ntoa(fromp->sin_addr));
680     if(secflag){
681         /*
682          *      check network authorization list
683          */
684         if (fetchnal(paddr,&nal) < 0) {
685             /*
686              *      NAL file inaccessible, abort connection.
687              */
688             error("Permission denied.\n");
689             exit(1);
690         }
691     }
692 #endif /* CRAY */
693     
694     pwd = getpwnam(locuser);
695     if (pwd == (struct passwd *) 0 ) {
696         syslog(LOG_ERR ,
697                "Principal %s (%s@%s) for local user %s has no account.\n",
698                kremuser, remuser, hostname, locuser);
699         error("Login incorrect.\n");
700         exit(1);
701     }
702     
703 #ifdef CRAY
704     /* Setup job entry, and validate udb entry. 
705        ( against packet level also ) */
706     if ((jid = setjob(pwd->pw_uid, 0)) < 0) {
707         error("Unable to create new job.\n");
708         exit(1);
709     }
710     if ((jtmpnam = makejtmp(pwd->pw_uid, pwd->pw_gid, jid))) {
711         register int pid, tpid;
712         int status;
713         switch(pid = fork()) {
714           case -1:
715             cleanjtmp(locuser, jtmpnam);
716             envinit[TMPDIRENV] = 0;
717             break;
718           case 0:
719             break;
720           default:
721             close(0);
722             close(1);
723             close(2);
724             close(f);
725             if (port)
726               close(s);
727             while ((tpid = wait(&status)) != pid) {
728                 if (tpid < 0)
729                   break;
730             }
731             cleanjtmp(locuser, jtmpnam);
732             exit(status>>8);
733             /* NOTREACHED */
734         }
735     } else {
736         envinit[TMPDIRENV] = 0;
737     }
738 #ifndef NO_UDB
739     (void)getsysudb();
740     
741     if ((ue = getudbnam(pwd->pw_name)) == (struct udb *)NULL) {
742         error("Unable to fetch account id.\n");
743         exit(1);
744     }
745     ue_static = *ue;                /* save from setlimits call */
746     endudb();
747     if (secflag) {
748         if(getsysv(&sysv, sizeof(struct sysv)) != 0) {
749             loglogin(hostname, SLG_LLERR, 0, ue);
750             error("Permission denied.\n");
751             exit(1);
752         }
753         if ((packet_level != ue->ue_deflvl) ||
754             ((packet_compart & ue->ue_comparts) != packet_compart )){
755             loglogin(hostname, SLG_LLERR, 0, ue);
756             error("Permission denied.\n");
757             exit(1);
758         }
759         if (ue->ue_disabled != 0) {
760             loglogin(hostname,SLG_LOCK,ue->ue_logfails,ue);
761             error("Permission denied.\n");
762             exit(1);
763         }
764         maxlogs = sysv.sy_maxlogs;
765     }
766     if (acctid(getpid(), ue->ue_acids[0]) == -1) {
767         error("Unable to set account id.\n");
768         exit(1);
769     }
770     if (setshares(pwd->pw_uid, acctid(0, -1), error, 1, 0)) {
771         error("Unable to set shares.\n");
772         exit(1);
773     }
774     if (setlimits(pwd->pw_name, C_PROC, getpid(), UDBRC_INTER)) {
775         error("Unable to set limits.\n");
776         exit(1);
777     }
778     if (setlimits(pwd->pw_name, C_JOB, jid, UDBRC_INTER)) {
779         error("Unable to set limits.\n");
780         exit(1);
781     }
782     ue = &ue_static;                /* restore after setlimits call */
783     endudb();                   /* setlimits opens udb and leaves it
784                                    open so close it here. */
785 #endif  /* !NO_UDB */
786 #endif /*CRAY*/
787     
788     /* Setup wtmp entry : we do it here so that if this is a CRAY
789        the Process Id is correct and we have not lost our trusted
790        privileges. */
791     if (port) {
792         /* Place entry into wtmp */
793         sprintf(ttyn,"krsh%1d",getpid());
794         logwtmp(ttyn,locuser,hostname,1);
795     }
796     /*      We are simply execing a program over rshd : log entry into wtmp,
797             as kexe(pid), then finish out the session right after that.
798             Syslog should have the information as to what was exec'd */
799     else {
800         logwtmp(ttyn,locuser,hostname,1);
801     }
802     
803 #ifdef CRAY
804     
805     /* If  we are a secure system then we need to get rid of our
806        trusted facility, so that MAC on the chdir we work. Before we
807        do this make an entry into wtmp, and any other audit recording. */
808     
809     if (secflag) {
810         if (getusrv(&usrv)){
811             syslog(LOG_ERR,"Cannot getusrv");
812             error("Permission denied.\n");
813             loglogin(hostname, SLG_LVERR, ue->ue_logfails,ue);
814             goto signout_please;
815         }
816         /*
817          *      6.0 no longer allows any form ofTRUSTED_PROCESS logins.
818          */
819         if((ue->ue_valcat & TFM_TRUSTED) ||
820            (sysv.sy_oldtfm &&
821             ((ue->ue_comparts & TRUSTED_SUBJECT) == TRUSTED_SUBJECT))) {
822             loglogin(hostname, SLG_TRSUB, ue->ue_logfails,ue);
823             error("Permission denied.\n");
824             goto signout_please;
825         }
826         
827         loglogin(hostname, SLG_OKLOG, ue->ue_logfails,ue);
828         
829         /*      Setup usrv structure with user udb info and 
830                 packet_level and packet_compart. */
831         usrv.sv_actlvl = packet_level;
832         usrv.sv_actcmp = packet_compart; /*Note get_packet_level sets
833                                            compartment to users default
834                                            compartments....*/
835         usrv.sv_permit = ue->ue_permits;
836         usrv.sv_intcls = ue->ue_intcls;
837         usrv.sv_maxcls = ue->ue_maxcls;
838         usrv.sv_intcat = ue->ue_intcat;
839         usrv.sv_valcat = ue->ue_valcat;
840         usrv.sv_savcmp = 0;
841         usrv.sv_savlvl = 0;
842         
843         /*
844          *      Set user values to workstation boundaries
845          */
846 #ifdef MIN
847 #undef MIN
848 #endif
849 #ifdef MAX
850 #undef MAX
851 #endif
852         
853 #define MIN(a,b) ((a) < (b) ? (a) : (b))
854 #define MAX(a,b) ((a) > (b) ? (a) : (b))
855         
856         nal_error = 0;
857         
858         if (nal.na_sort) {
859             if ((ue->ue_minlvl > nal.na_smax) ||
860                 (ue->ue_maxlvl < nal.na_smin))
861               nal_error++;
862             else {
863                 usrv.sv_minlvl=MAX(ue->ue_minlvl, nal.na_smin);
864                 usrv.sv_maxlvl=MIN(ue->ue_maxlvl, nal.na_smax);
865                 
866 #ifndef IP_SECURITY
867
868                 if (usrv.sv_actlvl < usrv.sv_minlvl)
869                     usrv.sv_actlvl = usrv.sv_minlvl;
870                 if (usrv.sv_actlvl > usrv.sv_maxlvl)
871                   usrv.sv_actlvl = usrv.sv_maxlvl;
872                 
873 #else /*IP_SECURITY*/
874                 if (usrv.sv_actlvl < usrv.sv_minlvl)
875                   nal_error++;
876                 if (usrv.sv_actlvl > usrv.sv_maxlvl)
877                   nal_error++;
878                 if (usrv.sv_actlvl != ue->ue_deflvl)
879                   nal_error++;
880                 
881                 usrv.sv_valcmp = ue->ue_comparts & nal.na_scmp;
882                 usrv.sv_actcmp &= nal.na_scmp;
883 #endif /*IP_SECURITY*/
884                 usrv.sv_valcmp = ue->ue_comparts & nal.na_scmp;
885                 usrv.sv_actcmp = (usrv.sv_valcmp &
886                                   ue->ue_defcomps);
887             }
888         } else {
889             /*
890              *      If the user's minimum level is greater than
891              *      zero, they cannot log on from this (ie. an
892              *      unclassified) host.
893              */
894             if (ue->ue_minlvl > 0)
895               nal_error++;
896             /*
897               /*
898                *      Address not in NAL, if EXEMPT_NAL is not
899                *      true, then even an unclassified user is
900                *      not allowed.
901                */
902               if (!EXEMPT_NAL)
903                 nal_error++;
904               else {
905                   usrv.sv_minlvl = 0;
906                   usrv.sv_maxlvl = 0;
907                   usrv.sv_valcmp = 0;
908                   usrv.sv_actcmp = 0;
909                   usrv.sv_actlvl = 0;
910               }
911         }
912         if (nal_error) {
913             loglogin(hostname, SLG_LVERR, ue->ue_logfails,ue);
914             error("Permission denied.\n");
915             goto signout_please;
916         }
917 #undef  MIN
918 #undef  MAX
919         /* Before the setusrv is done then do a sethost for paddr */
920         sethost(paddr);
921         
922         if (setusrv(&usrv) == -1) {
923             loglogin(hostname, SLG_LVERR, ue->ue_logfails,ue);
924             error("Permission denied.\n");
925             goto signout_please;
926         }
927         if (getusrv(&usrv) == -1) {
928             error("Getusrv Permission denied.\n");
929             goto signout_please;
930         }
931         
932     }
933 #endif /*CRAY*/
934     
935     if (chdir(pwd->pw_dir) < 0) {
936         syslog(LOG_ERR ,
937                "Principal %s  (%s@%s) for local user %s has no home directory.\n",
938                kremuser, remuser, hostname, locuser);
939         error("No remote directory.\n");
940         goto signout_please;
941     }
942
943 #ifdef KERBEROS
944     if (must_pass_k5 || must_pass_one) {
945 #if defined(KRB5_KRB4_COMPAT) && !defined(ALWAYS_V5_KUSEROK)
946         if (auth_sys == KRB5_RECVAUTH_V4) {
947             /* kuserok returns 0 if OK */
948             if (kuserok(v4_kdata, locuser)){
949                 syslog(LOG_ERR ,
950                        "Principal %s (%s@%s) for local user %s failed kuserok.\n",
951                        kremuser, remuser, hostname, locuser);
952                 if (must_pass_k5) {
953                     error("Permission denied.\n");
954                     goto signout_please;
955                 }
956                 failed_k5 = 1;
957             }
958         } else
959 #endif
960         {
961             /* krb5_kuserok returns 1 if OK */
962             if (!krb5_kuserok(client, locuser)){
963                 syslog(LOG_ERR ,
964                        "Principal %s (%s@%s) for local user %s failed krb5_kuserok.\n",
965                        kremuser, remuser, hostname, locuser);
966                 if (must_pass_k5) {
967                     error("Permission denied.\n");
968                     goto signout_please;
969                 }
970                 failed_k5 = 1;
971             }
972         }
973     }
974         
975     if (must_pass_rhosts || (failed_k5 && must_pass_one)) {
976         /* Cannot check .rhosts unless connection from privileged port */
977         if (non_privileged) {
978             syslog(LOG_ERR , "connection from bad port\n");
979             exit(1);
980         }
981
982         if (ruserok(hostname, pwd->pw_uid == 0,
983                     remuser, locuser) < 0) {
984             syslog(LOG_ERR ,
985                    "Principal %s (%s@%s) for local user %s failed ruserok.\n",
986                    kremuser, remuser, hostname, locuser);
987             error("Permission denied.\n");
988             goto signout_please;
989         }
990     }
991 #else
992     if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
993         ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
994         error("Permission denied.\n");
995         goto signout_please;
996     }
997 #endif /* KERBEROS */
998     
999     if (pwd->pw_uid && !access("/etc/nologin", F_OK)) {
1000         error("Logins currently disabled.\n");
1001         goto signout_please;
1002     }
1003     
1004     /* Log access to account */
1005     pwd = (struct passwd *) getpwnam(locuser);
1006     if (pwd && (pwd->pw_uid == 0)) {
1007 #ifdef LOG_CMD
1008         syslog(LOG_NOTICE, "Executing %s for principal %s (%s@%s) as ROOT", 
1009                cmdbuf, kremuser, remuser, hostname);
1010 #else
1011         syslog(LOG_NOTICE ,"Access as ROOT by principal %s (%s@%s)",
1012                kremuser, remuser, hostname);
1013 #endif
1014     }
1015 #if defined(KERBEROS) && defined(LOG_REMOTE_REALM) && !defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
1016     /* Log if principal is from a remote realm */
1017     else if (client && !default_realm(client))
1018 #endif
1019   
1020 #if defined(KERBEROS) && defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS) 
1021     /* Log if principal name does not map to local username */
1022     else if (client && !princ_maps_to_lname(client, locuser))
1023 #endif /* LOG_OTHER_USERS */
1024   
1025 #ifdef LOG_ALL_LOGINS /* Log everything */
1026     else 
1027 #endif 
1028   
1029 #if defined(LOG_REMOTE_REALM) || defined(LOG_OTHER_USERS) || defined(LOG_ALL_LOGINS)
1030       {
1031 #ifdef LOG_CMD
1032           syslog(LOG_NOTICE, "Executing %s for principal %s (%s@%s) as local user %s", 
1033                  cmdbuf, kremuser, remuser, hostname, locuser);
1034 #else
1035           syslog(LOG_NOTICE ,"Access as %s by principal %s (%s@%s)",
1036                  locuser, kremuser, remuser, hostname);
1037 #endif
1038       }
1039 #endif
1040     
1041     (void) write(2, "", 1);
1042     
1043     if (port) {
1044         if (pipe(pv) < 0) {
1045             error("Can't make pipe.\n");
1046             goto signout_please;
1047         }
1048         if (pipe(pw) < 0) {
1049             error("Can't make pipe 2.\n");
1050             goto signout_please;
1051         }
1052         if (pipe(px) < 0) {
1053             error("Can't make pipe 3.\n");
1054             goto signout_please;
1055         }
1056         pid = fork();
1057         if (pid == -1)  {
1058             error("Fork failed.\n");
1059             goto signout_please;
1060         }
1061         if (pid) {
1062 #ifdef POSIX_SIGNALS
1063             sa.sa_handler = cleanup;
1064             (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
1065             (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
1066             (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
1067             (void)sigaction(SIGPIPE, &sa, (struct sigaction *)0);
1068             (void)sigaction(SIGHUP, &sa, (struct sigaction *)0);
1069
1070             sa.sa_handler = SIG_IGN;
1071             (void)sigaction(SIGCHLD, &sa, (struct sigaction *)0);
1072 #else
1073             signal(SIGINT, cleanup);
1074             signal(SIGQUIT, cleanup);
1075             signal(SIGTERM, cleanup);
1076             signal(SIGPIPE, cleanup);
1077             signal(SIGHUP, cleanup);
1078             signal(SIGCHLD,SIG_IGN);
1079 #endif
1080             
1081             (void) close(0); (void) close(1); (void) close(2);
1082             (void) close(pv[1]);
1083             (void) close(pw[1]);
1084             (void) close(px[0]);
1085             
1086             ioctl(pv[0], FIONBIO, (char *)&one);
1087             ioctl(pw[0], FIONBIO, (char *)&one);
1088             /* should set s nbio! */
1089
1090             if (do_encrypt)
1091                 if (((*des_write)(s, SECURE_MESSAGE, sizeof(SECURE_MESSAGE))) < 0)
1092                     fatal(pw[0], "Cannot encrypt-write network.");
1093             
1094             FD_ZERO(&readfrom);
1095             FD_SET(f, &readfrom);
1096             FD_SET(s, &readfrom);
1097             FD_SET(pv[0], &readfrom);
1098             FD_SET(pw[0], &readfrom);
1099             
1100             do {
1101                 ready = readfrom;
1102                 if (select(8*sizeof(ready), &ready, (fd_set *)0,
1103                            (fd_set *)0, (struct timeval *)0) < 0)
1104                   break;
1105                 if (FD_ISSET(s, &ready)) {
1106                     if ((*des_read)(s, &sig, 1) <= 0)
1107                         FD_CLR(s, &readfrom);
1108                     else {
1109 #ifdef POSIX_SIGNALS
1110                         sa.sa_handler = cleanup;
1111                         (void)sigaction(sig, &sa, (struct sigaction *)0);
1112                         kill(-pid, sig);
1113 #else
1114                         signal(sig, cleanup);
1115                         killpg(pid, sig);
1116 #endif
1117                     }
1118                 }
1119                 if (FD_ISSET(f, &ready)) {
1120                     errno = 0;
1121                     cc = (*des_read)(f, buf, sizeof(buf));
1122                     if (cc <= 0) {
1123                         (void) close(px[1]);
1124                         FD_CLR(f, &readfrom);
1125                     } else
1126                         (void) write(px[1], buf, cc);
1127                 }
1128                 if (FD_ISSET(pv[0], &ready)) {
1129                     errno = 0;
1130                     cc = read(pv[0], buf, sizeof (buf));
1131                     if (cc <= 0) {
1132                         shutdown(s, 1+1);
1133                         FD_CLR(pv[0], &readfrom);
1134                     } else
1135                         (void) (*des_write)(s, buf, cc);
1136                 }
1137                 if (FD_ISSET(pw[0], &ready)) {
1138                     errno = 0;
1139                     cc = read(pw[0], buf, sizeof (buf));
1140                     if (cc <= 0) {
1141                         shutdown(f, 1+1);
1142                         FD_CLR(pw[0], &readfrom);
1143                     } else
1144                         (void) (*des_write)(f, buf, cc);
1145                 }
1146             } while (FD_ISSET(s, &readfrom) ||
1147                      FD_ISSET(f, &readfrom) ||
1148                      FD_ISSET(pv[0], &readfrom) ||
1149                      FD_ISSET(pw[0], &readfrom));
1150 #ifdef KERBEROS
1151             syslog(LOG_INFO ,
1152                    "Shell process completed.");
1153 #endif
1154             /* Finish session in wmtp */
1155             logwtmp(ttyn,"","",0);
1156             exit(0);
1157         }
1158 #ifdef SETPGRP_TWOARG
1159         setpgrp(0, getpid());
1160 #else
1161         setpgrp();
1162 #endif
1163         (void) close(s);
1164         (void) close(f);
1165         (void) close(pw[0]);
1166         (void) close(pv[0]);
1167         (void) close(px[1]);
1168
1169         (void) dup2(px[0], 0);
1170         (void) dup2(pw[1], 1);
1171         (void) dup2(pv[1], 2);
1172
1173         (void) close(px[0]);
1174         (void) close(pw[1]);
1175         (void) close(pv[1]);
1176     }
1177     
1178     /*      We are simply execing a program over rshd : log entry into wtmp, 
1179             as kexe(pid), then finish out the session right after that.
1180             Syslog should have the information as to what was exec'd */
1181     else {
1182         logwtmp(ttyn,"","",0);
1183     }
1184     
1185     if (*pwd->pw_shell == '\0')
1186       pwd->pw_shell = "/bin/sh";
1187     (void) close(f);
1188     (void) setgid((gid_t)pwd->pw_gid);
1189 #ifndef sgi
1190     initgroups(pwd->pw_name, pwd->pw_gid);
1191 #endif
1192     (void) setuid((uid_t)pwd->pw_uid);
1193     environ = envinit;
1194     strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
1195     strncat(shell, pwd->pw_shell, sizeof(shell)-7);
1196     strncat(username, pwd->pw_name, sizeof(username)-6);
1197     strcat(path, KPROGDIR);
1198     strcat(path, ":");
1199     strcat(path, path_rest);
1200     cp = strrchr(pwd->pw_shell, '/');
1201     if (cp)
1202       cp++;
1203     else
1204       cp = pwd->pw_shell;
1205
1206     if (do_encrypt && !strncmp(cmdbuf, "-x ", 3)) {
1207         execl(pwd->pw_shell, cp, "-c", (char *)cmdbuf + 3, 0);
1208     }
1209     else
1210         execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
1211
1212     perror(pwd->pw_shell);
1213     perror(cp);
1214     exit(1);
1215     
1216   signout_please:
1217     logwtmp(ttyn,"","",0);
1218     exit(1);
1219 }
1220     
1221
1222
1223 /*VARARGS1*/
1224 error(fmt, a1, a2, a3)
1225      char *fmt;
1226      char *a1, *a2, *a3;
1227 {
1228     char buf[BUFSIZ];
1229     
1230     buf[0] = 1;
1231     (void) sprintf(buf+1, "%s: ", progname);
1232     (void) sprintf(buf+strlen(buf), fmt, a1, a2, a3);
1233     (void) write(2, buf, strlen(buf));
1234     syslog(LOG_ERR ,"%s",buf+1);
1235 }
1236
1237
1238
1239 getstr(fd, buf, cnt, err)
1240      char *buf;
1241      int cnt;
1242      char *err;
1243 {
1244     char c;
1245     
1246     do {
1247         if (read(fd, &c, 1) != 1)
1248           exit(1);
1249         *buf++ = c;
1250         if (--cnt == 0) {
1251             error("%s too long\n", err);
1252             exit(1);
1253         }
1254     } while (c != 0);
1255 }
1256
1257
1258
1259 krb5_sigtype 
1260   cleanup()
1261 {
1262 #ifdef POSIX_SIGNALS
1263     struct sigaction sa;
1264
1265     (void)sigemptyset(&sa.sa_mask);
1266     sa.sa_flags = 0;
1267     sa.sa_handler = SIG_IGN;
1268     (void)sigaction(SIGINT, &sa, (struct sigaction *)0);
1269     (void)sigaction(SIGQUIT, &sa, (struct sigaction *)0);
1270     (void)sigaction(SIGTERM, &sa, (struct sigaction *)0);
1271     (void)sigaction(SIGPIPE, &sa, (struct sigaction *)0);
1272     (void)sigaction(SIGHUP, &sa, (struct sigaction *)0);
1273
1274     (void)kill(-pid, SIGTERM);
1275 #else
1276     signal(SIGINT, SIG_IGN);
1277     signal(SIGQUIT, SIG_IGN);
1278     signal(SIGTERM, SIG_IGN);
1279     signal(SIGPIPE, SIG_IGN);
1280     signal(SIGHUP, SIG_IGN);
1281     
1282     killpg(pid, SIGTERM);
1283 #endif
1284     wait(0);
1285     
1286     logwtmp(ttyn,"","",0);
1287     syslog(LOG_INFO ,"Shell process completed.");
1288     exit(0);
1289 }
1290
1291
1292
1293 #ifdef  CRAY
1294 char *makejtmp(uid, gid, jid)
1295      register int uid, gid, jid;
1296 {
1297     extern int errno;
1298     
1299     register char *endc, *tdp = &tmpdir[strlen(tmpdir)];
1300     register int i;
1301     
1302     sprintf(tdp, "%s/jtmp.%06d", JTMPDIR, jid);
1303     endc = &tmpdir[strlen(tmpdir)];
1304     
1305     endc[1] = '\0';
1306     for (i = 0; i < 26; i++) {
1307         endc[0] = 'a' + i;
1308         if (mkdir(tdp, JTMPMODE) != -1) {
1309             chown(tdp, uid, gid);
1310             return (tdp);
1311         } else if (errno != EEXIST)
1312           break;
1313     }
1314     return(NULL);
1315 }
1316
1317
1318
1319 cleanjtmp(user, tpath)
1320      register char *user, *tpath;
1321 {
1322     switch(fork()) {
1323       case -1:
1324         break;
1325       case 0:
1326         if (secflag) {
1327             execl("/bin/rm", "rm", "-rf", tpath, 0);
1328             error("exec of %s failed; errno = %d\n",
1329                   "/bin/rm", errno);
1330         } else {
1331             execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
1332             error("exec of %s failed; errno = %d\n",
1333                   CLEANTMPCMD, errno);
1334         }
1335         exit(1);
1336         break;
1337       default:
1338         /*
1339          * Just forget about the child, let init will pick it
1340          * up after we exit.
1341          */
1342         break;
1343     }
1344 }
1345
1346
1347
1348 /***get_packet_classification
1349  *
1350  *
1351  *      int get_packet_classification():
1352  *      Obtain packet level and compartments from passed fd...
1353  *
1354  *      Returns:
1355  *             -1: If could not get user defaults.
1356  *              0: success
1357  */
1358 #ifdef IP_SECURITY
1359 static int get_packet_classification(fd,useruid,level,comp)
1360      int fd;
1361      uid_t useruid;
1362      int *level;
1363      long *comp;
1364 {
1365     struct socket_security pkt_sec;
1366     struct udb *udb;
1367     int retval;
1368     int sockoptlen;
1369     
1370     retval = 0;
1371     getsysudb ();
1372     udb = getudbuid ((int) useruid);
1373     endudb ();
1374     if (udb == (struct udb *) 0) return(-1);
1375     /* Get packet IP packet label */
1376     sockoptlen = SIZEOF_sec;
1377     if ( getsockopt(fd,SOL_SOCKET,SO_SECURITY,
1378                     (char *) &pkt_sec,&sockoptlen)){  /* Failed */
1379         return(-2);
1380     }
1381     *level = pkt_sec.sec_level;
1382     *comp = udb->ue_defcomps;
1383     return(0);
1384 }
1385
1386 #else  /* If no IP_SECURITY set level to users default */
1387
1388 static int get_packet_classification(fd,useruid,level,comp)
1389      int fd;
1390      uid_t useruid;
1391      int *level;
1392      long *comp;
1393 {
1394     struct udb    *udb;
1395     getsysudb ();
1396     udb = getudbuid ((int) useruid);
1397     endudb ();
1398     if (udb == (struct udb *) 0) return(-1);
1399     *level = udb->ue_deflvl;
1400     *comp = udb->ue_defcomps;
1401     return(0);
1402 }
1403
1404 #endif /* IP_SECURITY */
1405         
1406         
1407
1408 /*
1409  * Make a security log entry for the login attempt.
1410  *     host = pointer to host id
1411  *     flag = status of login
1412  *     failures = current losing streak in login attempts
1413  */
1414 /* Make a security log entry for the login attempt.
1415  *  host = pointer to host id
1416  *  flag = status of login
1417  *  failures = current losing streak in login attempts
1418  */
1419
1420 loglogin(host, flag, failures, ue)
1421      char    *host;
1422      int     flag;
1423      int     failures;
1424      struct udb * ue;
1425 {
1426     char   urec[sizeof(struct slghdr) + sizeof(struct slglogin)];
1427     struct slghdr   *uhdr = (struct slghdr *)urec;
1428     struct slglogin *ulogin=(struct slglogin *)&urec[sizeof(struct slghdr)];
1429     
1430     strncpy(ulogin->sl_line, ttyn, sizeof(ulogin->sl_line));
1431     strncpy(ulogin->sl_host, host, sizeof(ulogin->sl_host));
1432     ulogin->sl_failures = failures;
1433     if ( maxlogs && (failures >= maxlogs))
1434       flag |= SLG_DSABL;
1435     ulogin->sl_result = flag;
1436     uhdr->sl_uid = ue->ue_uid;
1437     uhdr->sl_ruid = ue->ue_uid;
1438     uhdr->sl_juid = ue->ue_uid;
1439     uhdr->sl_gid = ue->ue_gids[0];
1440     uhdr->sl_rgid = ue->ue_gids[0];
1441     uhdr->sl_slvl = ue->ue_deflvl;
1442     /*      uhdr->sl_scls = ue->ue_defcls;  enable for integrity policy */
1443     uhdr->sl_olvl = 0;
1444     uhdr->sl_len = sizeof(urec);
1445     
1446 #ifdef  CRAY2
1447     slgentry(SLG_LOGN, (word *)urec);
1448 #else /*        ! CRAY2 */
1449     slgentry(SLG_LOGN, (waddr_t)urec);
1450 #endif
1451     return;
1452 }
1453
1454 #endif /* CRAY */
1455         
1456
1457
1458 usage()
1459 {
1460 #ifdef KERBEROS
1461     syslog(LOG_ERR, "usage: kshd [-rRkK] or [r/R][k/K]shd");
1462 #else
1463     syslog(LOG_ERR, "usage: rshd");
1464 #endif
1465 }
1466
1467
1468
1469 int princ_maps_to_lname(principal, luser)       
1470      krb5_principal principal;
1471      char *luser;
1472 {
1473     char kuser[10];
1474     if (!(krb5_aname_to_localname(principal,
1475                                   sizeof(kuser), kuser))
1476         && (strcmp(kuser, luser) == 0)) {
1477         return 1;
1478     }
1479     return 0;
1480 }
1481
1482
1483 int default_realm(principal)
1484      krb5_principal principal;
1485 {
1486     char *def_realm;
1487     int realm_length;
1488     int retval;
1489     
1490     realm_length = krb5_princ_realm(principal)->length;
1491     
1492     if (retval = krb5_get_default_realm(&def_realm)) {
1493         return 0;
1494     }
1495     
1496     if ((realm_length != strlen(def_realm)) ||
1497         (memcmp(def_realm, krb5_princ_realm(principal)->data, realm_length))) {
1498         free(def_realm);
1499         return 0;
1500     }   
1501     free(def_realm);
1502     return 1;
1503 }
1504
1505 #ifdef KERBEROS
1506
1507 #ifndef KRB_SENDAUTH_VLEN
1508 #define KRB_SENDAUTH_VLEN 8         /* length for version strings */
1509 #endif
1510
1511 #define KRB_SENDAUTH_VERS       "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
1512                                               chars */
1513
1514 krb5_error_code
1515 recvauth(netf, peersin, peeraddr)
1516      int netf;
1517      struct sockaddr_in peersin;
1518      krb5_address peeraddr;
1519 {
1520     krb5_error_code status;
1521     struct sockaddr_in laddr;
1522     char krb_vers[KRB_SENDAUTH_VLEN + 1];
1523     int len;
1524     krb5_principal server;
1525     krb5_data inbuf;
1526     char v4_instance[INST_SZ];  /* V4 Instance */
1527     char v4_version[9];
1528     krb5_ticket        *ticket;
1529
1530     len = sizeof(laddr);
1531     if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
1532             exit(1);
1533     }
1534         
1535 #ifdef unicos61
1536 #define SIZEOF_INADDR  SIZEOF_in_addr
1537 #else
1538 #define SIZEOF_INADDR sizeof(struct in_addr)
1539 #endif
1540
1541     if (status = krb5_sname_to_principal(NULL, "host", KRB5_NT_SRV_HST,
1542                                          &server)) {
1543             syslog(LOG_ERR, "parse server name %s: %s", "host",
1544                    error_message(status));
1545             exit(1);
1546     }
1547
1548     strcpy(v4_instance, "*");
1549
1550     status = krb5_compat_recvauth(&netf,
1551                                   "KCMDV0.1",
1552                                   server, /* Specify daemon principal */
1553                                   &peeraddr, /* We do want to match */
1554                                              /* this against caddrs in */
1555                                              /* the ticket */
1556                                   0, /* use v5srvtab */
1557                                   0, /* no keyproc */
1558                                   0, /* no keyprocarg */
1559                                   0, /* default rc_type */
1560                                   0, /* no flags */
1561
1562                                   0, /*v4_opts*/
1563                                   "rcmd", /* v4_service */
1564                                   v4_instance, /* v4_instance */
1565                                   &peersin, /* foriegn address */
1566                                   &laddr, /* our local address */
1567                                   "", /* use default srvtab */
1568
1569                                   &auth_sys, /* which authentication system */
1570                                   0, /* no seq number */
1571                                   &client, /* return client */
1572                                   &ticket, /* return ticket */
1573                                   &kdata, /* return authenticator */
1574                                   
1575                                   &v4_kdata, 0, v4_version);
1576
1577     if (status) {
1578         if (auth_sys == KRB5_RECVAUTH_V5) {
1579             /*
1580              * clean up before exiting
1581              */
1582             getstr(netf, locuser, sizeof(locuser), "locuser");
1583             getstr(netf, cmdbuf, sizeof(cmdbuf), "command");
1584             getstr(netf, remuser, sizeof(locuser), "remuser");
1585         }
1586         return status;
1587     }
1588
1589     getstr(netf, locuser, sizeof(locuser), "locuser");
1590     getstr(netf, cmdbuf, sizeof(cmdbuf), "command");
1591
1592     if (auth_sys == KRB5_RECVAUTH_V4) {
1593         /* We do not really know the remote user's login name.
1594          * Assume it to be the same as the first component of the
1595          * principal's name. 
1596          */
1597         strcpy(remuser, v4_kdata->pname);
1598         kremuser = (char *) malloc(strlen(v4_kdata->pname) + 1 +
1599                                    strlen(v4_kdata->pinst) + 1 +
1600                                    strlen(v4_kdata->prealm) + 1);
1601         sprintf(kremuser, "%s/%s@%s", v4_kdata->pname,
1602                 v4_kdata->pinst, v4_kdata->prealm);
1603         
1604         if (status = krb5_parse_name(kremuser, &client))
1605           return(status);
1606         return 0;
1607     }
1608
1609     /* Must be V5  */
1610         
1611     getstr(netf, remuser, sizeof(locuser), "remuser");
1612
1613     if (status = krb5_unparse_name(client, &kremuser))
1614         return status;
1615     
1616     /* Setup eblock for encrypted sessions. */
1617     krb5_use_keytype(&eblock, ticket->enc_part2->session->keytype);
1618     if (status = krb5_process_key(&eblock, ticket->enc_part2->session))
1619         fatal(netf, "Permission denied");
1620
1621     /* Null out the "session" because eblock.key references the session
1622      * key here, and we do not want krb5_free_ticket() to destroy it. */
1623     ticket->enc_part2->session = 0;
1624
1625     if (status = krb5_read_message((krb5_pointer)&netf, &inbuf)) {
1626         error("Error reading message: %s\n", error_message(status));
1627         exit(1);
1628     }
1629
1630     if (inbuf.length) { /* Forwarding being done, read creds */
1631         if (status = rd_and_store_for_creds(&inbuf, ticket, locuser)) {
1632             error("Can't get forwarded credentials: %s\n",
1633                   error_message(status));
1634             exit(1);
1635         }
1636     }
1637     krb5_free_ticket(ticket);
1638     return 0;
1639 }
1640
1641
1642 char storage[2*BUFSIZ];                    /* storage for the decryption */
1643 int nstored = 0;
1644 char *store_ptr = storage;
1645
1646 int
1647 v5_des_read(fd, buf, len)
1648      int fd;
1649      register char *buf;
1650      int len;
1651 {
1652     int nreturned = 0;
1653     krb5_ui_4 net_len,rd_len;
1654     int cc,retry;
1655     unsigned char len_buf[4];
1656     
1657     if (!do_encrypt)
1658       return(read(fd, buf, len));
1659     
1660     if (nstored >= len) {
1661         memcpy(buf, store_ptr, len);
1662         store_ptr += len;
1663         nstored -= len;
1664         return(len);
1665     } else if (nstored) {
1666         memcpy(buf, store_ptr, nstored);
1667         nreturned += nstored;
1668         buf += nstored;
1669         len -= nstored;
1670         nstored = 0;
1671     }
1672     
1673     if ((cc = krb5_net_read(fd, (char *)len_buf, 4)) != 4) {
1674         if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
1675             return(cc);
1676         /* XXX can't read enough, pipe must have closed */
1677         return(0);
1678     }
1679     rd_len =
1680         ((len_buf[0]<<24) |
1681          (len_buf[1]<<16) |
1682          (len_buf[2]<<8) |
1683          len_buf[3]);
1684     net_len = krb5_encrypt_size(rd_len, eblock.crypto_entry);
1685     if (net_len < 0 || net_len > sizeof(des_inbuf)) {
1686         /* XXX preposterous length, probably out of sync.
1687            act as if pipe closed */
1688         syslog(LOG_ERR,"Read size problem (rd_len=%d, net_len=%d)",
1689                rd_len, net_len);
1690         return(0);
1691     }
1692     retry = 0;
1693   datard:
1694     if ((cc = krb5_net_read(fd, desinbuf.data, net_len)) != net_len) {
1695         /* XXX can't read enough, pipe must have closed */
1696         if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
1697             retry++;
1698             if (retry > MAXRETRIES){
1699                 syslog(LOG_ERR, "des_read retry count exceeded %d\n", retry);
1700                 return(0);
1701             }
1702             sleep(1);
1703             goto datard;
1704         }
1705         syslog(LOG_ERR,
1706                "Read data received %d != expected %d.",
1707                cc, net_len);
1708         return(0);
1709     }
1710
1711     /* decrypt info */
1712     if (krb5_decrypt(desinbuf.data, (krb5_pointer) storage, net_len,
1713                      &eblock, 0)) {
1714         syslog(LOG_ERR,"Read decrypt problem.");
1715         return(0);
1716     }
1717
1718     store_ptr = storage;
1719     nstored = rd_len;
1720     if (nstored > len) {
1721         memcpy(buf, store_ptr, len);
1722         nreturned += len;
1723         store_ptr += len;
1724         nstored -= len;
1725     } else {
1726         memcpy(buf, store_ptr, nstored);
1727         nreturned += nstored;
1728         nstored = 0;
1729     }
1730     return(nreturned);
1731 }
1732     
1733
1734 int
1735 v5_des_write(fd, buf, len)
1736      int fd;
1737      char *buf;
1738      int len;
1739 {
1740     unsigned char len_buf[4];
1741     
1742     if (!do_encrypt)
1743       return(write(fd, buf, len));
1744     
1745     desoutbuf.length = krb5_encrypt_size(len, eblock.crypto_entry);
1746     if (desoutbuf.length > sizeof(des_outbuf)){
1747         syslog(LOG_ERR,"Write size problem (%d > %d)",
1748                desoutbuf.length, sizeof(des_outbuf));
1749         return(-1);
1750     }
1751
1752     if (krb5_encrypt((krb5_pointer)buf, desoutbuf.data, len, &eblock, 0)) {
1753         syslog(LOG_ERR,"Write encrypt problem.");
1754         return(-1);
1755     }
1756     
1757     len_buf[0] = (len & 0xff000000) >> 24;
1758     len_buf[1] = (len & 0xff0000) >> 16;
1759     len_buf[2] = (len & 0xff00) >> 8;
1760     len_buf[3] = (len & 0xff);
1761     (void) write(fd, len_buf, 4);
1762
1763     if (write(fd, desoutbuf.data, desoutbuf.length) != desoutbuf.length){
1764         syslog(LOG_ERR,"Could not write out all data.");
1765         return(-1);
1766     }
1767     else return(len);
1768 }
1769
1770
1771 void fatal(f, msg)
1772      int f;
1773      char *msg;
1774 {
1775     char buf[512];
1776     int out = 1 ;          /* Output queue of f */
1777
1778     buf[0] = '\01';             /* error indicator */
1779     (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
1780     if ((f == netf) && (pid > 0))
1781       (void) (*des_write)(f, buf, strlen(buf));
1782     else
1783       (void) write(f, buf, strlen(buf));
1784     syslog(LOG_ERR,"%s\n",msg);
1785     if (pid > 0) {
1786         signal(SIGCHLD,SIG_IGN);
1787         kill(pid,SIGKILL);
1788 #ifdef POSIX_TERMIOS
1789         (void) tcflush(1, TCOFLUSH);
1790 #else
1791         (void) ioctl(f, TIOCFLUSH, (char *)&out);
1792 #endif
1793         cleanup();
1794     }
1795     exit(1);
1796 }
1797 #endif /* KERBEROS */