1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
  29  * All Rights Reserved.
  30  */
  31 
  32 /*
  33  * University Copyright- Copyright (c) 1982, 1986, 1988
  34  * The Regents of the University of California.
  35  * All Rights Reserved.
  36  *
  37  * University Acknowledgment- Portions of this document are derived from
  38  * software developed by the University of California, Berkeley, and its
  39  * contributors.
  40  */
  41 
  42 /*
  43  * Telnet server.
  44  */
  45 #include <sys/types.h>
  46 #include <sys/param.h>
  47 #include <sys/socket.h>
  48 #include <sys/wait.h>
  49 #include <sys/file.h>
  50 #include <sys/stat.h>
  51 #include <sys/filio.h>
  52 #include <sys/time.h>
  53 #include <sys/stropts.h>
  54 #include <sys/stream.h>
  55 #include <sys/tihdr.h>
  56 #include <sys/utsname.h>
  57 #include <unistd.h>
  58 
  59 #include <netinet/in.h>
  60 
  61 #define AUTHWHO_STR
  62 #define AUTHTYPE_NAMES
  63 #define AUTHHOW_NAMES
  64 #define AUTHRSP_NAMES
  65 #define ENCRYPT_NAMES
  66 
  67 #include <arpa/telnet.h>
  68 #include <arpa/inet.h>
  69 #include <stdio.h>
  70 #include <stdarg.h>
  71 #include <signal.h>
  72 #include <errno.h>
  73 #include <netdb.h>
  74 #include <syslog.h>
  75 #include <ctype.h>
  76 #include <fcntl.h>
  77 #include <sac.h>  /* for SC_WILDC */
  78 #include <utmpx.h>
  79 #include <sys/ttold.h>
  80 #include <malloc.h>
  81 #include <string.h>
  82 #include <security/pam_appl.h>
  83 #include <sys/tihdr.h>
  84 #include <sys/logindmux.h>
  85 #include <sys/telioctl.h>
  86 #include <deflt.h>
  87 #include <stdlib.h>
  88 #include <string.h>
  89 #include <stropts.h>
  90 #include <termios.h>
  91 
  92 #include <com_err.h>
  93 #include <krb5.h>
  94 #include <krb5_repository.h>
  95 #include <des/des.h>
  96 #include <rpc/des_crypt.h>
  97 #include <sys/cryptmod.h>
  98 #include <bsm/adt.h>
  99 
 100 #define TELNETD_OPTS "Ss:a:dEXUhR:M:"
 101 #ifdef DEBUG
 102 #define DEBUG_OPTS "p:e"
 103 #else
 104 #define DEBUG_OPTS ""
 105 #endif /* DEBUG */
 106 
 107 #define OPT_NO                  0               /* won't do this option */
 108 #define OPT_YES                 1               /* will do this option */
 109 #define OPT_YES_BUT_ALWAYS_LOOK 2
 110 #define OPT_NO_BUT_ALWAYS_LOOK  3
 111 
 112 #define MAXOPTLEN 256
 113 #define MAXUSERNAMELEN 256
 114 
 115 static char     remopts[MAXOPTLEN];
 116 static char     myopts[MAXOPTLEN];
 117 static uchar_t  doopt[] = { (uchar_t)IAC, (uchar_t)DO, '%', 'c', 0 };
 118 static uchar_t  dont[] = { (uchar_t)IAC, (uchar_t)DONT, '%', 'c', 0 };
 119 static uchar_t  will[] = { (uchar_t)IAC, (uchar_t)WILL, '%', 'c', 0 };
 120 static uchar_t  wont[] = { (uchar_t)IAC, (uchar_t)WONT, '%', 'c', 0 };
 121 /*
 122  * I/O data buffers, pointers, and counters.
 123  */
 124 static char     ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
 125 
 126 static char     *netibuf, *netip;
 127 static int      netibufsize;
 128 
 129 #define NIACCUM(c)      {   *netip++ = c; \
 130                             ncc++; \
 131                         }
 132 
 133 static char     netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
 134 static char     *neturg = 0;            /* one past last bye of urgent data */
 135 /* the remote system seems to NOT be an old 4.2 */
 136 static int      not42 = 1;
 137 static char     defaultfile[] = "/etc/default/telnetd";
 138 static char     bannervar[] = "BANNER=";
 139 
 140 static char BANNER1[] = "\r\n\r\n";
 141 static char BANNER2[] = "\r\n\r\0\r\n\r\0";
 142 
 143 /*
 144  * buffer for sub-options - enlarged to 4096 to handle credentials
 145  * from AUTH options
 146  */
 147 static char     subbuffer[4096], *subpointer = subbuffer, *subend = subbuffer;
 148 #define SB_CLEAR()      subpointer = subbuffer;
 149 #define SB_TERM()       { subend = subpointer; SB_CLEAR(); }
 150 #define SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof (subbuffer))) { \
 151                                 *subpointer++ = (c); \
 152                         }
 153 #define SB_GET()        ((*subpointer++)&0xff)
 154 #define SB_EOF()        (subpointer >= subend)
 155 #define SB_LEN()        (subend - subpointer)
 156 
 157 #define MAXERRSTRLEN 1024
 158 #define MAXPRINCLEN 256
 159 
 160 extern uint_t kwarn_add_warning(char *, int);
 161 extern uint_t kwarn_del_warning(char *);
 162 
 163 static boolean_t auth_debug = 0;
 164 static boolean_t negotiate_auth_krb5 = 1;
 165 static boolean_t auth_negotiated = 0;
 166 static int auth_status = 0;
 167 static int auth_level = 0;
 168 static char     *AuthenticatingUser = NULL;
 169 static char     *krb5_name = NULL;
 170 
 171 static krb5_address rsaddr = { 0, 0, 0, NULL };
 172 static krb5_address rsport = { 0, 0, 0, NULL };
 173 
 174 static krb5_context telnet_context = 0;
 175 static krb5_auth_context auth_context = 0;
 176 
 177 /* telnetd gets session key from here */
 178 static krb5_ticket *ticket = NULL;
 179 static krb5_keyblock *session_key = NULL;
 180 static char *telnet_srvtab = NULL;
 181 
 182 typedef struct {
 183         uchar_t AuthName;
 184         uchar_t AuthHow;
 185         char  *AuthString;
 186 } AuthInfo;
 187 
 188 static AuthInfo auth_list[] = {
 189         {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL |
 190         AUTH_ENCRYPT_ON, "KRB5 MUTUAL CRYPTO"},
 191         {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL,
 192         "KRB5 MUTUAL" },
 193         {AUTHTYPE_KERBEROS_V5,  AUTH_WHO_CLIENT | AUTH_HOW_ONE_WAY,
 194         "KRB5 1-WAY" },
 195         {0, 0, "NONE"}
 196 };
 197 
 198 static AuthInfo NoAuth = {0, 0, NULL};
 199 
 200 static AuthInfo *authenticated = NULL;
 201 
 202 #define PREAMBLE_SIZE           5       /* for auth_reply_str allocation */
 203 #define POSTAMBLE_SIZE          5
 204 #define STR_DATA_LEN(len)       ((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE)
 205 
 206 static void auth_name(uchar_t *, int);
 207 static void auth_is(uchar_t *, int);
 208 
 209 #define NO_ENCRYPTION   0x00
 210 #define SEND_ENCRYPTED  0x01
 211 #define RECV_ENCRYPTED  0x02
 212 #define ENCRYPT_BOTH_WAYS    (SEND_ENCRYPTED | RECV_ENCRYPTED)
 213 
 214 static telnet_enc_data_t  encr_data;
 215 static boolean_t negotiate_encrypt = B_TRUE;
 216 static boolean_t sent_encrypt_support = B_FALSE;
 217 static boolean_t sent_will_encrypt = B_FALSE;
 218 static boolean_t sent_do_encrypt = B_FALSE;
 219 static boolean_t enc_debug = 0;
 220 
 221 static void encrypt_session_key(Session_Key *key, cipher_info_t *cinfo);
 222 static int  encrypt_send_encrypt_is();
 223 
 224 extern void mit_des_fixup_key_parity(Block);
 225 extern int krb5_setenv(const char *, const char *, int);
 226 /* need to know what FD to use to talk to the crypto module */
 227 static int cryptmod_fd = -1;
 228 
 229 #define LOGIN_PROGRAM "/bin/login"
 230 
 231 /*
 232  * State for recv fsm
 233  */
 234 #define TS_DATA         0       /* base state */
 235 #define TS_IAC          1       /* look for double IAC's */
 236 #define TS_CR           2       /* CR-LF ->'s CR */
 237 #define TS_SB           3       /* throw away begin's... */
 238 #define TS_SE           4       /* ...end's (suboption negotiation) */
 239 #define TS_WILL         5       /* will option negotiation */
 240 #define TS_WONT         6       /* wont " */
 241 #define TS_DO           7       /* do " */
 242 #define TS_DONT         8       /* dont " */
 243 
 244 static int      ncc;
 245 static int      manager;        /* manager side of pty */
 246 static int      pty;            /* side of pty that gets ioctls */
 247 static int      net;
 248 static int      inter;
 249 extern char **environ;
 250 static char     *line;
 251 static int      SYNCHing = 0;           /* we are in TELNET SYNCH mode */
 252 static int      state = TS_DATA;
 253 
 254 static int env_ovar = -1;       /* XXX.sparker */
 255 static int env_ovalue = -1;     /* XXX.sparker */
 256 static char pam_svc_name[64];
 257 static boolean_t        telmod_init_done = B_FALSE;
 258 
 259 static void     doit(int, struct sockaddr_storage *);
 260 static void     willoption(int);
 261 static void     wontoption(int);
 262 static void     dooption(int);
 263 static void     dontoption(int);
 264 static void     fatal(int, char *);
 265 static void     fatalperror(int, char *, int);
 266 static void     mode(int, int);
 267 static void     interrupt(void);
 268 static void     drainstream(int);
 269 static int      readstream(int, char *, int);
 270 static int      send_oob(int fd, char *ptr, int count);
 271 static int      local_setenv(const char *name, const char *value, int rewrite);
 272 static void     local_unsetenv(const char *name);
 273 static void     suboption(void);
 274 static int      removemod(int f, char *modname);
 275 static void     willoption(int option);
 276 static void     wontoption(int option);
 277 static void     dooption(int option);
 278 static void     dontoption(int option);
 279 static void     write_data(const char *, ...);
 280 static void     write_data_len(const char *, int);
 281 static void     rmut(void);
 282 static void     cleanup(int);
 283 static void     telnet(int, int);
 284 static void     telrcv(void);
 285 static void     sendbrk(void);
 286 static void     ptyflush(void);
 287 static void     netclear(void);
 288 static void     netflush(void);
 289 static void     showbanner(void);
 290 static void     map_banner(char *);
 291 static void     defbanner(void);
 292 static void ttloop(void);
 293 
 294 /*
 295  * The env_list linked list is used to store the environment variables
 296  * until the final exec of login.  A malevolent client might try to
 297  * send an environment variable intended to affect the telnet daemon's
 298  * execution.  Right now the BANNER expansion is the only instance.
 299  * Note that it is okay to pass the environment variables to login
 300  * because login protects itself against environment variables mischief.
 301  */
 302 
 303 struct envlist {
 304         struct envlist  *next;
 305         char            *name;
 306         char            *value;
 307         int             delete;
 308 };
 309 
 310 static struct envlist *envlist_head = NULL;
 311 
 312 /*
 313  * The following are some clocks used to decide how to interpret
 314  * the relationship between various variables.
 315  */
 316 
 317 static struct {
 318         int
 319         system,                 /* what the current time is */
 320         echotoggle,             /* last time user entered echo character */
 321         modenegotiated,         /* last time operating mode negotiated */
 322         didnetreceive,          /* last time we read data from network */
 323         ttypeopt,               /* ttype will/won't received */
 324         ttypesubopt,            /* ttype subopt is received */
 325         getterminal,            /* time started to get terminal information */
 326         xdisplocopt,            /* xdisploc will/wont received */
 327         xdisplocsubopt,         /* xdisploc suboption received */
 328         nawsopt,                /* window size will/wont received */
 329         nawssubopt,             /* window size received */
 330         environopt,             /* environment option will/wont received */
 331         oenvironopt,            /* "old" environ option will/wont received */
 332         environsubopt,          /* environment option suboption received */
 333         oenvironsubopt,         /* "old environ option suboption received */
 334         gotDM;                  /* when did we last see a data mark */
 335 
 336         int getauth;
 337         int authopt;    /* Authentication option negotiated */
 338         int authdone;
 339 
 340         int getencr;
 341         int encropt;
 342         int encr_support;
 343 } clocks;
 344 
 345 static int init_neg_done = 0;
 346 static boolean_t resolve_hostname = 0;
 347 static boolean_t show_hostinfo = 1;
 348 
 349 #define settimer(x)     (clocks.x = ++clocks.system)
 350 #define sequenceIs(x, y)        (clocks.x < clocks.y)
 351 
 352 static void send_will(int);
 353 static void send_wont(int);
 354 static void send_do(int);
 355 static char *__findenv(const char *name, int *offset);
 356 
 357 /* ARGSUSED */
 358 static void
 359 auth_finished(AuthInfo *ap, int result)
 360 {
 361         if ((authenticated = ap) == NULL) {
 362                 authenticated = &NoAuth;
 363                 if (myopts[TELOPT_ENCRYPT] == OPT_YES)
 364                         send_wont(TELOPT_ENCRYPT);
 365                 myopts[TELOPT_ENCRYPT] = remopts[TELOPT_ENCRYPT] = OPT_NO;
 366                 encr_data.encrypt.autoflag = 0;
 367         } else if (result != AUTH_REJECT &&
 368                 myopts[TELOPT_ENCRYPT] == OPT_YES &&
 369                 remopts[TELOPT_ENCRYPT] == OPT_YES) {
 370 
 371                 /*
 372                  * Authentication successful, so we have a session key, and
 373                  * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT.
 374                  *
 375                  * Can't have sent ENCRYPT SUPPORT yet!  And if we're sending it
 376                  * now it's really only because we did the DO ENCRYPT/WILL
 377                  * ENCRYPT dance before authentication, which is ok, but not too
 378                  * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT
 379                  * dance if authentication fails, though clients typically just
 380                  * don't care.
 381                  */
 382                 write_data("%c%c%c%c%c%c%c",
 383                         (uchar_t)IAC,
 384                         (uchar_t)SB,
 385                         (uchar_t)TELOPT_ENCRYPT,
 386                         (uchar_t)ENCRYPT_SUPPORT,
 387                         (uchar_t)TELOPT_ENCTYPE_DES_CFB64,
 388                         (uchar_t)IAC,
 389                         (uchar_t)SE);
 390 
 391                 netflush();
 392 
 393                 sent_encrypt_support = B_TRUE;
 394 
 395                 if (enc_debug)
 396                         (void) fprintf(stderr,
 397                         "SENT ENCRYPT SUPPORT\n");
 398 
 399                 (void) encrypt_send_encrypt_is();
 400         }
 401 
 402         auth_status = result;
 403 
 404         settimer(authdone);
 405 }
 406 
 407 static void
 408 reply_to_client(AuthInfo *ap, int type, void *data, int len)
 409 {
 410         uchar_t reply[BUFSIZ];
 411         uchar_t *p = reply;
 412         uchar_t *cd = (uchar_t *)data;
 413 
 414         if (len == -1 && data != NULL)
 415                 len = strlen((char *)data);
 416         else if (len > (sizeof (reply) - 9)) {
 417                 syslog(LOG_ERR,
 418                     "krb5 auth reply length too large (%d)", len);
 419                 if (auth_debug)
 420                         (void) fprintf(stderr,
 421                                     "krb5 auth reply length too large (%d)\n",
 422                                     len);
 423                 return;
 424         } else if (data == NULL)
 425                 len = 0;
 426 
 427         *p++ = IAC;
 428         *p++ = SB;
 429         *p++ = TELOPT_AUTHENTICATION;
 430         *p++ = AUTHTYPE_KERBEROS_V5;
 431         *p++ = ap->AuthName;
 432         *p++ = ap->AuthHow; /* MUTUAL, ONE-WAY, etc */
 433         *p++ = type;        /* RESPONSE or ACCEPT */
 434         while (len-- > 0) {
 435                 if ((*p++ = *cd++) == IAC)
 436                         *p++ = IAC;
 437         }
 438         *p++ = IAC;
 439         *p++ = SE;
 440 
 441         /* queue the data to be sent */
 442         write_data_len((const char *)reply, p-reply);
 443 
 444 #if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\
 445 defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES)
 446         if (auth_debug) {
 447                 (void) fprintf(stderr, "SENT TELOPT_AUTHENTICATION REPLY "
 448                             "%s %s|%s %s\n",
 449                             AUTHTYPE_NAME(ap->AuthName),
 450                             AUTHWHO_NAME(ap->AuthHow & AUTH_WHO_MASK),
 451                             AUTHHOW_NAME(ap->AuthHow & AUTH_HOW_MASK),
 452                             AUTHRSP_NAME(type));
 453         }
 454 #endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */
 455 
 456         netflush();
 457 }
 458 
 459 /* Decode, decrypt and store the forwarded creds in the local ccache. */
 460 static krb5_error_code
 461 rd_and_store_forwarded_creds(krb5_context context,
 462                             krb5_auth_context auth_context,
 463                             krb5_data *inbuf, krb5_ticket *ticket,
 464                             char *username)
 465 {
 466         krb5_creds **creds;
 467         krb5_error_code retval;
 468         char ccname[MAXPATHLEN];
 469         krb5_ccache ccache = NULL;
 470         char *client_name = NULL;
 471 
 472         if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))
 473                 return (retval);
 474 
 475         (void) sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", getpid());
 476         (void) krb5_setenv("KRB5CCNAME", ccname, 1);
 477 
 478         if ((retval = krb5_cc_default(context, &ccache)))
 479                 goto cleanup;
 480 
 481         if ((retval = krb5_cc_initialize(context, ccache,
 482                                         ticket->enc_part2->client)) != 0)
 483                 goto cleanup;
 484 
 485         if ((retval = krb5_cc_store_cred(context, ccache, *creds)) != 0)
 486                 goto cleanup;
 487 
 488         if ((retval = krb5_cc_close(context, ccache)) != 0)
 489                 goto cleanup;
 490 
 491         /* Register with ktkt_warnd(1M) */
 492         if ((retval = krb5_unparse_name(context, (*creds)->client,
 493                                         &client_name)) != 0)
 494                 goto cleanup;
 495         (void) kwarn_del_warning(client_name);
 496         if (kwarn_add_warning(client_name, (*creds)->times.endtime) != 0) {
 497                 syslog(LOG_AUTH|LOG_NOTICE,
 498                     "rd_and_store_forwarded_creds: kwarn_add_warning"
 499                     " failed: ktkt_warnd(1M) down? ");
 500                 if (auth_debug)
 501                         (void) fprintf(stderr,
 502                                     "kwarn_add_warning failed:"
 503                                     " ktkt_warnd(1M) down?\n");
 504         }
 505         free(client_name);
 506         client_name = NULL;
 507 
 508         if (username != NULL) {
 509                 /*
 510                  * This verifies that the user is valid on the local system,
 511                  * maps the username from KerberosV5 to unix,
 512                  * and moves the KRB5CCNAME file to the correct place
 513                  *  /tmp/krb5cc_[uid] with correct ownership (0600 uid gid).
 514                  *
 515                  * NOTE: the user must be in the gsscred table in order to map
 516                  * from KRB5 to Unix.
 517                  */
 518                 (void) krb5_kuserok(context, ticket->enc_part2->client,
 519                                 username);
 520         }
 521         if (auth_debug)
 522                 (void) fprintf(stderr,
 523                             "Successfully stored forwarded creds\n");
 524 
 525 cleanup:
 526         krb5_free_creds(context, *creds);
 527         return (retval);
 528 }
 529 
 530 static void
 531 kerberos5_is(AuthInfo *ap, uchar_t *data, int cnt)
 532 {
 533         krb5_error_code err = 0;
 534         krb5_principal server;
 535         krb5_keyblock *newkey = NULL;
 536         krb5_keytab keytabid = 0;
 537         krb5_data outbuf;
 538         krb5_data inbuf;
 539         krb5_authenticator *authenticator;
 540         char errbuf[MAXERRSTRLEN];
 541         char *name;
 542         krb5_data auth;
 543 
 544         Session_Key skey;
 545 
 546         if (cnt-- < 1)
 547                 return;
 548         switch (*data++) {
 549         case KRB_AUTH:
 550                 auth.data = (char *)data;
 551                 auth.length = cnt;
 552 
 553                 if (auth_context == NULL) {
 554                         err = krb5_auth_con_init(telnet_context, &auth_context);
 555                         if (err)
 556                                 syslog(LOG_ERR,
 557                                     "Error getting krb5 auth "
 558                                     "context: %s", error_message(err));
 559                 }
 560                 if (!err) {
 561                         krb5_rcache rcache;
 562 
 563                         err = krb5_auth_con_getrcache(telnet_context,
 564                                                     auth_context,
 565                                                     &rcache);
 566                         if (!err && !rcache) {
 567                                 err = krb5_sname_to_principal(telnet_context,
 568                                                             0, 0,
 569                                                             KRB5_NT_SRV_HST,
 570                                                             &server);
 571                                 if (!err) {
 572                                         err = krb5_get_server_rcache(
 573                                                 telnet_context,
 574                                                 krb5_princ_component(
 575                                                         telnet_context,
 576                                                         server, 0),
 577                                                 &rcache);
 578 
 579                                         krb5_free_principal(telnet_context,
 580                                                             server);
 581                                 }
 582                         }
 583                         if (err)
 584                                 syslog(LOG_ERR,
 585                                     "Error allocating krb5 replay cache: %s",
 586                                     error_message(err));
 587                         else {
 588                                 err = krb5_auth_con_setrcache(telnet_context,
 589                                                             auth_context,
 590                                                             rcache);
 591                                 if (err)
 592                                         syslog(LOG_ERR,
 593                                             "Error creating krb5 "
 594                                             "replay cache: %s",
 595                                             error_message(err));
 596                         }
 597                 }
 598                 if (!err && telnet_srvtab != NULL)
 599                         err = krb5_kt_resolve(telnet_context,
 600                                             telnet_srvtab, &keytabid);
 601                 if (!err)
 602                         err = krb5_rd_req(telnet_context, &auth_context, &auth,
 603                                         NULL, keytabid, NULL, &ticket);
 604                 if (err) {
 605                         (void) snprintf(errbuf, sizeof (errbuf),
 606                                 "Error reading krb5 auth information:"
 607                                 " %s", error_message(err));
 608                         goto errout;
 609                 }
 610 
 611                 /*
 612                  * Verify that the correct principal was used
 613                  */
 614                 if (krb5_princ_component(telnet_context,
 615                                 ticket->server, 0)->length < MAXPRINCLEN) {
 616                         char princ[MAXPRINCLEN];
 617                         (void) strncpy(princ,
 618                                     krb5_princ_component(telnet_context,
 619                                                 ticket->server, 0)->data,
 620                                     krb5_princ_component(telnet_context,
 621                                             ticket->server, 0)->length);
 622                         princ[krb5_princ_component(telnet_context,
 623                                         ticket->server, 0)->length] = '\0';
 624                         if (strcmp("host", princ)) {
 625                                 if (strlen(princ) < sizeof (errbuf) - 39) {
 626                                     (void) snprintf(errbuf, sizeof (errbuf),
 627                                                 "incorrect service "
 628                                                     "name: \"%s\" != "
 629                                                     "\"host\"",
 630                                                     princ);
 631                             } else {
 632                                     (void) strncpy(errbuf,
 633                                                 "incorrect service "
 634                                                 "name: principal != "
 635                                                 "\"host\"",
 636                                                 sizeof (errbuf));
 637                             }
 638                             goto errout;
 639                         }
 640                 } else {
 641                         (void) strlcpy(errbuf, "service name too long",
 642                                         sizeof (errbuf));
 643                         goto errout;
 644                 }
 645 
 646                 err = krb5_auth_con_getauthenticator(telnet_context,
 647                                                 auth_context,
 648                                                 &authenticator);
 649                 if (err) {
 650                         (void) snprintf(errbuf, sizeof (errbuf),
 651                                 "Failed to get authenticator: %s",
 652                                 error_message(err));
 653                         goto errout;
 654                 }
 655                 if ((ap->AuthHow & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
 656                         !authenticator->checksum) {
 657                         (void) strlcpy(errbuf,
 658                                     "authenticator is missing checksum",
 659                                     sizeof (errbuf));
 660                         goto errout;
 661                 }
 662                 if (authenticator->checksum) {
 663                         char type_check[2];
 664                         krb5_checksum *cksum = authenticator->checksum;
 665                         krb5_keyblock *key;
 666                         krb5_data input;
 667                         krb5_boolean valid;
 668 
 669                         type_check[0] = ap->AuthName;
 670                         type_check[1] = ap->AuthHow;
 671 
 672                         err = krb5_auth_con_getkey(telnet_context,
 673                                                 auth_context, &key);
 674                         if (err) {
 675                                 (void) snprintf(errbuf, sizeof (errbuf),
 676                                         "Failed to get key from "
 677                                         "authenticator: %s",
 678                                         error_message(err));
 679                                 goto errout;
 680                         }
 681 
 682                         input.data = type_check;
 683                         input.length = 2;
 684                         err = krb5_c_verify_checksum(telnet_context,
 685                                                         key, 0,
 686                                                         &input,
 687                                                         cksum,
 688                                                         &valid);
 689                         if (!err && !valid)
 690                                 err = KRB5KRB_AP_ERR_BAD_INTEGRITY;
 691 
 692                         if (err) {
 693                                 (void) snprintf(errbuf, sizeof (errbuf),
 694                                                 "Kerberos checksum "
 695                                                 "verification failed: "
 696                                                 "%s",
 697                                                 error_message(err));
 698                                 goto errout;
 699                         }
 700                         krb5_free_keyblock(telnet_context, key);
 701                 }
 702 
 703                 krb5_free_authenticator(telnet_context, authenticator);
 704                 if ((ap->AuthHow & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
 705                         /* do ap_rep stuff here */
 706                         if ((err = krb5_mk_rep(telnet_context, auth_context,
 707                                             &outbuf))) {
 708                                 (void) snprintf(errbuf, sizeof (errbuf),
 709                                                 "Failed to make "
 710                                                 "Kerberos auth reply: "
 711                                                 "%s",
 712                                                 error_message(err));
 713                                 goto errout;
 714                         }
 715                         reply_to_client(ap, KRB_RESPONSE, outbuf.data,
 716                                         outbuf.length);
 717                 }
 718                 if (krb5_unparse_name(telnet_context,
 719                                     ticket->enc_part2->client,
 720                                     &name))
 721                         name = 0;
 722                 reply_to_client(ap, KRB_ACCEPT, name, name ? -1 : 0);
 723                 if (auth_debug) {
 724                         syslog(LOG_NOTICE,
 725                             "\tKerberos5 identifies user as ``%s''\r\n",
 726                             name ? name : "");
 727                 }
 728                 if (name != NULL) {
 729                         krb5_name = (char *)strdup(name);
 730                 }
 731                 auth_finished(ap, AUTH_USER);
 732 
 733                 if (name != NULL)
 734                         free(name);
 735                 (void) krb5_auth_con_getremotesubkey(telnet_context,
 736                     auth_context, &newkey);
 737                 if (session_key != NULL) {
 738                         krb5_free_keyblock(telnet_context, session_key);
 739                         session_key = 0;
 740                 }
 741                 if (newkey != NULL) {
 742                         (void) krb5_copy_keyblock(telnet_context,
 743                             newkey, &session_key);
 744                         krb5_free_keyblock(telnet_context, newkey);
 745                 } else {
 746                         (void) krb5_copy_keyblock(telnet_context,
 747                             ticket->enc_part2->session, &session_key);
 748                 }
 749 
 750                 /*
 751                  * Initialize encryption stuff.  Currently, we are only
 752                  * supporting 8 byte keys and blocks. Check for this later.
 753                  */
 754                 skey.type = SK_DES;
 755                 skey.length = DES_BLOCKSIZE;
 756                 skey.data = session_key->contents;
 757                 encrypt_session_key(&skey, &encr_data.encrypt);
 758                 encrypt_session_key(&skey, &encr_data.decrypt);
 759                 break;
 760         case KRB_FORWARD:
 761                 inbuf.length = cnt;
 762                 inbuf.data = (char *)data;
 763                 if (auth_debug)
 764                         (void) fprintf(stderr,
 765                                     "RCVD KRB_FORWARD data (%d bytes)\n", cnt);
 766 
 767                 if (auth_context != NULL) {
 768                         krb5_rcache rcache;
 769 
 770                         err = krb5_auth_con_getrcache(telnet_context,
 771                                                     auth_context, &rcache);
 772                         if (!err && !rcache) {
 773                                 err = krb5_sname_to_principal(telnet_context,
 774                                         0, 0, KRB5_NT_SRV_HST, &server);
 775                                 if (!err) {
 776                                         err = krb5_get_server_rcache(
 777                                                 telnet_context,
 778                                                 krb5_princ_component(
 779                                                         telnet_context,
 780                                                         server, 0),
 781                                                 &rcache);
 782                                         krb5_free_principal(telnet_context,
 783                                                                 server);
 784                                 }
 785                         }
 786                         if (err) {
 787                                 syslog(LOG_ERR,
 788                                     "Error allocating krb5 replay cache: %s",
 789                                     error_message(err));
 790                         } else {
 791                                 err = krb5_auth_con_setrcache(telnet_context,
 792                                         auth_context, rcache);
 793                                 if (err)
 794                                         syslog(LOG_ERR,
 795                                             "Error creating krb5 replay cache:"
 796                                             " %s",
 797                                             error_message(err));
 798                         }
 799                 }
 800                 /*
 801                  * Use the 'rsaddr' and 'rsport' (remote service addr/port)
 802                  * from the original connection.  This data is used to
 803                  * verify the forwarded credentials.
 804                  */
 805                 if (!(err = krb5_auth_con_setaddrs(telnet_context, auth_context,
 806                                             NULL, &rsaddr)))
 807                         err = krb5_auth_con_setports(telnet_context,
 808                                                 auth_context, NULL, &rsport);
 809 
 810                 if (err == 0)
 811                         /*
 812                          * If all is well, store the forwarded creds in
 813                          * the users local credential cache.
 814                          */
 815                         err = rd_and_store_forwarded_creds(telnet_context,
 816                                                         auth_context, &inbuf,
 817                                                         ticket,
 818                                                         AuthenticatingUser);
 819                 if (err) {
 820                         (void) snprintf(errbuf, sizeof (errbuf),
 821                                         "Read forwarded creds failed: %s",
 822                                         error_message(err));
 823                         syslog(LOG_ERR, "%s", errbuf);
 824 
 825                         reply_to_client(ap, KRB_FORWARD_REJECT, errbuf, -1);
 826                         if (auth_debug)
 827                                 (void) fprintf(stderr,
 828                                             "\tCould not read "
 829                                             "forwarded credentials\r\n");
 830                 } else
 831                         reply_to_client(ap, KRB_FORWARD_ACCEPT, (void *) 0, 0);
 832 
 833                 if (rsaddr.contents != NULL)
 834                         free(rsaddr.contents);
 835 
 836                 if (rsport.contents != NULL)
 837                         free(rsport.contents);
 838 
 839                 if (auth_debug)
 840                         (void) fprintf(stderr, "\tForwarded "
 841                                                 "credentials obtained\r\n");
 842                 break;
 843         default:
 844                 if (auth_debug)
 845                         (void) fprintf(stderr,
 846                                     "\tUnknown Kerberos option %d\r\n",
 847                                     data[-1]);
 848                 reply_to_client(ap, KRB_REJECT, (void *) 0, 0);
 849                 break;
 850         }
 851         return;
 852 
 853 errout:
 854         reply_to_client(ap, KRB_REJECT, errbuf, -1);
 855 
 856         if (auth_debug)
 857                 (void) fprintf(stderr, "\tKerberos V5 error: %s\r\n", errbuf);
 858 
 859         syslog(LOG_ERR, "%s", errbuf);
 860 
 861         if (auth_context != NULL) {
 862                 (void) krb5_auth_con_free(telnet_context, auth_context);
 863                 auth_context = 0;
 864         }
 865 }
 866 
 867 static int
 868 krb5_init()
 869 {
 870         int code = 0;
 871 
 872         if (telnet_context == NULL) {
 873                 code = krb5_init_context(&telnet_context);
 874                 if (code != 0 && auth_debug)
 875                         syslog(LOG_NOTICE,
 876                             "Cannot initialize Kerberos V5: %s",
 877                             error_message(code));
 878         }
 879 
 880         return (code);
 881 }
 882 
 883 static void
 884 auth_name(uchar_t *data, int cnt)
 885 {
 886         char namebuf[MAXPRINCLEN];
 887 
 888         if (cnt < 1) {
 889                 if (auth_debug)
 890                         (void) fprintf(stderr,
 891                                     "\t(auth_name) Empty NAME in auth "
 892                                     "reply\n");
 893                 return;
 894         }
 895         if (cnt > sizeof (namebuf)-1) {
 896                 if (auth_debug)
 897                         (void) fprintf(stderr,
 898                                     "\t(auth_name) NAME exceeds %d bytes\n",
 899                                 sizeof (namebuf)-1);
 900                 return;
 901         }
 902         (void) memcpy((void *)namebuf, (void *)data, cnt);
 903         namebuf[cnt] = 0;
 904         if (auth_debug)
 905                 (void) fprintf(stderr, "\t(auth_name) name [%s]\n", namebuf);
 906         AuthenticatingUser = (char *)strdup(namebuf);
 907 }
 908 
 909 static void
 910 auth_is(uchar_t *data, int cnt)
 911 {
 912         AuthInfo *aptr = auth_list;
 913 
 914         if (cnt < 2)
 915                 return;
 916 
 917         /*
 918          * We failed to negoiate secure authentication
 919          */
 920         if (data[0] == AUTHTYPE_NULL) {
 921                 auth_finished(0, AUTH_REJECT);
 922                 return;
 923         }
 924 
 925         while (aptr->AuthName != 0 &&
 926             (aptr->AuthName != data[0] || aptr->AuthHow != data[1]))
 927                 aptr++;
 928 
 929         if (aptr != NULL) {
 930                 if (auth_debug)
 931                         (void) fprintf(stderr, "\t(auth_is) auth type is %s "
 932                                 "(%d bytes)\n", aptr->AuthString, cnt);
 933 
 934                 if (aptr->AuthName == AUTHTYPE_KERBEROS_V5)
 935                         kerberos5_is(aptr, data+2, cnt-2);
 936         }
 937 }
 938 
 939 static int
 940 krb5_user_status(char *name, int namelen, int level)
 941 {
 942         int retval = AUTH_USER;
 943 
 944         if (auth_debug)
 945                 (void) fprintf(stderr, "\t(krb5_user_status) level = %d "
 946                         "auth_level = %d  user = %s\n",
 947                         level, auth_level,
 948                         (AuthenticatingUser != NULL ? AuthenticatingUser : ""));
 949 
 950         if (level < AUTH_USER)
 951                 return (level);
 952 
 953         if (AuthenticatingUser != NULL &&
 954             (retval = krb5_kuserok(telnet_context, ticket->enc_part2->client,
 955                             AuthenticatingUser))) {
 956                 (void) strncpy(name, AuthenticatingUser, namelen);
 957                 return (AUTH_VALID);
 958         } else {
 959                 if (!retval)
 960                         syslog(LOG_ERR,
 961                             "Krb5 principal lacks permission to "
 962                             "access local account for %s",
 963                             AuthenticatingUser);
 964                 return (AUTH_USER);
 965         }
 966 }
 967 
 968 /*
 969  * Wrapper around /dev/urandom
 970  */
 971 static int
 972 getrandom(char *buf, int buflen)
 973 {
 974         static int devrandom = -1;
 975 
 976         if (devrandom == -1 &&
 977             (devrandom = open("/dev/urandom", O_RDONLY)) == -1) {
 978                 fatalperror(net, "Unable to open /dev/urandom: ",
 979                             errno);
 980                 return (-1);
 981         }
 982 
 983         if (read(devrandom, buf, buflen) == -1) {
 984                 fatalperror(net, "Unable to read from /dev/urandom: ",
 985                             errno);
 986                 return (-1);
 987         }
 988 
 989         return (0);
 990 }
 991 
 992 /*
 993  * encrypt_init
 994  *
 995  * Initialize the encryption data structures
 996  */
 997 static void
 998 encrypt_init()
 999 {
1000         (void) memset(&encr_data.encrypt, 0, sizeof (cipher_info_t));
1001         (void) memset(&encr_data.decrypt, 0, sizeof (cipher_info_t));
1002 
1003         encr_data.encrypt.state = ENCR_STATE_NOT_READY;
1004         encr_data.decrypt.state = ENCR_STATE_NOT_READY;
1005 }
1006 
1007 /*
1008  * encrypt_send_request_start
1009  *
1010  * Request that the remote side automatically start sending
1011  * encrypted output
1012  */
1013 static void
1014 encrypt_send_request_start()
1015 {
1016         uchar_t buf[6+TELNET_MAXKEYIDLEN], *p;
1017 
1018         p = buf;
1019 
1020         *p++ = IAC;
1021         *p++ = SB;
1022         *p++ = TELOPT_ENCRYPT;
1023         *p++ = ENCRYPT_REQSTART;
1024         /*
1025          * We are telling the remote side which
1026          * decrypt key we will use so that it may
1027          * encrypt in the same key.
1028          */
1029         (void) memcpy(p, encr_data.decrypt.keyid, encr_data.decrypt.keyidlen);
1030         p += encr_data.decrypt.keyidlen;
1031 
1032         *p++ = IAC;
1033         *p++ = SE;
1034 
1035         write_data_len((const char *)buf, p-buf);
1036         netflush();
1037         if (enc_debug)
1038                 (void) fprintf(stderr,
1039                             "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
1040 }
1041 
1042 /*
1043  * encrypt_is
1044  *
1045  * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
1046  * message, the client is telling us that it will be sending
1047  * encrypted data using the indicated cipher.
1048  * We must initialize the read (decrypt) side of our connection
1049  */
1050 static void
1051 encrypt_is(uchar_t *data, int cnt)
1052 {
1053         register int type;
1054         register int iv_status = CFB64_IV_OK;
1055         register int lstate = 0;
1056 
1057         uchar_t sbbuf[] = {
1058                 (uchar_t)IAC,
1059                 (uchar_t)SB,
1060                 (uchar_t)TELOPT_ENCRYPT,
1061                 (uchar_t)ENCRYPT_REPLY,
1062                 (uchar_t)0,             /* placeholder:  sbbuf[4] */
1063                 (uchar_t)CFB64_IV_OK,   /* placeholder:  sbbuf[5] */
1064                 (uchar_t)IAC,
1065                 (uchar_t)SE,
1066         };
1067 
1068         if (--cnt < 0)
1069                 return;
1070 
1071         type = sbbuf[4] = *data++;
1072 
1073         /*
1074          * Steps to take:
1075          *   1. Create the proper stream Initialization vector
1076          *              - copy the correct 'seed' to IV and output blocks
1077          *              - set the correct key schedule
1078          *   2. Generate reply for the other side:
1079          *              IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
1080          *              [ data ... ] IAC SE
1081          *   3. Tell crypto module:  method, direction, IV
1082          */
1083         switch (type) {
1084         case TELOPT_ENCTYPE_DES_CFB64:
1085                 encr_data.decrypt.type = type;
1086 
1087                 lstate = encr_data.decrypt.state;
1088                 if (enc_debug)
1089                         (void) fprintf(stderr,
1090                                     "\t(encrypt_is) initial state = %d\n",
1091                                     lstate);
1092                 /*
1093                  * Before we extract the IV bytes, make sure we got
1094                  * enough data.
1095                  */
1096                 if (cnt < sizeof (Block)) {
1097                         iv_status = CFB64_IV_BAD;
1098                         if (enc_debug)
1099                                 (void) fprintf(stderr,
1100                                             "\t(encrypt_is) Not enough "
1101                                             "IV bytes\n");
1102                         lstate = ENCR_STATE_NOT_READY;
1103                 } else {
1104                         data++; /* skip over the CFB64_IV byte */
1105                         (void) memcpy(encr_data.decrypt.ivec, data,
1106                                     sizeof (Block));
1107                         lstate = ENCR_STATE_IN_PROGRESS;
1108                 }
1109                 break;
1110         case TELOPT_ENCTYPE_NULL:
1111                 encr_data.decrypt.type = type;
1112                 lstate &= ~ENCR_STATE_NO_RECV_IV;
1113                 lstate &= ~ENCR_STATE_NO_SEND_IV;
1114                 if (enc_debug)
1115                         (void) fprintf(stderr,
1116                                 "\t(encrypt_is) We accept NULL encr\n");
1117                 break;
1118         default:
1119                 iv_status = CFB64_IV_BAD;
1120                 encr_data.decrypt.type = 0;
1121                 if (enc_debug)
1122                         (void) fprintf(stderr,
1123                                     "\t(encrypt_is) Can't find type (%d) "
1124                                     "for initial negotiation\r\n",
1125                                     type);
1126                 lstate = ENCR_STATE_NOT_READY;
1127                 break;
1128         }
1129 
1130         sbbuf[5] = (uchar_t)iv_status; /* either CFB64_IV_OK or BAD */
1131 
1132         if (iv_status == CFB64_IV_OK) {
1133                 /*
1134                  * send IV to crypto module and indicate it is for
1135                  * decrypt only
1136                  */
1137                 lstate &= ~ENCR_STATE_NO_RECV_IV;  /* we received an OK IV */
1138                 lstate &= ~ENCR_STATE_NO_SEND_IV;  /* we dont send an IV */
1139         } else {
1140                 /* tell crypto module to disable crypto on "read" stream */
1141                 lstate = ENCR_STATE_NOT_READY;
1142         }
1143 
1144         write_data_len((const char *)sbbuf, sizeof (sbbuf));
1145         netflush();
1146 #ifdef ENCRYPT_NAMES
1147         if (enc_debug)
1148                 (void) fprintf(stderr,
1149                             "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
1150                             ENCTYPE_NAME(type),
1151                             (iv_status == CFB64_IV_OK ? "CFB64_IV_OK" :
1152                             "CFB64_IV_BAD"));
1153 #endif /* ENCRYPT_NAMES */
1154         /* Update the state of the decryption negotiation */
1155         encr_data.decrypt.state = lstate;
1156 
1157         if (lstate == ENCR_STATE_NOT_READY)
1158                 encr_data.decrypt.autoflag = 0;
1159         else {
1160                 if (lstate == ENCR_STATE_OK && encr_data.decrypt.autoflag)
1161                         encrypt_send_request_start();
1162         }
1163         if (enc_debug)
1164                 (void) fprintf(stderr,
1165                             "\t(encrypt_is) final DECRYPT state = %d\n",
1166                             encr_data.decrypt.state);
1167 }
1168 
1169 /*
1170  * encrypt_send_encrypt_is
1171  *
1172  * Tell the client what encryption we will use
1173  * and what our IV will be.
1174  */
1175 static int
1176 encrypt_send_encrypt_is()
1177 {
1178         register int lstate;
1179         krb5_error_code kret;
1180         uchar_t sbbuf[MAXOPTLEN], *p;
1181         int i;
1182 
1183         lstate = encr_data.encrypt.state;
1184 
1185         if (encr_data.encrypt.type == ENCTYPE_NULL) {
1186                 /*
1187                  * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
1188                  * on a cipher.
1189                  */
1190                 return (lstate);
1191         }
1192 
1193         /*
1194          * - Create a random DES key
1195          *
1196          * - DES ECB encrypt
1197          *   encrypt the IV using itself as the key.
1198          *
1199          * - Send response
1200          *   IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
1201          *   IAC SE
1202          *
1203          */
1204         if (lstate == ENCR_STATE_NOT_READY)
1205                 lstate = ENCR_STATE_IN_PROGRESS;
1206         else if ((lstate & ENCR_STATE_NO_SEND_IV) == 0) {
1207                 if (enc_debug)
1208                         (void) fprintf(stderr,
1209                                 "\t(encrypt_send_is) IV already sent,"
1210                                 " state = %d\n", lstate);
1211                 return (lstate);
1212         }
1213 
1214         if (!VALIDKEY(encr_data.encrypt.krbdes_key)) {
1215                 /*
1216                  * Invalid key, set flag so we try again later
1217                  * when we get a good one
1218                  */
1219                 encr_data.encrypt.need_start = 1;
1220                 if (enc_debug)
1221                         (void) fprintf(stderr,
1222                                 "\t(encrypt_send_is) No Key, cannot "
1223                                 "start encryption yet\n");
1224                 return (lstate);
1225         }
1226         if (enc_debug)
1227                 (void) fprintf(stderr,
1228                             "\t(encrypt_send_is) Creating new feed\n");
1229 
1230         /*
1231          * Create a random feed and send it over.
1232          *
1233          * Use the /dev/[u]random interface to generate
1234          * our encryption IV.
1235          */
1236         kret = getrandom((char *)encr_data.encrypt.ivec, sizeof (Block));
1237 
1238         if (kret) {
1239                 if (enc_debug)
1240                         (void) fprintf(stderr,
1241                                     "\t(encrypt_send_is) error from "
1242                                     "getrandom: %d\n", kret);
1243                 syslog(LOG_ERR, "Failed to create encryption key (err %d)\n");
1244                 encr_data.encrypt.type = ENCTYPE_NULL;
1245         } else {
1246                 mit_des_fixup_key_parity(encr_data.encrypt.ivec);
1247         }
1248 
1249         p = sbbuf;
1250         *p++ = IAC;
1251         *p++ = SB;
1252         *p++ = TELOPT_ENCRYPT;
1253         *p++ = ENCRYPT_IS;
1254         *p++ = encr_data.encrypt.type;
1255         *p++ = CFB64_IV;
1256 
1257         /*
1258          * Copy the IV bytes individually so that when a
1259          * 255 (telnet IAC) is used, it can be "escaped" by
1260          * adding it twice (telnet RFC 854).
1261          */
1262         for (i = 0; i < sizeof (Block); i++)
1263                 if ((*p++ = encr_data.encrypt.ivec[i]) == IAC)
1264                         *p++ = IAC;
1265 
1266         *p++ = IAC;
1267         *p++ = SE;
1268         write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1269         netflush();
1270 
1271         if (!kret) {
1272                 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we sent our IV */
1273                 lstate &= ~ENCR_STATE_NO_SEND_IV; /* dont need decrypt IV */
1274         }
1275         encr_data.encrypt.state = lstate;
1276 
1277         if (enc_debug) {
1278                 int i;
1279                 (void) fprintf(stderr,
1280                             "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
1281                             encr_data.encrypt.type);
1282                 for (i = 0; i < (p-sbbuf); i++)
1283                         (void) fprintf(stderr, "%d ", (int)sbbuf[i]);
1284                 (void) fprintf(stderr, "\n");
1285         }
1286 
1287         return (lstate);
1288 }
1289 
1290 /*
1291  * stop_stream
1292  *
1293  * Utility routine to send a CRIOCSTOP ioctl to the
1294  * crypto module (cryptmod).
1295  */
1296 static void
1297 stop_stream(int fd, int dir)
1298 {
1299         struct strioctl  crioc;
1300         uint32_t stopdir = dir;
1301 
1302         crioc.ic_cmd = CRYPTIOCSTOP;
1303         crioc.ic_timout = -1;
1304         crioc.ic_len = sizeof (stopdir);
1305         crioc.ic_dp = (char *)&stopdir;
1306 
1307         if (ioctl(fd, I_STR, &crioc)) {
1308                 syslog(LOG_ERR, "Error sending CRYPTIOCSTOP ioctl: %m");
1309         }
1310 }
1311 
1312 /*
1313  * start_stream
1314  *
1315  * Utility routine to send a CRYPTIOCSTART ioctl to the
1316  * crypto module (cryptmod).  This routine may contain optional
1317  * payload data that the cryptmod will interpret as bytes that
1318  * need to be decrypted and sent back up to the application
1319  * via the data stream.
1320  */
1321 static void
1322 start_stream(int fd, int dir, int datalen, char *data)
1323 {
1324         struct strioctl crioc;
1325 
1326         crioc.ic_cmd = (dir == CRYPT_ENCRYPT ? CRYPTIOCSTARTENC :
1327                         CRYPTIOCSTARTDEC);
1328         crioc.ic_timout = -1;
1329         crioc.ic_len = datalen;
1330         crioc.ic_dp = data;
1331 
1332         if (ioctl(fd, I_STR, &crioc)) {
1333                 syslog(LOG_ERR, "Error sending CRYPTIOCSTART ioctl: %m");
1334         }
1335 }
1336 
1337 /*
1338  * encrypt_start_output
1339  *
1340  * Tell the other side to start encrypting its data
1341  */
1342 static void
1343 encrypt_start_output()
1344 {
1345         int lstate;
1346         uchar_t *p;
1347         uchar_t sbbuf[MAXOPTLEN];
1348         struct strioctl crioc;
1349         struct cr_info_t cki;
1350 
1351         /*
1352          * Initialize crypto and send the ENCRYPT_IS msg
1353          */
1354         lstate = encrypt_send_encrypt_is();
1355 
1356         if (lstate != ENCR_STATE_OK) {
1357                 if (enc_debug)
1358                         (void) fprintf(stderr,
1359                                 "\t(encrypt_start_output) ENCRYPT state "
1360                                 "= %d\n", lstate);
1361                 return;
1362         }
1363 
1364         p = sbbuf;
1365 
1366         *p++ = IAC;
1367         *p++ = SB;
1368         *p++ = TELOPT_ENCRYPT;
1369         *p++ = ENCRYPT_START;
1370 
1371         (void) memcpy(p, encr_data.encrypt.keyid, encr_data.encrypt.keyidlen);
1372         p += encr_data.encrypt.keyidlen;
1373 
1374         *p++ = IAC;
1375         *p++ = SE;
1376 
1377         /* Flush this data out before we start encrypting */
1378         write_data_len((const char *)sbbuf, (int)(p-sbbuf));
1379         netflush();
1380 
1381         if (enc_debug)
1382                 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
1383                         "(lstate = %d) data waiting = %d\n",
1384                         (int)encr_data.encrypt.keyid[0],
1385                         lstate, nfrontp-nbackp);
1386 
1387         encr_data.encrypt.state = lstate;
1388 
1389         /*
1390          * tell crypto module what key to use for encrypting
1391          * Note that the ENCRYPT has not yet been enabled, but we
1392          * need to first set the crypto key to use.
1393          */
1394         cki.direction_mask = CRYPT_ENCRYPT;
1395 
1396         if (encr_data.encrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1397                 cki.crypto_method = CRYPT_METHOD_DES_CFB;
1398         } else {
1399                 if (enc_debug)
1400                         (void) fprintf(stderr,
1401                                 "\t(encrypt_start_output) - unknown "
1402                                 "crypto_method %d\n",
1403                                 encr_data.encrypt.type);
1404                 syslog(LOG_ERR, "unrecognized crypto encrypt method: %d",
1405                                 encr_data.encrypt.type);
1406 
1407                 return;
1408         }
1409 
1410         /*
1411          * If we previously configured this crypto method, we dont want to
1412          * overwrite the key or ivec information already given to the crypto
1413          * module as it will cause the cipher data between the client and server
1414          * to become out of synch and impossible to decipher.
1415          */
1416         if (encr_data.encrypt.setup == cki.crypto_method) {
1417                 cki.keylen = 0;
1418                 cki.iveclen = 0;
1419         } else {
1420                 cki.keylen = DES_BLOCKSIZE;
1421                 (void) memcpy(cki.key, (void *)encr_data.encrypt.krbdes_key,
1422                     DES_BLOCKSIZE);
1423 
1424                 cki.iveclen = DES_BLOCKSIZE;
1425                 (void) memcpy(cki.ivec, (void *)encr_data.encrypt.ivec,
1426                     DES_BLOCKSIZE);
1427 
1428                 cki.ivec_usage = IVEC_ONETIME;
1429         }
1430 
1431         cki.option_mask = 0;
1432 
1433         /* Stop encrypt side prior to setup so we dont lose data */
1434         stop_stream(cryptmod_fd, CRYPT_ENCRYPT);
1435 
1436         crioc.ic_cmd = CRYPTIOCSETUP;
1437         crioc.ic_timout = -1;
1438         crioc.ic_len = sizeof (struct cr_info_t);
1439         crioc.ic_dp = (char *)&cki;
1440 
1441         if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1442                 perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
1443         } else {
1444                 /* Setup completed OK */
1445                 encr_data.encrypt.setup = cki.crypto_method;
1446         }
1447 
1448         /*
1449          * We do not check for "stuck" data when setting up the
1450          * outbound "encrypt" channel.  Any data queued prior to
1451          * this IOCTL will get processed correctly without our help.
1452          */
1453         start_stream(cryptmod_fd, CRYPT_ENCRYPT, 0, NULL);
1454 
1455         /*
1456          * tell crypto module to start encrypting
1457          */
1458         if (enc_debug)
1459                 (void) fprintf(stderr,
1460                         "\t(encrypt_start_output) Encrypting output\n");
1461 }
1462 
1463 /*
1464  * encrypt_request_start
1465  *
1466  * The client requests that we start encryption immediately after
1467  * successful negotiation
1468  */
1469 static void
1470 encrypt_request_start(void)
1471 {
1472         if (encr_data.encrypt.type == ENCTYPE_NULL) {
1473                 encr_data.encrypt.autoflag = 1;
1474                 if (enc_debug)
1475                         (void) fprintf(stderr, "\t(encrypt_request_start) "
1476                                 "autoencrypt = ON\n");
1477         } else {
1478                 encrypt_start_output();
1479         }
1480 }
1481 
1482 /*
1483  * encrypt_end
1484  *
1485  * ENCRYPT END received, stop decrypting the read stream
1486  */
1487 static void
1488 encrypt_end(int direction)
1489 {
1490         struct cr_info_t cki;
1491         struct strioctl  crioc;
1492         uint32_t stopdir;
1493 
1494         stopdir = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1495                 CRYPT_ENCRYPT);
1496 
1497         stop_stream(cryptmod_fd, stopdir);
1498 
1499         /*
1500          * Call this function when we wish to disable crypto in
1501          * either direction (ENCRYPT or DECRYPT)
1502          */
1503         cki.direction_mask = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1504                             CRYPT_ENCRYPT);
1505         cki.crypto_method = CRYPT_METHOD_NONE;
1506         cki.option_mask = 0;
1507 
1508         cki.keylen = 0;
1509         cki.iveclen = 0;
1510         cki.ivec_usage = IVEC_ONETIME;
1511 
1512         crioc.ic_cmd = CRYPTIOCSETUP;
1513         crioc.ic_timout = -1;
1514         crioc.ic_len = sizeof (cki);
1515         crioc.ic_dp = (char *)&cki;
1516 
1517         if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1518                 perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
1519         }
1520 
1521         start_stream(cryptmod_fd, stopdir, 0, NULL);
1522 }
1523 
1524 /*
1525  * encrypt_request_end
1526  *
1527  * When we receive a REQEND from the client, it means
1528  * that we are supposed to stop encrypting
1529  */
1530 static void
1531 encrypt_request_end()
1532 {
1533         /*
1534          * Tell the other side we are done encrypting
1535          */
1536 
1537         write_data("%c%c%c%c%c%c",
1538                 (uchar_t)IAC,
1539                 (uchar_t)SB,
1540                 (uchar_t)TELOPT_ENCRYPT,
1541                 (uchar_t)ENCRYPT_END,
1542                 (uchar_t)IAC,
1543                 (uchar_t)SE);
1544         netflush();
1545         if (enc_debug)
1546                 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
1547 
1548         /*
1549          * Turn off encryption of the write stream
1550          */
1551         encrypt_end(TELNET_DIR_ENCRYPT);
1552 }
1553 
1554 /*
1555  * encrypt_send_request_end
1556  *
1557  * We stop encrypting the write stream and tell the other side about it.
1558  */
1559 static void
1560 encrypt_send_request_end()
1561 {
1562         write_data("%c%c%c%c%c%c",
1563                 (uchar_t)IAC,
1564                 (uchar_t)SB,
1565                 (uchar_t)TELOPT_ENCRYPT,
1566                 (uchar_t)ENCRYPT_REQEND,
1567                 (uchar_t)IAC,
1568                 (uchar_t)SE);
1569         netflush();
1570         if (enc_debug)
1571                 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
1572 }
1573 
1574 /*
1575  * encrypt_start
1576  *
1577  * The client is going to start sending encrypted data
1578  * using the previously negotiated cipher (see what we set
1579  * when we did the REPLY in encrypt_is).
1580  */
1581 static void
1582 encrypt_start(void)
1583 {
1584         struct cr_info_t cki;
1585         struct strioctl  crioc;
1586         int bytes = 0;
1587         char *dataptr = NULL;
1588 
1589         if (encr_data.decrypt.type == ENCTYPE_NULL) {
1590                 if (enc_debug)
1591                         (void) fprintf(stderr,
1592                                 "\t(encrypt_start) No DECRYPT method "
1593                                 "defined yet\n");
1594                 encrypt_send_request_end();
1595                 return;
1596         }
1597 
1598         cki.direction_mask = CRYPT_DECRYPT;
1599 
1600         if (encr_data.decrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1601                 cki.crypto_method = CRYPT_METHOD_DES_CFB;
1602         } else {
1603                 if (enc_debug)
1604                         (void) fprintf(stderr,
1605                                 "\t(encrypt_start) - unknown "
1606                                 "crypto_method %d\n", encr_data.decrypt.type);
1607 
1608                 syslog(LOG_ERR, "unrecognized crypto decrypt method: %d",
1609                                 encr_data.decrypt.type);
1610 
1611                 return;
1612         }
1613 
1614         /*
1615          * Don't overwrite previously configured key and ivec info
1616          */
1617         if (encr_data.decrypt.setup != cki.crypto_method) {
1618                 (void) memcpy(cki.key, (void *)encr_data.decrypt.krbdes_key,
1619                     DES_BLOCKSIZE);
1620                 (void) memcpy(cki.ivec, (void *)encr_data.decrypt.ivec,
1621                     DES_BLOCKSIZE);
1622 
1623                 cki.keylen = DES_BLOCKSIZE;
1624                 cki.iveclen = DES_BLOCKSIZE;
1625                 cki.ivec_usage = IVEC_ONETIME;
1626         } else {
1627                 cki.keylen = 0;
1628                 cki.iveclen = 0;
1629         }
1630         cki.option_mask = 0;
1631 
1632         stop_stream(cryptmod_fd, CRYPT_DECRYPT);
1633 
1634         crioc.ic_cmd = CRYPTIOCSETUP;
1635         crioc.ic_timout = -1;
1636         crioc.ic_len = sizeof (struct cr_info_t);
1637         crioc.ic_dp = (char *)&cki;
1638 
1639         if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1640                 syslog(LOG_ERR, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
1641                     "error: %m");
1642         } else {
1643                 encr_data.decrypt.setup = cki.crypto_method;
1644         }
1645         if (enc_debug)
1646                 (void) fprintf(stderr,
1647                             "\t(encrypt_start) called CRYPTIOCSETUP for "
1648                             "decrypt side\n");
1649 
1650         /*
1651          * Read any data stuck between the cryptmod and the application
1652          * so we can pass it back down to be properly decrypted after
1653          * this operation finishes.
1654          */
1655         if (ioctl(cryptmod_fd, I_NREAD, &bytes) < 0) {
1656                 syslog(LOG_ERR, "I_NREAD returned error %m");
1657                 bytes = 0;
1658         }
1659 
1660         /*
1661          * Any data which was read AFTER the ENCRYPT START message
1662          * must be sent back down to be decrypted properly.
1663          *
1664          * 'ncc' is the number of bytes that have been read but
1665          * not yet processed by the telnet state machine.
1666          *
1667          * 'bytes' is the number of bytes waiting to be read from
1668          * the stream.
1669          *
1670          * If either one is a positive value, then those bytes
1671          * must be pulled up and sent back down to be decrypted.
1672          */
1673         if (ncc || bytes) {
1674                 drainstream(bytes);
1675                 if (enc_debug)
1676                         (void) fprintf(stderr,
1677                                 "\t(encrypt_start) after drainstream, "
1678                                 "ncc=%d bytes = %d\n", ncc, bytes);
1679                 bytes += ncc;
1680                 dataptr = netip;
1681         }
1682 
1683         start_stream(cryptmod_fd, CRYPT_DECRYPT, bytes, dataptr);
1684 
1685         /*
1686          * The bytes putback into the stream are no longer
1687          * available to be read by the server, so adjust the
1688          * counter accordingly.
1689          */
1690         ncc = 0;
1691         netip = netibuf;
1692         (void) memset(netip, 0, netibufsize);
1693 
1694 #ifdef ENCRYPT_NAMES
1695         if (enc_debug) {
1696                 (void) fprintf(stderr,
1697                             "\t(encrypt_start) Start DECRYPT using %s\n",
1698                             ENCTYPE_NAME(encr_data.decrypt.type));
1699         }
1700 #endif /* ENCRYPT_NAMES */
1701 }
1702 
1703 /*
1704  * encrypt_support
1705  *
1706  * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
1707  * message from a client.
1708  *
1709  * Choose an agreeable method (DES_CFB64) and
1710  * respond with  TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
1711  *
1712  * from: RFC 2946
1713  */
1714 static void
1715 encrypt_support(char *data, int cnt)
1716 {
1717         int lstate = ENCR_STATE_NOT_READY;
1718         int type, use_type = 0;
1719 
1720         while (cnt-- > 0 && use_type == 0) {
1721                 type = *data++;
1722 #ifdef ENCRYPT_NAMES
1723                 if (enc_debug)
1724                         (void) fprintf(stderr,
1725                                     "RCVD ENCRYPT SUPPORT %s\n",
1726                                     ENCTYPE_NAME(type));
1727 #endif /* ENCRYPT_NAMES */
1728                 /*
1729                  * Prefer CFB64
1730                  */
1731                 if (type == TELOPT_ENCTYPE_DES_CFB64) {
1732                         use_type = type;
1733                 }
1734         }
1735         encr_data.encrypt.type = use_type;
1736 
1737         if (use_type != TELOPT_ENCTYPE_NULL &&
1738             authenticated != NULL && authenticated != &NoAuth &&
1739             auth_status != AUTH_REJECT) {
1740 
1741                 /* Authenticated -> have session key -> send ENCRYPT IS */
1742                 lstate = encrypt_send_encrypt_is();
1743                 if (lstate == ENCR_STATE_OK)
1744                         encrypt_start_output();
1745         } else if (use_type == TELOPT_ENCTYPE_NULL) {
1746                 if (enc_debug)
1747                         (void) fprintf(stderr,
1748                                     "\t(encrypt_support) Cannot agree "
1749                                     "on crypto algorithm, output encryption "
1750                                     "disabled.\n");
1751 
1752                 /*
1753                  * Cannot agree on crypto algorithm
1754                  * RFC 2946 sez:
1755                  *    send "IAC SB ENCRYPT IS NULL IAC SE"
1756                  *    optionally, also send IAC WONT ENCRYPT
1757                  */
1758                 write_data("%c%c%c%c%c%c%c",
1759                         (uchar_t)IAC,
1760                         (uchar_t)SB,
1761                         (uchar_t)TELOPT_ENCRYPT,
1762                         (uchar_t)ENCRYPT_IS,
1763                         (uchar_t)TELOPT_ENCTYPE_NULL,
1764                         (uchar_t)IAC,
1765                         (uchar_t)SE);
1766                 send_wont(TELOPT_ENCRYPT);
1767                 netflush();
1768                 if (enc_debug)
1769                         (void) fprintf(stderr,
1770                                     "SENT TELOPT_ENCRYPT ENCRYPT_IS "
1771                                     "[NULL]\n");
1772 
1773                 remopts[TELOPT_ENCRYPT] = OPT_NO;
1774         }
1775         settimer(encr_support);
1776 }
1777 
1778 /*
1779  * encrypt_send_keyid
1780  *
1781  * Sent the key id we will use to the client
1782  */
1783 static void
1784 encrypt_send_keyid(int dir, uchar_t *keyid, int keylen, boolean_t saveit)
1785 {
1786         uchar_t sbbuf[128], *p;
1787 
1788         p = sbbuf;
1789 
1790         *p++ = IAC;
1791         *p++ = SB;
1792         *p++ = TELOPT_ENCRYPT;
1793         *p++ = (dir == TELNET_DIR_ENCRYPT ? ENCRYPT_ENC_KEYID :
1794                 ENCRYPT_DEC_KEYID);
1795         if (saveit) {
1796                 if (enc_debug)
1797                         (void) fprintf(stderr,
1798                                 "\t(send_keyid) store %d byte %s keyid\n",
1799                                 keylen,
1800                                 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1801                                 "DECRYPT"));
1802 
1803                 if (dir == TELNET_DIR_ENCRYPT) {
1804                         (void) memcpy(encr_data.encrypt.keyid, keyid, keylen);
1805                         encr_data.encrypt.keyidlen = keylen;
1806                 } else {
1807                         (void) memcpy(encr_data.decrypt.keyid, keyid, keylen);
1808                         encr_data.decrypt.keyidlen = keylen;
1809                 }
1810         }
1811         (void) memcpy(p, keyid, keylen);
1812         p += keylen;
1813 
1814         *p++ = IAC;
1815         *p++ = SE;
1816         write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1817         netflush();
1818 
1819         if (enc_debug)
1820                 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT %s %d\n",
1821                         (dir == TELNET_DIR_ENCRYPT ? "ENC_KEYID" :
1822                         "DEC_KEYID"), keyid[0]);
1823 }
1824 
1825 /*
1826  * encrypt_reply
1827  *
1828  * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
1829  * message, process it accordingly.
1830  * If the vector is acceptable, tell client we are encrypting and
1831  * enable encryption on our write stream.
1832  *
1833  * Negotiate the KEYID next..
1834  * RFC 2946, 2952
1835  */
1836 static void
1837 encrypt_reply(char *data, int len)
1838 {
1839         uchar_t type = (uchar_t)(*data++);
1840         uchar_t result = (uchar_t)(*data);
1841         int lstate;
1842 
1843 #ifdef ENCRYPT_NAMES
1844         if (enc_debug)
1845                 (void) fprintf(stderr,
1846                         "\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
1847                         ENCRYPT_NAME(type),
1848                         (result == CFB64_IV_OK ? "CFB64_IV_OK" :
1849                         "CFB64_IV_BAD"), len);
1850 #endif /* ENCRYPT_NAMES */
1851 
1852         lstate = encr_data.encrypt.state;
1853         if (enc_debug)
1854                 (void) fprintf(stderr,
1855                         "\t(encrypt_reply) initial ENCRYPT state = %d\n",
1856                         lstate);
1857         switch (result) {
1858         case CFB64_IV_OK:
1859                 if (lstate == ENCR_STATE_NOT_READY)
1860                         lstate = ENCR_STATE_IN_PROGRESS;
1861                 lstate &= ~ENCR_STATE_NO_RECV_IV; /* we got the IV */
1862                 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont need to send IV */
1863 
1864                 /*
1865                  * The correct response here is to send the encryption key id
1866                  * RFC 2752.
1867                  *
1868                  * Send keyid 0 to indicate that we will just use default
1869                  * keys.
1870                  */
1871                 encrypt_send_keyid(TELNET_DIR_ENCRYPT, (uchar_t *)"\0", 1, 1);
1872 
1873                 break;
1874         case CFB64_IV_BAD:
1875                 /*
1876                  * Clear the ivec
1877                  */
1878                 (void) memset(encr_data.encrypt.ivec, 0, sizeof (Block));
1879                 lstate = ENCR_STATE_NOT_READY;
1880                 break;
1881         default:
1882                 if (enc_debug)
1883                         (void) fprintf(stderr,
1884                                 "\t(encrypt_reply) Got unknown IV value in "
1885                                 "REPLY message\n");
1886                 lstate = ENCR_STATE_NOT_READY;
1887                 break;
1888         }
1889 
1890         encr_data.encrypt.state = lstate;
1891         if (lstate == ENCR_STATE_NOT_READY) {
1892                 encr_data.encrypt.autoflag = 0;
1893                 encr_data.encrypt.type = ENCTYPE_NULL;
1894                 if (enc_debug)
1895                         (void) fprintf(stderr,
1896                                     "\t(encrypt_reply) encrypt.autoflag = "
1897                                     "OFF\n");
1898         } else {
1899                 encr_data.encrypt.type = type;
1900                 if ((lstate == ENCR_STATE_OK) && encr_data.encrypt.autoflag)
1901                         encrypt_start_output();
1902         }
1903 
1904         if (enc_debug)
1905                 (void) fprintf(stderr,
1906                             "\t(encrypt_reply) ENCRYPT final state = %d\n",
1907                             lstate);
1908 }
1909 
1910 static void
1911 encrypt_set_keyid_state(uchar_t *keyid, int *keyidlen, int dir)
1912 {
1913         int lstate;
1914 
1915         lstate = (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state :
1916                 encr_data.decrypt.state);
1917 
1918         if (enc_debug)
1919                 (void) fprintf(stderr,
1920                             "\t(set_keyid_state) %s initial state = %d\n",
1921                             (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1922                             "DECRYPT"), lstate);
1923 
1924         /*
1925          * Currently, we only support using the default keyid,
1926          * so it should be an error if the len > 1 or the keyid != 0.
1927          */
1928         if (*keyidlen != 1 || (*keyid != '\0')) {
1929                 if (enc_debug)
1930                         (void) fprintf(stderr,
1931                                     "\t(set_keyid_state) unexpected keyid: "
1932                                     "len=%d value=%d\n", *keyidlen, *keyid);
1933                 *keyidlen = 0;
1934                 syslog(LOG_ERR, "rcvd unexpected keyid %d  - only keyid of 0 "
1935                     "is supported",  *keyid);
1936         } else {
1937                 /*
1938                  * We move to the "IN_PROGRESS" state.
1939                  */
1940                 if (lstate == ENCR_STATE_NOT_READY)
1941                         lstate = ENCR_STATE_IN_PROGRESS;
1942                 /*
1943                  * Clear the NO_KEYID bit because we now have a valid keyid
1944                  */
1945                 lstate &= ~ENCR_STATE_NO_KEYID;
1946         }
1947 
1948         if (enc_debug)
1949                 (void) fprintf(stderr,
1950                             "\t(set_keyid_state) %s final state = %d\n",
1951                             (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1952                             "DECRYPT"), lstate);
1953 
1954         if (dir == TELNET_DIR_ENCRYPT)
1955                 encr_data.encrypt.state = lstate;
1956         else
1957                 encr_data.decrypt.state = lstate;
1958 }
1959 
1960 /*
1961  * encrypt_keyid
1962  *
1963  * Set the keyid value in the key_info structure.
1964  * if necessary send a response to the sender
1965  */
1966 static void
1967 encrypt_keyid(uchar_t *newkeyid, int *keyidlen, uchar_t *keyid,
1968         int len, int dir)
1969 {
1970         if (len > TELNET_MAXNUMKEYS) {
1971                 if (enc_debug)
1972                         (void) fprintf(stderr,
1973                                     "\t(keyid) keylen too big (%d)\n", len);
1974                 return;
1975         }
1976 
1977         if (enc_debug) {
1978                 (void) fprintf(stderr, "\t(keyid) set KEYID for %s len = %d\n",
1979                             (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1980                             "DECRYPT"), len);
1981         }
1982 
1983         if (len == 0) {
1984                 if (*keyidlen == 0) {
1985                         if (enc_debug)
1986                                 (void) fprintf(stderr,
1987                                             "\t(keyid) Got 0 length keyid - "
1988                                             "failure\n");
1989                         return;
1990                 }
1991                 *keyidlen = 0;
1992                 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
1993 
1994         } else if (len != *keyidlen || memcmp(keyid, newkeyid, len)) {
1995                 if (enc_debug)
1996                         (void) fprintf(stderr,
1997                                     "\t(keyid) Setting new key (%d bytes)\n",
1998                                     len);
1999 
2000                 *keyidlen = len;
2001                 (void) memcpy(newkeyid, keyid, len);
2002 
2003                 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2004         } else {
2005                 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2006 
2007                 if (enc_debug)
2008                         (void) fprintf(stderr,
2009                                     "\t(keyid) %s Key already in place,"
2010                                     "state = %d autoflag=%d\n",
2011                         (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT"),
2012                         (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state:
2013                         encr_data.decrypt.state),
2014                         (dir == TELNET_DIR_ENCRYPT ?
2015                                 encr_data.encrypt.autoflag:
2016                                 encr_data.decrypt.autoflag));
2017 
2018                 /* key already in place */
2019                 if ((encr_data.encrypt.state == ENCR_STATE_OK) &&
2020                     dir == TELNET_DIR_ENCRYPT && encr_data.encrypt.autoflag) {
2021                         encrypt_start_output();
2022                 }
2023                 return;
2024         }
2025 
2026         if (enc_debug)
2027                 (void) fprintf(stderr, "\t(keyid) %s final state = %d\n",
2028                             (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
2029                             "DECRYPT"),
2030                             (dir == TELNET_DIR_ENCRYPT ?
2031                             encr_data.encrypt.state :
2032                             encr_data.decrypt.state));
2033 
2034         encrypt_send_keyid(dir, newkeyid, *keyidlen, 0);
2035 }
2036 
2037 /*
2038  * encrypt_enc_keyid
2039  *
2040  * We received the ENC_KEYID message from a client indicating that
2041  * the client wishes to verify that the indicated keyid maps to a
2042  * valid key.
2043  */
2044 static void
2045 encrypt_enc_keyid(char *data, int cnt)
2046 {
2047         /*
2048          * Verify the decrypt keyid is valid
2049          */
2050         encrypt_keyid(encr_data.decrypt.keyid, &encr_data.decrypt.keyidlen,
2051                     (uchar_t *)data, cnt, TELNET_DIR_DECRYPT);
2052 }
2053 
2054 /*
2055  * encrypt_dec_keyid
2056  *
2057  * We received the DEC_KEYID message from a client indicating that
2058  * the client wants to verify that the indicated keyid maps to a valid key.
2059  */
2060 static void
2061 encrypt_dec_keyid(char *data, int cnt)
2062 {
2063         encrypt_keyid(encr_data.encrypt.keyid, &encr_data.encrypt.keyidlen,
2064                     (uchar_t *)data, cnt, TELNET_DIR_ENCRYPT);
2065 }
2066 
2067 /*
2068  * encrypt_session_key
2069  *
2070  * Store the session key in the encryption data record
2071  */
2072 static void
2073 encrypt_session_key(Session_Key *key, cipher_info_t *cinfo)
2074 {
2075         if (key == NULL || key->type != SK_DES) {
2076                 if (enc_debug)
2077                         (void) fprintf(stderr,
2078                                     "\t(session_key) Cannot set krb5 "
2079                                     "session key (unknown type = %d)\n",
2080                                     key ? key->type : -1);
2081         }
2082         if (enc_debug)
2083                 (void) fprintf(stderr,
2084                             "\t(session_key) Settting session key "
2085                             "for server\n");
2086 
2087         /* store the key in the cipher info data struct */
2088         (void) memcpy(cinfo->krbdes_key, (void *)key->data, sizeof (Block));
2089 
2090         /*
2091          * Now look to see if we still need to send the key and start
2092          * encrypting.
2093          *
2094          * If so, go ahead an call it now that we have the key.
2095          */
2096         if (cinfo->need_start) {
2097                 if (encrypt_send_encrypt_is() == ENCR_STATE_OK) {
2098                         cinfo->need_start = 0;
2099                 }
2100         }
2101 }
2102 
2103 /*
2104  * new_env
2105  *
2106  * Used to add an environment variable and value to the
2107  * linked list structure.
2108  */
2109 static int
2110 new_env(const char *name, const char *value)
2111 {
2112         struct envlist *env;
2113 
2114         env = malloc(sizeof (struct envlist));
2115         if (env == NULL)
2116                 return (1);
2117         if ((env->name = strdup(name)) == NULL) {
2118                 free(env);
2119                 return (1);
2120         }
2121         if ((env->value = strdup(value)) == NULL) {
2122                 free(env->name);
2123                 free(env);
2124                 return (1);
2125         }
2126         env->delete = 0;
2127         env->next = envlist_head;
2128         envlist_head = env;
2129         return (0);
2130 }
2131 
2132 /*
2133  * del_env
2134  *
2135  * Used to delete an environment variable from the linked list
2136  * structure.  We just set a flag because we will delete the list
2137  * anyway before we exec login.
2138  */
2139 static int
2140 del_env(const char *name)
2141 {
2142         struct envlist *env;
2143 
2144         for (env = envlist_head; env; env = env->next) {
2145                 if (strcmp(env->name, name) == 0) {
2146                         env->delete = 1;
2147                         break;
2148                 }
2149         }
2150         return (0);
2151 }
2152 
2153 static int
2154 issock(int fd)
2155 {
2156         struct stat stats;
2157 
2158         if (fstat(fd, &stats) == -1)
2159                 return (0);
2160         return (S_ISSOCK(stats.st_mode));
2161 }
2162 
2163 /*
2164  * audit_telnet_settid stores the terminal id while it is still
2165  * available.  Subsequent calls to adt_load_hostname() return
2166  * the id which is stored here.
2167  */
2168 static int
2169 audit_telnet_settid(int sock) {
2170         adt_session_data_t      *ah;
2171         adt_termid_t            *termid;
2172         int                     rc;
2173 
2174         if ((rc = adt_start_session(&ah, NULL, 0)) == 0) {
2175                 if ((rc = adt_load_termid(sock, &termid)) == 0) {
2176                         if ((rc = adt_set_user(ah, ADT_NO_AUDIT,
2177                             ADT_NO_AUDIT, 0, ADT_NO_AUDIT,
2178                             termid, ADT_SETTID)) == 0)
2179                                 (void) adt_set_proc(ah);
2180                         free(termid);
2181                 }
2182                 (void) adt_end_session(ah);
2183         }
2184         return (rc);
2185 }
2186 
2187 /* ARGSUSED */
2188 int
2189 main(int argc, char *argv[])
2190 {
2191         struct sockaddr_storage from;
2192         int on = 1;
2193         socklen_t fromlen;
2194         int issocket;
2195 #if     defined(DEBUG)
2196         ushort_t porttouse = 0;
2197         boolean_t standalone = 0;
2198 #endif /* defined(DEBUG) */
2199         extern char *optarg;
2200         char c;
2201         int tos = -1;
2202 
2203         while ((c = getopt(argc, argv, TELNETD_OPTS DEBUG_OPTS)) != -1) {
2204                 switch (c) {
2205 #if defined(DEBUG)
2206                 case 'p':
2207                         /*
2208                          * note: alternative port number only used in
2209                          * standalone mode.
2210                          */
2211                         porttouse = atoi(optarg);
2212                         standalone = 1;
2213                         break;
2214                 case 'e':
2215                         enc_debug = 1;
2216                         break;
2217 #endif /* DEBUG */
2218                 case 'a':
2219                         if (strcasecmp(optarg, "none") == 0) {
2220                                 auth_level = 0;
2221                         } else if (strcasecmp(optarg, "user") == 0) {
2222                                 auth_level = AUTH_USER;
2223                         } else if (strcasecmp(optarg, "valid") == 0) {
2224                                 auth_level = AUTH_VALID;
2225                         } else if (strcasecmp(optarg, "off") == 0) {
2226                                 auth_level = -1;
2227                                 negotiate_auth_krb5 = 0;
2228                         } else if (strcasecmp(optarg, "debug") == 0) {
2229                                 auth_debug = 1;
2230                         } else {
2231                                 syslog(LOG_ERR,
2232                                     "unknown authentication level specified "
2233                                     "with \'-a\' option (%s)", optarg);
2234                                 auth_level = AUTH_USER;
2235                         }
2236                         break;
2237                 case 'X':
2238                         /* disable authentication negotiation */
2239                         negotiate_auth_krb5 = 0;
2240                         break;
2241                 case 'R':
2242                 case 'M':
2243                         if (optarg != NULL) {
2244                                 int ret = krb5_init();
2245                                 if (ret) {
2246                                         syslog(LOG_ERR,
2247                                                 "Unable to use Kerberos V5 as "
2248                                                 "requested, exiting");
2249                                         exit(1);
2250                                 }
2251                                 (void) krb5_set_default_realm(telnet_context,
2252                                     optarg);
2253                                 syslog(LOG_NOTICE,
2254                                     "using %s as default KRB5 realm", optarg);
2255                         }
2256                         break;
2257                 case 'S':
2258                         telnet_srvtab = (char *)strdup(optarg);
2259                         break;
2260                 case 'E': /* disable automatic encryption */
2261                         negotiate_encrypt = B_FALSE;
2262                         break;
2263                 case 'U':
2264                         resolve_hostname = 1;
2265                         break;
2266                 case 's':
2267                         if (optarg == NULL || (tos = atoi(optarg)) < 0 ||
2268                             tos > 255) {
2269                                 syslog(LOG_ERR, "telnetd: illegal tos value: "
2270                                     "%s\n", optarg);
2271                         } else {
2272                                 if (tos < 0)
2273                                         tos = 020;
2274                         }
2275                         break;
2276                 case 'h':
2277                         show_hostinfo = 0;
2278                         break;
2279                 default:
2280                         syslog(LOG_ERR, "telnetd: illegal cmd line option %c",
2281                             c);
2282                         break;
2283                 }
2284         }
2285 
2286         netibufsize = BUFSIZ;
2287         if (!(netibuf = (char *)malloc(netibufsize)))
2288                 syslog(LOG_ERR, "netibuf malloc failed\n");
2289         (void) memset(netibuf, 0, netibufsize);
2290         netip = netibuf;
2291 
2292 #if     defined(DEBUG)
2293         if (standalone) {
2294                 int s, ns, foo;
2295                 struct servent *sp;
2296                 static struct sockaddr_in6 sin6 = { AF_INET6 };
2297                 int option = 1;
2298 
2299                 if (porttouse) {
2300                         sin6.sin6_port = htons(porttouse);
2301                 } else {
2302                         sp = getservbyname("telnet", "tcp");
2303                         if (sp == 0) {
2304                                 (void) fprintf(stderr,
2305                                             "telnetd: tcp/telnet: "
2306                                             "unknown service\n");
2307                                 exit(EXIT_FAILURE);
2308                         }
2309                         sin6.sin6_port = sp->s_port;
2310                 }
2311 
2312                 s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
2313                 if (s < 0) {
2314                         perror("telnetd: socket");
2315                         exit(EXIT_FAILURE);
2316                 }
2317                 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&option,
2318                     sizeof (option)) == -1)
2319                         perror("setsockopt SO_REUSEADDR");
2320                 if (bind(s, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) {
2321                         perror("bind");
2322                         exit(EXIT_FAILURE);
2323                 }
2324                 if (listen(s, 32) < 0) {
2325                         perror("listen");
2326                         exit(EXIT_FAILURE);
2327                 }
2328 
2329                 /* automatically reap all child processes */
2330                 (void) signal(SIGCHLD, SIG_IGN);
2331 
2332                 for (;;) {
2333                         pid_t pid;
2334 
2335                         foo = sizeof (sin6);
2336                         ns = accept(s, (struct sockaddr *)&sin6, &foo);
2337                         if (ns < 0) {
2338                                 perror("accept");
2339                                 exit(EXIT_FAILURE);
2340                         }
2341                         pid = fork();
2342                         if (pid == -1) {
2343                                 perror("fork");
2344                                 exit(EXIT_FAILURE);
2345                         }
2346                         if (pid == 0) {
2347                                 (void) dup2(ns, 0);
2348                                 (void) close(s);
2349                                 (void) signal(SIGCHLD, SIG_DFL);
2350                                 break;
2351                         }
2352                         (void) close(ns);
2353                 }
2354         }
2355 #endif /* defined(DEBUG) */
2356 
2357         openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
2358 
2359         issocket = issock(0);
2360         if (!issocket)
2361                 fatal(0, "stdin is not a socket file descriptor");
2362 
2363         fromlen = (socklen_t)sizeof (from);
2364         (void) memset((char *)&from, 0, sizeof (from));
2365         if (getpeername(0, (struct sockaddr *)&from, &fromlen)
2366             < 0) {
2367                 (void) fprintf(stderr, "%s: ", argv[0]);
2368                 perror("getpeername");
2369                 _exit(EXIT_FAILURE);
2370         }
2371 
2372         if (audit_telnet_settid(0)) {   /* set terminal ID */
2373                 (void) fprintf(stderr, "%s: ", argv[0]);
2374                 perror("audit");
2375                 exit(EXIT_FAILURE);
2376         }
2377 
2378         if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on,
2379                                                 sizeof (on)) < 0) {
2380                 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
2381         }
2382 
2383         /*
2384          * Set the TOS value
2385          */
2386         if (tos != -1 &&
2387             setsockopt(0, IPPROTO_IP, IP_TOS,
2388                     (char *)&tos, sizeof (tos)) < 0 &&
2389                 errno != ENOPROTOOPT) {
2390                 syslog(LOG_ERR, "setsockopt (IP_TOS %d): %m", tos);
2391         }
2392 
2393         if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on,
2394             sizeof (on)) < 0) {
2395                 syslog(LOG_WARNING, "setsockopt (SO_OOBINLINE): %m");
2396         }
2397 
2398         /* set the default PAM service name */
2399         (void) strcpy(pam_svc_name, "telnet");
2400 
2401         doit(0, &from);
2402         return (EXIT_SUCCESS);
2403 }
2404 
2405 static char     *terminaltype = 0;
2406 
2407 /*
2408  * ttloop
2409  *
2410  *      A small subroutine to flush the network output buffer, get some data
2411  * from the network, and pass it through the telnet state machine.  We
2412  * also flush the pty input buffer (by dropping its data) if it becomes
2413  * too full.
2414  */
2415 static void
2416 ttloop(void)
2417 {
2418         if (nfrontp-nbackp) {
2419                 netflush();
2420         }
2421 read_again:
2422         ncc = read(net, netibuf, netibufsize);
2423         if (ncc < 0) {
2424                 if (errno == EINTR)
2425                         goto read_again;
2426                 syslog(LOG_INFO, "ttloop:  read: %m");
2427                 exit(EXIT_FAILURE);
2428         } else if (ncc == 0) {
2429                 syslog(LOG_INFO, "ttloop:  peer closed connection\n");
2430                 exit(EXIT_FAILURE);
2431         }
2432 
2433         netip = netibuf;
2434         telrcv();               /* state machine */
2435         if (ncc > 0) {
2436                 pfrontp = pbackp = ptyobuf;
2437                 telrcv();
2438         }
2439 }
2440 
2441 static void
2442 send_do(int option)
2443 {
2444         write_data("%c%c%c", (uchar_t)IAC, (uchar_t)DO, (uchar_t)option);
2445 }
2446 
2447 static void
2448 send_will(int option)
2449 {
2450         write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WILL, (uchar_t)option);
2451 }
2452 
2453 static void
2454 send_wont(int option)
2455 {
2456         write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WONT, (uchar_t)option);
2457 }
2458 
2459 
2460 /*
2461  * getauthtype
2462  *
2463  * Negotiate automatic authentication, is possible.
2464  */
2465 static int
2466 getauthtype(char *username, int *len)
2467 {
2468         int init_status = -1;
2469 
2470         init_status = krb5_init();
2471 
2472         if (auth_level == -1 || init_status != 0) {
2473                 remopts[TELOPT_AUTHENTICATION] = OPT_NO;
2474                 myopts[TELOPT_AUTHENTICATION] = OPT_NO;
2475                 negotiate_auth_krb5 = B_FALSE;
2476                 negotiate_encrypt = B_FALSE;
2477                 return (AUTH_REJECT);
2478         }
2479 
2480         if (init_status == 0 && auth_level != -1) {
2481                 if (negotiate_auth_krb5) {
2482                         /*
2483                          * Negotiate Authentication FIRST
2484                          */
2485                         send_do(TELOPT_AUTHENTICATION);
2486                         remopts[TELOPT_AUTHENTICATION] =
2487                                 OPT_YES_BUT_ALWAYS_LOOK;
2488                 }
2489                 while (sequenceIs(authopt, getauth))
2490                         ttloop();
2491 
2492                 if (remopts[TELOPT_AUTHENTICATION] == OPT_YES) {
2493                         /*
2494                          * Request KRB5 Mutual authentication and if that fails,
2495                          * KRB5 1-way client authentication
2496                          */
2497                         uchar_t sbbuf[MAXOPTLEN], *p;
2498                         p = sbbuf;
2499                         *p++ = (uchar_t)IAC;
2500                         *p++ = (uchar_t)SB;
2501                         *p++ = (uchar_t)TELOPT_AUTHENTICATION;
2502                         *p++ = (uchar_t)TELQUAL_SEND;
2503                         if (negotiate_auth_krb5) {
2504                                 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2505                                 *p++ = (uchar_t)(AUTH_WHO_CLIENT |
2506                                                 AUTH_HOW_MUTUAL |
2507                                                 AUTH_ENCRYPT_ON);
2508                                 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2509                                 *p++ = (uchar_t)(AUTH_WHO_CLIENT |
2510                                                 AUTH_HOW_MUTUAL);
2511                                 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2512                                 *p++ = (uchar_t)(AUTH_WHO_CLIENT|
2513                                                 AUTH_HOW_ONE_WAY);
2514                         } else {
2515                                 *p++ = (uchar_t)AUTHTYPE_NULL;
2516                         }
2517                         *p++ = (uchar_t)IAC;
2518                         *p++ = (uchar_t)SE;
2519 
2520                         write_data_len((const char *)sbbuf,
2521                                     (size_t)(p - sbbuf));
2522                         netflush();
2523                         if (auth_debug)
2524                                 (void) fprintf(stderr,
2525                                             "SENT TELOPT_AUTHENTICATION "
2526                                             "[data]\n");
2527 
2528                         /* auth_wait returns the authentication level */
2529                         /* status = auth_wait(username, len); */
2530                         while (sequenceIs(authdone, getauth))
2531                                 ttloop();
2532                         /*
2533                          * Now check to see if the user is valid or not
2534                          */
2535                         if (authenticated == NULL || authenticated == &NoAuth)
2536                                 auth_status = AUTH_REJECT;
2537                         else {
2538                                 /*
2539                                  * We cant be VALID until the user status is
2540                                  * checked.
2541                                  */
2542                                 if (auth_status == AUTH_VALID)
2543                                         auth_status = AUTH_USER;
2544 
2545                                 if (authenticated->AuthName ==
2546                                         AUTHTYPE_KERBEROS_V5)
2547                                         auth_status = krb5_user_status(
2548                                                 username, *len, auth_status);
2549                         }
2550                 }
2551         }
2552         return (auth_status);
2553 }
2554 
2555 static void
2556 getencrtype(void)
2557 {
2558         if (krb5_privacy_allowed() && negotiate_encrypt) {
2559                 if (myopts[TELOPT_ENCRYPT] != OPT_YES) {
2560                         if (!sent_will_encrypt) {
2561                                 send_will(TELOPT_ENCRYPT);
2562                                 sent_will_encrypt = B_TRUE;
2563                         }
2564                         if (enc_debug)
2565                                 (void) fprintf(stderr, "SENT WILL ENCRYPT\n");
2566                 }
2567                 if (remopts[TELOPT_ENCRYPT] != OPT_YES) {
2568                         if (!sent_do_encrypt) {
2569                                 send_do(TELOPT_ENCRYPT);
2570                                 sent_do_encrypt = B_TRUE;
2571                                 remopts[TELOPT_ENCRYPT] =
2572                                     OPT_YES_BUT_ALWAYS_LOOK;
2573                         }
2574                         if (enc_debug)
2575                                 (void) fprintf(stderr, "SENT DO ENCRYPT\n");
2576                 }
2577                 myopts[TELOPT_ENCRYPT] = OPT_YES;
2578 
2579                 while (sequenceIs(encropt, getencr))
2580                     ttloop();
2581 
2582                 if (auth_status != AUTH_REJECT &&
2583                     remopts[TELOPT_ENCRYPT] == OPT_YES &&
2584                     myopts[TELOPT_ENCRYPT] == OPT_YES) {
2585 
2586                         if (sent_encrypt_support == B_FALSE) {
2587                                 write_data("%c%c%c%c%c%c%c",
2588                                         (uchar_t)IAC,
2589                                         (uchar_t)SB,
2590                                         (uchar_t)TELOPT_ENCRYPT,
2591                                         (uchar_t)ENCRYPT_SUPPORT,
2592                                         (uchar_t)TELOPT_ENCTYPE_DES_CFB64,
2593                                         (uchar_t)IAC,
2594                                         (uchar_t)SE);
2595 
2596                                 netflush();
2597                         }
2598                         /*
2599                          * Now wait for a response to these messages before
2600                          * continuing...
2601                          * Look for TELOPT_ENCRYPT suboptions
2602                          */
2603                         while (sequenceIs(encr_support, getencr))
2604                                 ttloop();
2605                 }
2606         } else {
2607                 /* Dont need responses to these, so dont wait for them */
2608                 settimer(encropt);
2609                 remopts[TELOPT_ENCRYPT] = OPT_NO;
2610                 myopts[TELOPT_ENCRYPT] = OPT_NO;
2611         }
2612 
2613 }
2614 
2615 /*
2616  * getterminaltype
2617  *
2618  * Ask the other end to send along its terminal type.
2619  * Output is the variable terminaltype filled in.
2620  */
2621 static void
2622 getterminaltype(void)
2623 {
2624         /*
2625          * The remote side may have already sent this info, so
2626          * dont ask for these options if the other side already
2627          * sent the information.
2628          */
2629         if (sequenceIs(ttypeopt, getterminal)) {
2630                 send_do(TELOPT_TTYPE);
2631                 remopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK;
2632         }
2633 
2634         if (sequenceIs(nawsopt, getterminal)) {
2635                 send_do(TELOPT_NAWS);
2636                 remopts[TELOPT_NAWS] = OPT_YES_BUT_ALWAYS_LOOK;
2637         }
2638 
2639         if (sequenceIs(xdisplocopt, getterminal)) {
2640                 send_do(TELOPT_XDISPLOC);
2641                 remopts[TELOPT_XDISPLOC] = OPT_YES_BUT_ALWAYS_LOOK;
2642         }
2643 
2644         if (sequenceIs(environopt, getterminal)) {
2645                 send_do(TELOPT_NEW_ENVIRON);
2646                 remopts[TELOPT_NEW_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2647         }
2648 
2649         if (sequenceIs(oenvironopt, getterminal)) {
2650                 send_do(TELOPT_OLD_ENVIRON);
2651                 remopts[TELOPT_OLD_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2652         }
2653 
2654         /* make sure encryption is started here */
2655         while (auth_status != AUTH_REJECT &&
2656                 authenticated != &NoAuth && authenticated != NULL &&
2657                 remopts[TELOPT_ENCRYPT] == OPT_YES &&
2658                 encr_data.encrypt.autoflag &&
2659                 encr_data.encrypt.state != ENCR_STATE_OK) {
2660             if (enc_debug)
2661                 (void) fprintf(stderr, "getterminaltype() forcing encrypt\n");
2662             ttloop();
2663         }
2664 
2665         if (enc_debug) {
2666             (void) fprintf(stderr, "getterminaltype() encryption %sstarted\n",
2667                     encr_data.encrypt.state == ENCR_STATE_OK ? "" : "not ");
2668         }
2669 
2670         while (sequenceIs(ttypeopt, getterminal) ||
2671             sequenceIs(nawsopt, getterminal) ||
2672             sequenceIs(xdisplocopt, getterminal) ||
2673             sequenceIs(environopt, getterminal) ||
2674             sequenceIs(oenvironopt, getterminal)) {
2675                 ttloop();
2676         }
2677 
2678 
2679         if (remopts[TELOPT_TTYPE] == OPT_YES) {
2680                 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2681                     (uchar_t)TELOPT_TTYPE, (uchar_t)TELQUAL_SEND,
2682                     (uchar_t)IAC, (uchar_t)SE };
2683 
2684                 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2685         }
2686         if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2687                 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2688                     (uchar_t)TELOPT_XDISPLOC, (uchar_t)TELQUAL_SEND,
2689                     (uchar_t)IAC, (uchar_t)SE };
2690 
2691                 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2692         }
2693         if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2694                 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2695                     (uchar_t)TELOPT_NEW_ENVIRON, (uchar_t)TELQUAL_SEND,
2696                     (uchar_t)IAC, (uchar_t)SE };
2697 
2698                 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2699         }
2700         if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2701                 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2702                     (uchar_t)TELOPT_OLD_ENVIRON, (uchar_t)TELQUAL_SEND,
2703                     (uchar_t)IAC, (uchar_t)SE };
2704 
2705                 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2706         }
2707 
2708         if (remopts[TELOPT_TTYPE] == OPT_YES) {
2709                 while (sequenceIs(ttypesubopt, getterminal)) {
2710                         ttloop();
2711                 }
2712         }
2713         if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2714                 while (sequenceIs(xdisplocsubopt, getterminal)) {
2715                         ttloop();
2716                 }
2717         }
2718         if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2719                 while (sequenceIs(environsubopt, getterminal)) {
2720                         ttloop();
2721                 }
2722         }
2723         if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2724                 while (sequenceIs(oenvironsubopt, getterminal)) {
2725                         ttloop();
2726                 }
2727         }
2728         init_neg_done = 1;
2729 }
2730 
2731 pid_t pid;
2732 
2733 /*
2734  * Get a pty, scan input lines.
2735  */
2736 static void
2737 doit(int f, struct sockaddr_storage *who)
2738 {
2739         char *host;
2740         char host_name[MAXHOSTNAMELEN];
2741         int p, t, tt;
2742         struct sgttyb b;
2743         int     ptmfd;  /* fd of logindmux connected to pty */
2744         int     netfd;  /* fd of logindmux connected to netf */
2745         struct  stat    buf;
2746         struct  protocol_arg    telnetp;
2747         struct  strioctl        telnetmod;
2748         struct  envlist *env, *next;
2749         int     nsize = 0;
2750         char abuf[INET6_ADDRSTRLEN];
2751         struct sockaddr_in *sin;
2752         struct sockaddr_in6 *sin6;
2753         socklen_t wholen;
2754         char username[MAXUSERNAMELEN];
2755         int len;
2756         uchar_t passthru;
2757         char *subsidname;
2758 
2759         if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) {
2760                 fatalperror(f, "open /dev/ptmx", errno);
2761         }
2762         if (grantpt(p) == -1)
2763                 fatal(f, "could not grant subsidiary pty");
2764         if (unlockpt(p) == -1)
2765                 fatal(f, "could not unlock subsidiary pty");
2766         if ((subsidname = ptsname(p)) == NULL)
2767                 fatal(f, "could not enable subsidiary pty");
2768         (void) dup2(f, 0);
2769         if ((t = open(subsidname, O_RDWR | O_NOCTTY)) == -1)
2770                 fatal(f, "could not open subsidiary pty");
2771         if (ioctl(t, I_PUSH, "ptem") == -1)
2772                 fatalperror(f, "ioctl I_PUSH ptem", errno);
2773         if (ioctl(t, I_PUSH, "ldterm") == -1)
2774                 fatalperror(f, "ioctl I_PUSH ldterm", errno);
2775         if (ioctl(t, I_PUSH, "ttcompat") == -1)
2776                 fatalperror(f, "ioctl I_PUSH ttcompat", errno);
2777 
2778         line = subsidname;
2779 
2780         pty = t;
2781 
2782         if (ioctl(t, TIOCGETP, &b) == -1)
2783                 syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n");
2784         b.sg_flags = O_CRMOD|O_XTABS|O_ANYP;
2785         /* XXX - ispeed and ospeed must be non-zero */
2786         b.sg_ispeed = B38400;
2787         b.sg_ospeed = B38400;
2788         if (ioctl(t, TIOCSETN, &b) == -1)
2789                 syslog(LOG_INFO, "ioctl TIOCSETN pty t: %m\n");
2790         if (ioctl(pty, TIOCGETP, &b) == -1)
2791                 syslog(LOG_INFO, "ioctl TIOCGETP pty pty: %m\n");
2792         b.sg_flags &= ~O_ECHO;
2793         if (ioctl(pty, TIOCSETN, &b) == -1)
2794                 syslog(LOG_INFO, "ioctl TIOCSETN pty pty: %m\n");
2795 
2796         if (who->ss_family == AF_INET) {
2797                 char *addrbuf = NULL;
2798                 char *portbuf = NULL;
2799 
2800                 sin = (struct sockaddr_in *)who;
2801                 wholen = sizeof (struct sockaddr_in);
2802 
2803                 addrbuf = (char *)malloc(wholen);
2804                 if (addrbuf == NULL)
2805                         fatal(f, "Cannot alloc memory for address info\n");
2806                 portbuf = (char *)malloc(sizeof (sin->sin_port));
2807                 if (portbuf == NULL) {
2808                         free(addrbuf);
2809                         fatal(f, "Cannot alloc memory for port info\n");
2810                 }
2811 
2812                 (void) memcpy(addrbuf, (const void *)&sin->sin_addr, wholen);
2813                 (void) memcpy(portbuf, (const void *)&sin->sin_port,
2814                             sizeof (sin->sin_port));
2815 
2816                 if (rsaddr.contents != NULL)
2817                         free(rsaddr.contents);
2818 
2819                 rsaddr.contents = (krb5_octet *)addrbuf;
2820                 rsaddr.length = wholen;
2821                 rsaddr.addrtype = ADDRTYPE_INET;
2822 
2823                 if (rsport.contents != NULL)
2824                         free(rsport.contents);
2825 
2826                 rsport.contents = (krb5_octet *)portbuf;
2827                 rsport.length = sizeof (sin->sin_port);
2828                 rsport.addrtype = ADDRTYPE_IPPORT;
2829         } else if (who->ss_family == AF_INET6) {
2830                 struct in_addr ipv4_addr;
2831                 char *addrbuf = NULL;
2832                 char *portbuf = NULL;
2833 
2834                 sin6 = (struct sockaddr_in6 *)who;
2835                 wholen = sizeof (struct sockaddr_in6);
2836 
2837                 IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2838                                     &ipv4_addr);
2839 
2840                 addrbuf = (char *)malloc(wholen);
2841                 if (addrbuf == NULL)
2842                         fatal(f, "Cannot alloc memory for address info\n");
2843 
2844                 portbuf = (char *)malloc(sizeof (sin6->sin6_port));
2845                 if (portbuf == NULL) {
2846                         free(addrbuf);
2847                         fatal(f, "Cannot alloc memory for port info\n");
2848                 }
2849 
2850                 (void) memcpy((void *) addrbuf,
2851                             (const void *)&ipv4_addr,
2852                             wholen);
2853                 /*
2854                  * If we already used rsaddr.contents, free the previous
2855                  * buffer.
2856                  */
2857                 if (rsaddr.contents != NULL)
2858                         free(rsaddr.contents);
2859 
2860                 rsaddr.contents = (krb5_octet *)addrbuf;
2861                 rsaddr.length = sizeof (ipv4_addr);
2862                 rsaddr.addrtype = ADDRTYPE_INET;
2863 
2864                 (void) memcpy((void *) portbuf, (const void *)&sin6->sin6_port,
2865                             sizeof (sin6->sin6_port));
2866 
2867                 if (rsport.contents != NULL)
2868                         free(rsport.contents);
2869 
2870                 rsport.contents = (krb5_octet *)portbuf;
2871                 rsport.length = sizeof (sin6->sin6_port);
2872                 rsport.addrtype = ADDRTYPE_IPPORT;
2873         } else {
2874                 syslog(LOG_ERR, "unknown address family %d\n",
2875                     who->ss_family);
2876                 fatal(f, "getpeername: unknown address family\n");
2877         }
2878 
2879         if (getnameinfo((const struct sockaddr *) who, wholen, host_name,
2880             sizeof (host_name), NULL, 0, 0) == 0) {
2881                 host = host_name;
2882         } else {
2883                 /*
2884                  * If the '-U' option was given on the cmd line, we must
2885                  * be able to lookup the hostname
2886                  */
2887                 if (resolve_hostname) {
2888                         fatal(f, "Couldn't resolve your address into a "
2889                             "host name.\r\nPlease contact your net "
2890                             "administrator");
2891                 }
2892 
2893                 if (who->ss_family == AF_INET6) {
2894                         if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2895                                 struct in_addr ipv4_addr;
2896 
2897                                 IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2898                                     &ipv4_addr);
2899                                 host = (char *)inet_ntop(AF_INET,
2900                                     &ipv4_addr, abuf, sizeof (abuf));
2901                         } else {
2902                                 host = (char *)inet_ntop(AF_INET6,
2903                                     &sin6->sin6_addr, abuf,
2904                                     sizeof (abuf));
2905                         }
2906                 } else if (who->ss_family == AF_INET) {
2907                                 host = (char *)inet_ntop(AF_INET,
2908                                     &sin->sin_addr, abuf, sizeof (abuf));
2909                         }
2910         }
2911         /*
2912          * Note that sockmod has to be removed since readstream assumes
2913          * a "raw" TPI endpoint (e.g. it uses getmsg).
2914          */
2915         if (removemod(f, "sockmod") < 0)
2916                 fatalperror(f, "couldn't remove sockmod", errno);
2917 
2918         encrypt_init();
2919 
2920         /*
2921          * Push the crypto module on the stream before 'telmod' so it
2922          * can encrypt/decrypt without interfering with telmod functionality
2923          * We must push it now because many of the crypto options negotiated
2924          * initially must be saved in the crypto module (via IOCTL calls).
2925          */
2926         if (ioctl(f, I_PUSH, "cryptmod") < 0)
2927                 fatalperror(f, "ioctl I_PUSH cryptmod", errno);
2928 
2929         cryptmod_fd = f;
2930         /*
2931          * gotta set the encryption clock now because it is often negotiated
2932          * immediately by the client, and if we wait till after we negotiate
2933          * auth, it will be out of whack with when the WILL/WONT ENCRYPT
2934          * option is received.
2935          */
2936         settimer(getencr);
2937 
2938         /*
2939          * get terminal type.
2940          */
2941         username[0] = '\0';
2942         len = sizeof (username);
2943 
2944         settimer(getterminal);
2945         settimer(getauth);
2946         /*
2947          * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
2948          */
2949         auth_status = getauthtype(username, &len);
2950         /*
2951          * Exchange TELOPT_ENCRYPT options per RFC 2946
2952          */
2953         getencrtype();
2954         getterminaltype();
2955 
2956         if (ioctl(f, I_PUSH, "telmod") < 0)
2957                 fatalperror(f, "ioctl I_PUSH telmod", errno);
2958 
2959         /*
2960          * Make sure telmod will pass unrecognized IOCTLs to cryptmod
2961          */
2962         passthru = 1;
2963 
2964         telnetmod.ic_cmd = CRYPTPASSTHRU;
2965         telnetmod.ic_timout = -1;
2966         telnetmod.ic_len = sizeof (uchar_t);
2967         telnetmod.ic_dp = (char *)&passthru;
2968 
2969         if (ioctl(f, I_STR, &telnetmod) < 0)
2970                 fatal(f, "ioctl CRPASSTHRU failed\n");
2971 
2972         if (!ncc)
2973                 netip = netibuf;
2974 
2975         /*
2976          * readstream will do a getmsg till it receives M_PROTO type
2977          * T_DATA_REQ from telnetmodopen().  This signals that all data
2978          * in-flight before telmod was pushed has been received at the
2979          * stream head.
2980          */
2981         while ((nsize = readstream(f, netibuf, ncc + netip - netibuf)) > 0) {
2982                 ncc += nsize;
2983         }
2984 
2985         if (nsize < 0) {
2986                 fatalperror(f, "readstream failed\n", errno);
2987         }
2988 
2989         /*
2990          * open logindmux drivers and link them with network and ptm
2991          * file descriptors.
2992          */
2993         if ((ptmfd = open("/dev/logindmux", O_RDWR)) == -1) {
2994                 fatalperror(f, "open /dev/logindmux", errno);
2995         }
2996         if ((netfd = open("/dev/logindmux", O_RDWR)) == -1) {
2997                 fatalperror(f, "open /dev/logindmux", errno);
2998         }
2999 
3000         if (ioctl(ptmfd, I_LINK, p) < 0)
3001                 fatal(f, "ioctl I_LINK of /dev/ptmx failed\n");
3002         if (ioctl(netfd, I_LINK, f) < 0)
3003                 fatal(f, "ioctl I_LINK of tcp connection failed\n");
3004 
3005         /*
3006          * Figure out the device number of ptm's mux fd, and pass that
3007          * to the net's mux.
3008          */
3009         if (fstat(ptmfd, &buf) < 0) {
3010                 fatalperror(f, "fstat ptmfd failed", errno);
3011         }
3012         telnetp.dev = buf.st_rdev;
3013         telnetp.flag = 0;
3014 
3015         telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
3016         telnetmod.ic_timout = -1;
3017         telnetmod.ic_len = sizeof (struct protocol_arg);
3018         telnetmod.ic_dp = (char *)&telnetp;
3019 
3020         if (ioctl(netfd, I_STR, &telnetmod) < 0)
3021                 fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
3022 
3023         /*
3024          * Figure out the device number of the net's mux fd, and pass that
3025          * to the ptm's mux.
3026          */
3027         if (fstat(netfd, &buf) < 0) {
3028                 fatalperror(f, "fstat netfd failed", errno);
3029         }
3030         telnetp.dev = buf.st_rdev;
3031         telnetp.flag = 1;
3032 
3033         telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
3034         telnetmod.ic_timout = -1;
3035         telnetmod.ic_len = sizeof (struct protocol_arg);
3036         telnetmod.ic_dp = (char *)&telnetp;
3037 
3038         if (ioctl(ptmfd, I_STR, &telnetmod) < 0)
3039                 fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
3040 
3041         net = netfd;
3042         manager = ptmfd;
3043         cryptmod_fd = netfd;
3044 
3045         /*
3046          * Show banner that getty never gave, but
3047          * only if the user did not automatically authenticate.
3048          */
3049         if (getenv("USER") == NULL && auth_status < AUTH_USER)
3050                 showbanner();
3051 
3052         /*
3053          * If the user automatically authenticated with Kerberos
3054          * we must set the service name that PAM will use.  We
3055          * need to do it BEFORE the child fork so that 'cleanup'
3056          * in the parent can call the PAM cleanup stuff with the
3057          * same PAM service that /bin/login will use to authenticate
3058          * this session.
3059          */
3060         if (auth_level >= 0 && auth_status >= AUTH_USER &&
3061             (AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) {
3062                 (void) strcpy(pam_svc_name, "ktelnet");
3063         }
3064         /*
3065          * Request to do suppress go ahead.
3066          *
3067          * Send this before sending the TELOPT_ECHO stuff below because
3068          * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
3069          * that has them turn off local echo mode if SGA is not received first.
3070          * This also has the odd side-effect of causing the client to enable
3071          * encryption and then immediately disable it during the ECHO option
3072          * negotiations.  Its just better to to SGA first now that we support
3073          * encryption.
3074          */
3075         if (!myopts[TELOPT_SGA]) {
3076             dooption(TELOPT_SGA);
3077         }
3078 
3079         /*
3080          * Pretend we got a DO ECHO from the client if we have not
3081          * yet negotiated the ECHO.
3082          */
3083         if (!myopts[TELOPT_ECHO]) {
3084             dooption(TELOPT_ECHO);
3085         }
3086 
3087         /*
3088          * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
3089          * because 4.2 clients are unable to deal with TCP urgent data.
3090          *
3091          * To find out, we send out a "DO ECHO".  If the remote system
3092          * answers "WILL ECHO" it is probably a 4.2 client, and we note
3093          * that fact ("WILL ECHO" ==> that the client will echo what
3094          * WE, the server, sends it; it does NOT mean that the client will
3095          * echo the terminal input).
3096          */
3097         send_do(TELOPT_ECHO);
3098         remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;
3099 
3100         if ((pid = fork()) < 0)
3101                 fatalperror(netfd, "fork", errno);
3102         if (pid)
3103                 telnet(net, manager);
3104         /*
3105          * The child process needs to be the session leader
3106          * and have the pty as its controlling tty.  Thus we need
3107          * to re-open the subsidiary side of the pty no without
3108          * the O_NOCTTY flag that we have been careful to
3109          * use up to this point.
3110          */
3111         (void) setsid();
3112 
3113         tt = open(line, O_RDWR);
3114         if (tt < 0)
3115                 fatalperror(netfd, line, errno);
3116         (void) close(netfd);
3117         (void) close(ptmfd);
3118         (void) close(f);
3119         (void) close(p);
3120         (void) close(t);
3121         if (tt != 0)
3122                 (void) dup2(tt, 0);
3123         if (tt != 1)
3124                 (void) dup2(tt, 1);
3125         if (tt != 2)
3126                 (void) dup2(tt, 2);
3127         if (tt > 2)
3128                 (void) close(tt);
3129 
3130         if (terminaltype)
3131                 (void) local_setenv("TERM", terminaltype+5, 1);
3132         /*
3133          *      -h : pass on name of host.
3134          *              WARNING:  -h is accepted by login if and only if
3135          *                      getuid() == 0.
3136          *      -p : don't clobber the environment (so terminal type stays set).
3137          */
3138         {
3139                 /* System V login expects a utmp entry to already be there */
3140                 struct utmpx ut;
3141                 (void) memset((char *)&ut, 0, sizeof (ut));
3142                 (void) strncpy(ut.ut_user, ".telnet", sizeof (ut.ut_user));
3143                 (void) strncpy(ut.ut_line, line, sizeof (ut.ut_line));
3144                 ut.ut_pid = getpid();
3145                 ut.ut_id[0] = 't';
3146                 ut.ut_id[1] = (char)SC_WILDC;
3147                 ut.ut_id[2] = (char)SC_WILDC;
3148                 ut.ut_id[3] = (char)SC_WILDC;
3149                 ut.ut_type = LOGIN_PROCESS;
3150                 ut.ut_exit.e_termination = 0;
3151                 ut.ut_exit.e_exit = 0;
3152                 (void) time(&ut.ut_tv.tv_sec);
3153                 if (makeutx(&ut) == NULL)
3154                         syslog(LOG_INFO, "in.telnetd:\tmakeutx failed");
3155         }
3156 
3157         /*
3158          * Load in the cached environment variables and either
3159          * set/unset them in the environment.
3160          */
3161         for (next = envlist_head; next; ) {
3162                 env = next;
3163                 if (env->delete)
3164                         (void) local_unsetenv(env->name);
3165                 else
3166                         (void) local_setenv(env->name, env->value, 1);
3167                 free(env->name);
3168                 free(env->value);
3169                 next = env->next;
3170                 free(env);
3171         }
3172 
3173         if (!username || !username[0])
3174                 auth_status = AUTH_REJECT; /* we dont know who this is */
3175 
3176         /* If the current auth status is less than the required level, exit */
3177         if (auth_status < auth_level) {
3178                 fatal(net, "Authentication failed\n");
3179                 exit(EXIT_FAILURE);
3180         }
3181 
3182         /*
3183          * If AUTH_VALID (proper authentication REQUIRED and we have
3184          * a krb5_name), exec '/bin/login', make sure it uses the
3185          * correct PAM service name (pam_svc_name). If possible,
3186          * make sure the krb5 authenticated user's name (krb5_name)
3187          * is in the PAM REPOSITORY for krb5.
3188          */
3189         if (auth_level >= 0 &&
3190             (auth_status == AUTH_VALID || auth_status == AUTH_USER) &&
3191             ((krb5_name != NULL) && strlen(krb5_name)) &&
3192             ((AuthenticatingUser != NULL) && strlen(AuthenticatingUser))) {
3193                 (void) execl(LOGIN_PROGRAM, "login",
3194                             "-p",
3195                             "-d", subsidname,
3196                             "-h", host,
3197                             "-u", krb5_name,
3198                             "-s", pam_svc_name,
3199                             "-R", KRB5_REPOSITORY_NAME,
3200                             AuthenticatingUser, 0);
3201         } else if (auth_level >= 0 &&
3202                 auth_status >= AUTH_USER &&
3203                 (((AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) ||
3204                 getenv("USER"))) {
3205                 /*
3206                  * If we only know the name but not the principal,
3207                  * login will have to authenticate further.
3208                  */
3209                 (void) execl(LOGIN_PROGRAM, "login",
3210                     "-p",
3211                     "-d", subsidname,
3212                     "-h", host,
3213                     "-s", pam_svc_name, "--",
3214                     (AuthenticatingUser != NULL ? AuthenticatingUser :
3215                         getenv("USER")), 0);
3216 
3217         } else /* default, no auth. info available, login does it all */ {
3218                 (void) execl(LOGIN_PROGRAM, "login",
3219                     "-p", "-h", host, "-d", subsidname, "--",
3220                     getenv("USER"), 0);
3221         }
3222 
3223         fatalperror(netfd, LOGIN_PROGRAM, errno);
3224         /*NOTREACHED*/
3225 }
3226 
3227 static void
3228 fatal(int f, char *msg)
3229 {
3230         char buf[BUFSIZ];
3231 
3232         (void) snprintf(buf, sizeof (buf), "telnetd: %s.\r\n", msg);
3233         (void) write(f, buf, strlen(buf));
3234         exit(EXIT_FAILURE);
3235         /*NOTREACHED*/
3236 }
3237 
3238 static void
3239 fatalperror(int f, char *msg, int errnum)
3240 {
3241         char buf[BUFSIZ];
3242 
3243         (void) snprintf(buf, sizeof (buf),
3244                         "%s: %s\r\n", msg, strerror(errnum));
3245         fatal(f, buf);
3246         /*NOTREACHED*/
3247 }
3248 
3249 /*
3250  * Main loop.  Select from pty and network, and
3251  * hand data to telnet receiver finite state machine
3252  * when it receives telnet protocol. Regular data
3253  * flow between pty and network takes place through
3254  * inkernel telnet streams module (telmod).
3255  */
3256 static void
3257 telnet(int net, int manager)
3258 {
3259         int on = 1;
3260         char mode;
3261         struct  strioctl        telnetmod;
3262         int     nsize = 0;
3263         char    binary_in = 0;
3264         char binary_out = 0;
3265 
3266         if (ioctl(net, FIONBIO, &on) == -1)
3267                 syslog(LOG_INFO, "ioctl FIONBIO net: %m\n");
3268         if (ioctl(manager, FIONBIO, &on) == -1)
3269                 syslog(LOG_INFO, "ioctl FIONBIO pty p: %m\n");
3270         (void) signal(SIGTSTP, SIG_IGN);
3271         (void) signal(SIGCHLD, (void (*)())cleanup);
3272         (void) setpgrp();
3273 
3274         /*
3275          * Call telrcv() once to pick up anything received during
3276          * terminal type negotiation.
3277          */
3278         telrcv();
3279 
3280         netflush();
3281         ptyflush();
3282 
3283         for (;;) {
3284                 fd_set ibits, obits, xbits;
3285                 int c;
3286 
3287                 if (ncc < 0)
3288                         break;
3289 
3290                 FD_ZERO(&ibits);
3291                 FD_ZERO(&obits);
3292                 FD_ZERO(&xbits);
3293 
3294                 /*
3295                  * If we couldn't flush all our output to the network,
3296                  * keep checking for when we can.
3297                  */
3298                 if (nfrontp - nbackp)
3299                         FD_SET(net, &obits);
3300                 /*
3301                  * Never look for input if there's still
3302                  * stuff in the corresponding output buffer
3303                  */
3304                 if (pfrontp - pbackp) {
3305                         FD_SET(manager, &obits);
3306                 } else {
3307                         FD_SET(net, &ibits);
3308                 }
3309                 if (!SYNCHing) {
3310                         FD_SET(net, &xbits);
3311                 }
3312 
3313 #define max(x, y)       (((x) < (y)) ? (y) : (x))
3314 
3315                 /*
3316                  * make an ioctl to telnet module (net side) to send
3317                  * binary mode of telnet daemon. binary_in and
3318                  * binary_out are 0 if not in binary mode.
3319                  */
3320                 if (binary_in != myopts[TELOPT_BINARY] ||
3321                     binary_out != remopts[TELOPT_BINARY]) {
3322 
3323                         mode = 0;
3324                         if (myopts[TELOPT_BINARY] != OPT_NO)
3325                                 mode |= TEL_BINARY_IN;
3326 
3327                         if (remopts[TELOPT_BINARY] != OPT_NO)
3328                                 mode |= TEL_BINARY_OUT;
3329 
3330                         telnetmod.ic_cmd = TEL_IOC_MODE;
3331                         telnetmod.ic_timout = -1;
3332                         telnetmod.ic_len = 1;
3333                         telnetmod.ic_dp = &mode;
3334 
3335                         syslog(LOG_DEBUG, "TEL_IOC_MODE binary has changed\n");
3336 
3337                         if (ioctl(net, I_STR, &telnetmod) < 0)
3338                                 fatal(net, "ioctl TEL_IOC_MODE failed\n");
3339                         binary_in = myopts[TELOPT_BINARY];
3340                         binary_out = remopts[TELOPT_BINARY];
3341                 }
3342                 if (state == TS_DATA) {
3343                         if ((nfrontp == nbackp) &&
3344                                 (pfrontp == pbackp)) {
3345                                 if (ioctl(net, I_NREAD, &nsize) < 0)
3346                                         fatalperror(net,
3347                                             "ioctl I_NREAD failed\n", errno);
3348                                 if (nsize)
3349                                         drainstream(nsize);
3350 
3351                                 /*
3352                                  * make an ioctl to reinsert remaining data at
3353                                  * streamhead. After this, ioctl reenables the
3354                                  * telnet lower put queue. This queue was
3355                                  * noenabled by telnet module after sending
3356                                  * protocol/urgent data to telnetd.
3357                                  */
3358 
3359                                 telnetmod.ic_cmd = TEL_IOC_ENABLE;
3360                                 telnetmod.ic_timout = -1;
3361                                 if (ncc || nsize) {
3362                                         telnetmod.ic_len = ncc + nsize;
3363                                         telnetmod.ic_dp = netip;
3364                                 } else {
3365                                         telnetmod.ic_len = 0;
3366                                         telnetmod.ic_dp = NULL;
3367                                 }
3368                                 if (ioctl(net, I_STR, &telnetmod) < 0)
3369                                         fatal(net, "ioctl TEL_IOC_ENABLE \
3370                                                 failed\n");
3371 
3372                                 telmod_init_done = B_TRUE;
3373 
3374                                 netip = netibuf;
3375                                 (void) memset(netibuf, 0, netibufsize);
3376 
3377                                 ncc = 0;
3378                         }
3379                 } else {
3380                         /*
3381                          * state not changed to TS_DATA and hence, more to read
3382                          * send ioctl to get one more message block.
3383                          */
3384                         telnetmod.ic_cmd = TEL_IOC_GETBLK;
3385                         telnetmod.ic_timout = -1;
3386                         telnetmod.ic_len = 0;
3387                         telnetmod.ic_dp = NULL;
3388 
3389                         if (ioctl(net, I_STR, &telnetmod) < 0)
3390                                 fatal(net, "ioctl TEL_IOC_GETBLK failed\n");
3391                 }
3392 
3393                 if ((c = select(max(net, manager) + 1, &ibits, &obits, &xbits,
3394                     (struct timeval *)0)) < 1) {
3395                         if (c == -1) {
3396                                 if (errno == EINTR) {
3397                                         continue;
3398                                 }
3399                         }
3400                         (void) sleep(5);
3401                         continue;
3402                 }
3403 
3404                 /*
3405                  * Any urgent data?
3406                  */
3407                 if (FD_ISSET(net, &xbits)) {
3408                         SYNCHing = 1;
3409                 }
3410 
3411                 /*
3412                  * Something to read from the network...
3413                  */
3414                 if (FD_ISSET(net, &ibits)) {
3415                     ncc = read(net, netibuf, netibufsize);
3416                     if (ncc < 0 && errno == EWOULDBLOCK)
3417                         ncc = 0;
3418                     else {
3419                         if (ncc <= 0) {
3420                             break;
3421                         }
3422                         netip = netibuf;
3423                     }
3424                 }
3425 
3426                 if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0)
3427                         netflush();
3428                 if (ncc > 0)
3429                         telrcv();
3430                 if (FD_ISSET(manager, &obits) && (pfrontp - pbackp) > 0)
3431                         ptyflush();
3432         }
3433         cleanup(0);
3434 }
3435 
3436 static void
3437 telrcv(void)
3438 {
3439         int c;
3440 
3441         while (ncc > 0) {
3442                 if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
3443                         return;
3444                 c = *netip & 0377;
3445                 /*
3446                  * Once we hit data, we want to transition back to
3447                  * in-kernel processing.  However, this code is shared
3448                  * by getterminaltype()/ttloop() which run before the
3449                  * in-kernel plumbing is available.  So if we are still
3450                  * processing the initial option negotiation, even TS_DATA
3451                  * must be processed here.
3452                  */
3453                 if (c != IAC && state == TS_DATA && init_neg_done) {
3454                         break;
3455                 }
3456                 netip++;
3457                 ncc--;
3458                 switch (state) {
3459 
3460                 case TS_CR:
3461                         state = TS_DATA;
3462                         /* Strip off \n or \0 after a \r */
3463                         if ((c == 0) || (c == '\n')) {
3464                                 break;
3465                         }
3466                         /* FALLTHRU */
3467 
3468                 case TS_DATA:
3469                         if (c == IAC) {
3470                                 state = TS_IAC;
3471                                 break;
3472                         }
3473                         if (inter > 0)
3474                                 break;
3475                         /*
3476                          * We map \r\n ==> \r, since
3477                          * We now map \r\n ==> \r for pragmatic reasons.
3478                          * Many client implementations send \r\n when
3479                          * the user hits the CarriageReturn key.
3480                          *
3481                          * We USED to map \r\n ==> \n, since \r\n says
3482                          * that we want to be in column 1 of the next
3483                          * line.
3484                          */
3485                         if (c == '\r' && (myopts[TELOPT_BINARY] == OPT_NO)) {
3486                                 state = TS_CR;
3487                         }
3488                         *pfrontp++ = c;
3489                         break;
3490 
3491                 case TS_IAC:
3492                         switch (c) {
3493 
3494                         /*
3495                          * Send the process on the pty side an
3496                          * interrupt.  Do this with a NULL or
3497                          * interrupt char; depending on the tty mode.
3498                          */
3499                         case IP:
3500                                 interrupt();
3501                                 break;
3502 
3503                         case BREAK:
3504                                 sendbrk();
3505                                 break;
3506 
3507                         /*
3508                          * Are You There?
3509                          */
3510                         case AYT:
3511                                 write_data_len("\r\n[Yes]\r\n", 9);
3512                                 break;
3513 
3514                         /*
3515                          * Abort Output
3516                          */
3517                         case AO: {
3518                                         struct ltchars tmpltc;
3519 
3520                                         ptyflush();     /* half-hearted */
3521                                         if (ioctl(pty, TIOCGLTC, &tmpltc) == -1)
3522                                                 syslog(LOG_INFO,
3523                                                     "ioctl TIOCGLTC: %m\n");
3524                                         if (tmpltc.t_flushc != '\377') {
3525                                                 *pfrontp++ = tmpltc.t_flushc;
3526                                         }
3527                                         netclear();     /* clear buffer back */
3528                                         write_data("%c%c", (uchar_t)IAC,
3529                                                 (uchar_t)DM);
3530 
3531                                         neturg = nfrontp-1; /* off by one XXX */
3532                                         netflush();
3533                                         netflush(); /* XXX.sparker */
3534                                         break;
3535                                 }
3536 
3537                         /*
3538                          * Erase Character and
3539                          * Erase Line
3540                          */
3541                         case EC:
3542                         case EL: {
3543                                         struct sgttyb b;
3544                                         char ch;
3545 
3546                                         ptyflush();     /* half-hearted */
3547                                         if (ioctl(pty, TIOCGETP, &b) == -1)
3548                                                 syslog(LOG_INFO,
3549                                                     "ioctl TIOCGETP: %m\n");
3550                                         ch = (c == EC) ?
3551                                                 b.sg_erase : b.sg_kill;
3552                                         if (ch != '\377') {
3553                                                 *pfrontp++ = ch;
3554                                         }
3555                                         break;
3556                                 }
3557 
3558                         /*
3559                          * Check for urgent data...
3560                          */
3561                         case DM:
3562                                 break;
3563 
3564                         /*
3565                          * Begin option subnegotiation...
3566                          */
3567                         case SB:
3568                                 state = TS_SB;
3569                                 SB_CLEAR();
3570                                 continue;
3571 
3572                         case WILL:
3573                                 state = TS_WILL;
3574                                 continue;
3575 
3576                         case WONT:
3577                                 state = TS_WONT;
3578                                 continue;
3579 
3580                         case DO:
3581                                 state = TS_DO;
3582                                 continue;
3583 
3584                         case DONT:
3585                                 state = TS_DONT;
3586                                 continue;
3587 
3588                         case IAC:
3589                                 *pfrontp++ = c;
3590                                 break;
3591                         }
3592                         state = TS_DATA;
3593                         break;
3594                 case TS_SB:
3595                         if (c == IAC) {
3596                                 state = TS_SE;
3597                         } else {
3598                                 SB_ACCUM(c);
3599                         }
3600                         break;
3601                 case TS_SE:
3602                         if (c != SE) {
3603                                 if (c != IAC) {
3604                                         SB_ACCUM((uchar_t)IAC);
3605                                 }
3606                                 SB_ACCUM(c);
3607                                 state = TS_SB;
3608 
3609                         } else {
3610                                 SB_TERM();
3611                                 suboption();    /* handle sub-option */
3612                                 state = TS_DATA;
3613                         }
3614                         break;
3615 
3616                 case TS_WILL:
3617                         if (remopts[c] != OPT_YES)
3618                                 willoption(c);
3619                         state = TS_DATA;
3620                         continue;
3621 
3622                 case TS_WONT:
3623                         if (remopts[c] != OPT_NO)
3624                                 wontoption(c);
3625                         state = TS_DATA;
3626                         continue;
3627 
3628                 case TS_DO:
3629                         if (myopts[c] != OPT_YES)
3630                                 dooption(c);
3631                         state = TS_DATA;
3632                         continue;
3633 
3634                 case TS_DONT:
3635                         if (myopts[c] != OPT_NO) {
3636                                 dontoption(c);
3637                         }
3638                         state = TS_DATA;
3639                         continue;
3640 
3641                 default:
3642                         syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
3643                         (void) printf("telnetd: panic state=%d\n", state);
3644                         exit(EXIT_FAILURE);
3645                 }
3646         }
3647 }
3648 
3649 static void
3650 willoption(int option)
3651 {
3652         uchar_t *fmt;
3653         boolean_t send_reply = B_TRUE;
3654 
3655         switch (option) {
3656         case TELOPT_BINARY:
3657                 mode(O_RAW, 0);
3658                 fmt = doopt;
3659                 break;
3660 
3661         case TELOPT_ECHO:
3662                 not42 = 0;              /* looks like a 4.2 system */
3663                 /*
3664                  * Now, in a 4.2 system, to break them out of ECHOing
3665                  * (to the terminal) mode, we need to send a "WILL ECHO".
3666                  * Kludge upon kludge!
3667                  */
3668                 if (myopts[TELOPT_ECHO] == OPT_YES) {
3669                         dooption(TELOPT_ECHO);
3670                 }
3671                 fmt = dont;
3672                 break;
3673         case TELOPT_TTYPE:
3674                 settimer(ttypeopt);
3675                 goto common;
3676 
3677         case TELOPT_NAWS:
3678                 settimer(nawsopt);
3679                 goto common;
3680 
3681         case TELOPT_XDISPLOC:
3682                 settimer(xdisplocopt);
3683                 goto common;
3684 
3685         case TELOPT_NEW_ENVIRON:
3686                 settimer(environopt);
3687                 goto common;
3688 
3689         case TELOPT_AUTHENTICATION:
3690                 settimer(authopt);
3691                 if (remopts[option] == OPT_NO ||
3692                     negotiate_auth_krb5 == 0)
3693                         fmt = dont;
3694                 else
3695                         fmt = doopt;
3696                 break;
3697 
3698         case TELOPT_OLD_ENVIRON:
3699                 settimer(oenvironopt);
3700                 goto common;
3701 common:
3702                 if (remopts[option] == OPT_YES_BUT_ALWAYS_LOOK) {
3703                         remopts[option] = OPT_YES;
3704                         return;
3705                 }
3706                 /*FALLTHRU*/
3707         case TELOPT_SGA:
3708                 fmt = doopt;
3709                 break;
3710 
3711         case TELOPT_TM:
3712                 fmt = dont;
3713                 break;
3714 
3715         case TELOPT_ENCRYPT:
3716                 settimer(encropt); /* got response to do/dont */
3717                 if (enc_debug)
3718                         (void) fprintf(stderr,
3719                                     "RCVD IAC WILL TELOPT_ENCRYPT\n");
3720                 if (krb5_privacy_allowed()) {
3721                         fmt = doopt;
3722                         if (sent_do_encrypt)
3723                                 send_reply = B_FALSE;
3724                         else
3725                                 sent_do_encrypt = B_TRUE;
3726                 } else {
3727                         fmt = dont;
3728                 }
3729                 break;
3730 
3731         default:
3732                 fmt = dont;
3733                 break;
3734         }
3735         if (fmt == doopt) {
3736                 remopts[option] = OPT_YES;
3737         } else {
3738                 remopts[option] = OPT_NO;
3739         }
3740         if (send_reply) {
3741                 write_data((const char *)fmt, option);
3742                 netflush();
3743         }
3744 }
3745 
3746 static void
3747 wontoption(int option)
3748 {
3749         uchar_t *fmt;
3750         int send_reply = 1;
3751 
3752         switch (option) {
3753         case TELOPT_ECHO:
3754                 not42 = 1;              /* doesn't seem to be a 4.2 system */
3755                 break;
3756 
3757         case TELOPT_BINARY:
3758                 mode(0, O_RAW);
3759                 break;
3760 
3761         case TELOPT_TTYPE:
3762                 settimer(ttypeopt);
3763                 break;
3764 
3765         case TELOPT_NAWS:
3766                 settimer(nawsopt);
3767                 break;
3768 
3769         case TELOPT_XDISPLOC:
3770                 settimer(xdisplocopt);
3771                 break;
3772 
3773         case TELOPT_NEW_ENVIRON:
3774                 settimer(environopt);
3775                 break;
3776 
3777         case TELOPT_OLD_ENVIRON:
3778                 settimer(oenvironopt);
3779                 break;
3780 
3781         case TELOPT_AUTHENTICATION:
3782                 settimer(authopt);
3783                 auth_finished(0, AUTH_REJECT);
3784                 if (auth_debug)
3785                         (void) fprintf(stderr,
3786                                     "RCVD WONT TELOPT_AUTHENTICATE\n");
3787 
3788                 remopts[option] = OPT_NO;
3789                 send_reply = 0;
3790                 break;
3791 
3792         case TELOPT_ENCRYPT:
3793                 if (enc_debug)
3794                         (void) fprintf(stderr,
3795                                     "RCVD IAC WONT TELOPT_ENCRYPT\n");
3796                 settimer(encropt); /* got response to will/wont */
3797                 /*
3798                  * Remote side cannot send encryption. No reply necessary
3799                  * Treat this as if "IAC SB ENCRYPT END IAC SE" were
3800                  * received (RFC 2946) and disable crypto.
3801                  */
3802                 encrypt_end(TELNET_DIR_DECRYPT);
3803                 send_reply = 0;
3804                 break;
3805         }
3806 
3807         fmt = dont;
3808         remopts[option] = OPT_NO;
3809         if (send_reply) {
3810                 write_data((const char *)fmt, option);
3811         }
3812 }
3813 
3814 /*
3815  * We received an "IAC DO ..." message from the client, change our state
3816  * to OPT_YES.
3817  */
3818 static void
3819 dooption(int option)
3820 {
3821         uchar_t *fmt;
3822         boolean_t send_reply = B_TRUE;
3823 
3824         switch (option) {
3825 
3826         case TELOPT_TM:
3827                 fmt = wont;
3828                 break;
3829 
3830         case TELOPT_ECHO:
3831                 mode(O_ECHO|O_CRMOD, 0);
3832                 fmt = will;
3833                 break;
3834 
3835         case TELOPT_BINARY:
3836                 mode(O_RAW, 0);
3837                 fmt = will;
3838                 break;
3839 
3840         case TELOPT_SGA:
3841                 fmt = will;
3842                 break;
3843 
3844         case TELOPT_LOGOUT:
3845                 /*
3846                  * Options don't get much easier.  Acknowledge the option,
3847                  * and then clean up and exit.
3848                  */
3849                 write_data((const char *)will, option);
3850                 netflush();
3851                 cleanup(0);
3852                 /*NOTREACHED*/
3853 
3854         case TELOPT_ENCRYPT:
3855                 if (enc_debug)
3856                         (void) fprintf(stderr, "RCVD DO TELOPT_ENCRYPT\n");
3857                 settimer(encropt);
3858                 /*
3859                  * We received a "DO".  This indicates that the other side
3860                  * wants us to encrypt our data (pending negotiatoin).
3861                  * reply with "IAC WILL ENCRYPT" if we are able to send
3862                  * encrypted data.
3863                  */
3864                 if (krb5_privacy_allowed() && negotiate_encrypt) {
3865                         fmt = will;
3866                         if (sent_will_encrypt)
3867                                 send_reply = B_FALSE;
3868                         else
3869                                 sent_will_encrypt = B_TRUE;
3870                         /* return if we already sent "WILL ENCRYPT" */
3871                         if (myopts[option] == OPT_YES)
3872                                 return;
3873                 } else {
3874                         fmt = wont;
3875                 }
3876                 break;
3877 
3878         case TELOPT_AUTHENTICATION:
3879                 if (auth_debug) {
3880                         (void) fprintf(stderr,
3881                                     "RCVD DO TELOPT_AUTHENTICATION\n");
3882                 }
3883                 /*
3884                  * RFC 2941 - only the server can send
3885                  * "DO TELOPT_AUTHENTICATION".
3886                  * if a server receives this, it must respond with WONT...
3887                  */
3888                 fmt = wont;
3889                 break;
3890 
3891         default:
3892                 fmt = wont;
3893                 break;
3894         }
3895         if (fmt == will) {
3896                 myopts[option] = OPT_YES;
3897         } else {
3898                 myopts[option] = OPT_NO;
3899         }
3900         if (send_reply) {
3901                 write_data((const char *)fmt, option);
3902                 netflush();
3903         }
3904 }
3905 
3906 /*
3907  * We received an "IAC DONT ..." message from client.
3908  * Client does not agree with the option so act accordingly.
3909  */
3910 static void
3911 dontoption(int option)
3912 {
3913         int send_reply = 1;
3914         switch (option) {
3915         case TELOPT_ECHO:
3916                 /*
3917                  * we should stop echoing, since the client side will be doing
3918                  * it, but keep mapping CR since CR-LF will be mapped to it.
3919                  */
3920                 mode(0, O_ECHO);
3921                 break;
3922 
3923         case TELOPT_ENCRYPT:
3924                 if (enc_debug)
3925                         (void) fprintf(stderr, "RCVD IAC DONT ENCRYPT\n");
3926                 settimer(encropt);
3927                 /*
3928                  * Remote side cannot receive any encrypted data,
3929                  * so dont send any.  No reply necessary.
3930                  */
3931                 send_reply = 0;
3932                 break;
3933 
3934         default:
3935                 break;
3936         }
3937 
3938         myopts[option] = OPT_NO;
3939 
3940         if (send_reply) {
3941                 write_data((const char *)wont, option);
3942         }
3943 }
3944 
3945 /*
3946  * suboption()
3947  *
3948  *      Look at the sub-option buffer, and try to be helpful to the other
3949  * side.
3950  *
3951  */
3952 static void
3953 suboption(void)
3954 {
3955         int subchar;
3956 
3957         switch (subchar = SB_GET()) {
3958         case TELOPT_TTYPE: {            /* Yaaaay! */
3959                 static char terminalname[5+41] = "TERM=";
3960 
3961                 settimer(ttypesubopt);
3962 
3963                 if (SB_GET() != TELQUAL_IS) {
3964                         return; /* ??? XXX but, this is the most robust */
3965                 }
3966 
3967                 terminaltype = terminalname+strlen(terminalname);
3968 
3969                 while (terminaltype < (terminalname + sizeof (terminalname) -
3970                     1) && !SB_EOF()) {
3971                         int c;
3972 
3973                         c = SB_GET();
3974                         if (isupper(c)) {
3975                                 c = tolower(c);
3976                         }
3977                         *terminaltype++ = c;    /* accumulate name */
3978                 }
3979                 *terminaltype = 0;
3980                 terminaltype = terminalname;
3981                 break;
3982         }
3983 
3984         case TELOPT_NAWS: {
3985                 struct winsize ws;
3986 
3987                 if (SB_EOF()) {
3988                         return;
3989                 }
3990                 ws.ws_col = SB_GET() << 8;
3991                 if (SB_EOF()) {
3992                         return;
3993                 }
3994                 ws.ws_col |= SB_GET();
3995                 if (SB_EOF()) {
3996                         return;
3997                 }
3998                 ws.ws_row = SB_GET() << 8;
3999                 if (SB_EOF()) {
4000                         return;
4001                 }
4002                 ws.ws_row |= SB_GET();
4003                 ws.ws_xpixel = 0; ws.ws_ypixel = 0;
4004                 (void) ioctl(pty, TIOCSWINSZ, &ws);
4005                 settimer(nawsopt);
4006                 break;
4007         }
4008 
4009         case TELOPT_XDISPLOC: {
4010                 if (SB_EOF() || SB_GET() != TELQUAL_IS) {
4011                         return;
4012                 }
4013                 settimer(xdisplocsubopt);
4014                 subpointer[SB_LEN()] = '\0';
4015                 if ((new_env("DISPLAY", subpointer)) == 1)
4016                         perror("malloc");
4017                 break;
4018         }
4019 
4020         case TELOPT_NEW_ENVIRON:
4021         case TELOPT_OLD_ENVIRON: {
4022                 int c;
4023                 char *cp, *varp, *valp;
4024 
4025                 if (SB_EOF())
4026                         return;
4027                 c = SB_GET();
4028                 if (c == TELQUAL_IS) {
4029                         if (subchar == TELOPT_OLD_ENVIRON)
4030                                 settimer(oenvironsubopt);
4031                         else
4032                                 settimer(environsubopt);
4033                 } else if (c != TELQUAL_INFO) {
4034                         return;
4035                 }
4036 
4037                 if (subchar == TELOPT_NEW_ENVIRON) {
4038                     while (!SB_EOF()) {
4039                         c = SB_GET();
4040                         if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
4041                                 break;
4042                     }
4043                 } else
4044                 {
4045                         while (!SB_EOF()) {
4046                                 c = SB_GET();
4047                                 if ((c == env_ovar) || (c == ENV_USERVAR))
4048                                         break;
4049                         }
4050                 }
4051 
4052                 if (SB_EOF())
4053                         return;
4054 
4055                 cp = varp = (char *)subpointer;
4056                 valp = 0;
4057 
4058                 while (!SB_EOF()) {
4059                         c = SB_GET();
4060                         if (subchar == TELOPT_OLD_ENVIRON) {
4061                                 if (c == env_ovar)
4062                                         c = NEW_ENV_VAR;
4063                                 else if (c == env_ovalue)
4064                                         c = NEW_ENV_VALUE;
4065                         }
4066                         switch (c) {
4067 
4068                         case NEW_ENV_VALUE:
4069                                 *cp = '\0';
4070                                 cp = valp = (char *)subpointer;
4071                                 break;
4072 
4073                         case NEW_ENV_VAR:
4074                         case ENV_USERVAR:
4075                                 *cp = '\0';
4076                                 if (valp) {
4077                                         if ((new_env(varp, valp)) == 1) {
4078                                                 perror("malloc");
4079                                         }
4080                                 } else {
4081                                         (void) del_env(varp);
4082                                 }
4083                                 cp = varp = (char *)subpointer;
4084                                 valp = 0;
4085                                 break;
4086 
4087                         case ENV_ESC:
4088                                 if (SB_EOF())
4089                                         break;
4090                                 c = SB_GET();
4091                                 /* FALL THROUGH */
4092                         default:
4093                                 *cp++ = c;
4094                                 break;
4095                         }
4096                 }
4097                 *cp = '\0';
4098                 if (valp) {
4099                         if ((new_env(varp, valp)) == 1) {
4100                                 perror("malloc");
4101                         }
4102                 } else {
4103                         (void) del_env(varp);
4104                 }
4105                 break;
4106         }  /* end of case TELOPT_NEW_ENVIRON */
4107 
4108         case TELOPT_AUTHENTICATION:
4109                 if (SB_EOF())
4110                         break;
4111                 switch (SB_GET()) {
4112                 case TELQUAL_SEND:
4113                 case TELQUAL_REPLY:
4114                         /*
4115                          * These are sent server only and cannot be sent by the
4116                          * client.
4117                          */
4118                         break;
4119                 case TELQUAL_IS:
4120                         if (auth_debug)
4121                                 (void) fprintf(stderr,
4122                                             "RCVD AUTHENTICATION IS "
4123                                             "(%d bytes)\n",
4124                                             SB_LEN());
4125                         if (!auth_negotiated)
4126                                 auth_is((uchar_t *)subpointer, SB_LEN());
4127                         break;
4128                 case TELQUAL_NAME:
4129                         if (auth_debug)
4130                                 (void) fprintf(stderr,
4131                                             "RCVD AUTHENTICATION NAME "
4132                                             "(%d bytes)\n",
4133                                             SB_LEN());
4134                         if (!auth_negotiated)
4135                                 auth_name((uchar_t *)subpointer, SB_LEN());
4136                         break;
4137                 }
4138                 break;
4139 
4140         case TELOPT_ENCRYPT: {
4141                 int c;
4142                 if (SB_EOF())
4143                         break;
4144                 c = SB_GET();
4145 #ifdef ENCRYPT_NAMES
4146                 if (enc_debug)
4147                         (void) fprintf(stderr, "RCVD ENCRYPT %s\n",
4148                                     ENCRYPT_NAME(c));
4149 #endif /* ENCRYPT_NAMES */
4150                 switch (c) {
4151                 case ENCRYPT_SUPPORT:
4152                         encrypt_support(subpointer, SB_LEN());
4153                         break;
4154                 case ENCRYPT_IS:
4155                         encrypt_is((uchar_t *)subpointer, SB_LEN());
4156                         break;
4157                 case ENCRYPT_REPLY:
4158                         (void) encrypt_reply(subpointer, SB_LEN());
4159                         break;
4160                 case ENCRYPT_START:
4161                         encrypt_start();
4162                         break;
4163                 case ENCRYPT_END:
4164                         encrypt_end(TELNET_DIR_DECRYPT);
4165                         break;
4166                 case ENCRYPT_REQSTART:
4167                         encrypt_request_start();
4168                         break;
4169                 case ENCRYPT_REQEND:
4170                         /*
4171                          * We can always send an REQEND so that we cannot
4172                          * get stuck encrypting.  We should only get this
4173                          * if we have been able to get in the correct mode
4174                          * anyhow.
4175                          */
4176                         encrypt_request_end();
4177                         break;
4178                 case ENCRYPT_ENC_KEYID:
4179                         encrypt_enc_keyid(subpointer, SB_LEN());
4180                         break;
4181                 case ENCRYPT_DEC_KEYID:
4182                         encrypt_dec_keyid(subpointer, SB_LEN());
4183                         break;
4184                 default:
4185                         break;
4186                 }
4187         }
4188         break;
4189 
4190         default:
4191                 break;
4192         }
4193 }
4194 
4195 static void
4196 mode(int on, int off)
4197 {
4198         struct termios  tios;
4199 
4200         ptyflush();
4201         if (tcgetattr(pty, &tios) < 0)
4202                 syslog(LOG_INFO, "tcgetattr: %m\n");
4203 
4204         if (on & O_RAW) {
4205                 tios.c_cflag |= CS8;
4206                 tios.c_iflag &= ~IUCLC;
4207                 tios.c_lflag &= ~(XCASE|IEXTEN);
4208         }
4209         if (off & O_RAW) {
4210                 if ((tios.c_cflag & PARENB) != 0)
4211                         tios.c_cflag &= ~CS8;
4212                 tios.c_lflag |= IEXTEN;
4213         }
4214 
4215         if (on & O_ECHO)
4216                 tios.c_lflag |= ECHO;
4217         if (off & O_ECHO)
4218                 tios.c_lflag &= ~ECHO;
4219 
4220         if (on & O_CRMOD) {
4221                 tios.c_iflag |= ICRNL;
4222                 tios.c_oflag |= ONLCR;
4223         }
4224         /*
4225          * Because "O_CRMOD" will never be set in "off" we don't have to
4226          * handle this case here.
4227          */
4228 
4229         if (tcsetattr(pty, TCSANOW, &tios) < 0)
4230                 syslog(LOG_INFO, "tcsetattr: %m\n");
4231 }
4232 
4233 /*
4234  * Send interrupt to process on other side of pty.
4235  * If it is in raw mode, just write NULL;
4236  * otherwise, write intr char.
4237  */
4238 static void
4239 interrupt(void)
4240 {
4241         struct sgttyb b;
4242         struct tchars tchars;
4243 
4244         ptyflush();     /* half-hearted */
4245         if (ioctl(pty, TIOCGETP, &b) == -1)
4246                 syslog(LOG_INFO, "ioctl TIOCGETP: %m\n");
4247         if (b.sg_flags & O_RAW) {
4248                 *pfrontp++ = '\0';
4249                 return;
4250         }
4251         *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4252                 '\177' : tchars.t_intrc;
4253 }
4254 
4255 /*
4256  * Send quit to process on other side of pty.
4257  * If it is in raw mode, just write NULL;
4258  * otherwise, write quit char.
4259  */
4260 static void
4261 sendbrk(void)
4262 {
4263         struct sgttyb b;
4264         struct tchars tchars;
4265 
4266         ptyflush();     /* half-hearted */
4267         (void) ioctl(pty, TIOCGETP, &b);
4268         if (b.sg_flags & O_RAW) {
4269                 *pfrontp++ = '\0';
4270                 return;
4271         }
4272         *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4273                 '\034' : tchars.t_quitc;
4274 }
4275 
4276 static void
4277 ptyflush(void)
4278 {
4279         int n;
4280 
4281         if ((n = pfrontp - pbackp) > 0)
4282                 n = write(manager, pbackp, n);
4283         if (n < 0)
4284                 return;
4285         pbackp += n;
4286         if (pbackp == pfrontp)
4287                 pbackp = pfrontp = ptyobuf;
4288 }
4289 
4290 /*
4291  * nextitem()
4292  *
4293  *      Return the address of the next "item" in the TELNET data
4294  * stream.  This will be the address of the next character if
4295  * the current address is a user data character, or it will
4296  * be the address of the character following the TELNET command
4297  * if the current address is a TELNET IAC ("I Am a Command")
4298  * character.
4299  */
4300 
4301 static char *
4302 nextitem(char *current)
4303 {
4304         if ((*current&0xff) != IAC) {
4305                 return (current+1);
4306         }
4307         switch (*(current+1)&0xff) {
4308         case DO:
4309         case DONT:
4310         case WILL:
4311         case WONT:
4312                 return (current+3);
4313         case SB:                /* loop forever looking for the SE */
4314         {
4315                 char *look = current+2;
4316 
4317                 for (;;) {
4318                         if ((*look++&0xff) == IAC) {
4319                                 if ((*look++&0xff) == SE) {
4320                                         return (look);
4321                                 }
4322                         }
4323                 }
4324         }
4325         default:
4326                 return (current+2);
4327         }
4328 }
4329 
4330 
4331 /*
4332  * netclear()
4333  *
4334  *      We are about to do a TELNET SYNCH operation.  Clear
4335  * the path to the network.
4336  *
4337  *      Things are a bit tricky since we may have sent the first
4338  * byte or so of a previous TELNET command into the network.
4339  * So, we have to scan the network buffer from the beginning
4340  * until we are up to where we want to be.
4341  *
4342  *      A side effect of what we do, just to keep things
4343  * simple, is to clear the urgent data pointer.  The principal
4344  * caller should be setting the urgent data pointer AFTER calling
4345  * us in any case.
4346  */
4347 static void
4348 netclear(void)
4349 {
4350         char *thisitem, *next;
4351         char *good;
4352 #define wewant(p)       ((nfrontp > p) && ((*p&0xff) == IAC) && \
4353                                 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
4354 
4355         thisitem = netobuf;
4356 
4357         while ((next = nextitem(thisitem)) <= nbackp) {
4358                 thisitem = next;
4359         }
4360 
4361         /* Now, thisitem is first before/at boundary. */
4362 
4363         good = netobuf; /* where the good bytes go */
4364 
4365         while (nfrontp > thisitem) {
4366                 if (wewant(thisitem)) {
4367                         int length;
4368 
4369                         next = thisitem;
4370                         do {
4371                                 next = nextitem(next);
4372                         } while (wewant(next) && (nfrontp > next));
4373                         length = next-thisitem;
4374                         (void) memmove(good, thisitem, length);
4375                         good += length;
4376                         thisitem = next;
4377                 } else {
4378                         thisitem = nextitem(thisitem);
4379                 }
4380         }
4381 
4382         nbackp = netobuf;
4383         nfrontp = good;         /* next byte to be sent */
4384         neturg = 0;
4385 }
4386 
4387 
4388 /*
4389  *  netflush
4390  *              Send as much data as possible to the network,
4391  *      handling requests for urgent data.
4392  */
4393 static void
4394 netflush(void)
4395 {
4396         int n;
4397 
4398         if ((n = nfrontp - nbackp) > 0) {
4399                 /*
4400                  * if no urgent data, or if the other side appears to be an
4401                  * old 4.2 client (and thus unable to survive TCP urgent data),
4402                  * write the entire buffer in non-OOB mode.
4403                  */
4404                 if ((neturg == 0) || (not42 == 0)) {
4405                         n = write(net, nbackp, n);      /* normal write */
4406                 } else {
4407                         n = neturg - nbackp;
4408                         /*
4409                          * In 4.2 (and 4.3) systems, there is some question
4410                          * about what byte in a sendOOB operation is the "OOB"
4411                          * data.  To make ourselves compatible, we only send ONE
4412                          * byte out of band, the one WE THINK should be OOB
4413                          * (though we really have more the TCP philosophy of
4414                          * urgent data rather than the Unix philosophy of OOB
4415                          * data).
4416                          */
4417                         if (n > 1) {
4418                                 /* send URGENT all by itself */
4419                                 n = write(net, nbackp, n-1);
4420                         } else {
4421                                 /* URGENT data */
4422                                 n = send_oob(net, nbackp, n);
4423                         }
4424                 }
4425         }
4426         if (n < 0) {
4427                 if (errno == EWOULDBLOCK)
4428                         return;
4429                 /* should blow this guy away... */
4430                 return;
4431         }
4432 
4433         nbackp += n;
4434 
4435         if (nbackp >= neturg) {
4436                 neturg = 0;
4437         }
4438         if (nbackp == nfrontp) {
4439                 nbackp = nfrontp = netobuf;
4440         }
4441 }
4442 
4443 /* ARGSUSED */
4444 static void
4445 cleanup(int signum)
4446 {
4447         /*
4448          * If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
4449          * handle closing differently.  We close "net" first and then
4450          * "manager" in that order.  We do close(net) first because
4451          * we have no other way to disconnect forwarding between the network
4452          * and manager.  So by issuing the close()'s we ensure that no further
4453          * data rises from TCP.  A more complex fix would be adding proper
4454          * support for throwing a "stop" switch for forwarding data between
4455          * logindmux peers.  It's possible to block in the close of the tty
4456          * while the network still receives data and the telmod module is
4457          * TEL_STOPPED.  A denial-of-service attack generates this case,
4458          * see 4102102.
4459          */
4460 
4461         if (!telmod_init_done) {
4462                 (void) close(net);
4463                 (void) close(manager);
4464         }
4465         rmut();
4466 
4467         exit(EXIT_FAILURE);
4468 }
4469 
4470 static void
4471 rmut(void)
4472 {
4473         pam_handle_t    *pamh;
4474         struct utmpx *up;
4475         char user[sizeof (up->ut_user) + 1];
4476         char ttyn[sizeof (up->ut_line) + 1];
4477         char rhost[sizeof (up->ut_host) + 1];
4478 
4479         /* while cleaning up don't allow disruption */
4480         (void) signal(SIGCHLD, SIG_IGN);
4481 
4482         setutxent();
4483         while (up = getutxent()) {
4484                 if (up->ut_pid == pid) {
4485                         if (up->ut_type == DEAD_PROCESS) {
4486                                 /*
4487                                  * Cleaned up elsewhere.
4488                                  */
4489                                 break;
4490                         }
4491 
4492                         /*
4493                          * call pam_close_session if login changed
4494                          * the utmpx user entry from type LOGIN_PROCESS
4495                          * to type USER_PROCESS, which happens
4496                          * after pam_open_session is called.
4497                          */
4498                         if (up->ut_type == USER_PROCESS) {
4499                                 (void) strlcpy(user, up->ut_user,
4500                                             sizeof (user));
4501                                 (void) strlcpy(ttyn, up->ut_line,
4502                                             sizeof (ttyn));
4503                                 (void) strlcpy(rhost, up->ut_host,
4504                                             sizeof (rhost));
4505                                 if ((pam_start("telnet", user, NULL, &pamh)) ==
4506                                     PAM_SUCCESS) {
4507                                         (void) pam_set_item(pamh, PAM_TTY,
4508                                                             ttyn);
4509                                         (void) pam_set_item(pamh, PAM_RHOST,
4510                                                             rhost);
4511                                         (void) pam_close_session(pamh, 0);
4512                                         (void) pam_end(pamh, PAM_SUCCESS);
4513                                 }
4514                         }
4515 
4516                         up->ut_type = DEAD_PROCESS;
4517                         up->ut_exit.e_termination = WTERMSIG(0);
4518                         up->ut_exit.e_exit = WEXITSTATUS(0);
4519                         (void) time(&up->ut_tv.tv_sec);
4520 
4521                         if (modutx(up) == NULL) {
4522                                 /*
4523                                  * Since modutx failed we'll
4524                                  * write out the new entry
4525                                  * ourselves.
4526                                  */
4527                                 (void) pututxline(up);
4528                                 updwtmpx("wtmpx", up);
4529                         }
4530                         break;
4531                 }
4532         }
4533 
4534         endutxent();
4535 
4536         (void) signal(SIGCHLD, (void (*)())cleanup);
4537 }
4538 
4539 static int
4540 readstream(int fd, char *buf, int offset)
4541 {
4542         struct strbuf ctlbuf, datbuf;
4543         union T_primitives tpi;
4544         int     ret = 0;
4545         int     flags = 0;
4546         int     bytes_avail, count;
4547 
4548         (void) memset((char *)&ctlbuf, 0, sizeof (ctlbuf));
4549         (void) memset((char *)&datbuf, 0, sizeof (datbuf));
4550 
4551         ctlbuf.buf = (char *)&tpi;
4552         ctlbuf.maxlen = sizeof (tpi);
4553 
4554         if (ioctl(fd, I_NREAD, &bytes_avail) < 0) {
4555                 syslog(LOG_ERR, "I_NREAD returned error %m");
4556                 return (-1);
4557         }
4558         if (bytes_avail > netibufsize - offset) {
4559                 count = netip - netibuf;
4560                 netibuf = (char *)realloc(netibuf,
4561                     (unsigned)netibufsize + bytes_avail);
4562                 if (netibuf == NULL) {
4563                         fatal(net, "netibuf realloc failed\n");
4564                 }
4565                 netibufsize += bytes_avail;
4566                 netip = netibuf + count;
4567                 buf = netibuf;
4568         }
4569         datbuf.buf = buf + offset;
4570         datbuf.maxlen = netibufsize;
4571         ret = getmsg(fd, &ctlbuf, &datbuf, &flags);
4572         if (ret < 0) {
4573                 syslog(LOG_ERR, "getmsg returned -1, errno %d\n",
4574                         errno);
4575                 return (-1);
4576         }
4577         if (ctlbuf.len <= 0) {
4578                 return (datbuf.len);
4579         }
4580 
4581         if (tpi.type == T_DATA_REQ) {
4582                 return (0);
4583         }
4584 
4585         if ((tpi.type == T_ORDREL_IND) || (tpi.type == T_DISCON_IND))
4586                 cleanup(0);
4587         fatal(fd, "no data or protocol element recognized");
4588         return (0);
4589 }
4590 
4591 static void
4592 drainstream(int size)
4593 {
4594         int     nbytes;
4595         int     tsize;
4596 
4597         tsize = netip - netibuf;
4598 
4599         if ((tsize + ncc + size) > netibufsize) {
4600                 if (!(netibuf = (char *)realloc(netibuf,
4601                     (unsigned)tsize + ncc + size)))
4602                         fatalperror(net, "netibuf realloc failed\n", errno);
4603                 netibufsize = tsize + ncc + size;
4604 
4605                 netip = netibuf + tsize;
4606         }
4607 
4608         if ((nbytes = read(net, (char *)netip + ncc, size)) != size)
4609                 syslog(LOG_ERR, "read %d bytes\n", nbytes);
4610 }
4611 
4612 /*
4613  * TPI style replacement for socket send() primitive, so we don't require
4614  * sockmod to be on the stream.
4615  */
4616 static int
4617 send_oob(int fd, char *ptr, int count)
4618 {
4619         struct T_exdata_req exd_req;
4620         struct strbuf hdr, dat;
4621         int ret;
4622 
4623         exd_req.PRIM_type = T_EXDATA_REQ;
4624         exd_req.MORE_flag = 0;
4625 
4626         hdr.buf = (char *)&exd_req;
4627         hdr.len = sizeof (exd_req);
4628 
4629         dat.buf = ptr;
4630         dat.len = count;
4631 
4632         ret = putmsg(fd, &hdr, &dat, 0);
4633         if (ret == 0) {
4634                 ret = count;
4635         }
4636         return (ret);
4637 }
4638 
4639 
4640 /*
4641  * local_setenv --
4642  *      Set the value of the environmental variable "name" to be
4643  *      "value".  If rewrite is set, replace any current value.
4644  */
4645 static int
4646 local_setenv(const char *name, const char *value, int rewrite)
4647 {
4648         static int alloced;                     /* if allocated space before */
4649         char *c;
4650         int l_value, offset;
4651 
4652         /*
4653          * Do not allow environment variables which begin with LD_ to be
4654          * inserted into the environment.  While normally the dynamic linker
4655          * protects the login program, that is based on the assumption hostile
4656          * invocation of login are from non-root users.  However, since telnetd
4657          * runs as root, this cannot be utilized.  So instead we simply
4658          * prevent LD_* from being inserted into the environment.
4659          * This also applies to other environment variables that
4660          * are to be ignored in setugid apps.
4661          * Note that at this point name can contain '='!
4662          * Also, do not allow TTYPROMPT to be passed along here.
4663          */
4664         if (strncmp(name, "LD_", 3) == 0 ||
4665             strncmp(name, "NLSPATH", 7) == 0 ||
4666             (strncmp(name, "TTYPROMPT", 9) == 0 &&
4667                 (name[9] == '\0' || name[9] == '='))) {
4668                 return (-1);
4669         }
4670         if (*value == '=')                      /* no `=' in value */
4671                 ++value;
4672         l_value = strlen(value);
4673         if ((c = __findenv(name, &offset))) {       /* find if already exists */
4674                 if (!rewrite)
4675                         return (0);
4676                 if ((int)strlen(c) >= l_value) { /* old larger; copy over */
4677                         while (*c++ = *value++)
4678                                 ;
4679                         return (0);
4680                 }
4681         } else {                                        /* create new slot */
4682                 int cnt;
4683                 char **p;
4684 
4685                 for (p = environ, cnt = 0; *p; ++p, ++cnt)
4686                         ;
4687                 if (alloced) {                  /* just increase size */
4688                         environ = (char **)realloc((char *)environ,
4689                             (size_t)(sizeof (char *) * (cnt + 2)));
4690                         if (!environ)
4691                                 return (-1);
4692                 } else {                                /* get new space */
4693                         alloced = 1;            /* copy old entries into it */
4694                         p = (char **)malloc((size_t)(sizeof (char *)*
4695                             (cnt + 2)));
4696                         if (!p)
4697                                 return (-1);
4698                         (void) memcpy(p, environ, cnt * sizeof (char *));
4699                         environ = p;
4700                 }
4701                 environ[cnt + 1] = NULL;
4702                 offset = cnt;
4703         }
4704         for (c = (char *)name; *c && *c != '='; ++c)    /* no `=' in name */
4705                 ;
4706         if (!(environ[offset] =                 /* name + `=' + value */
4707             malloc((size_t)((int)(c - name) + l_value + 2))))
4708                 return (-1);
4709         for (c = environ[offset]; ((*c = *name++) != 0) && (*c != '='); ++c)
4710                 ;
4711         for (*c++ = '='; *c++ = *value++; )
4712                 ;
4713         return (0);
4714 }
4715 
4716 /*
4717  * local_unsetenv(name) --
4718  *      Delete environmental variable "name".
4719  */
4720 static void
4721 local_unsetenv(const char *name)
4722 {
4723         char **p;
4724         int offset;
4725 
4726         while (__findenv(name, &offset))    /* if set multiple times */
4727                 for (p = &environ[offset]; ; ++p)
4728                         if ((*p = *(p + 1)) == 0)
4729                                 break;
4730 }
4731 
4732 /*
4733  * __findenv --
4734  *      Returns pointer to value associated with name, if any, else NULL.
4735  *      Sets offset to be the offset of the name/value combination in the
4736  *      environmental array, for use by local_setenv() and local_unsetenv().
4737  *      Explicitly removes '=' in argument name.
4738  */
4739 static char *
4740 __findenv(const char *name, int *offset)
4741 {
4742         extern char **environ;
4743         int len;
4744         const char *np;
4745         char **p, *c;
4746 
4747         if (name == NULL || environ == NULL)
4748                 return (NULL);
4749         for (np = name; *np && *np != '='; ++np)
4750                 continue;
4751         len = np - name;
4752         for (p = environ; (c = *p) != NULL; ++p)
4753                 if (strncmp(c, name, len) == 0 && c[len] == '=') {
4754                         *offset = p - environ;
4755                         return (c + len + 1);
4756                 }
4757         return (NULL);
4758 }
4759 
4760 static void
4761 showbanner(void)
4762 {
4763         char    *cp;
4764         char    evalbuf[BUFSIZ];
4765 
4766         if (defopen(defaultfile) == 0) {
4767                 int     flags;
4768 
4769                 /* ignore case */
4770                 flags = defcntl(DC_GETFLAGS, 0);
4771                 TURNOFF(flags, DC_CASE);
4772                 (void) defcntl(DC_SETFLAGS, flags);
4773                 if (cp = defread(bannervar)) {
4774                         FILE    *fp;
4775 
4776                         if (strlen(cp) + strlen("eval echo '") + strlen("'\n")
4777                             + 1 < sizeof (evalbuf)) {
4778                                 (void) strlcpy(evalbuf, "eval echo '",
4779                                         sizeof (evalbuf));
4780                                 (void) strlcat(evalbuf, cp, sizeof (evalbuf));
4781                                 (void) strlcat(evalbuf, "'\n",
4782                                                 sizeof (evalbuf));
4783 
4784                                 if (fp = popen(evalbuf, "r")) {
4785                                         char    buf[BUFSIZ];
4786                                         size_t  size;
4787 
4788                                         /*
4789                                          * Pipe I/O atomicity guarantees we
4790                                          * need only one read.
4791                                          */
4792                                         if ((size = fread(buf, 1,
4793                                                         sizeof (buf) - 1,
4794                                                         fp)) != 0) {
4795                                                 char    *p;
4796                                                 buf[size] = '\0';
4797                                                 p = strrchr(buf, '\n');
4798                                                 if (p != NULL)
4799                                                         *p = '\0';
4800                                                 if (strlen(buf)) {
4801                                                         map_banner(buf);
4802                                                         netflush();
4803                                                 }
4804                                         }
4805                                         (void) pclose(fp);
4806                                         /* close default file */
4807                                         (void) defopen(NULL);
4808                                         return;
4809                                 }
4810                         }
4811                 }
4812                 (void) defopen(NULL);   /* close default file */
4813         }
4814 
4815         defbanner();
4816         netflush();
4817 }
4818 
4819 static void
4820 map_banner(char *p)
4821 {
4822         char    *q;
4823 
4824         /*
4825          *      Map the banner:  "\n" -> "\r\n" and "\r" -> "\r\0"
4826          */
4827         for (q = nfrontp; p && *p && q < nfrontp + sizeof (netobuf) - 1; )
4828                 if (*p == '\n') {
4829                         *q++ = '\r';
4830                         *q++ = '\n';
4831                         p++;
4832                 } else if (*p == '\r') {
4833                         *q++ = '\r';
4834                         *q++ = '\0';
4835                         p++;
4836                 } else
4837                         *q++ = *p++;
4838 
4839         nfrontp += q - netobuf;
4840 }
4841 
4842 /*
4843  * Show banner that getty never gave.  By default, this is `uname -sr`.
4844  *
4845  * The banner includes some null's (for TELNET CR disambiguation),
4846  * so we have to be somewhat complicated.
4847  */
4848 static void
4849 defbanner(void)
4850 {
4851         struct utsname u;
4852 
4853         /*
4854          * Dont show this if the '-h' option was present
4855          */
4856         if (!show_hostinfo)
4857                 return;
4858 
4859         if (uname(&u) == -1)
4860                 return;
4861 
4862         write_data_len((const char *) BANNER1, sizeof (BANNER1) - 1);
4863         write_data_len(u.sysname, strlen(u.sysname));
4864         write_data_len(" ", 1);
4865         write_data_len(u.release, strlen(u.release));
4866         write_data_len((const char *)BANNER2, sizeof (BANNER2) - 1);
4867 }
4868 
4869 /*
4870  * Verify that the named module is at the top of the stream
4871  * and then pop it off.
4872  */
4873 static int
4874 removemod(int f, char *modname)
4875 {
4876         char topmodname[BUFSIZ];
4877 
4878         if (ioctl(f, I_LOOK, topmodname) < 0)
4879                 return (-1);
4880         if (strcmp(modname, topmodname) != 0) {
4881                 errno = ENXIO;
4882                 return (-1);
4883         }
4884         if (ioctl(f, I_POP, 0) < 0)
4885                 return (-1);
4886         return (0);
4887 }
4888 
4889 static void
4890 write_data(const char *format, ...)
4891 {
4892         va_list args;
4893         int             len;
4894         char    argp[BUFSIZ];
4895 
4896         va_start(args, format);
4897 
4898         if ((len = vsnprintf(argp, sizeof (argp), format, args)) == -1)
4899                 return;
4900 
4901         write_data_len(argp, len);
4902         va_end(args);
4903 }
4904 
4905 static void
4906 write_data_len(const char *buf, int len)
4907 {
4908         int remaining, copied;
4909 
4910         remaining = BUFSIZ - (nfrontp - netobuf);
4911         while (len > 0) {
4912                 /*
4913                  * If there's not enough space in netobuf then
4914                  * try to make some.
4915                  */
4916         if ((len > BUFSIZ ? BUFSIZ : len) > remaining) {
4917                         netflush();
4918                         remaining = BUFSIZ - (nfrontp - netobuf);
4919                 }
4920                 /* Copy as much as we can */
4921                 copied = remaining > len ? len : remaining;
4922                 (void) memmove(nfrontp, buf, copied);
4923                 nfrontp += copied;
4924                 len -= copied;
4925                 remaining -= copied;
4926                 buf += copied;
4927         }
4928 }