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