* krlogind.c (main): LOG_AUTH in openlog arguments in wrong place.
[krb5.git] / src / appl / bsd / krlogind.c
1 /*
2  *      appl/bsd/krlogind.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 @(#)rlogind.c       5.17 (Berkeley) 8/31/88 */
29      
30      /*
31       * remote login server:
32       * remuser\0
33       * locuser\0
34       * terminal info\0
35       * data
36       */
37      
38 /*
39  * This is the rlogin 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  * 3) Prompt for password if any checks fail, or if so configured.
46  * Allow login if all goes well either by calling the accompanying 
47  * login.krb5 or /bin/login, according to the definition of 
48  * DO_NOT_USE_K_LOGIN.
49  * 
50  * The configuration is done either by command-line arguments passed by 
51  * inetd, or by the name of the daemon. If command-line arguments are
52  * present, they  take priority. The options are:
53  * -k and -K means check .k5login (using krb5_kuserok).
54  * -r and -R means check .rhosts  (using ruserok).
55  * -p and -P means prompt for password.
56  * The difference between upper and lower case is as follows:
57  *    If lower case -r or -k, then as long as one of krb5_kuserok or 
58  * ruserok passes, allow login without password. If the -p option is
59  * passed with -r or -k, then if both checks fail, allow login but
60  * only after password verification. 
61  *    If uppercase -R or -K, then those checks must be passed,
62  * regardless of other checks, else no login with or without password.
63  *    If the -P option is passed, then the password is verified in 
64  * addition to all other checks. If -p is not passed with -k or -r,
65  * and both checks fail, then login permission is denied.
66  *    -x and -e means use encryption.
67  *
68  *    If no command-line arguments are present, then the presence of the 
69  * letters kKrRexpP in the program-name before "logind" determine the 
70  * behaviour of the program exactly as with the command-line arguments.
71  *
72  * If the ruserok check is to be used, then the client should connect
73  * from a privileged port, else deny permission.
74  */ 
75      
76 /* DEFINES:
77  *   KERBEROS - Define this if application is to be kerberised.
78  *   CRYPT    - Define this if encryption is to be an option.
79  *   DO_NOT_USE_K_LOGIN - Define this if you want to use /bin/login
80  *              instead  of the accompanying login.krb5. In that case,
81  *              the remote user's name must be present in the local
82  *              .rhosts file, regardless of any options specified.
83  *   KRB5_KRB4_COMPAT - Define this if v4 rlogin clients are also to be served.
84  *   ALWAYS_V5_KUSEROK - Define this if you want .k5login to be
85  *              checked even for v4 clients (instead of .klogin).
86  *   LOG_ALL_LOGINS - Define this if you want to log all logins.
87  *   LOG_OTHER_USERS - Define this if you want to log all principals
88  *              that do not map onto the local user.
89  *   LOG_REMOTE_REALM - Define this if you want to log all principals from 
90  *              remote realms.
91  *       Note:  Root logins are always logged.
92  */
93
94 /*
95  * This is usually done in the Makefile.  Actually, these sources may
96  * not work without the KERBEROS #defined.
97  *
98  * #define KERBEROS
99  */
100 #define LOG_REMOTE_REALM
101 #define CRYPT
102
103
104 #ifdef HAVE_UNISTD_H
105 #include <unistd.h>
106 #endif
107 #ifdef __SCO__
108 #include <sys/unistd.h>
109 #endif
110 #ifdef HAVE_STDLIB_H
111 #include <stdlib.h>
112 #endif
113
114 #include <stdio.h>
115 #include <sys/types.h>
116 #include <sys/stat.h>
117 #include <sys/socket.h>
118 #include <sys/ioctl.h>
119 #include <sys/wait.h>
120 #include <sys/file.h>
121 #include <sys/time.h>
122 #include <ctype.h>
123 #include <fcntl.h>
124 #include <netinet/in.h>
125 #include <errno.h>
126 #include <pwd.h>
127      
128 #ifdef HAVE_SYS_LABEL_H
129 /* only SunOS 4? */
130 #include <sys/label.h>
131 #include <sys/audit.h>
132 #include <pwdadj.h>
133 #endif
134      
135 #include <signal.h>
136
137 #ifdef hpux
138 #include <sys/ptyio.h>
139 #endif
140 #ifdef sysvimp
141 #include <compat.h>
142 #endif
143
144 #ifdef HAVE_SYS_SELECT_H
145 #include <sys/select.h>
146 #endif
147
148 #ifdef HAVE_STREAMS
149 #include <sys/stream.h>
150 #include <sys/stropts.h>
151 #endif
152
153 #if defined(POSIX_TERMIOS) && !defined(ultrix)
154 #include <termios.h>
155 #else
156 #include <sgtty.h>
157 #endif
158      
159 #include <netdb.h>
160 #include <syslog.h>
161 #include <string.h>
162 #include <sys/param.h>
163 #include <utmp.h>
164
165 #ifdef HAVE_STREAMS
166 /* krlogin doesn't test sys/tty... */
167 #ifdef HAVE_SYS_TTY_H
168 #include <sys/tty.h>
169 #endif
170
171 #ifdef HAVE_SYS_PTYVAR_H
172 /* Solaris actually uses packet mode, so the real macros are needed too */
173 #include <sys/ptyvar.h>
174 #endif
175 #endif
176
177
178 #ifndef TIOCPKT_NOSTOP
179 /* These values are over-the-wire protocol, *not* local values */
180 #define TIOCPKT_NOSTOP          0x10
181 #define TIOCPKT_DOSTOP          0x20
182 #define TIOCPKT_FLUSHWRITE      0x02
183 #endif
184
185 #ifdef HAVE_SYS_FILIO_H
186 /* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
187 #include <sys/filio.h>
188 #endif
189
190 #ifndef SETPGRP_TWOARG
191 #define setpgrp(a,b) setpgrp()
192 #endif
193
194 #ifndef HAVE_KILLPG
195 #define killpg(pid, sig) kill(-(pid), (sig))
196 #endif
197
198 #ifdef NO_WINSIZE
199 struct winsize {
200     unsigned short ws_row, ws_col;
201     unsigned short ws_xpixel, ws_ypixel;
202 };
203 #endif /* NO_WINSIZE */
204      
205 #ifndef roundup
206 #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
207 #endif
208
209 #ifdef KERBEROS
210      
211 #include "krb5.h"
212 #include <kerberosIV/krb.h>
213
214 #ifdef BUFSIZ
215 #undef BUFSIZ
216 #endif
217
218 int auth_sys = 0;       /* Which version of Kerberos used to authenticate */
219
220 #define KRB5_RECVAUTH_V4        4
221 #define KRB5_RECVAUTH_V5        5
222
223 int non_privileged = 0; /* set when connection is seen to be from */
224                         /* a non-privileged port */
225
226 AUTH_DAT        *v4_kdata;
227 Key_schedule v4_schedule;
228 int v4_des_read(), v4_des_write();
229
230 #define BUFSIZ 5120
231
232 int v5_des_read(), v5_des_write();
233
234 #include "com_err.h"
235      
236 #define SECURE_MESSAGE  "This rlogin session is using DES encryption for all data transmissions.\r\n"
237
238 int (*des_read)(), (*des_write)();
239 char des_inbuf[2*BUFSIZ];         /* needs to be > largest read size */
240 char des_outbuf[2*BUFSIZ];        /* needs to be > largest write size */
241 krb5_data desinbuf,desoutbuf;
242 krb5_encrypt_block eblock;        /* eblock for encrypt/decrypt */
243
244 krb5_authenticator      *kdata;
245 krb5_ticket     *ticket = 0;
246 krb5_context bsd_context;
247
248 char *srvtab = NULL;
249
250 #define ARGSTR  "rRkKeExXpPD:S:M:L:?"
251 #else /* !KERBEROS */
252 #define ARGSTR  "rRpPD:?"
253 #define (*des_read)  read
254 #define (*des_write) write
255 #endif /* KERBEROS */
256
257 #ifndef LOGIN_PROGRAM
258 #ifdef DO_NOT_USE_K_LOGIN
259 #ifdef sysvimp
260 #define LOGIN_PROGRAM "/bin/remlogin"
261 #else
262 #define LOGIN_PROGRAM "/bin/login"
263 #endif
264 #else /* DO_NOT_USE_K_LOGIN */
265 #define LOGIN_PROGRAM KRB5_PATH_LOGIN
266 #endif /* DO_NOT_USE_K_LOGIN */
267 #endif /* LOGIN_PROGRAM */
268
269 char *login_program = LOGIN_PROGRAM;
270
271 #define MAXRETRIES 4
272 #define MAX_PROG_NAME 16
273
274 #ifndef UT_NAMESIZE     /* linux defines it directly in <utmp.h> */
275 #define UT_NAMESIZE     sizeof(((struct utmp *)0)->ut_name)
276 #endif
277
278 char            lusername[UT_NAMESIZE+1];
279 char            rusername[UT_NAMESIZE+1];
280 char            *krusername = 0;
281 char            term[64];
282 char            rhost_name[128];
283 krb5_principal  client;
284
285 extern  int errno;
286 int     reapchild();
287 char    *progname;
288
289 static  int Pfd;
290
291 #if (defined(_AIX) && defined(i386)) || defined(ibm032) || (defined(vax) && !defined(ultrix)) || (defined(SunOS) && SunOS > 40) || defined(solaris20)
292 #define VHANG_FIRST
293 #endif
294
295 #if defined(ultrix)
296 #define VHANG_LAST              /* vhangup must occur on close, not open */
297 #endif
298
299 void    fatal(), fatalperror(), doit(), usage(), do_krb_login();
300 int     princ_maps_to_lname(), default_realm();
301 krb5_sigtype    cleanup();
302
303 int must_pass_rhosts = 0, must_pass_k5 = 0, must_pass_one = 0;
304 int do_encrypt = 0, passwd_if_fail = 0, passwd_req = 0;
305
306 main(argc, argv)
307      int argc;
308      char **argv;
309 {
310     extern int opterr, optind;
311     extern char * optarg;
312     int on = 1, fromlen, ch, i;
313     struct sockaddr_in from;
314     char *options;
315     int debug_port = 0;
316     int fd;
317     
318     progname = *argv;
319     
320 #ifndef LOG_NDELAY
321 #define LOG_NDELAY 0
322 #endif
323     
324 #ifdef KERBEROS
325     krb5_init_context(&bsd_context);
326     krb5_init_ets(bsd_context);
327 #endif
328     
329 #ifndef LOG_AUTH /* 4.2 syslog */
330     openlog(progname, LOG_PID | LOG_NDELAY);
331 #else
332     openlog(progname, LOG_PID | LOG_NDELAY, LOG_AUTH);
333 #endif /* 4.2 syslog */
334     
335     if (argc == 1) { /* Get parameters from program name. */
336         if (strlen(progname) > MAX_PROG_NAME) {
337             usage();
338             exit(1);
339         }
340         options = (char *) malloc(MAX_PROG_NAME+1);
341         options[0] = '\0';
342         for (i = 0; (progname[i] != '\0') && (i < MAX_PROG_NAME); i++)
343           if (!strcmp(progname+i, "logind")) {
344               char **newargv;
345
346               newargv = (char **) malloc(sizeof(char *) * 3);
347
348               strcpy(options, "-");
349               strncat(options, progname, i);
350
351               argc = 2;
352               
353               newargv[0] = argv[0];
354               newargv[1] = options;
355               newargv[2] = NULL;
356
357               argv = newargv;
358               break;
359           }
360         if (options[0] == '\0') {
361             usage();
362             exit(1);
363         }
364     }
365     
366     /* Analyse parameters. */
367     opterr = 0;
368     while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
369       switch (ch) {
370         case 'r':         
371           must_pass_one = 1; /* If just 'r', any one check must succeed */
372           break;
373         case 'R':         /* If 'R', must pass .rhosts check*/
374           must_pass_rhosts = 1;
375           if (must_pass_one)
376             must_pass_one = 0;
377           break;
378 #ifdef KERBEROS
379         case 'k':
380           must_pass_one = 1; /* If just 'k', any one check must succeed */
381           break;
382         case 'K':         /* If 'K', must pass .k5login check*/
383           must_pass_k5 = 1;
384           if (must_pass_one)
385             must_pass_one = 0;
386           break;
387 #ifdef CRYPT
388         case 'x':         /* Use encryption. */
389         case 'X':
390         case 'e':
391         case 'E':
392           do_encrypt = 1;
393           break;
394 #endif
395         case 'S':
396           srvtab = optarg;
397           break;
398         case 'M':
399           krb5_set_default_realm(bsd_context, optarg);
400           break;
401 #endif
402         case 'p':
403           passwd_if_fail = 1; /* Passwd reqd if any check fails */
404           break;
405         case 'P':         /* passwd is a must */
406           passwd_req = 1;
407           break;
408         case 'D':
409           debug_port = atoi(optarg);
410           break;
411         case 'L':
412 #ifndef DO_NOT_USE_K_LOGIN
413           login_program = optarg;
414 #endif
415           break;
416         case '?':
417         default:
418           usage();
419           exit(1);
420           break;
421       }
422     argc -= optind;
423     argv += optind;
424     
425     fromlen = sizeof (from);
426
427      if (debug_port) {
428          int s;
429          struct sockaddr_in sin;
430          
431          if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
432              fprintf(stderr, "Error in socket: %s\n", strerror(errno));
433              exit(2);
434          }
435          
436          memset((char *) &sin, 0,sizeof(sin));
437          sin.sin_family = AF_INET;
438          sin.sin_port = htons(debug_port);
439          sin.sin_addr.s_addr = INADDR_ANY;
440          
441          (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
442                            (char *)&on, sizeof(on));
443
444          if ((bind(s, (struct sockaddr *) &sin, sizeof(sin))) < 0) {
445              fprintf(stderr, "Error in bind: %s\n", strerror(errno));
446              exit(2);
447          }
448          
449          if ((listen(s, 5)) < 0) {
450              fprintf(stderr, "Error in listen: %s\n", strerror(errno));
451              exit(2);
452          }
453          
454          if ((fd = accept(s, (struct sockaddr *) &from, &fromlen)) < 0) {
455              fprintf(stderr, "Error in accept: %s\n", strerror(errno));
456              exit(2);
457          }
458          
459          close(s);
460      } 
461      else {
462          if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
463              syslog(LOG_ERR,"Can't get peer name of remote host: %m");
464 #ifdef STDERR_FILENO
465              fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
466 #else
467              fatal(3, "Can't get peer name of remote host", 1);
468 #endif
469          }
470          fd = 0;
471      }
472
473     if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
474       syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
475     
476     doit(fd, &from);
477 }
478
479
480
481 #ifndef LOG_AUTH
482 #define LOG_AUTH 0
483 #endif
484
485 int     child;
486 int     netf;
487 char    line[MAXPATHLEN];
488 extern  char    *inet_ntoa();
489
490 #ifdef TIOCSWINSZ
491 struct winsize win = { 0, 0, 0, 0 };
492 #endif
493
494 int pid; /* child process id */
495
496 void doit(f, fromp)
497      int f;
498      struct sockaddr_in *fromp;
499 {
500     int i, p, t, vfd, on = 1;
501     register struct hostent *hp;
502     char c;
503     char buferror[255];
504     struct passwd *pwd;
505 #ifdef POSIX_SIGNALS
506     struct sigaction sa;
507 #endif
508     
509     netf = -1;
510     alarm(60);
511     read(f, &c, 1);
512     
513     if (c != 0){
514         exit(1);
515     }
516
517     alarm(0);
518
519 #ifdef POSIX_SIGNALS
520     /* Initialize "sa" structure. */
521     (void) sigemptyset(&sa.sa_mask);
522     sa.sa_flags = 0;
523 #endif
524
525     fromp->sin_port = ntohs((u_short)fromp->sin_port);
526     hp = gethostbyaddr((char *) &fromp->sin_addr, sizeof (struct in_addr),
527                        fromp->sin_family);
528     if (hp == 0) {
529         /*
530          * Only the name is used below.
531          */
532         sprintf(rhost_name,"%s",inet_ntoa(fromp->sin_addr));
533     }
534     
535     /* Save hostent information.... */
536     else strcpy(rhost_name,hp->h_name);
537     
538     if (fromp->sin_family != AF_INET)
539       fatal(f, "Permission denied - Malformed from address\n");
540     
541 #ifdef KERBEROS
542     if (must_pass_k5 || must_pass_one) {
543         /* setup des buffers */
544         desinbuf.data = des_inbuf;
545         desoutbuf.data = des_outbuf;    /* Set up des buffers */
546     }
547     /* Must come from privileged port when .rhosts is being looked into */
548     if ((must_pass_rhosts || must_pass_one) 
549         && (fromp->sin_port >= IPPORT_RESERVED ||
550             fromp->sin_port < IPPORT_RESERVED/2))
551       non_privileged = 1;
552 #else /* !KERBEROS */
553     if (fromp->sin_port >= IPPORT_RESERVED ||
554         fromp->sin_port < IPPORT_RESERVED/2)
555       fatal(f, "Permission denied - Connection from bad port");
556 #endif /* KERBEROS */
557     
558     /* Set global netf to f now : we may need to drop everything
559        in do_krb_login. */
560     netf = f;
561     
562 #if defined(KERBEROS)
563     /* All validation, and authorization goes through do_krb_login() */
564     do_krb_login(rhost_name);
565 #else
566     getstr(f, rusername, sizeof(rusername), "remuser");
567     getstr(f, lusername, sizeof(lusername), "locuser");
568     getstr(f, term, sizeof(term), "Terminal type");
569 #endif
570     
571     write(f, "", 1);
572     if (getpty(&p,line))
573       fatal(f, "Out of ptys");
574     Pfd = p;
575 #ifdef TIOCSWINSZ
576     (void) ioctl(p, TIOCSWINSZ, &win);
577 #endif
578     
579 #ifdef VHANG_FIRST
580     vfd = open(line, O_RDWR);
581     if (vfd < 0)
582       fatalperror(f, line);
583 #ifdef NOFCHMOD
584     if (chmod(line, 0))
585       fatalperror(f, line);
586 #else
587     if (fchmod(vfd, 0))
588       fatalperror(f, line);
589 #endif
590     if (f == 0) {  /* if operating standalone, do not reset tty!! */
591 #ifdef POSIX_SIGNALS
592         sa.sa_handler = SIG_IGN;
593         (void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
594         vhangup();
595         sa.sa_handler = SIG_DFL;
596         (void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
597 #else
598         signal(SIGHUP, SIG_IGN);
599         vhangup();
600         signal(SIGHUP, SIG_DFL);
601 #endif
602     }
603 #endif /* VHANG_FIRST */
604
605 #ifdef TIOCNOTTY
606       {
607         int con_fd;
608         /* Void tty association first */
609         if ((con_fd = open("/dev/tty", O_RDWR)) >= 0) {
610           ioctl(con_fd, TIOCNOTTY, 0);
611           close(con_fd);
612         }
613       }
614 #endif
615
616 #ifdef HAVE_SETSID
617     (void) setsid();
618 #endif
619
620 #ifdef ultrix
621     /* The Ultrix (and other BSD tty drivers) require the process group
622      * to be zero, in order to acquire the new tty as a controlling tty. */
623     (void) setpgrp(0, 0);
624 #endif
625
626     t = open(line, O_RDWR);
627     if (t < 0)
628       fatalperror(f, line);
629
630 #ifdef ultrix
631     setpgrp(0, getpid());
632 #endif
633         
634 #if defined(VHANG_FIRST) && !defined(VHANG_NO_CLOSE)
635     (void) close(vfd);
636 #endif
637
638 #ifdef TIOCSCTTY
639     if(ioctl(t, TIOCSCTTY, 0) < 0) /* set controlling tty */
640       fatalperror(f, "setting controlling tty");
641 #endif
642
643 #ifdef POSIX_SIGNALS
644     sa.sa_handler = cleanup;
645     (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
646     (void) sigaction(SIGTERM, &sa, (struct sigaction *)0);
647 #else
648     signal(SIGCHLD, cleanup);
649     signal(SIGTERM, cleanup);
650 #endif
651     pid = fork();
652     if (pid < 0)
653       fatalperror(f, "");
654     if (pid == 0) {
655 #if defined(POSIX_TERMIOS) && !defined(ultrix)
656         struct termios new_termio;
657 #else
658         struct sgttyb b;
659 #endif /* POSIX_TERMIOS */
660
661 #ifdef HAVE_STREAMS
662 #ifdef HAVE_LINE_PUSH
663         while (ioctl (t, I_POP, 0) == 0); /*Clear out any old lined's*/
664         if (line_push(t) < 0)
665           fatalperror(f, "IPUSH");
666 #else
667 #ifdef sun
668         while (ioctl (t, I_POP, 0) == 0); /*Clear out any old lined's*/
669         if (ioctl(t, I_PUSH, "ptem") < 0)
670           fatalperror(f, "IPUSH-ptem");
671         if (ioctl(t, I_PUSH, "ldterm") < 0)
672           fatalperror(f, "IPUSH-ldterm");
673         if (ioctl(t, I_PUSH, "ttcompat") < 0)
674           fatalperror(f, "IPUSH-ttcompat");
675 #endif /* sun */
676 #endif /* HAVE_LINE_PUSH */
677 #endif /* HAVE_STREAMS */
678         
679         /*
680          * Under Ultrix 3.0, the pgrp of the slave pty terminal
681          * needs to be set explicitly.  Why rlogind works at all
682          * without this on 4.3BSD is a mystery.
683          */
684         close(f), close(p);
685         dup2(t, 0), dup2(t, 1), dup2(t, 2);
686         if (t > 2)
687           close(t);
688
689 #ifdef GETPGRP_ONEARG
690         pid = getpgrp(getpid());
691 #else
692         pid = getpgrp();
693 #endif
694
695 #ifdef TIOCSPGRP
696         ioctl(0, TIOCSPGRP, &pid);
697 #endif
698
699 #if defined(POSIX_TERMIOS) && !defined(ultrix)
700         tcsetpgrp(0, pid);
701         tcgetattr(0,&new_termio);
702         new_termio.c_lflag &=  ~(ICANON|ECHO|ISIG);
703         /* so that login can read the authenticator */
704         new_termio.c_iflag &= ~(IXON|IXANY|BRKINT|INLCR|ICRNL|ISTRIP);
705         /* new_termio.c_iflag = 0; */
706         /* new_termio.c_oflag = 0; */
707         new_termio.c_cc[VMIN] = 1;
708         new_termio.c_cc[VTIME] = 0;
709         tcsetattr(0,TCSANOW,&new_termio);
710 #else
711         (void)ioctl(0, TIOCGETP, &b);
712         b.sg_flags = RAW|ANYP;
713         (void)ioctl(0, TIOCSETP, &b);
714 #endif /* POSIX_TERMIOS */
715
716         pid = 0;                        /*reset pid incase exec fails*/
717             
718         /*
719          **      signal the parent that we have turned off echo
720          **      on the slave side of the pty ... he's waiting
721          **      because otherwise the rlogin protocol junk gets
722          **      echo'd to the user (locuser^@remuser^@term/baud)
723          **      and we don't get the right tty affiliation, and
724          **      other kinds of hell breaks loose ...
725          */
726         (void) write(1, &c, 1);
727         
728 #if defined(sysvimp)
729         setcompat (COMPAT_CLRPGROUP | (getcompat() & ~COMPAT_BSDTTY));
730 #endif
731         
732         /* Log access to account */
733         pwd = (struct passwd *) getpwnam(lusername);
734         if (pwd && (pwd->pw_uid == 0)) {
735             if (passwd_req)
736               syslog(LOG_NOTICE, "ROOT login by %s (%s@%s) forcing password access",
737                      krusername ? krusername : "", rusername, rhost_name);
738             else
739               syslog(LOG_NOTICE, "ROOT login by %s (%s@%s) ", 
740                      krusername ? krusername : "", rusername, rhost_name);
741         }
742 #ifdef KERBEROS
743 #if defined(LOG_REMOTE_REALM) && !defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
744         /* Log if principal is from a remote realm */
745         else if (client && !default_realm(client))
746 #endif /* LOG_REMOTE_REALM */
747   
748 #if defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS) 
749         /* Log if principal name does not map to local username */
750         else if (client && !princ_maps_to_lname(client, lusername))
751 #endif /* LOG_OTHER_USERS */
752
753 #if defined(LOG_ALL_LOGINS)
754         else
755 #endif /* LOG_ALL_LOGINS */
756
757 #if defined(LOG_REMOTE_REALM) || defined(LOG_OTHER_USERS) || defined(LOG_ALL_LOGINS)
758         {
759             if (passwd_req)
760               syslog(LOG_NOTICE,
761                      "login by %s (%s@%s) as %s forcing password access\n",
762                      krusername ? krusername : "", rusername,
763                      rhost_name, lusername);
764             else 
765               syslog(LOG_NOTICE,
766                      "login by %s (%s@%s) as %s\n",
767                      krusername ? krusername : "", rusername,
768                      rhost_name, lusername); 
769         }
770 #endif /* LOG_REMOTE_REALM || LOG_OTHER_USERS || LOG_ALL_LOGINS */
771 #endif /* KERBEROS */
772
773 #ifndef NO_UT_PID
774         {
775             struct utmp ent;
776
777             ent.ut_pid = getpid();
778             ent.ut_type = LOGIN_PROCESS;
779             update_utmp(&ent, "rlogin", line, ""/*host*/);
780         }
781 #endif
782
783 #ifdef DO_NOT_USE_K_LOGIN
784         execl(login_program, "login", "-r", rhost_name, 0);
785 #else
786         if (passwd_req)
787           execl(login_program, "login","-h", rhost_name, lusername, 0);
788         else
789           execl(login_program, "login", "-h", rhost_name, "-e", lusername, 0);
790 #endif
791         
792         fatalperror(2, login_program);
793         /*NOTREACHED*/
794     } /* if (pid == 0) */
795
796     /*
797      **      wait for child to start ... read one byte
798      **      -- see the child, who writes one byte after
799      **      turning off echo on the slave side ...
800      **      The master blocks here until it reads a byte.
801      */
802     close(t);
803     if (read(p, &c, 1) != 1) {
804         /*
805          * Problems read failed ...
806          */
807         sprintf(buferror, "Cannot read slave pty %s ",line);
808         fatalperror(p,buferror);
809     }
810     
811 #if defined(KERBEROS) 
812     if (do_encrypt) {
813         if (((*des_write)(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE))) < 0){
814             sprintf(buferror, "Cannot encrypt-write network.");
815             fatal(p,buferror);
816         }
817     }
818     else 
819       /*
820        * if encrypting, don't turn on NBIO, else the read/write routines
821        * will fail to work properly
822        */
823 #endif /* KERBEROS */
824       ioctl(f, FIONBIO, &on);
825     ioctl(p, FIONBIO, &on);
826
827     /* FIONBIO doesn't always work on ptys, use fcntl to set O_NDELAY? */
828     (void) fcntl(p,F_SETFL,fcntl(p,F_GETFL,0) | O_NDELAY);
829
830 /*** XXX -- make this portable ***/
831 #if defined(TIOCPKT) && !defined(__svr4__) || defined(solaris20)
832     ioctl(p, TIOCPKT, &on);
833 #endif
834
835 #ifdef POSIX_SIGNALS
836     sa.sa_handler = SIG_IGN;
837     (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
838 #else
839     signal(SIGTSTP, SIG_IGN);
840 #endif
841
842 #ifdef hpux
843     setpgrp2(0, 0);
844 #else
845     setpgrp(0, 0);
846 #endif
847     
848 #ifdef DO_NOT_USE_K_LOGIN
849     /* Pass down rusername and lusername to login. */
850     (void) write(p, rusername, strlen(rusername) +1);
851     (void) write(p, lusername, strlen(lusername) +1);
852 #endif
853     /* stuff term info down to login */
854     if( write(p, term, strlen(term)+1) != strlen(term)+1 ){
855         /*
856          * Problems write failed ...
857          */
858         sprintf(buferror,"Cannot write slave pty %s ",line);
859         fatalperror(f,buferror);
860     }
861     protocol(f, p);
862     signal(SIGCHLD, SIG_IGN);
863     cleanup();
864 }
865
866 unsigned char   magic[2] = { 0377, 0377 };
867 #ifdef TIOCSWINSZ
868 #ifndef TIOCPKT_WINDOW
869 #define TIOCPKT_WINDOW 0x80
870 #endif
871 unsigned char   oobdata[] = {TIOCPKT_WINDOW};
872 #else
873 char    oobdata[] = {0};
874 #endif
875
876 /*
877  * Handle a "control" request (signaled by magic being present)
878  * in the data stream.  For now, we are only willing to handle
879  * window size changes.
880  */
881 control(pty, cp, n)
882      int pty;
883      unsigned char *cp;
884      int n;
885 {
886     struct winsize w;
887     int pgrp;
888     
889     if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
890       return (0);
891 #ifdef TIOCSWINSZ
892     oobdata[0] &= ~TIOCPKT_WINDOW;      /* we know he heard */
893     memcpy((char *)&w,cp+4, sizeof(w));
894     w.ws_row = ntohs(w.ws_row);
895     w.ws_col = ntohs(w.ws_col);
896     w.ws_xpixel = ntohs(w.ws_xpixel);
897     w.ws_ypixel = ntohs(w.ws_ypixel);
898     (void)ioctl(pty, TIOCSWINSZ, &w);
899     if (ioctl(pty, TIOCGPGRP, &pgrp) >= 0)
900       (void) killpg(pgrp, SIGWINCH);
901 #endif
902     return (4+sizeof (w));
903 }
904
905
906
907 /*
908  * rlogin "protocol" machine.
909  */
910 protocol(f, p)
911      int f, p;
912 {
913     unsigned char pibuf[1024], fibuf[1024], *pbp, *fbp;
914     register pcc = 0, fcc = 0;
915     int cc;
916     char cntl;
917 #ifdef POSIX_SIGNALS
918     struct sigaction sa;
919 #endif
920     
921     /*
922      * Must ignore SIGTTOU, otherwise we'll stop
923      * when we try and set slave pty's window shape
924      * (our controlling tty is the master pty).
925      */
926 #ifdef POSIX_SIGNALS
927     (void) sigemptyset(&sa.sa_mask);
928     sa.sa_flags = 0;
929     sa.sa_handler = SIG_IGN;
930     (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0);
931 #else
932     signal(SIGTTOU, SIG_IGN);
933 #endif
934 #ifdef TIOCSWINSZ
935     send(f, oobdata, 1, MSG_OOB);       /* indicate new rlogin */
936 #endif
937     for (;;) {
938         fd_set ibits, obits, ebits;
939
940         FD_ZERO(&ibits);
941         FD_ZERO(&obits);
942         FD_ZERO(&ebits);
943
944         if (fcc)
945             FD_SET(p, &obits);
946         else
947             FD_SET(f, &ibits);
948         if (pcc >= 0)
949             if (pcc)
950                 FD_SET(f, &obits);
951             else
952                 FD_SET(p, &ibits);
953         FD_SET(p, &ebits);
954         
955         if (select(8*sizeof(ibits), &ibits, &obits, &ebits, 0) < 0) {
956             if (errno == EINTR)
957               continue;
958             fatalperror(f, "select");
959         }
960 #define pkcontrol(c)    ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
961         if (FD_ISSET(p, &ebits)) {
962             cc = read(p, &cntl, 1);
963             if (cc == 1 && pkcontrol(cntl)) {
964                 cntl |= oobdata[0];
965                 send(f, &cntl, 1, MSG_OOB);
966                 if (cntl & TIOCPKT_FLUSHWRITE) {
967                     pcc = 0;
968                     FD_CLR(p, &ibits);
969                 }
970             }
971         }
972         if (FD_ISSET(f, &ibits)) {
973             fcc = (*des_read)(f, fibuf, sizeof (fibuf));
974             if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
975               fcc = 0;
976             else {
977                 register unsigned char *cp;
978                 int left, n;
979                 
980                 if (fcc <= 0)
981                   break;
982                 fbp = fibuf;
983                 
984               top:
985                 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
986                   if (cp[0] == magic[0] &&
987                       cp[1] == magic[1]) {
988                       left = fcc - (cp-fibuf);
989                       n = control(p, cp, left);
990                       if (n) {
991                           left -= n;
992                           if (left > 0)
993                             memmove(cp, cp+n, left);
994                           fcc -= n;
995                           goto top; /* n^2 */
996                       }
997                   }
998             }
999         }
1000         
1001         if (FD_ISSET(p, &obits) && fcc > 0) {
1002             cc = write(p, fbp, fcc);
1003             if (cc > 0) {
1004                 fcc -= cc;
1005                 fbp += cc;
1006             }
1007         }
1008         
1009         if (FD_ISSET(p, &ibits)) {
1010             pcc = read(p, pibuf, sizeof (pibuf));
1011             pbp = pibuf;
1012             if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
1013               pcc = 0;
1014             else if (pcc <= 0)
1015               break;
1016             else if (pibuf[0] == 0)
1017               pbp++, pcc--;
1018 #ifndef sun
1019             else {
1020                 if (pkcontrol(pibuf[0])) {
1021                     pibuf[0] |= oobdata[0];
1022                     send(f, &pibuf[0], 1, MSG_OOB);
1023                 }
1024                 pcc = 0;
1025             }
1026 #endif
1027         }
1028         if (FD_ISSET(f, &obits) && pcc > 0) {
1029             cc = (*des_write)(f, pbp, pcc);
1030             if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
1031                 /* also shouldn't happen */
1032                 sleep(5);
1033                 continue;
1034             }
1035             if (cc > 0) {
1036                 pcc -= cc;
1037                 pbp += cc;
1038             }
1039         }
1040     }
1041 }
1042
1043
1044
1045 krb5_sigtype cleanup()
1046 {
1047     struct utmp ut;
1048     
1049 #ifndef NO_UT_PID
1050     ut.ut_pid = 0;
1051     ut.ut_type = DEAD_PROCESS;
1052 #endif
1053     update_utmp(&ut, "", line, (char *)0);
1054     
1055     (void)chmod(line, 0666);
1056     (void)chown(line, 0, 0);
1057 #ifndef HAVE_STREAMS
1058     line[strlen("/dev/")] = 'p';
1059     (void)chmod(line, 0666);
1060     (void)chown(line, 0, 0);
1061 #endif
1062 #ifdef VHANG_LAST
1063     close(Pfd);
1064     vhangup();
1065 #endif
1066     shutdown(netf, 2);
1067     exit(1);
1068 }
1069
1070
1071 void fatal(f, msg)
1072      int f;
1073      char *msg;
1074 {
1075     char buf[512];
1076     int out = 1 ;          /* Output queue of f */
1077 #ifdef POSIX_SIGNALS
1078     struct sigaction sa;
1079 #endif
1080     
1081     buf[0] = '\01';             /* error indicator */
1082     (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
1083     if ((f == netf) && (pid > 0))
1084       (void) (*des_write)(f, buf, strlen(buf));
1085     else
1086       (void) write(f, buf, strlen(buf));
1087     syslog(LOG_ERR,"%s\n",msg);
1088     if (pid > 0) {
1089 #ifdef POSIX_SIGNALS
1090         (void) sigemptyset(&sa.sa_mask);
1091         sa.sa_flags = 0;
1092         sa.sa_handler = SIG_IGN;
1093         (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
1094 #else
1095         signal(SIGCHLD,SIG_IGN);
1096 #endif
1097         kill(pid,SIGKILL);
1098 #ifdef  TIOCFLUSH
1099         (void) ioctl(f, TIOCFLUSH, (char *)&out);
1100 #else
1101         (void) ioctl(f, TCFLSH, out);
1102 #endif
1103         cleanup();
1104     }
1105     exit(1);
1106 }
1107
1108
1109
1110 void fatalperror(f, msg)
1111      int f;
1112      char *msg;
1113 {
1114     char buf[512];
1115     extern int sys_nerr;
1116     extern char *sys_errlist[];
1117     
1118     if ((unsigned)errno < sys_nerr)
1119       (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
1120     else
1121       (void) sprintf(buf, "%s: Error %d", msg, errno);
1122     fatal(f, buf);
1123 }
1124
1125 #ifdef KERBEROS
1126
1127 void
1128 do_krb_login(host)
1129      char *host;
1130 {
1131     krb5_error_code status;
1132     struct passwd *pwd;
1133     int passed_krb, passed_rhosts;
1134     char *msg_fail;
1135
1136     passed_krb = passed_rhosts = 0;
1137
1138     if (getuid()) {
1139         exit(1);
1140     }
1141
1142     /* Check authentication. This can be either Kerberos V5, */
1143     /* Kerberos V4, or host-based. */
1144     if (status = recvauth()) {
1145         if (ticket)
1146           krb5_free_ticket(bsd_context, ticket);
1147         if (status != 255)
1148           syslog(LOG_ERR,
1149                  "Authentication failed from %s: %s\n",
1150                  host,error_message(status));
1151         fatal(netf, "Kerberos authentication failed");
1152         return;
1153     }
1154     
1155     /* OK we have authenticated this user - now check authorization. */
1156     /* The Kerberos authenticated programs must use krb5_kuserok or kuserok*/
1157     
1158 #ifndef KRB5_KRB4_COMPAT
1159     if (auth_sys == KRB5_RECVAUTH_V4) {
1160           fatal(netf, "This server does not support Kerberos V4");
1161   }
1162 #endif
1163     
1164     if (must_pass_k5 || must_pass_one) {
1165 #if (defined(ALWAYS_V5_KUSEROK) || !defined(KRB5_KRB4_COMPAT))
1166         /* krb5_kuserok returns 1 if OK */
1167         if (client && krb5_kuserok(bsd_context, client, lusername))
1168             passed_krb++;
1169 #else
1170         if (auth_sys == KRB5_RECVAUTH_V4) {
1171             /* kuserok returns 0 if OK */
1172             if (!kuserok(v4_kdata, lusername))
1173                 passed_krb++;
1174         } else {
1175             /* krb5_kuserok returns 1 if OK */
1176             if (client && krb5_kuserok(bsd_context, client, lusername))
1177                 passed_krb++;
1178         }
1179 #endif
1180     }
1181     
1182     /*  The kerberos authenticated request must pass ruserok also
1183         if asked for. */
1184     
1185     if (!must_pass_k5 &&
1186         (must_pass_rhosts || (!passed_krb && must_pass_one))) {
1187         /* Cannot check .rhosts unless connection from a privileged port. */
1188         if (non_privileged) 
1189           fatal(netf, "Permission denied - Connection from bad port");
1190
1191         pwd = (struct passwd *) getpwnam(lusername);
1192         if (pwd &&
1193             !ruserok(rhost_name, pwd->pw_uid == 0, rusername, lusername))
1194             passed_rhosts++;
1195     }
1196
1197     if ((must_pass_k5 && passed_krb) ||
1198         (must_pass_rhosts && passed_rhosts) ||
1199         (must_pass_one && (passed_krb || passed_rhosts)))
1200             return;
1201     
1202     if (ticket)
1203         krb5_free_ticket(bsd_context, ticket);
1204
1205     msg_fail =  (char *) malloc( strlen(krusername) + strlen(lusername) + 80 );
1206     if (!msg_fail)
1207         fatal(netf, "User is not authorized to login to specified account");
1208     sprintf(msg_fail, "User %s is not authorized to login to account %s",
1209             krusername, lusername);
1210     fatal(netf, msg_fail);
1211     /* NOTREACHED */
1212 }
1213
1214
1215
1216 getstr(fd, buf, cnt, err)
1217      int fd;
1218      char *buf;
1219      int cnt;
1220      char *err;
1221 {
1222     
1223     char c;
1224     
1225     do {
1226         if (read(fd, &c, 1) != 1) {
1227             exit(1);
1228         }
1229         if (--cnt < 0) {
1230             printf("%s too long\r\n", err);
1231             exit(1);
1232         }
1233         *buf++ = c;
1234     } while (c != 0);
1235 }
1236
1237
1238
1239 char storage[2*BUFSIZ];                    /* storage for the decryption */
1240 int nstored = 0;
1241 char *store_ptr = storage;
1242
1243 int
1244 v5_des_read(fd, buf, len)
1245      int fd;
1246      register char *buf;
1247      int len;
1248 {
1249     int nreturned = 0;
1250     krb5_ui_4 net_len,rd_len;
1251     int cc,retry;
1252     unsigned char len_buf[4];
1253     
1254     if (!do_encrypt)
1255       return(read(fd, buf, len));
1256     
1257     if (nstored >= len) {
1258         memcpy(buf, store_ptr, len);
1259         store_ptr += len;
1260         nstored -= len;
1261         return(len);
1262     } else if (nstored) {
1263         memcpy(buf, store_ptr, nstored);
1264         nreturned += nstored;
1265         buf += nstored;
1266         len -= nstored;
1267         nstored = 0;
1268     }
1269     
1270 #if 0
1271     if ((cc = krb5_net_read(bsd_context, fd, (char *)len_buf, 4)) != 4) {
1272         if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
1273             return(cc);
1274         /* XXX can't read enough, pipe must have closed */
1275         return(0);
1276     }
1277     rd_len =
1278         (((krb5_ui_4)len_buf[0]<<24) |
1279          ((krb5_ui_4)len_buf[1]<<16) |
1280          ((krb5_ui_4)len_buf[2]<<8) |
1281          (krb5_ui_4)len_buf[3]);
1282 #else
1283         {
1284             unsigned char c;
1285             int gotzero = 0;
1286
1287             /* See the comment in v4_des_read. */
1288             do {
1289                 cc = krb5_net_read(bsd_context, fd, &c, 1);
1290                 /* we should check for non-blocking here, but we'd have
1291                    to make it save partial reads as well. */
1292                 if (cc < 0) return 0; /* read error */
1293                 if (cc == 1) {
1294                     if (c == 0) gotzero = 1;
1295                 }
1296             } while (!gotzero);
1297
1298             if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
1299             rd_len = c;
1300             if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
1301             rd_len = (rd_len << 8) | c;
1302             if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
1303             rd_len = (rd_len << 8) | c;
1304         }
1305 #endif
1306     net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
1307     if (net_len < 0 || net_len > sizeof(des_inbuf)) {
1308         /* XXX preposterous length, probably out of sync.
1309            act as if pipe closed */
1310         syslog(LOG_ERR,"Read size problem.");
1311         return(0);
1312     }
1313     retry = 0;
1314   datard:
1315     if ((cc = krb5_net_read(bsd_context,fd,desinbuf.data,net_len)) != net_len) {
1316         /* XXX can't read enough, pipe must have closed */
1317         if ((cc < 0)  && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
1318             retry++;
1319             sleep(1);
1320             if (retry > MAXRETRIES){
1321                 syslog(LOG_ERR,
1322                        "des_read retry count exceeded %d\n",
1323                        retry);
1324                 return(0);
1325             }
1326             goto datard;
1327         }
1328         syslog(LOG_ERR,
1329                "Read data received %d != expected %d.",
1330                cc, net_len);
1331         return(0);
1332     }
1333     /* decrypt info */
1334     if ((krb5_decrypt(bsd_context, desinbuf.data,
1335                       (krb5_pointer) storage,
1336                       net_len,
1337                       &eblock, 0))) {
1338         syslog(LOG_ERR,"Read decrypt problem.");
1339         return(0);
1340     }
1341     store_ptr = storage;
1342     nstored = rd_len;
1343     if (nstored > len) {
1344         memcpy(buf, store_ptr, len);
1345         nreturned += len;
1346         store_ptr += len;
1347         nstored -= len;
1348     } else {
1349         memcpy(buf, store_ptr, nstored);
1350         nreturned += nstored;
1351         nstored = 0;
1352     }
1353     return(nreturned);
1354 }
1355     
1356
1357 int
1358 v5_des_write(fd, buf, len)
1359      int fd;
1360      char *buf;
1361      int len;
1362 {
1363     unsigned char len_buf[4];
1364     
1365     if (!do_encrypt)
1366       return(write(fd, buf, len));
1367     
1368     
1369     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
1370     if (desoutbuf.length > sizeof(des_outbuf)){
1371         syslog(LOG_ERR,"Write size problem.");
1372         return(-1);
1373     }
1374     if ((krb5_encrypt(bsd_context, (krb5_pointer)buf,
1375                       desoutbuf.data,
1376                       len,
1377                       &eblock,
1378                       0))){
1379         syslog(LOG_ERR,"Write encrypt problem.");
1380         return(-1);
1381     }
1382
1383     len_buf[0] = (len & 0xff000000) >> 24;
1384     len_buf[1] = (len & 0xff0000) >> 16;
1385     len_buf[2] = (len & 0xff00) >> 8;
1386     len_buf[3] = (len & 0xff);
1387     (void) write(fd, len_buf, 4);
1388     if (write(fd, desoutbuf.data,desoutbuf.length) != desoutbuf.length){
1389         syslog(LOG_ERR,"Could not write out all data.");
1390         return(-1);
1391     }
1392     else return(len);
1393 }
1394 #endif /* KERBEROS */
1395
1396
1397
1398 getpty(fd,slave)
1399      int *fd;
1400      char *slave;
1401 {
1402     char c;
1403     char *p;
1404     int i,ptynum;
1405     struct stat stb;
1406
1407 #ifdef HAVE_OPENPTY
1408     int slavefd;
1409
1410     if(openpty(fd, &slavefd, slave, (struct termios *) 0,
1411          (struct winsize *) 0)) return 1;
1412     return 0;
1413 #else
1414
1415     *fd = open("/dev/ptmx", O_RDWR|O_NDELAY);   /* Solaris, IRIX */
1416     if (*fd < 0) *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */
1417     if (*fd < 0) *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */
1418
1419     if (*fd >= 0) {
1420
1421 #ifdef HAVE_GRANTPT
1422         if (grantpt(*fd) || unlockpt(*fd)) return 1;
1423 #endif
1424     
1425 #ifdef  HAVE_TTYNAME
1426         p = ttyname(*fd);
1427 #else
1428 #ifdef HAVE_PTSNAME
1429         p = ptsname(*fd);
1430 #else
1431         /* XXX If we don't have either what do we do */
1432 #endif
1433 #endif
1434         if (p) {
1435             strcpy(slave, p);
1436             return 0;
1437         }
1438
1439         if (fstat(*fd, &stb) < 0) {
1440             close(*fd);
1441             return 1;
1442         }
1443         ptynum = (int)(stb.st_rdev&0xFF);
1444         sprintf(slave, "/dev/ttyp%x", ptynum);
1445         return 0;
1446
1447     } else {
1448     
1449         for (c = 'p'; c <= 's'; c++) {
1450             sprintf(slave,"/dev/ptyXX");
1451             slave[strlen("/dev/pty")] = c;
1452             slave[strlen("/dev/ptyp")] = '0';
1453             if (stat(slave, &stb) < 0)
1454                 break;
1455             for (i = 0; i < 16; i++) {
1456                 slave[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
1457                 *fd = open(slave, O_RDWR);
1458                 if (*fd < 0) continue;
1459
1460                 /* got pty */
1461                 slave[strlen("/dev/")] = 't';
1462                 return 0;
1463             }
1464         }
1465         return 1;
1466     }
1467 #endif /* HAVE_OPENPTY */
1468 }
1469
1470
1471
1472 void usage()
1473 {
1474 #ifdef KERBEROS
1475     syslog(LOG_ERR, 
1476            "usage: klogind [-rRkKxpP] [-D port] or [r/R][k/K][x/e][p/P]logind");
1477 #else
1478     syslog(LOG_ERR, 
1479            "usage: rlogind [-rRpP] [-D port] or [r/R][p/P]logind");
1480 #endif
1481 }
1482
1483
1484
1485 #ifdef KERBEROS
1486 int princ_maps_to_lname(principal, luser)       
1487      krb5_principal principal;
1488      char *luser;
1489 {
1490     char kuser[10];
1491     if (!(krb5_aname_to_localname(bsd_context, principal,
1492                                   sizeof(kuser), kuser))
1493         && (strcmp(kuser, luser) == 0)) {
1494         return 1;
1495     }
1496     return 0;
1497 }
1498
1499 int default_realm(principal)
1500      krb5_principal principal;
1501 {
1502     char *def_realm;
1503     int realm_length;
1504     int retval;
1505     
1506     realm_length = krb5_princ_realm(bsd_context, principal)->length;
1507     
1508     if (retval = krb5_get_default_realm(bsd_context, &def_realm)) {
1509         return 0;
1510     }
1511     
1512     if ((realm_length != strlen(def_realm)) ||
1513         (memcmp(def_realm, krb5_princ_realm(bsd_context, principal)->data, realm_length))) {
1514         free(def_realm);
1515         return 0;
1516     }   
1517     free(def_realm);
1518     return 1;
1519 }
1520
1521
1522 #ifndef KRB_SENDAUTH_VLEN
1523 #define KRB_SENDAUTH_VLEN 8         /* length for version strings */
1524 #endif
1525
1526 #define KRB_SENDAUTH_VERS       "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
1527                                               chars */
1528
1529 krb5_error_code
1530 recvauth()
1531 {
1532     krb5_auth_context * auth_context = NULL;
1533     krb5_error_code status;
1534     struct sockaddr_in peersin, laddr;
1535     char krb_vers[KRB_SENDAUTH_VLEN + 1];
1536     int len;
1537     krb5_principal server;
1538     krb5_data inbuf;
1539     char v4_instance[INST_SZ];  /* V4 Instance */
1540     char v4_version[9];
1541
1542     len = sizeof(laddr);
1543     if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
1544             exit(1);
1545     }
1546         
1547     len = sizeof(peersin);
1548     if (getpeername(netf, (struct sockaddr *)&peersin, &len)) {
1549         syslog(LOG_ERR, "get peer name failed %d", netf);
1550         exit(1);
1551     }
1552
1553     if (status = krb5_sname_to_principal(bsd_context, NULL, "host", 
1554                                          KRB5_NT_SRV_HST, &server)) {
1555             syslog(LOG_ERR, "parse server name %s: %s", "host",
1556                    error_message(status));
1557             exit(1);
1558     }
1559
1560     strcpy(v4_instance, "*");
1561
1562     if (status = krb5_auth_con_init(bsd_context, &auth_context))
1563         return status;
1564  
1565     /* Only need remote address for rd_cred() to verify client */
1566     if (status = krb5_auth_con_genaddrs(bsd_context, auth_context, netf,
1567                         KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR))
1568         return status;
1569
1570     if (status = krb5_compat_recvauth(bsd_context, &auth_context, &netf,
1571                                   "KCMDV0.1",
1572                                   server,       /* Specify daemon principal */
1573                                   0,            /* default rc_type */
1574                                   0,            /* no flags */
1575                                   srvtab, /* normally NULL to use v5srvtab */
1576
1577                                   do_encrypt ? KOPT_DO_MUTUAL : 0, /*v4_opts*/
1578                                   "rcmd",       /* v4_service */
1579                                   v4_instance,  /* v4_instance */
1580                                   &peersin,     /* foriegn address */
1581                                   &laddr,       /* our local address */
1582                                   "",           /* use default srvtab */
1583
1584                                   &ticket,      /* return ticket */
1585                                   &auth_sys,    /* which authentication system*/
1586                                   &v4_kdata, v4_schedule, v4_version)) {
1587
1588         if (auth_sys == KRB5_RECVAUTH_V5) {
1589             /*
1590              * clean up before exiting
1591              */
1592             getstr(netf, lusername, sizeof (lusername), "locuser");
1593             getstr(netf, term, sizeof(term), "Terminal type");
1594             getstr(netf, rusername, sizeof(rusername), "remuser");
1595         }
1596         return status;
1597     }
1598
1599     getstr(netf, lusername, sizeof (lusername), "locuser");
1600     getstr(netf, term, sizeof(term), "Terminal type");
1601
1602 #ifdef KRB5_KRB4_COMPAT
1603     if (auth_sys == KRB5_RECVAUTH_V4) {
1604
1605         des_read  = v4_des_read;
1606         des_write = v4_des_write;
1607
1608         /* We do not really know the remote user's login name.
1609          * Assume it to be the same as the first component of the
1610          * principal's name. 
1611          */
1612         strcpy(rusername, v4_kdata->pname);
1613         krusername = (char *) malloc(strlen(v4_kdata->pname) + 1 +
1614                                      strlen(v4_kdata->pinst) + 1 +
1615                                      strlen(v4_kdata->prealm) + 1);
1616         sprintf(krusername, "%s/%s@%s", v4_kdata->pname,
1617                 v4_kdata->pinst, v4_kdata->prealm);
1618         
1619         if (status = krb5_parse_name(bsd_context, krusername, &client))
1620           return(status);
1621         return 0;
1622     }
1623 #endif
1624
1625     /* Must be V5  */
1626         
1627     if (status = krb5_copy_principal(bsd_context, ticket->enc_part2->client, 
1628                                      &client))
1629         return status;
1630
1631     des_read  = v5_des_read;
1632     des_write = v5_des_write;
1633
1634     getstr(netf, rusername, sizeof(rusername), "remuser");
1635
1636     if (status = krb5_unparse_name(bsd_context, client, &krusername))
1637         return status;
1638     
1639     /* Setup up eblock if encrypted login session */
1640     /* otherwise zero out session key */
1641     if (do_encrypt) {
1642         krb5_use_keytype(bsd_context, &eblock,
1643                          ticket->enc_part2->session->keytype);
1644         if (status = krb5_process_key(bsd_context, &eblock,
1645                                       ticket->enc_part2->session))
1646             fatal(netf, "Permission denied");
1647     }      
1648
1649     if (status = krb5_read_message(bsd_context, (krb5_pointer)&netf, &inbuf))
1650         fatal(netf, "Error reading message");
1651
1652     if (inbuf.length) { /* Forwarding being done, read creds */
1653         if (status = krb5_auth_con_genaddrs(bsd_context, auth_context, netf,
1654                         KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))
1655             fatal(netf, "Can't generate full address for client");
1656
1657         if (status = rd_and_store_for_creds(bsd_context, auth_context, &inbuf, 
1658                                             ticket, lusername))
1659             fatal(netf, "Can't get forwarded credentials");
1660     }
1661     return 0;
1662 }
1663
1664
1665 #ifdef KRB5_KRB4_COMPAT
1666
1667 int
1668 v4_des_read(fd, buf, len)
1669 int fd;
1670 register char *buf;
1671 int len;
1672 {
1673         int nreturned = 0;
1674         krb5_ui_4 net_len, rd_len;
1675         int cc;
1676         unsigned char len_buf[4];
1677
1678         if (!do_encrypt)
1679                 return(read(fd, buf, len));
1680
1681         if (nstored >= len) {
1682                 memcpy(buf, store_ptr, len);
1683                 store_ptr += len;
1684                 nstored -= len;
1685                 return(len);
1686         } else if (nstored) {
1687                 memcpy(buf, store_ptr, nstored);
1688                 nreturned += nstored;
1689                 buf += nstored;
1690                 len -= nstored;
1691                 nstored = 0;
1692         }
1693
1694 #if 0
1695         if ((cc = krb_net_read(fd, (char *)len_buf, 4)) != 4) {
1696                 /* XXX can't read enough, pipe
1697                    must have closed */
1698                 return(0);
1699         }
1700         net_len = (((krb5_ui_4)len_buf[0]<<24) |
1701                    ((krb5_ui_4)len_buf[1]<<16) |
1702                    ((krb5_ui_4)len_buf[2]<<8) |
1703                    (krb5_ui_4)len_buf[3]);
1704 #else
1705         {
1706             unsigned char c;
1707             int gotzero = 0;
1708
1709             /* We're fetching the length which is MSB first, and the MSB
1710                has to be zero unless the client is sending more than 2^24
1711                (16M) bytes in a single write (which is why this code is in
1712                rlogin but not rcp or rsh.) The only reasons we'd get something
1713                other than zero are:
1714                    -- corruption of the tcp stream (which will show up when
1715                       everything else is out of sync too)
1716                    -- un-caught Berkeley-style "pseudo out-of-band data" which
1717                       happens any time the user hits ^C twice.
1718                The latter is *very* common, as shown by an 'rlogin -x -d' 
1719                using the CNS V4 rlogin.         Mark EIchin 1/95
1720               */
1721             do {
1722                 cc = krb_net_read(fd, &c, 1);
1723                 if (cc < 0) return 0; /* read error */
1724                 if (cc == 1) {
1725                     if (c == 0) gotzero = 1;
1726                 }
1727             } while (!gotzero);
1728
1729             if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
1730             net_len = c;
1731             if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
1732             net_len = (net_len << 8) | c;
1733             if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
1734             net_len = (net_len << 8) | c;
1735         }
1736
1737 #endif
1738         if (net_len < 0 || net_len > sizeof(des_inbuf)) {
1739                 /* XXX preposterous length, probably out of sync.
1740                    act as if pipe closed */
1741                 return(0);
1742         }
1743         /* the writer tells us how much real data we are getting, but
1744            we need to read the pad bytes (8-byte boundary) */
1745         rd_len = roundup(net_len, 8);
1746         if ((cc = krb_net_read(fd, des_inbuf, rd_len)) != rd_len) {
1747                 /* XXX can't read enough, pipe
1748                    must have closed */
1749                 return(0);
1750         }
1751         (void) pcbc_encrypt(des_inbuf,
1752                             storage,
1753                             (net_len < 8) ? 8 : net_len,
1754                             v4_schedule,
1755                             v4_kdata->session,
1756                             DECRYPT);
1757         /* 
1758          * when the cleartext block is < 8 bytes, it is "right-justified"
1759          * in the block, so we need to adjust the pointer to the data
1760          */
1761         if (net_len < 8)
1762                 store_ptr = storage + 8 - net_len;
1763         else
1764                 store_ptr = storage;
1765         nstored = net_len;
1766         if (nstored > len) {
1767                 memcpy(buf, store_ptr, len);
1768                 nreturned += len;
1769                 store_ptr += len;
1770                 nstored -= len;
1771         } else {
1772                 memcpy(buf, store_ptr, nstored);
1773                 nreturned += nstored;
1774                 nstored = 0;
1775         }
1776         
1777         return(nreturned);
1778 }
1779
1780 int
1781 v4_des_write(fd, buf, len)
1782 int fd;
1783 char *buf;
1784 int len;
1785 {
1786         static char garbage_buf[8];
1787         unsigned char len_buf[4];
1788
1789         if (!do_encrypt)
1790                 return(write(fd, buf, len));
1791
1792         /* 
1793          * pcbc_encrypt outputs in 8-byte (64 bit) increments
1794          *
1795          * it zero-fills the cleartext to 8-byte padding,
1796          * so if we have cleartext of < 8 bytes, we want
1797          * to insert random garbage before it so that the ciphertext
1798          * differs for each transmission of the same cleartext.
1799          * if len < 8 - sizeof(long), sizeof(long) bytes of random
1800          * garbage should be sufficient; leave the rest as-is in the buffer.
1801          * if len > 8 - sizeof(long), just garbage fill the rest.
1802          */
1803
1804 #ifdef min
1805 #undef min
1806 #endif
1807 #define min(a,b) ((a < b) ? a : b)
1808
1809         if (len < 8) {
1810                 krb5_random_confounder(8 - len, garbage_buf);
1811                 /* this "right-justifies" the data in the buffer */
1812                 (void) memcpy(garbage_buf + 8 - len, buf, len);
1813         }
1814         (void) pcbc_encrypt((len < 8) ? garbage_buf : buf,
1815                             des_outbuf,
1816                             (len < 8) ? 8 : len,
1817                             v4_schedule,
1818                             v4_kdata->session,
1819                             ENCRYPT);
1820
1821         /* tell the other end the real amount, but send an 8-byte padded
1822            packet */
1823         len_buf[0] = (len & 0xff000000) >> 24;
1824         len_buf[1] = (len & 0xff0000) >> 16;
1825         len_buf[2] = (len & 0xff00) >> 8;
1826         len_buf[3] = (len & 0xff);
1827         (void) write(fd, len_buf, 4);
1828         (void) write(fd, des_outbuf, roundup(len,8));
1829         return(len);
1830 }
1831
1832 #endif /* KRB5_KRB4_COMPAT */
1833 #endif /* KERBEROS */