1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 2923 raf * Common Development and Distribution License (the "License"). 6 2923 raf * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 2923 raf */ 21 2923 raf 22 2923 raf /* 23 6536 gtb * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel /* 28 0 stevel * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T 29 0 stevel * All Rights Reserved. 30 0 stevel */ 31 0 stevel 32 0 stevel /* 33 0 stevel * University Copyright- Copyright (c) 1982, 1986, 1988 34 0 stevel * The Regents of the University of California. 35 0 stevel * All Rights Reserved. 36 0 stevel * 37 0 stevel * University Acknowledgment- Portions of this document are derived from 38 0 stevel * software developed by the University of California, Berkeley, and its 39 0 stevel * contributors. 40 0 stevel */ 41 0 stevel 42 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 43 0 stevel 44 0 stevel /* 45 0 stevel * Telnet server. 46 0 stevel */ 47 0 stevel #include <sys/types.h> 48 0 stevel #include <sys/param.h> 49 0 stevel #include <sys/socket.h> 50 0 stevel #include <sys/wait.h> 51 0 stevel #include <sys/file.h> 52 0 stevel #include <sys/stat.h> 53 0 stevel #include <sys/filio.h> 54 0 stevel #include <sys/time.h> 55 0 stevel #include <sys/stropts.h> 56 0 stevel #include <sys/stream.h> 57 0 stevel #include <sys/tihdr.h> 58 0 stevel #include <sys/utsname.h> 59 0 stevel #include <unistd.h> 60 0 stevel 61 0 stevel #include <netinet/in.h> 62 0 stevel 63 0 stevel #define AUTHWHO_STR 64 0 stevel #define AUTHTYPE_NAMES 65 0 stevel #define AUTHHOW_NAMES 66 0 stevel #define AUTHRSP_NAMES 67 0 stevel #define ENCRYPT_NAMES 68 0 stevel 69 0 stevel #include <arpa/telnet.h> 70 0 stevel #include <arpa/inet.h> 71 0 stevel #include <stdio.h> 72 0 stevel #include <stdarg.h> 73 0 stevel #include <signal.h> 74 0 stevel #include <errno.h> 75 0 stevel #include <netdb.h> 76 0 stevel #include <syslog.h> 77 0 stevel #include <ctype.h> 78 0 stevel #include <fcntl.h> 79 0 stevel #include <sac.h> /* for SC_WILDC */ 80 0 stevel #include <utmpx.h> 81 0 stevel #include <sys/ttold.h> 82 0 stevel #include <malloc.h> 83 0 stevel #include <string.h> 84 0 stevel #include <security/pam_appl.h> 85 0 stevel #include <sys/tihdr.h> 86 0 stevel #include <sys/logindmux.h> 87 0 stevel #include <sys/telioctl.h> 88 0 stevel #include <deflt.h> 89 0 stevel #include <stdlib.h> 90 0 stevel #include <string.h> 91 0 stevel #include <stropts.h> 92 0 stevel #include <termios.h> 93 0 stevel 94 0 stevel #include <com_err.h> 95 0 stevel #include <krb5.h> 96 0 stevel #include <krb5_repository.h> 97 0 stevel #include <des/des.h> 98 0 stevel #include <rpc/des_crypt.h> 99 0 stevel #include <sys/cryptmod.h> 100 0 stevel #include <bsm/adt.h> 101 0 stevel 102 0 stevel #define TELNETD_OPTS "Ss:a:dEXUhR:M:" 103 0 stevel #ifdef DEBUG 104 0 stevel #define DEBUG_OPTS "p:e" 105 0 stevel #else 106 0 stevel #define DEBUG_OPTS "" 107 0 stevel #endif /* DEBUG */ 108 0 stevel 109 0 stevel #define OPT_NO 0 /* won't do this option */ 110 0 stevel #define OPT_YES 1 /* will do this option */ 111 0 stevel #define OPT_YES_BUT_ALWAYS_LOOK 2 112 0 stevel #define OPT_NO_BUT_ALWAYS_LOOK 3 113 0 stevel 114 0 stevel #define MAXOPTLEN 256 115 0 stevel #define MAXUSERNAMELEN 256 116 0 stevel 117 0 stevel static char remopts[MAXOPTLEN]; 118 0 stevel static char myopts[MAXOPTLEN]; 119 0 stevel static uchar_t doopt[] = { (uchar_t)IAC, (uchar_t)DO, '%', 'c', 0 }; 120 0 stevel static uchar_t dont[] = { (uchar_t)IAC, (uchar_t)DONT, '%', 'c', 0 }; 121 0 stevel static uchar_t will[] = { (uchar_t)IAC, (uchar_t)WILL, '%', 'c', 0 }; 122 0 stevel static uchar_t wont[] = { (uchar_t)IAC, (uchar_t)WONT, '%', 'c', 0 }; 123 0 stevel /* 124 0 stevel * I/O data buffers, pointers, and counters. 125 0 stevel */ 126 0 stevel static char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf; 127 0 stevel 128 0 stevel static char *netibuf, *netip; 129 0 stevel static int netibufsize; 130 0 stevel 131 0 stevel #define NIACCUM(c) { *netip++ = c; \ 132 0 stevel ncc++; \ 133 0 stevel } 134 0 stevel 135 0 stevel static char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf; 136 0 stevel static char *neturg = 0; /* one past last bye of urgent data */ 137 0 stevel /* the remote system seems to NOT be an old 4.2 */ 138 0 stevel static int not42 = 1; 139 0 stevel static char defaultfile[] = "/etc/default/telnetd"; 140 0 stevel static char bannervar[] = "BANNER="; 141 0 stevel 142 0 stevel static char BANNER1[] = "\r\n\r\n"; 143 0 stevel static char BANNER2[] = "\r\n\r\0\r\n\r\0"; 144 0 stevel 145 0 stevel /* 146 0 stevel * buffer for sub-options - enlarged to 4096 to handle credentials 147 0 stevel * from AUTH options 148 0 stevel */ 149 0 stevel static char subbuffer[4096], *subpointer = subbuffer, *subend = subbuffer; 150 0 stevel #define SB_CLEAR() subpointer = subbuffer; 151 0 stevel #define SB_TERM() { subend = subpointer; SB_CLEAR(); } 152 0 stevel #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof (subbuffer))) { \ 153 0 stevel *subpointer++ = (c); \ 154 0 stevel } 155 0 stevel #define SB_GET() ((*subpointer++)&0xff) 156 0 stevel #define SB_EOF() (subpointer >= subend) 157 0 stevel #define SB_LEN() (subend - subpointer) 158 0 stevel 159 0 stevel #define MAXERRSTRLEN 1024 160 0 stevel #define MAXPRINCLEN 256 161 6536 gtb 162 6536 gtb extern uint_t kwarn_add_warning(char *, int); 163 6536 gtb extern uint_t kwarn_del_warning(char *); 164 0 stevel 165 0 stevel static boolean_t auth_debug = 0; 166 0 stevel static boolean_t negotiate_auth_krb5 = 1; 167 0 stevel static boolean_t auth_negotiated = 0; 168 0 stevel static int auth_status = 0; 169 0 stevel static int auth_level = 0; 170 0 stevel static char *AuthenticatingUser = NULL; 171 0 stevel static char *krb5_name = NULL; 172 0 stevel 173 0 stevel static krb5_address rsaddr = { 0, 0, 0, NULL }; 174 0 stevel static krb5_address rsport = { 0, 0, 0, NULL }; 175 0 stevel 176 0 stevel static krb5_context telnet_context = 0; 177 0 stevel static krb5_auth_context auth_context = 0; 178 0 stevel 179 0 stevel /* telnetd gets session key from here */ 180 0 stevel static krb5_ticket *ticket = NULL; 181 0 stevel static krb5_keyblock *session_key = NULL; 182 0 stevel static char *telnet_srvtab = NULL; 183 0 stevel 184 0 stevel typedef struct { 185 0 stevel uchar_t AuthName; 186 0 stevel uchar_t AuthHow; 187 0 stevel char *AuthString; 188 0 stevel } AuthInfo; 189 0 stevel 190 0 stevel static AuthInfo auth_list[] = { 191 0 stevel {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL | 192 0 stevel AUTH_ENCRYPT_ON, "KRB5 MUTUAL CRYPTO"}, 193 0 stevel {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL, 194 0 stevel "KRB5 MUTUAL" }, 195 0 stevel {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_ONE_WAY, 196 0 stevel "KRB5 1-WAY" }, 197 0 stevel {0, 0, "NONE"} 198 0 stevel }; 199 0 stevel 200 0 stevel static AuthInfo NoAuth = {0, 0, NULL}; 201 0 stevel 202 0 stevel static AuthInfo *authenticated = NULL; 203 0 stevel 204 0 stevel #define PREAMBLE_SIZE 5 /* for auth_reply_str allocation */ 205 0 stevel #define POSTAMBLE_SIZE 5 206 0 stevel #define STR_DATA_LEN(len) ((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE) 207 0 stevel 208 0 stevel static void auth_name(uchar_t *, int); 209 0 stevel static void auth_is(uchar_t *, int); 210 0 stevel 211 0 stevel #define NO_ENCRYPTION 0x00 212 0 stevel #define SEND_ENCRYPTED 0x01 213 0 stevel #define RECV_ENCRYPTED 0x02 214 0 stevel #define ENCRYPT_BOTH_WAYS (SEND_ENCRYPTED | RECV_ENCRYPTED) 215 0 stevel 216 0 stevel static telnet_enc_data_t encr_data; 217 0 stevel static boolean_t negotiate_encrypt = B_TRUE; 218 0 stevel static boolean_t sent_encrypt_support = B_FALSE; 219 0 stevel static boolean_t sent_will_encrypt = B_FALSE; 220 0 stevel static boolean_t sent_do_encrypt = B_FALSE; 221 0 stevel static boolean_t enc_debug = 0; 222 0 stevel 223 0 stevel static void encrypt_session_key(Session_Key *key, cipher_info_t *cinfo); 224 0 stevel static int encrypt_send_encrypt_is(); 225 0 stevel 226 0 stevel extern void mit_des_fixup_key_parity(Block); 227 0 stevel extern int krb5_setenv(const char *, const char *, int); 228 0 stevel /* need to know what FD to use to talk to the crypto module */ 229 0 stevel static int cryptmod_fd = -1; 230 0 stevel 231 0 stevel #define LOGIN_PROGRAM "/bin/login" 232 0 stevel 233 0 stevel /* 234 0 stevel * State for recv fsm 235 0 stevel */ 236 0 stevel #define TS_DATA 0 /* base state */ 237 0 stevel #define TS_IAC 1 /* look for double IAC's */ 238 0 stevel #define TS_CR 2 /* CR-LF ->'s CR */ 239 0 stevel #define TS_SB 3 /* throw away begin's... */ 240 0 stevel #define TS_SE 4 /* ...end's (suboption negotiation) */ 241 0 stevel #define TS_WILL 5 /* will option negotiation */ 242 0 stevel #define TS_WONT 6 /* wont " */ 243 0 stevel #define TS_DO 7 /* do " */ 244 0 stevel #define TS_DONT 8 /* dont " */ 245 0 stevel 246 0 stevel static int ncc; 247 0 stevel static int master; /* master side of pty */ 248 0 stevel static int pty; /* side of pty that gets ioctls */ 249 0 stevel static int net; 250 0 stevel static int inter; 251 0 stevel extern char **environ; 252 0 stevel static char *line; 253 0 stevel static int SYNCHing = 0; /* we are in TELNET SYNCH mode */ 254 0 stevel static int state = TS_DATA; 255 0 stevel 256 0 stevel static int env_ovar = -1; /* XXX.sparker */ 257 0 stevel static int env_ovalue = -1; /* XXX.sparker */ 258 0 stevel static char pam_svc_name[64]; 259 0 stevel static boolean_t telmod_init_done = B_FALSE; 260 0 stevel 261 0 stevel static void doit(int, struct sockaddr_storage *); 262 0 stevel static void willoption(int); 263 0 stevel static void wontoption(int); 264 0 stevel static void dooption(int); 265 0 stevel static void dontoption(int); 266 0 stevel static void fatal(int, char *); 267 0 stevel static void fatalperror(int, char *, int); 268 0 stevel static void mode(int, int); 269 0 stevel static void interrupt(void); 270 0 stevel static void drainstream(int); 271 0 stevel static int readstream(int, char *, int); 272 0 stevel static int send_oob(int fd, char *ptr, int count); 273 0 stevel static int local_setenv(const char *name, const char *value, int rewrite); 274 0 stevel static void local_unsetenv(const char *name); 275 0 stevel static void suboption(void); 276 0 stevel static int removemod(int f, char *modname); 277 0 stevel static void willoption(int option); 278 0 stevel static void wontoption(int option); 279 0 stevel static void dooption(int option); 280 0 stevel static void dontoption(int option); 281 0 stevel static void write_data(const char *, ...); 282 0 stevel static void write_data_len(const char *, int); 283 0 stevel static void rmut(void); 284 0 stevel static void cleanup(int); 285 0 stevel static void telnet(int, int); 286 0 stevel static void telrcv(void); 287 0 stevel static void sendbrk(void); 288 0 stevel static void ptyflush(void); 289 0 stevel static void netclear(void); 290 0 stevel static void netflush(void); 291 0 stevel static void showbanner(void); 292 0 stevel static void map_banner(char *); 293 0 stevel static void defbanner(void); 294 0 stevel static void ttloop(void); 295 0 stevel 296 0 stevel /* 297 0 stevel * The env_list linked list is used to store the environment variables 298 0 stevel * until the final exec of login. A malevolent client might try to 299 0 stevel * send an environment variable intended to affect the telnet daemon's 300 0 stevel * execution. Right now the BANNER expansion is the only instance. 301 0 stevel * Note that it is okay to pass the environment variables to login 302 0 stevel * because login protects itself against environment variables mischief. 303 0 stevel */ 304 0 stevel 305 0 stevel struct envlist { 306 0 stevel struct envlist *next; 307 0 stevel char *name; 308 0 stevel char *value; 309 0 stevel int delete; 310 0 stevel }; 311 0 stevel 312 0 stevel static struct envlist *envlist_head = NULL; 313 0 stevel 314 0 stevel /* 315 0 stevel * The following are some clocks used to decide how to interpret 316 0 stevel * the relationship between various variables. 317 0 stevel */ 318 0 stevel 319 0 stevel static struct { 320 0 stevel int 321 0 stevel system, /* what the current time is */ 322 0 stevel echotoggle, /* last time user entered echo character */ 323 0 stevel modenegotiated, /* last time operating mode negotiated */ 324 0 stevel didnetreceive, /* last time we read data from network */ 325 0 stevel ttypeopt, /* ttype will/won't received */ 326 0 stevel ttypesubopt, /* ttype subopt is received */ 327 0 stevel getterminal, /* time started to get terminal information */ 328 0 stevel xdisplocopt, /* xdisploc will/wont received */ 329 0 stevel xdisplocsubopt, /* xdisploc suboption received */ 330 0 stevel nawsopt, /* window size will/wont received */ 331 0 stevel nawssubopt, /* window size received */ 332 0 stevel environopt, /* environment option will/wont received */ 333 0 stevel oenvironopt, /* "old" environ option will/wont received */ 334 0 stevel environsubopt, /* environment option suboption received */ 335 0 stevel oenvironsubopt, /* "old environ option suboption received */ 336 0 stevel gotDM; /* when did we last see a data mark */ 337 0 stevel 338 0 stevel int getauth; 339 0 stevel int authopt; /* Authentication option negotiated */ 340 0 stevel int authdone; 341 0 stevel 342 0 stevel int getencr; 343 0 stevel int encropt; 344 0 stevel int encr_support; 345 0 stevel } clocks; 346 0 stevel 347 0 stevel static int init_neg_done = 0; 348 0 stevel static boolean_t resolve_hostname = 0; 349 0 stevel static boolean_t show_hostinfo = 1; 350 0 stevel 351 0 stevel #define settimer(x) (clocks.x = ++clocks.system) 352 0 stevel #define sequenceIs(x, y) (clocks.x < clocks.y) 353 0 stevel 354 0 stevel static void send_will(int); 355 0 stevel static void send_wont(int); 356 0 stevel static void send_do(int); 357 0 stevel static char *__findenv(const char *name, int *offset); 358 0 stevel 359 0 stevel /* ARGSUSED */ 360 0 stevel static void 361 0 stevel auth_finished(AuthInfo *ap, int result) 362 0 stevel { 363 0 stevel if ((authenticated = ap) == NULL) { 364 0 stevel authenticated = &NoAuth; 365 0 stevel if (myopts[TELOPT_ENCRYPT] == OPT_YES) 366 0 stevel send_wont(TELOPT_ENCRYPT); 367 0 stevel myopts[TELOPT_ENCRYPT] = remopts[TELOPT_ENCRYPT] = OPT_NO; 368 0 stevel encr_data.encrypt.autoflag = 0; 369 0 stevel } else if (result != AUTH_REJECT && 370 0 stevel myopts[TELOPT_ENCRYPT] == OPT_YES && 371 0 stevel remopts[TELOPT_ENCRYPT] == OPT_YES) { 372 0 stevel 373 0 stevel /* 374 0 stevel * Authentication successful, so we have a session key, and 375 0 stevel * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT. 376 0 stevel * 377 0 stevel * Can't have sent ENCRYPT SUPPORT yet! And if we're sending it 378 0 stevel * now it's really only because we did the DO ENCRYPT/WILL 379 0 stevel * ENCRYPT dance before authentication, which is ok, but not too 380 0 stevel * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT 381 0 stevel * dance if authentication fails, though clients typically just 382 0 stevel * don't care. 383 0 stevel */ 384 0 stevel write_data("%c%c%c%c%c%c%c", 385 0 stevel (uchar_t)IAC, 386 0 stevel (uchar_t)SB, 387 0 stevel (uchar_t)TELOPT_ENCRYPT, 388 0 stevel (uchar_t)ENCRYPT_SUPPORT, 389 0 stevel (uchar_t)TELOPT_ENCTYPE_DES_CFB64, 390 0 stevel (uchar_t)IAC, 391 0 stevel (uchar_t)SE); 392 0 stevel 393 0 stevel netflush(); 394 0 stevel 395 0 stevel sent_encrypt_support = B_TRUE; 396 0 stevel 397 0 stevel if (enc_debug) 398 0 stevel (void) fprintf(stderr, 399 0 stevel "SENT ENCRYPT SUPPORT\n"); 400 0 stevel 401 0 stevel (void) encrypt_send_encrypt_is(); 402 0 stevel } 403 0 stevel 404 0 stevel auth_status = result; 405 0 stevel 406 0 stevel settimer(authdone); 407 0 stevel } 408 0 stevel 409 0 stevel static void 410 0 stevel reply_to_client(AuthInfo *ap, int type, void *data, int len) 411 0 stevel { 412 0 stevel uchar_t reply[BUFSIZ]; 413 0 stevel uchar_t *p = reply; 414 0 stevel uchar_t *cd = (uchar_t *)data; 415 0 stevel 416 0 stevel if (len == -1 && data != NULL) 417 0 stevel len = strlen((char *)data); 418 0 stevel else if (len > (sizeof (reply) - 9)) { 419 0 stevel syslog(LOG_ERR, 420 0 stevel "krb5 auth reply length too large (%d)", len); 421 0 stevel if (auth_debug) 422 0 stevel (void) fprintf(stderr, 423 0 stevel "krb5 auth reply length too large (%d)\n", 424 0 stevel len); 425 0 stevel return; 426 0 stevel } else if (data == NULL) 427 0 stevel len = 0; 428 0 stevel 429 0 stevel *p++ = IAC; 430 0 stevel *p++ = SB; 431 0 stevel *p++ = TELOPT_AUTHENTICATION; 432 0 stevel *p++ = AUTHTYPE_KERBEROS_V5; 433 0 stevel *p++ = ap->AuthName; 434 0 stevel *p++ = ap->AuthHow; /* MUTUAL, ONE-WAY, etc */ 435 0 stevel *p++ = type; /* RESPONSE or ACCEPT */ 436 0 stevel while (len-- > 0) { 437 0 stevel if ((*p++ = *cd++) == IAC) 438 0 stevel *p++ = IAC; 439 0 stevel } 440 0 stevel *p++ = IAC; 441 0 stevel *p++ = SE; 442 0 stevel 443 0 stevel /* queue the data to be sent */ 444 0 stevel write_data_len((const char *)reply, p-reply); 445 0 stevel 446 0 stevel #if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\ 447 0 stevel defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES) 448 0 stevel if (auth_debug) { 449 0 stevel (void) fprintf(stderr, "SENT TELOPT_AUTHENTICATION REPLY " 450 0 stevel "%s %s|%s %s\n", 451 0 stevel AUTHTYPE_NAME(ap->AuthName), 452 0 stevel AUTHWHO_NAME(ap->AuthHow & AUTH_WHO_MASK), 453 0 stevel AUTHHOW_NAME(ap->AuthHow & AUTH_HOW_MASK), 454 0 stevel AUTHRSP_NAME(type)); 455 0 stevel } 456 0 stevel #endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */ 457 0 stevel 458 0 stevel netflush(); 459 0 stevel } 460 0 stevel 461 0 stevel /* Decode, decrypt and store the forwarded creds in the local ccache. */ 462 0 stevel static krb5_error_code 463 0 stevel rd_and_store_forwarded_creds(krb5_context context, 464 0 stevel krb5_auth_context auth_context, 465 0 stevel krb5_data *inbuf, krb5_ticket *ticket, 466 0 stevel char *username) 467 0 stevel { 468 0 stevel krb5_creds **creds; 469 0 stevel krb5_error_code retval; 470 6536 gtb char ccname[MAXPATHLEN]; 471 0 stevel krb5_ccache ccache = NULL; 472 6536 gtb char *client_name = NULL; 473 0 stevel 474 0 stevel if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)) 475 0 stevel return (retval); 476 0 stevel 477 0 stevel (void) sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", getpid()); 478 0 stevel (void) krb5_setenv("KRB5CCNAME", ccname, 1); 479 0 stevel 480 0 stevel if ((retval = krb5_cc_default(context, &ccache))) 481 0 stevel goto cleanup; 482 0 stevel 483 0 stevel if ((retval = krb5_cc_initialize(context, ccache, 484 0 stevel ticket->enc_part2->client)) != 0) 485 0 stevel goto cleanup; 486 0 stevel 487 0 stevel if ((retval = krb5_cc_store_cred(context, ccache, *creds)) != 0) 488 0 stevel goto cleanup; 489 0 stevel 490 0 stevel if ((retval = krb5_cc_close(context, ccache)) != 0) 491 0 stevel goto cleanup; 492 6536 gtb 493 6536 gtb /* Register with ktkt_warnd(1M) */ 494 6536 gtb if ((retval = krb5_unparse_name(context, (*creds)->client, 495 6536 gtb &client_name)) != 0) 496 6536 gtb goto cleanup; 497 6536 gtb (void) kwarn_del_warning(client_name); 498 6536 gtb if (kwarn_add_warning(client_name, (*creds)->times.endtime) != 0) { 499 6536 gtb syslog(LOG_AUTH|LOG_NOTICE, 500 6536 gtb "rd_and_store_forwarded_creds: kwarn_add_warning" 501 6536 gtb " failed: ktkt_warnd(1M) down? "); 502 6536 gtb if (auth_debug) 503 6536 gtb (void) fprintf(stderr, 504 6536 gtb "kwarn_add_warning failed:" 505 6536 gtb " ktkt_warnd(1M) down?\n"); 506 6536 gtb } 507 6536 gtb free(client_name); 508 6536 gtb client_name = NULL; 509 0 stevel 510 0 stevel if (username != NULL) { 511 0 stevel /* 512 0 stevel * This verifies that the user is valid on the local system, 513 0 stevel * maps the username from KerberosV5 to unix, 514 0 stevel * and moves the KRB5CCNAME file to the correct place 515 0 stevel * /tmp/krb5cc_[uid] with correct ownership (0600 uid gid). 516 0 stevel * 517 0 stevel * NOTE: the user must be in the gsscred table in order to map 518 0 stevel * from KRB5 to Unix. 519 0 stevel */ 520 0 stevel (void) krb5_kuserok(context, ticket->enc_part2->client, 521 0 stevel username); 522 0 stevel } 523 0 stevel if (auth_debug) 524 0 stevel (void) fprintf(stderr, 525 0 stevel "Successfully stored forwarded creds\n"); 526 0 stevel 527 0 stevel cleanup: 528 0 stevel krb5_free_creds(context, *creds); 529 0 stevel return (retval); 530 0 stevel } 531 0 stevel 532 0 stevel static void 533 0 stevel kerberos5_is(AuthInfo *ap, uchar_t *data, int cnt) 534 0 stevel { 535 0 stevel krb5_error_code err = 0; 536 0 stevel krb5_principal server; 537 0 stevel krb5_keyblock *newkey = NULL; 538 0 stevel krb5_keytab keytabid = 0; 539 0 stevel krb5_data outbuf; 540 0 stevel krb5_data inbuf; 541 0 stevel krb5_authenticator *authenticator; 542 0 stevel char errbuf[MAXERRSTRLEN]; 543 0 stevel char *name; 544 0 stevel krb5_data auth; 545 0 stevel 546 0 stevel Session_Key skey; 547 0 stevel 548 0 stevel if (cnt-- < 1) 549 0 stevel return; 550 0 stevel switch (*data++) { 551 0 stevel case KRB_AUTH: 552 0 stevel auth.data = (char *)data; 553 0 stevel auth.length = cnt; 554 0 stevel 555 0 stevel if (auth_context == NULL) { 556 0 stevel err = krb5_auth_con_init(telnet_context, &auth_context); 557 0 stevel if (err) 558 0 stevel syslog(LOG_ERR, 559 0 stevel "Error getting krb5 auth " 560 0 stevel "context: %s", error_message(err)); 561 0 stevel } 562 0 stevel if (!err) { 563 0 stevel krb5_rcache rcache; 564 0 stevel 565 0 stevel err = krb5_auth_con_getrcache(telnet_context, 566 0 stevel auth_context, 567 0 stevel &rcache); 568 0 stevel if (!err && !rcache) { 569 0 stevel err = krb5_sname_to_principal(telnet_context, 570 0 stevel 0, 0, 571 0 stevel KRB5_NT_SRV_HST, 572 0 stevel &server); 573 0 stevel if (!err) { 574 0 stevel err = krb5_get_server_rcache( 575 0 stevel telnet_context, 576 0 stevel krb5_princ_component( 577 0 stevel telnet_context, 578 0 stevel server, 0), 579 0 stevel &rcache); 580 0 stevel 581 0 stevel krb5_free_principal(telnet_context, 582 0 stevel server); 583 0 stevel } 584 0 stevel } 585 0 stevel if (err) 586 0 stevel syslog(LOG_ERR, 587 0 stevel "Error allocating krb5 replay cache: %s", 588 0 stevel error_message(err)); 589 0 stevel else { 590 0 stevel err = krb5_auth_con_setrcache(telnet_context, 591 0 stevel auth_context, 592 0 stevel rcache); 593 0 stevel if (err) 594 0 stevel syslog(LOG_ERR, 595 0 stevel "Error creating krb5 " 596 0 stevel "replay cache: %s", 597 0 stevel error_message(err)); 598 0 stevel } 599 0 stevel } 600 0 stevel if (!err && telnet_srvtab != NULL) 601 0 stevel err = krb5_kt_resolve(telnet_context, 602 0 stevel telnet_srvtab, &keytabid); 603 0 stevel if (!err) 604 0 stevel err = krb5_rd_req(telnet_context, &auth_context, &auth, 605 0 stevel NULL, keytabid, NULL, &ticket); 606 0 stevel if (err) { 607 0 stevel (void) snprintf(errbuf, sizeof (errbuf), 608 0 stevel "Error reading krb5 auth information:" 609 0 stevel " %s", error_message(err)); 610 0 stevel goto errout; 611 0 stevel } 612 0 stevel 613 0 stevel /* 614 0 stevel * Verify that the correct principal was used 615 0 stevel */ 616 0 stevel if (krb5_princ_component(telnet_context, 617 0 stevel ticket->server, 0)->length < MAXPRINCLEN) { 618 0 stevel char princ[MAXPRINCLEN]; 619 0 stevel (void) strncpy(princ, 620 0 stevel krb5_princ_component(telnet_context, 621 0 stevel ticket->server, 0)->data, 622 0 stevel krb5_princ_component(telnet_context, 623 0 stevel ticket->server, 0)->length); 624 0 stevel princ[krb5_princ_component(telnet_context, 625 0 stevel ticket->server, 0)->length] = '\0'; 626 0 stevel if (strcmp("host", princ)) { 627 0 stevel if (strlen(princ) < sizeof (errbuf) - 39) { 628 0 stevel (void) snprintf(errbuf, sizeof (errbuf), 629 0 stevel "incorrect service " 630 0 stevel "name: \"%s\" != " 631 0 stevel "\"host\"", 632 0 stevel princ); 633 0 stevel } else { 634 0 stevel (void) strncpy(errbuf, 635 0 stevel "incorrect service " 636 0 stevel "name: principal != " 637 0 stevel "\"host\"", 638 0 stevel sizeof (errbuf)); 639 0 stevel } 640 0 stevel goto errout; 641 0 stevel } 642 0 stevel } else { 643 0 stevel (void) strlcpy(errbuf, "service name too long", 644 0 stevel sizeof (errbuf)); 645 0 stevel goto errout; 646 0 stevel } 647 0 stevel 648 0 stevel err = krb5_auth_con_getauthenticator(telnet_context, 649 0 stevel auth_context, 650 0 stevel &authenticator); 651 0 stevel if (err) { 652 0 stevel (void) snprintf(errbuf, sizeof (errbuf), 653 0 stevel "Failed to get authenticator: %s", 654 0 stevel error_message(err)); 655 0 stevel goto errout; 656 0 stevel } 657 0 stevel if ((ap->AuthHow & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON && 658 0 stevel !authenticator->checksum) { 659 0 stevel (void) strlcpy(errbuf, 660 0 stevel "authenticator is missing checksum", 661 0 stevel sizeof (errbuf)); 662 0 stevel goto errout; 663 0 stevel } 664 0 stevel if (authenticator->checksum) { 665 0 stevel char type_check[2]; 666 0 stevel krb5_checksum *cksum = authenticator->checksum; 667 0 stevel krb5_keyblock *key; 668 0 stevel krb5_data input; 669 0 stevel krb5_boolean valid; 670 0 stevel 671 0 stevel type_check[0] = ap->AuthName; 672 0 stevel type_check[1] = ap->AuthHow; 673 0 stevel 674 0 stevel err = krb5_auth_con_getkey(telnet_context, 675 0 stevel auth_context, &key); 676 0 stevel if (err) { 677 0 stevel (void) snprintf(errbuf, sizeof (errbuf), 678 0 stevel "Failed to get key from " 679 0 stevel "authenticator: %s", 680 0 stevel error_message(err)); 681 0 stevel goto errout; 682 0 stevel } 683 0 stevel 684 0 stevel input.data = type_check; 685 0 stevel input.length = 2; 686 0 stevel err = krb5_c_verify_checksum(telnet_context, 687 0 stevel key, 0, 688 0 stevel &input, 689 0 stevel cksum, 690 0 stevel &valid); 691 0 stevel if (!err && !valid) 692 0 stevel err = KRB5KRB_AP_ERR_BAD_INTEGRITY; 693 0 stevel 694 0 stevel if (err) { 695 0 stevel (void) snprintf(errbuf, sizeof (errbuf), 696 0 stevel "Kerberos checksum " 697 0 stevel "verification failed: " 698 0 stevel "%s", 699 0 stevel error_message(err)); 700 0 stevel goto errout; 701 0 stevel } 702 0 stevel krb5_free_keyblock(telnet_context, key); 703 0 stevel } 704 0 stevel 705 0 stevel krb5_free_authenticator(telnet_context, authenticator); 706 0 stevel if ((ap->AuthHow & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 707 0 stevel /* do ap_rep stuff here */ 708 0 stevel if ((err = krb5_mk_rep(telnet_context, auth_context, 709 0 stevel &outbuf))) { 710 0 stevel (void) snprintf(errbuf, sizeof (errbuf), 711 0 stevel "Failed to make " 712 0 stevel "Kerberos auth reply: " 713 0 stevel "%s", 714 0 stevel error_message(err)); 715 0 stevel goto errout; 716 0 stevel } 717 0 stevel reply_to_client(ap, KRB_RESPONSE, outbuf.data, 718 0 stevel outbuf.length); 719 0 stevel } 720 0 stevel if (krb5_unparse_name(telnet_context, 721 0 stevel ticket->enc_part2->client, 722 0 stevel &name)) 723 0 stevel name = 0; 724 0 stevel reply_to_client(ap, KRB_ACCEPT, name, name ? -1 : 0); 725 0 stevel if (auth_debug) { 726 0 stevel syslog(LOG_NOTICE, 727 0 stevel "\tKerberos5 identifies user as ``%s''\r\n", 728 0 stevel name ? name : ""); 729 0 stevel } 730 0 stevel if (name != NULL) { 731 0 stevel krb5_name = (char *)strdup(name); 732 0 stevel } 733 0 stevel auth_finished(ap, AUTH_USER); 734 0 stevel 735 0 stevel if (name != NULL) 736 0 stevel free(name); 737 0 stevel krb5_auth_con_getremotesubkey(telnet_context, auth_context, 738 0 stevel &newkey); 739 0 stevel if (session_key != NULL) { 740 0 stevel krb5_free_keyblock(telnet_context, session_key); 741 0 stevel session_key = 0; 742 0 stevel } 743 0 stevel if (newkey != NULL) { 744 0 stevel krb5_copy_keyblock(telnet_context, 745 0 stevel newkey, &session_key); 746 0 stevel krb5_free_keyblock(telnet_context, newkey); 747 0 stevel } else { 748 0 stevel krb5_copy_keyblock(telnet_context, 749 0 stevel ticket->enc_part2->session, 750 0 stevel &session_key); 751 0 stevel } 752 0 stevel 753 0 stevel /* 754 0 stevel * Initialize encryption stuff. Currently, we are only 755 0 stevel * supporting 8 byte keys and blocks. Check for this later. 756 0 stevel */ 757 0 stevel skey.type = SK_DES; 758 0 stevel skey.length = DES_BLOCKSIZE; 759 0 stevel skey.data = session_key->contents; 760 0 stevel encrypt_session_key(&skey, &encr_data.encrypt); 761 0 stevel encrypt_session_key(&skey, &encr_data.decrypt); 762 0 stevel break; 763 0 stevel case KRB_FORWARD: 764 0 stevel inbuf.length = cnt; 765 0 stevel inbuf.data = (char *)data; 766 0 stevel if (auth_debug) 767 0 stevel (void) fprintf(stderr, 768 0 stevel "RCVD KRB_FORWARD data (%d bytes)\n", cnt); 769 0 stevel 770 0 stevel if (auth_context != NULL) { 771 0 stevel krb5_rcache rcache; 772 0 stevel 773 0 stevel err = krb5_auth_con_getrcache(telnet_context, 774 0 stevel auth_context, &rcache); 775 0 stevel if (!err && !rcache) { 776 0 stevel err = krb5_sname_to_principal(telnet_context, 777 0 stevel 0, 0, KRB5_NT_SRV_HST, &server); 778 0 stevel if (!err) { 779 0 stevel err = krb5_get_server_rcache( 780 0 stevel telnet_context, 781 0 stevel krb5_princ_component( 782 0 stevel telnet_context, 783 0 stevel server, 0), 784 0 stevel &rcache); 785 0 stevel krb5_free_principal(telnet_context, 786 0 stevel server); 787 0 stevel } 788 0 stevel } 789 0 stevel if (err) { 790 0 stevel syslog(LOG_ERR, 791 0 stevel "Error allocating krb5 replay cache: %s", 792 0 stevel error_message(err)); 793 0 stevel } else { 794 0 stevel err = krb5_auth_con_setrcache(telnet_context, 795 0 stevel auth_context, rcache); 796 0 stevel if (err) 797 0 stevel syslog(LOG_ERR, 798 0 stevel "Error creating krb5 replay cache:" 799 0 stevel " %s", 800 0 stevel error_message(err)); 801 0 stevel } 802 0 stevel } 803 0 stevel /* 804 0 stevel * Use the 'rsaddr' and 'rsport' (remote service addr/port) 805 0 stevel * from the original connection. This data is used to 806 0 stevel * verify the forwarded credentials. 807 0 stevel */ 808 0 stevel if (!(err = krb5_auth_con_setaddrs(telnet_context, auth_context, 809 0 stevel NULL, &rsaddr))) 810 0 stevel err = krb5_auth_con_setports(telnet_context, 811 0 stevel auth_context, NULL, &rsport); 812 0 stevel 813 0 stevel if (err == 0) 814 0 stevel /* 815 0 stevel * If all is well, store the forwarded creds in 816 0 stevel * the users local credential cache. 817 0 stevel */ 818 0 stevel err = rd_and_store_forwarded_creds(telnet_context, 819 0 stevel auth_context, &inbuf, 820 0 stevel ticket, 821 0 stevel AuthenticatingUser); 822 0 stevel if (err) { 823 0 stevel (void) snprintf(errbuf, sizeof (errbuf), 824 0 stevel "Read forwarded creds failed: %s", 825 0 stevel error_message(err)); 826 0 stevel syslog(LOG_ERR, "%s", errbuf); 827 0 stevel 828 0 stevel reply_to_client(ap, KRB_FORWARD_REJECT, errbuf, -1); 829 0 stevel if (auth_debug) 830 0 stevel (void) fprintf(stderr, 831 0 stevel "\tCould not read " 832 0 stevel "forwarded credentials\r\n"); 833 0 stevel } else 834 0 stevel reply_to_client(ap, KRB_FORWARD_ACCEPT, (void *) 0, 0); 835 0 stevel 836 0 stevel if (rsaddr.contents != NULL) 837 0 stevel free(rsaddr.contents); 838 0 stevel 839 0 stevel if (rsport.contents != NULL) 840 0 stevel free(rsport.contents); 841 0 stevel 842 0 stevel if (auth_debug) 843 0 stevel (void) fprintf(stderr, "\tForwarded " 844 0 stevel "credentials obtained\r\n"); 845 0 stevel break; 846 0 stevel default: 847 0 stevel if (auth_debug) 848 0 stevel (void) fprintf(stderr, 849 0 stevel "\tUnknown Kerberos option %d\r\n", 850 0 stevel data[-1]); 851 0 stevel reply_to_client(ap, KRB_REJECT, (void *) 0, 0); 852 0 stevel break; 853 0 stevel } 854 0 stevel return; 855 0 stevel 856 0 stevel errout: 857 0 stevel reply_to_client(ap, KRB_REJECT, errbuf, -1); 858 0 stevel 859 0 stevel if (auth_debug) 860 0 stevel (void) fprintf(stderr, "\tKerberos V5 error: %s\r\n", errbuf); 861 0 stevel 862 0 stevel syslog(LOG_ERR, "%s", errbuf); 863 0 stevel 864 0 stevel if (auth_context != NULL) { 865 0 stevel krb5_auth_con_free(telnet_context, auth_context); 866 0 stevel auth_context = 0; 867 0 stevel } 868 0 stevel } 869 0 stevel 870 0 stevel static int 871 0 stevel krb5_init() 872 0 stevel { 873 0 stevel int code = 0; 874 0 stevel 875 0 stevel if (telnet_context == NULL) { 876 0 stevel code = krb5_init_context(&telnet_context); 877 0 stevel if (code != 0 && auth_debug) 878 0 stevel syslog(LOG_NOTICE, 879 0 stevel "Cannot initialize Kerberos V5: %s", 880 0 stevel error_message(code)); 881 0 stevel } 882 0 stevel 883 0 stevel return (code); 884 0 stevel } 885 0 stevel 886 0 stevel static void 887 0 stevel auth_name(uchar_t *data, int cnt) 888 0 stevel { 889 0 stevel char namebuf[MAXPRINCLEN]; 890 0 stevel 891 0 stevel if (cnt < 1) { 892 0 stevel if (auth_debug) 893 0 stevel (void) fprintf(stderr, 894 0 stevel "\t(auth_name) Empty NAME in auth " 895 0 stevel "reply\n"); 896 0 stevel return; 897 0 stevel } 898 0 stevel if (cnt > sizeof (namebuf)-1) { 899 0 stevel if (auth_debug) 900 0 stevel (void) fprintf(stderr, 901 0 stevel "\t(auth_name) NAME exceeds %d bytes\n", 902 0 stevel sizeof (namebuf)-1); 903 0 stevel return; 904 0 stevel } 905 0 stevel (void) memcpy((void *)namebuf, (void *)data, cnt); 906 0 stevel namebuf[cnt] = 0; 907 0 stevel if (auth_debug) 908 0 stevel (void) fprintf(stderr, "\t(auth_name) name [%s]\n", namebuf); 909 0 stevel AuthenticatingUser = (char *)strdup(namebuf); 910 0 stevel } 911 0 stevel 912 0 stevel static void 913 0 stevel auth_is(uchar_t *data, int cnt) 914 0 stevel { 915 0 stevel AuthInfo *aptr = auth_list; 916 0 stevel 917 0 stevel if (cnt < 2) 918 0 stevel return; 919 0 stevel 920 0 stevel /* 921 0 stevel * We failed to negoiate secure authentication 922 0 stevel */ 923 0 stevel if (data[0] == AUTHTYPE_NULL) { 924 0 stevel auth_finished(0, AUTH_REJECT); 925 0 stevel return; 926 0 stevel } 927 0 stevel 928 0 stevel while (aptr->AuthName != NULL && 929 0 stevel (aptr->AuthName != data[0] || aptr->AuthHow != data[1])) 930 0 stevel aptr++; 931 0 stevel 932 0 stevel if (aptr != NULL) { 933 0 stevel if (auth_debug) 934 0 stevel (void) fprintf(stderr, "\t(auth_is) auth type is %s " 935 0 stevel "(%d bytes)\n", aptr->AuthString, cnt); 936 0 stevel 937 0 stevel if (aptr->AuthName == AUTHTYPE_KERBEROS_V5) 938 0 stevel kerberos5_is(aptr, data+2, cnt-2); 939 0 stevel } 940 0 stevel } 941 0 stevel 942 0 stevel static int 943 0 stevel krb5_user_status(char *name, int namelen, int level) 944 0 stevel { 945 0 stevel int retval = AUTH_USER; 946 0 stevel 947 0 stevel if (auth_debug) 948 0 stevel (void) fprintf(stderr, "\t(krb5_user_status) level = %d " 949 0 stevel "auth_level = %d user = %s\n", 950 0 stevel level, auth_level, 951 0 stevel (AuthenticatingUser != NULL ? AuthenticatingUser : "")); 952 0 stevel 953 0 stevel if (level < AUTH_USER) 954 0 stevel return (level); 955 0 stevel 956 0 stevel if (AuthenticatingUser != NULL && 957 0 stevel (retval = krb5_kuserok(telnet_context, ticket->enc_part2->client, 958 0 stevel AuthenticatingUser))) { 959 0 stevel (void) strncpy(name, AuthenticatingUser, namelen); 960 0 stevel return (AUTH_VALID); 961 0 stevel } else { 962 0 stevel if (!retval) 963 0 stevel syslog(LOG_ERR, 964 0 stevel "Krb5 principal lacks permission to " 965 0 stevel "access local account for %s", 966 0 stevel AuthenticatingUser); 967 0 stevel return (AUTH_USER); 968 0 stevel } 969 0 stevel } 970 0 stevel 971 0 stevel /* 972 0 stevel * Wrapper around /dev/urandom 973 0 stevel */ 974 0 stevel static int 975 0 stevel getrandom(char *buf, int buflen) 976 0 stevel { 977 0 stevel static int devrandom = -1; 978 0 stevel 979 0 stevel if (devrandom == -1 && 980 0 stevel (devrandom = open("/dev/urandom", O_RDONLY)) == -1) { 981 0 stevel fatalperror(net, "Unable to open /dev/urandom: ", 982 0 stevel errno); 983 0 stevel return (-1); 984 0 stevel } 985 0 stevel 986 0 stevel if (read(devrandom, buf, buflen) == -1) { 987 0 stevel fatalperror(net, "Unable to read from /dev/urandom: ", 988 0 stevel errno); 989 0 stevel return (-1); 990 0 stevel } 991 0 stevel 992 0 stevel return (0); 993 0 stevel } 994 0 stevel 995 0 stevel /* 996 0 stevel * encrypt_init 997 0 stevel * 998 0 stevel * Initialize the encryption data structures 999 0 stevel */ 1000 0 stevel static void 1001 0 stevel encrypt_init() 1002 0 stevel { 1003 0 stevel (void) memset(&encr_data.encrypt, 0, sizeof (cipher_info_t)); 1004 0 stevel (void) memset(&encr_data.decrypt, 0, sizeof (cipher_info_t)); 1005 0 stevel 1006 0 stevel encr_data.encrypt.state = ENCR_STATE_NOT_READY; 1007 0 stevel encr_data.decrypt.state = ENCR_STATE_NOT_READY; 1008 0 stevel } 1009 0 stevel 1010 0 stevel /* 1011 0 stevel * encrypt_send_request_start 1012 0 stevel * 1013 0 stevel * Request that the remote side automatically start sending 1014 0 stevel * encrypted output 1015 0 stevel */ 1016 0 stevel static void 1017 0 stevel encrypt_send_request_start() 1018 0 stevel { 1019 0 stevel uchar_t buf[6+TELNET_MAXKEYIDLEN], *p; 1020 0 stevel 1021 0 stevel p = buf; 1022 0 stevel 1023 0 stevel *p++ = IAC; 1024 0 stevel *p++ = SB; 1025 0 stevel *p++ = TELOPT_ENCRYPT; 1026 0 stevel *p++ = ENCRYPT_REQSTART; 1027 0 stevel /* 1028 0 stevel * We are telling the remote side which 1029 0 stevel * decrypt key we will use so that it may 1030 0 stevel * encrypt in the same key. 1031 0 stevel */ 1032 0 stevel (void) memcpy(p, encr_data.decrypt.keyid, encr_data.decrypt.keyidlen); 1033 0 stevel p += encr_data.decrypt.keyidlen; 1034 0 stevel 1035 0 stevel *p++ = IAC; 1036 0 stevel *p++ = SE; 1037 0 stevel 1038 0 stevel write_data_len((const char *)buf, p-buf); 1039 0 stevel netflush(); 1040 0 stevel if (enc_debug) 1041 0 stevel (void) fprintf(stderr, 1042 0 stevel "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n"); 1043 0 stevel } 1044 0 stevel 1045 0 stevel /* 1046 0 stevel * encrypt_is 1047 0 stevel * 1048 0 stevel * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ... 1049 0 stevel * message, the client is telling us that it will be sending 1050 0 stevel * encrypted data using the indicated cipher. 1051 0 stevel * We must initialize the read (decrypt) side of our connection 1052 0 stevel */ 1053 0 stevel static void 1054 0 stevel encrypt_is(uchar_t *data, int cnt) 1055 0 stevel { 1056 0 stevel register int type; 1057 0 stevel register int iv_status = CFB64_IV_OK; 1058 0 stevel register int lstate = 0; 1059 0 stevel 1060 0 stevel uchar_t sbbuf[] = { 1061 0 stevel (uchar_t)IAC, 1062 0 stevel (uchar_t)SB, 1063 0 stevel (uchar_t)TELOPT_ENCRYPT, 1064 0 stevel (uchar_t)ENCRYPT_REPLY, 1065 0 stevel (uchar_t)0, /* placeholder: sbbuf[4] */ 1066 0 stevel (uchar_t)CFB64_IV_OK, /* placeholder: sbbuf[5] */ 1067 0 stevel (uchar_t)IAC, 1068 0 stevel (uchar_t)SE, 1069 0 stevel }; 1070 0 stevel 1071 0 stevel if (--cnt < 0) 1072 0 stevel return; 1073 0 stevel 1074 0 stevel type = sbbuf[4] = *data++; 1075 0 stevel 1076 0 stevel /* 1077 0 stevel * Steps to take: 1078 0 stevel * 1. Create the proper stream Initialization vector 1079 0 stevel * - copy the correct 'seed' to IV and output blocks 1080 0 stevel * - set the correct key schedule 1081 0 stevel * 2. Generate reply for the other side: 1082 0 stevel * IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK 1083 0 stevel * [ data ... ] IAC SE 1084 0 stevel * 3. Tell crypto module: method, direction, IV 1085 0 stevel */ 1086 0 stevel switch (type) { 1087 0 stevel case TELOPT_ENCTYPE_DES_CFB64: 1088 0 stevel encr_data.decrypt.type = type; 1089 0 stevel 1090 0 stevel lstate = encr_data.decrypt.state; 1091 0 stevel if (enc_debug) 1092 0 stevel (void) fprintf(stderr, 1093 0 stevel "\t(encrypt_is) initial state = %d\n", 1094 0 stevel lstate); 1095 0 stevel /* 1096 0 stevel * Before we extract the IV bytes, make sure we got 1097 0 stevel * enough data. 1098 0 stevel */ 1099 0 stevel if (cnt < sizeof (Block)) { 1100 0 stevel iv_status = CFB64_IV_BAD; 1101 0 stevel if (enc_debug) 1102 0 stevel (void) fprintf(stderr, 1103 0 stevel "\t(encrypt_is) Not enough " 1104 0 stevel "IV bytes\n"); 1105 0 stevel lstate = ENCR_STATE_NOT_READY; 1106 0 stevel } else { 1107 0 stevel data++; /* skip over the CFB64_IV byte */ 1108 0 stevel (void) memcpy(encr_data.decrypt.ivec, data, 1109 0 stevel sizeof (Block)); 1110 0 stevel lstate = ENCR_STATE_IN_PROGRESS; 1111 0 stevel } 1112 0 stevel break; 1113 0 stevel case TELOPT_ENCTYPE_NULL: 1114 0 stevel encr_data.decrypt.type = type; 1115 0 stevel lstate &= ~ENCR_STATE_NO_RECV_IV; 1116 0 stevel lstate &= ~ENCR_STATE_NO_SEND_IV; 1117 0 stevel if (enc_debug) 1118 0 stevel (void) fprintf(stderr, 1119 0 stevel "\t(encrypt_is) We accept NULL encr\n"); 1120 0 stevel break; 1121 0 stevel default: 1122 0 stevel iv_status = CFB64_IV_BAD; 1123 0 stevel encr_data.decrypt.type = NULL; 1124 0 stevel if (enc_debug) 1125 0 stevel (void) fprintf(stderr, 1126 0 stevel "\t(encrypt_is) Can't find type (%d) " 1127 0 stevel "for initial negotiation\r\n", 1128 0 stevel type); 1129 0 stevel lstate = ENCR_STATE_NOT_READY; 1130 0 stevel break; 1131 0 stevel } 1132 0 stevel 1133 0 stevel sbbuf[5] = (uchar_t)iv_status; /* either CFB64_IV_OK or BAD */ 1134 0 stevel 1135 0 stevel if (iv_status == CFB64_IV_OK) { 1136 0 stevel /* 1137 0 stevel * send IV to crypto module and indicate it is for 1138 0 stevel * decrypt only 1139 0 stevel */ 1140 0 stevel lstate &= ~ENCR_STATE_NO_RECV_IV; /* we received an OK IV */ 1141 0 stevel lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont send an IV */ 1142 0 stevel } else { 1143 0 stevel /* tell crypto module to disable crypto on "read" stream */ 1144 0 stevel lstate = ENCR_STATE_NOT_READY; 1145 0 stevel } 1146 0 stevel 1147 0 stevel write_data_len((const char *)sbbuf, sizeof (sbbuf)); 1148 0 stevel netflush(); 1149 0 stevel #ifdef ENCRYPT_NAMES 1150 0 stevel if (enc_debug) 1151 0 stevel (void) fprintf(stderr, 1152 0 stevel "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n", 1153 0 stevel ENCTYPE_NAME(type), 1154 0 stevel (iv_status == CFB64_IV_OK ? "CFB64_IV_OK" : 1155 0 stevel "CFB64_IV_BAD")); 1156 0 stevel #endif /* ENCRYPT_NAMES */ 1157 0 stevel /* Update the state of the decryption negotiation */ 1158 0 stevel encr_data.decrypt.state = lstate; 1159 0 stevel 1160 0 stevel if (lstate == ENCR_STATE_NOT_READY) 1161 0 stevel encr_data.decrypt.autoflag = 0; 1162 0 stevel else { 1163 0 stevel if (lstate == ENCR_STATE_OK && encr_data.decrypt.autoflag) 1164 0 stevel encrypt_send_request_start(); 1165 0 stevel } 1166 0 stevel if (enc_debug) 1167 0 stevel (void) fprintf(stderr, 1168 0 stevel "\t(encrypt_is) final DECRYPT state = %d\n", 1169 0 stevel encr_data.decrypt.state); 1170 0 stevel } 1171 0 stevel 1172 0 stevel /* 1173 0 stevel * encrypt_send_encrypt_is 1174 0 stevel * 1175 0 stevel * Tell the client what encryption we will use 1176 0 stevel * and what our IV will be. 1177 0 stevel */ 1178 0 stevel static int 1179 0 stevel encrypt_send_encrypt_is() 1180 0 stevel { 1181 0 stevel register int lstate; 1182 0 stevel krb5_error_code kret; 1183 0 stevel uchar_t sbbuf[MAXOPTLEN], *p; 1184 0 stevel int i; 1185 0 stevel 1186 0 stevel lstate = encr_data.encrypt.state; 1187 0 stevel 1188 0 stevel if (encr_data.encrypt.type == ENCTYPE_NULL) { 1189 0 stevel /* 1190 0 stevel * Haven't received ENCRYPT SUPPORT yet or we couldn't agree 1191 0 stevel * on a cipher. 1192 0 stevel */ 1193 0 stevel return (lstate); 1194 0 stevel } 1195 0 stevel 1196 0 stevel /* 1197 0 stevel * - Create a random DES key 1198 0 stevel * 1199 0 stevel * - DES ECB encrypt 1200 0 stevel * encrypt the IV using itself as the key. 1201 0 stevel * 1202 0 stevel * - Send response 1203 0 stevel * IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ] 1204 0 stevel * IAC SE 1205 0 stevel * 1206 0 stevel */ 1207 0 stevel if (lstate == ENCR_STATE_NOT_READY) 1208 0 stevel lstate = ENCR_STATE_IN_PROGRESS; 1209 0 stevel else if ((lstate & ENCR_STATE_NO_SEND_IV) == 0) { 1210 0 stevel if (enc_debug) 1211 0 stevel (void) fprintf(stderr, 1212 0 stevel "\t(encrypt_send_is) IV already sent," 1213 0 stevel " state = %d\n", lstate); 1214 0 stevel return (lstate); 1215 0 stevel } 1216 0 stevel 1217 0 stevel if (!VALIDKEY(encr_data.encrypt.krbdes_key)) { 1218 0 stevel /* 1219 0 stevel * Invalid key, set flag so we try again later 1220 0 stevel * when we get a good one 1221 0 stevel */ 1222 0 stevel encr_data.encrypt.need_start = 1; 1223 0 stevel if (enc_debug) 1224 0 stevel (void) fprintf(stderr, 1225 0 stevel "\t(encrypt_send_is) No Key, cannot " 1226 0 stevel "start encryption yet\n"); 1227 0 stevel return (lstate); 1228 0 stevel } 1229 0 stevel if (enc_debug) 1230 0 stevel (void) fprintf(stderr, 1231 0 stevel "\t(encrypt_send_is) Creating new feed\n"); 1232 0 stevel 1233 0 stevel /* 1234 0 stevel * Create a random feed and send it over. 1235 0 stevel * 1236 0 stevel * Use the /dev/[u]random interface to generate 1237 0 stevel * our encryption IV. 1238 0 stevel */ 1239 0 stevel kret = getrandom((char *)encr_data.encrypt.ivec, sizeof (Block)); 1240 0 stevel 1241 0 stevel if (kret) { 1242 0 stevel if (enc_debug) 1243 0 stevel (void) fprintf(stderr, 1244 0 stevel "\t(encrypt_send_is) error from " 1245 0 stevel "getrandom: %d\n", kret); 1246 0 stevel syslog(LOG_ERR, "Failed to create encryption key (err %d)\n"); 1247 0 stevel encr_data.encrypt.type = ENCTYPE_NULL; 1248 0 stevel } else { 1249 0 stevel mit_des_fixup_key_parity(encr_data.encrypt.ivec); 1250 0 stevel } 1251 0 stevel 1252 0 stevel p = sbbuf; 1253 0 stevel *p++ = IAC; 1254 0 stevel *p++ = SB; 1255 0 stevel *p++ = TELOPT_ENCRYPT; 1256 0 stevel *p++ = ENCRYPT_IS; 1257 0 stevel *p++ = encr_data.encrypt.type; 1258 0 stevel *p++ = CFB64_IV; 1259 0 stevel 1260 0 stevel /* 1261 0 stevel * Copy the IV bytes individually so that when a 1262 0 stevel * 255 (telnet IAC) is used, it can be "escaped" by 1263 0 stevel * adding it twice (telnet RFC 854). 1264 0 stevel */ 1265 0 stevel for (i = 0; i < sizeof (Block); i++) 1266 0 stevel if ((*p++ = encr_data.encrypt.ivec[i]) == IAC) 1267 0 stevel *p++ = IAC; 1268 0 stevel 1269 0 stevel *p++ = IAC; 1270 0 stevel *p++ = SE; 1271 0 stevel write_data_len((const char *)sbbuf, (size_t)(p-sbbuf)); 1272 0 stevel netflush(); 1273 0 stevel 1274 0 stevel if (!kret) { 1275 0 stevel lstate &= ~ENCR_STATE_NO_SEND_IV; /* we sent our IV */ 1276 0 stevel lstate &= ~ENCR_STATE_NO_SEND_IV; /* dont need decrypt IV */ 1277 0 stevel } 1278 0 stevel encr_data.encrypt.state = lstate; 1279 0 stevel 1280 0 stevel if (enc_debug) { 1281 0 stevel int i; 1282 0 stevel (void) fprintf(stderr, 1283 0 stevel "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ", 1284 0 stevel encr_data.encrypt.type); 1285 0 stevel for (i = 0; i < (p-sbbuf); i++) 1286 0 stevel (void) fprintf(stderr, "%d ", (int)sbbuf[i]); 1287 0 stevel (void) fprintf(stderr, "\n"); 1288 0 stevel } 1289 0 stevel 1290 0 stevel return (lstate); 1291 0 stevel } 1292 0 stevel 1293 0 stevel /* 1294 0 stevel * stop_stream 1295 0 stevel * 1296 0 stevel * Utility routine to send a CRIOCSTOP ioctl to the 1297 0 stevel * crypto module (cryptmod). 1298 0 stevel */ 1299 0 stevel static void 1300 0 stevel stop_stream(int fd, int dir) 1301 0 stevel { 1302 0 stevel struct strioctl crioc; 1303 0 stevel uint32_t stopdir = dir; 1304 0 stevel 1305 0 stevel crioc.ic_cmd = CRYPTIOCSTOP; 1306 0 stevel crioc.ic_timout = -1; 1307 0 stevel crioc.ic_len = sizeof (stopdir); 1308 0 stevel crioc.ic_dp = (char *)&stopdir; 1309 0 stevel 1310 0 stevel if (ioctl(fd, I_STR, &crioc)) { 1311 0 stevel syslog(LOG_ERR, "Error sending CRYPTIOCSTOP ioctl: %m"); 1312 0 stevel } 1313 0 stevel } 1314 0 stevel 1315 0 stevel /* 1316 0 stevel * start_stream 1317 0 stevel * 1318 0 stevel * Utility routine to send a CRYPTIOCSTART ioctl to the 1319 0 stevel * crypto module (cryptmod). This routine may contain optional 1320 0 stevel * payload data that the cryptmod will interpret as bytes that 1321 0 stevel * need to be decrypted and sent back up to the application 1322 0 stevel * via the data stream. 1323 0 stevel */ 1324 0 stevel static void 1325 0 stevel start_stream(int fd, int dir, int datalen, char *data) 1326 0 stevel { 1327 0 stevel struct strioctl crioc; 1328 0 stevel 1329 0 stevel crioc.ic_cmd = (dir == CRYPT_ENCRYPT ? CRYPTIOCSTARTENC : 1330 0 stevel CRYPTIOCSTARTDEC); 1331 0 stevel crioc.ic_timout = -1; 1332 0 stevel crioc.ic_len = datalen; 1333 0 stevel crioc.ic_dp = data; 1334 0 stevel 1335 0 stevel if (ioctl(fd, I_STR, &crioc)) { 1336 0 stevel syslog(LOG_ERR, "Error sending CRYPTIOCSTART ioctl: %m"); 1337 0 stevel } 1338 0 stevel } 1339 0 stevel 1340 0 stevel /* 1341 0 stevel * encrypt_start_output 1342 0 stevel * 1343 0 stevel * Tell the other side to start encrypting its data 1344 0 stevel */ 1345 0 stevel static void 1346 0 stevel encrypt_start_output() 1347 0 stevel { 1348 0 stevel int lstate; 1349 0 stevel uchar_t *p; 1350 0 stevel uchar_t sbbuf[MAXOPTLEN]; 1351 0 stevel struct strioctl crioc; 1352 0 stevel struct cr_info_t cki; 1353 0 stevel 1354 0 stevel /* 1355 0 stevel * Initialize crypto and send the ENCRYPT_IS msg 1356 0 stevel */ 1357 0 stevel lstate = encrypt_send_encrypt_is(); 1358 0 stevel 1359 0 stevel if (lstate != ENCR_STATE_OK) { 1360 0 stevel if (enc_debug) 1361 0 stevel (void) fprintf(stderr, 1362 0 stevel "\t(encrypt_start_output) ENCRYPT state " 1363 0 stevel "= %d\n", lstate); 1364 0 stevel return; 1365 0 stevel } 1366 0 stevel 1367 0 stevel p = sbbuf; 1368 0 stevel 1369 0 stevel *p++ = IAC; 1370 0 stevel *p++ = SB; 1371 0 stevel *p++ = TELOPT_ENCRYPT; 1372 0 stevel *p++ = ENCRYPT_START; 1373 0 stevel 1374 0 stevel (void) memcpy(p, encr_data.encrypt.keyid, encr_data.encrypt.keyidlen); 1375 0 stevel p += encr_data.encrypt.keyidlen; 1376 0 stevel 1377 0 stevel *p++ = IAC; 1378 0 stevel *p++ = SE; 1379 0 stevel 1380 0 stevel /* Flush this data out before we start encrypting */ 1381 0 stevel write_data_len((const char *)sbbuf, (int)(p-sbbuf)); 1382 0 stevel netflush(); 1383 0 stevel 1384 0 stevel if (enc_debug) 1385 0 stevel (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_START %d " 1386 0 stevel "(lstate = %d) data waiting = %d\n", 1387 0 stevel (int)encr_data.encrypt.keyid[0], 1388 0 stevel lstate, nfrontp-nbackp); 1389 0 stevel 1390 0 stevel encr_data.encrypt.state = lstate; 1391 0 stevel 1392 0 stevel /* 1393 0 stevel * tell crypto module what key to use for encrypting 1394 0 stevel * Note that the ENCRYPT has not yet been enabled, but we 1395 0 stevel * need to first set the crypto key to use. 1396 0 stevel */ 1397 0 stevel cki.direction_mask = CRYPT_ENCRYPT; 1398 0 stevel 1399 0 stevel if (encr_data.encrypt.type == TELOPT_ENCTYPE_DES_CFB64) { 1400 0 stevel cki.crypto_method = CRYPT_METHOD_DES_CFB; 1401 0 stevel } else { 1402 0 stevel if (enc_debug) 1403 0 stevel (void) fprintf(stderr, 1404 0 stevel "\t(encrypt_start_output) - unknown " 1405 0 stevel "crypto_method %d\n", 1406 0 stevel encr_data.encrypt.type); 1407 0 stevel syslog(LOG_ERR, "unrecognized crypto encrypt method: %d", 1408 0 stevel encr_data.encrypt.type); 1409 0 stevel 1410 0 stevel return; 1411 0 stevel } 1412 0 stevel 1413 0 stevel /* 1414 0 stevel * If we previously configured this crypto method, we dont want to 1415 0 stevel * overwrite the key or ivec information already given to the crypto 1416 0 stevel * module as it will cause the cipher data between the client and server 1417 0 stevel * to become out of synch and impossible to decipher. 1418 0 stevel */ 1419 0 stevel if (encr_data.encrypt.setup == cki.crypto_method) { 1420 0 stevel cki.keylen = 0; 1421 0 stevel cki.iveclen = 0; 1422 0 stevel } else { 1423 0 stevel cki.keylen = DES_BLOCKSIZE; 1424 0 stevel (void) memcpy(cki.key, (void *)encr_data.encrypt.krbdes_key, 1425 0 stevel DES_BLOCKSIZE); 1426 0 stevel 1427 0 stevel cki.iveclen = DES_BLOCKSIZE; 1428 0 stevel (void) memcpy(cki.ivec, (void *)encr_data.encrypt.ivec, 1429 0 stevel DES_BLOCKSIZE); 1430 0 stevel 1431 0 stevel cki.ivec_usage = IVEC_ONETIME; 1432 0 stevel } 1433 0 stevel 1434 0 stevel cki.option_mask = 0; 1435 0 stevel 1436 0 stevel /* Stop encrypt side prior to setup so we dont lose data */ 1437 0 stevel stop_stream(cryptmod_fd, CRYPT_ENCRYPT); 1438 0 stevel 1439 0 stevel crioc.ic_cmd = CRYPTIOCSETUP; 1440 0 stevel crioc.ic_timout = -1; 1441 0 stevel crioc.ic_len = sizeof (struct cr_info_t); 1442 0 stevel crioc.ic_dp = (char *)&cki; 1443 0 stevel 1444 0 stevel if (ioctl(cryptmod_fd, I_STR, &crioc)) { 1445 0 stevel perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error"); 1446 0 stevel } else { 1447 0 stevel /* Setup completed OK */ 1448 0 stevel encr_data.encrypt.setup = cki.crypto_method; 1449 0 stevel } 1450 0 stevel 1451 0 stevel /* 1452 0 stevel * We do not check for "stuck" data when setting up the 1453 0 stevel * outbound "encrypt" channel. Any data queued prior to 1454 0 stevel * this IOCTL will get processed correctly without our help. 1455 0 stevel */ 1456 0 stevel start_stream(cryptmod_fd, CRYPT_ENCRYPT, 0, NULL); 1457 0 stevel 1458 0 stevel /* 1459 0 stevel * tell crypto module to start encrypting 1460 0 stevel */ 1461 0 stevel if (enc_debug) 1462 0 stevel (void) fprintf(stderr, 1463 0 stevel "\t(encrypt_start_output) Encrypting output\n"); 1464 0 stevel } 1465 0 stevel 1466 0 stevel /* 1467 0 stevel * encrypt_request_start 1468 0 stevel * 1469 0 stevel * The client requests that we start encryption immediately after 1470 0 stevel * successful negotiation 1471 0 stevel */ 1472 0 stevel static void 1473 0 stevel encrypt_request_start(void) 1474 0 stevel { 1475 0 stevel if (encr_data.encrypt.type == ENCTYPE_NULL) { 1476 0 stevel encr_data.encrypt.autoflag = 1; 1477 0 stevel if (enc_debug) 1478 0 stevel (void) fprintf(stderr, "\t(encrypt_request_start) " 1479 0 stevel "autoencrypt = ON\n"); 1480 0 stevel } else { 1481 0 stevel encrypt_start_output(); 1482 0 stevel } 1483 0 stevel } 1484 0 stevel 1485 0 stevel /* 1486 0 stevel * encrypt_end 1487 0 stevel * 1488 0 stevel * ENCRYPT END received, stop decrypting the read stream 1489 0 stevel */ 1490 0 stevel static void 1491 0 stevel encrypt_end(int direction) 1492 0 stevel { 1493 0 stevel struct cr_info_t cki; 1494 0 stevel struct strioctl crioc; 1495 0 stevel uint32_t stopdir; 1496 0 stevel 1497 0 stevel stopdir = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT : 1498 0 stevel CRYPT_ENCRYPT); 1499 0 stevel 1500 0 stevel stop_stream(cryptmod_fd, stopdir); 1501 0 stevel 1502 0 stevel /* 1503 0 stevel * Call this function when we wish to disable crypto in 1504 0 stevel * either direction (ENCRYPT or DECRYPT) 1505 0 stevel */ 1506 0 stevel cki.direction_mask = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT : 1507 0 stevel CRYPT_ENCRYPT); 1508 0 stevel cki.crypto_method = CRYPT_METHOD_NONE; 1509 0 stevel cki.option_mask = 0; 1510 0 stevel 1511 0 stevel cki.keylen = 0; 1512 0 stevel cki.iveclen = 0; 1513 93 ethindra cki.ivec_usage = IVEC_ONETIME; 1514 0 stevel 1515 0 stevel crioc.ic_cmd = CRYPTIOCSETUP; 1516 0 stevel crioc.ic_timout = -1; 1517 0 stevel crioc.ic_len = sizeof (cki); 1518 0 stevel crioc.ic_dp = (char *)&cki; 1519 0 stevel 1520 0 stevel if (ioctl(cryptmod_fd, I_STR, &crioc)) { 1521 0 stevel perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error"); 1522 0 stevel } 1523 0 stevel 1524 0 stevel start_stream(cryptmod_fd, stopdir, 0, NULL); 1525 0 stevel } 1526 0 stevel 1527 0 stevel /* 1528 0 stevel * encrypt_request_end 1529 0 stevel * 1530 0 stevel * When we receive a REQEND from the client, it means 1531 0 stevel * that we are supposed to stop encrypting 1532 0 stevel */ 1533 0 stevel static void 1534 0 stevel encrypt_request_end() 1535 0 stevel { 1536 0 stevel /* 1537 0 stevel * Tell the other side we are done encrypting 1538 0 stevel */ 1539 0 stevel 1540 0 stevel write_data("%c%c%c%c%c%c", 1541 0 stevel (uchar_t)IAC, 1542 0 stevel (uchar_t)SB, 1543 0 stevel (uchar_t)TELOPT_ENCRYPT, 1544 0 stevel (uchar_t)ENCRYPT_END, 1545 0 stevel (uchar_t)IAC, 1546 0 stevel (uchar_t)SE); 1547 0 stevel netflush(); 1548 0 stevel if (enc_debug) 1549 0 stevel (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_END\n"); 1550 0 stevel 1551 0 stevel /* 1552 0 stevel * Turn off encryption of the write stream 1553 0 stevel */ 1554 0 stevel encrypt_end(TELNET_DIR_ENCRYPT); 1555 0 stevel } 1556 0 stevel 1557 0 stevel /* 1558 0 stevel * encrypt_send_request_end 1559 0 stevel * 1560 0 stevel * We stop encrypting the write stream and tell the other side about it. 1561 0 stevel */ 1562 0 stevel static void 1563 0 stevel encrypt_send_request_end() 1564 0 stevel { 1565 0 stevel write_data("%c%c%c%c%c%c", 1566 0 stevel (uchar_t)IAC, 1567 0 stevel (uchar_t)SB, 1568 0 stevel (uchar_t)TELOPT_ENCRYPT, 1569 0 stevel (uchar_t)ENCRYPT_REQEND, 1570 0 stevel (uchar_t)IAC, 1571 0 stevel (uchar_t)SE); 1572 0 stevel netflush(); 1573 0 stevel if (enc_debug) 1574 0 stevel (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n"); 1575 0 stevel } 1576 0 stevel 1577 0 stevel /* 1578 0 stevel * encrypt_start 1579 0 stevel * 1580 0 stevel * The client is going to start sending encrypted data 1581 0 stevel * using the previously negotiated cipher (see what we set 1582 0 stevel * when we did the REPLY in encrypt_is). 1583 0 stevel */ 1584 0 stevel static void 1585 0 stevel encrypt_start(void) 1586 0 stevel { 1587 0 stevel struct cr_info_t cki; 1588 0 stevel struct strioctl crioc; 1589 0 stevel int bytes = 0; 1590 0 stevel char *dataptr = NULL; 1591 0 stevel 1592 0 stevel if (encr_data.decrypt.type == ENCTYPE_NULL) { 1593 0 stevel if (enc_debug) 1594 0 stevel (void) fprintf(stderr, 1595 0 stevel "\t(encrypt_start) No DECRYPT method " 1596 0 stevel "defined yet\n"); 1597 0 stevel encrypt_send_request_end(); 1598 0 stevel return; 1599 0 stevel } 1600 0 stevel 1601 0 stevel cki.direction_mask = CRYPT_DECRYPT; 1602 0 stevel 1603 0 stevel if (encr_data.decrypt.type == TELOPT_ENCTYPE_DES_CFB64) { 1604 0 stevel cki.crypto_method = CRYPT_METHOD_DES_CFB; 1605 0 stevel } else { 1606 0 stevel if (enc_debug) 1607 0 stevel (void) fprintf(stderr, 1608 0 stevel "\t(encrypt_start) - unknown " 1609 0 stevel "crypto_method %d\n", encr_data.decrypt.type); 1610 0 stevel 1611 0 stevel syslog(LOG_ERR, "unrecognized crypto decrypt method: %d", 1612 0 stevel encr_data.decrypt.type); 1613 0 stevel 1614 0 stevel return; 1615 0 stevel } 1616 0 stevel 1617 0 stevel /* 1618 0 stevel * Don't overwrite previously configured key and ivec info 1619 0 stevel */ 1620 0 stevel if (encr_data.decrypt.setup != cki.crypto_method) { 1621 0 stevel (void) memcpy(cki.key, (void *)encr_data.decrypt.krbdes_key, 1622 0 stevel DES_BLOCKSIZE); 1623 0 stevel (void) memcpy(cki.ivec, (void *)encr_data.decrypt.ivec, 1624 0 stevel DES_BLOCKSIZE); 1625 0 stevel 1626 0 stevel cki.keylen = DES_BLOCKSIZE; 1627 0 stevel cki.iveclen = DES_BLOCKSIZE; 1628 0 stevel cki.ivec_usage = IVEC_ONETIME; 1629 0 stevel } else { 1630 0 stevel cki.keylen = 0; 1631 0 stevel cki.iveclen = 0; 1632 0 stevel } 1633 0 stevel cki.option_mask = 0; 1634 0 stevel 1635 0 stevel stop_stream(cryptmod_fd, CRYPT_DECRYPT); 1636 0 stevel 1637 0 stevel crioc.ic_cmd = CRYPTIOCSETUP; 1638 0 stevel crioc.ic_timout = -1; 1639 0 stevel crioc.ic_len = sizeof (struct cr_info_t); 1640 0 stevel crioc.ic_dp = (char *)&cki; 1641 0 stevel 1642 0 stevel if (ioctl(cryptmod_fd, I_STR, &crioc)) { 1643 0 stevel syslog(LOG_ERR, "ioctl(CRYPTIOCSETUP) [encrypt_start] " 1644 0 stevel "error: %m"); 1645 0 stevel } else { 1646 0 stevel encr_data.decrypt.setup = cki.crypto_method; 1647 0 stevel } 1648 0 stevel if (enc_debug) 1649 0 stevel (void) fprintf(stderr, 1650 0 stevel "\t(encrypt_start) called CRYPTIOCSETUP for " 1651 0 stevel "decrypt side\n"); 1652 0 stevel 1653 0 stevel /* 1654 0 stevel * Read any data stuck between the cryptmod and the application 1655 0 stevel * so we can pass it back down to be properly decrypted after 1656 0 stevel * this operation finishes. 1657 0 stevel */ 1658 0 stevel if (ioctl(cryptmod_fd, I_NREAD, &bytes) < 0) { 1659 0 stevel syslog(LOG_ERR, "I_NREAD returned error %m"); 1660 0 stevel bytes = 0; 1661 0 stevel } 1662 0 stevel 1663 0 stevel /* 1664 0 stevel * Any data which was read AFTER the ENCRYPT START message 1665 0 stevel * must be sent back down to be decrypted properly. 1666 0 stevel * 1667 0 stevel * 'ncc' is the number of bytes that have been read but 1668 0 stevel * not yet processed by the telnet state machine. 1669 0 stevel * 1670 0 stevel * 'bytes' is the number of bytes waiting to be read from 1671 0 stevel * the stream. 1672 0 stevel * 1673 0 stevel * If either one is a positive value, then those bytes 1674 0 stevel * must be pulled up and sent back down to be decrypted. 1675 0 stevel */ 1676 0 stevel if (ncc || bytes) { 1677 0 stevel drainstream(bytes); 1678 0 stevel if (enc_debug) 1679 0 stevel (void) fprintf(stderr, 1680 0 stevel "\t(encrypt_start) after drainstream, " 1681 0 stevel "ncc=%d bytes = %d\n", ncc, bytes); 1682 0 stevel bytes += ncc; 1683 0 stevel dataptr = netip; 1684 0 stevel } 1685 0 stevel 1686 0 stevel start_stream(cryptmod_fd, CRYPT_DECRYPT, bytes, dataptr); 1687 0 stevel 1688 0 stevel /* 1689 0 stevel * The bytes putback into the stream are no longer 1690 0 stevel * available to be read by the server, so adjust the 1691 0 stevel * counter accordingly. 1692 0 stevel */ 1693 0 stevel ncc = 0; 1694 0 stevel netip = netibuf; 1695 0 stevel (void) memset(netip, 0, netibufsize); 1696 0 stevel 1697 0 stevel #ifdef ENCRYPT_NAMES 1698 0 stevel if (enc_debug) { 1699 0 stevel (void) fprintf(stderr, 1700 0 stevel "\t(encrypt_start) Start DECRYPT using %s\n", 1701 0 stevel ENCTYPE_NAME(encr_data.decrypt.type)); 1702 0 stevel } 1703 0 stevel #endif /* ENCRYPT_NAMES */ 1704 0 stevel } 1705 0 stevel 1706 0 stevel /* 1707 0 stevel * encrypt_support 1708 0 stevel * 1709 0 stevel * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ] 1710 0 stevel * message from a client. 1711 0 stevel * 1712 0 stevel * Choose an agreeable method (DES_CFB64) and 1713 0 stevel * respond with TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ] 1714 0 stevel * 1715 0 stevel * from: RFC 2946 1716 0 stevel */ 1717 0 stevel static void 1718 0 stevel encrypt_support(char *data, int cnt) 1719 0 stevel { 1720 0 stevel int lstate = ENCR_STATE_NOT_READY; 1721 0 stevel int type, use_type = 0; 1722 0 stevel 1723 0 stevel while (cnt-- > 0 && use_type == 0) { 1724 0 stevel type = *data++; 1725 0 stevel #ifdef ENCRYPT_NAMES 1726 0 stevel if (enc_debug) 1727 0 stevel (void) fprintf(stderr, 1728 0 stevel "RCVD ENCRYPT SUPPORT %s\n", 1729 0 stevel ENCTYPE_NAME(type)); 1730 0 stevel #endif /* ENCRYPT_NAMES */ 1731 0 stevel /* 1732 0 stevel * Prefer CFB64 1733 0 stevel */ 1734 0 stevel if (type == TELOPT_ENCTYPE_DES_CFB64) { 1735 0 stevel use_type = type; 1736 0 stevel } 1737 0 stevel } 1738 0 stevel encr_data.encrypt.type = use_type; 1739 0 stevel 1740 0 stevel if (use_type != TELOPT_ENCTYPE_NULL && 1741 0 stevel authenticated != NULL && authenticated != &NoAuth && 1742 0 stevel auth_status != AUTH_REJECT) { 1743 0 stevel 1744 0 stevel /* Authenticated -> have session key -> send ENCRYPT IS */ 1745 0 stevel lstate = encrypt_send_encrypt_is(); 1746 0 stevel if (lstate == ENCR_STATE_OK) 1747 0 stevel encrypt_start_output(); 1748 0 stevel } else if (use_type == TELOPT_ENCTYPE_NULL) { 1749 0 stevel if (enc_debug) 1750 0 stevel (void) fprintf(stderr, 1751 0 stevel "\t(encrypt_support) Cannot agree " 1752 0 stevel "on crypto algorithm, output encryption " 1753 0 stevel "disabled.\n"); 1754 0 stevel 1755 0 stevel /* 1756 0 stevel * Cannot agree on crypto algorithm 1757 0 stevel * RFC 2946 sez: 1758 0 stevel * send "IAC SB ENCRYPT IS NULL IAC SE" 1759 0 stevel * optionally, also send IAC WONT ENCRYPT 1760 0 stevel */ 1761 0 stevel write_data("%c%c%c%c%c%c%c", 1762 0 stevel (uchar_t)IAC, 1763 0 stevel (uchar_t)SB, 1764 0 stevel (uchar_t)TELOPT_ENCRYPT, 1765 0 stevel (uchar_t)ENCRYPT_IS, 1766 0 stevel (uchar_t)TELOPT_ENCTYPE_NULL, 1767 0 stevel (uchar_t)IAC, 1768 0 stevel (uchar_t)SE); 1769 0 stevel send_wont(TELOPT_ENCRYPT); 1770 0 stevel netflush(); 1771 0 stevel if (enc_debug) 1772 0 stevel (void) fprintf(stderr, 1773 0 stevel "SENT TELOPT_ENCRYPT ENCRYPT_IS " 1774 0 stevel "[NULL]\n"); 1775 0 stevel 1776 0 stevel remopts[TELOPT_ENCRYPT] = OPT_NO; 1777 0 stevel } 1778 0 stevel settimer(encr_support); 1779 0 stevel } 1780 0 stevel 1781 0 stevel /* 1782 0 stevel * encrypt_send_keyid 1783 0 stevel * 1784 0 stevel * Sent the key id we will use to the client 1785 0 stevel */ 1786 0 stevel static void 1787 0 stevel encrypt_send_keyid(int dir, uchar_t *keyid, int keylen, boolean_t saveit) 1788 0 stevel { 1789 0 stevel uchar_t sbbuf[128], *p; 1790 0 stevel 1791 0 stevel p = sbbuf; 1792 0 stevel 1793 0 stevel *p++ = IAC; 1794 0 stevel *p++ = SB; 1795 0 stevel *p++ = TELOPT_ENCRYPT; 1796 0 stevel *p++ = (dir == TELNET_DIR_ENCRYPT ? ENCRYPT_ENC_KEYID : 1797 0 stevel ENCRYPT_DEC_KEYID); 1798 0 stevel if (saveit) { 1799 0 stevel if (enc_debug) 1800 0 stevel (void) fprintf(stderr, 1801 0 stevel "\t(send_keyid) store %d byte %s keyid\n", 1802 0 stevel keylen, 1803 0 stevel (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : 1804 0 stevel "DECRYPT")); 1805 0 stevel 1806 0 stevel if (dir == TELNET_DIR_ENCRYPT) { 1807 0 stevel (void) memcpy(encr_data.encrypt.keyid, keyid, keylen); 1808 0 stevel encr_data.encrypt.keyidlen = keylen; 1809 0 stevel } else { 1810 0 stevel (void) memcpy(encr_data.decrypt.keyid, keyid, keylen); 1811 0 stevel encr_data.decrypt.keyidlen = keylen; 1812 0 stevel } 1813 0 stevel } 1814 0 stevel (void) memcpy(p, keyid, keylen); 1815 0 stevel p += keylen; 1816 0 stevel 1817 0 stevel *p++ = IAC; 1818 0 stevel *p++ = SE; 1819 0 stevel write_data_len((const char *)sbbuf, (size_t)(p-sbbuf)); 1820 0 stevel netflush(); 1821 0 stevel 1822 0 stevel if (enc_debug) 1823 0 stevel (void) fprintf(stderr, "SENT TELOPT_ENCRYPT %s %d\n", 1824 0 stevel (dir == TELNET_DIR_ENCRYPT ? "ENC_KEYID" : 1825 0 stevel "DEC_KEYID"), keyid[0]); 1826 0 stevel } 1827 0 stevel 1828 0 stevel /* 1829 0 stevel * encrypt_reply 1830 0 stevel * 1831 0 stevel * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE 1832 0 stevel * message, process it accordingly. 1833 0 stevel * If the vector is acceptable, tell client we are encrypting and 1834 0 stevel * enable encryption on our write stream. 1835 0 stevel * 1836 0 stevel * Negotiate the KEYID next.. 1837 0 stevel * RFC 2946, 2952 1838 0 stevel */ 1839 0 stevel static void 1840 0 stevel encrypt_reply(char *data, int len) 1841 0 stevel { 1842 0 stevel uchar_t type = (uchar_t)(*data++); 1843 0 stevel uchar_t result = (uchar_t)(*data); 1844 0 stevel int lstate; 1845 0 stevel 1846 0 stevel #ifdef ENCRYPT_NAMES 1847 0 stevel if (enc_debug) 1848 0 stevel (void) fprintf(stderr, 1849 0 stevel "\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n", 1850 0 stevel ENCRYPT_NAME(type), 1851 0 stevel (result == CFB64_IV_OK ? "CFB64_IV_OK" : 1852 0 stevel "CFB64_IV_BAD"), len); 1853 0 stevel #endif /* ENCRYPT_NAMES */ 1854 0 stevel 1855 0 stevel lstate = encr_data.encrypt.state; 1856 0 stevel if (enc_debug) 1857 0 stevel (void) fprintf(stderr, 1858 0 stevel "\t(encrypt_reply) initial ENCRYPT state = %d\n", 1859 0 stevel lstate); 1860 0 stevel switch (result) { 1861 0 stevel case CFB64_IV_OK: 1862 0 stevel if (lstate == ENCR_STATE_NOT_READY) 1863 0 stevel lstate = ENCR_STATE_IN_PROGRESS; 1864 0 stevel lstate &= ~ENCR_STATE_NO_RECV_IV; /* we got the IV */ 1865 0 stevel lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont need to send IV */ 1866 0 stevel 1867 0 stevel /* 1868 0 stevel * The correct response here is to send the encryption key id 1869 0 stevel * RFC 2752. 1870 0 stevel * 1871 0 stevel * Send keyid 0 to indicate that we will just use default 1872 0 stevel * keys. 1873 0 stevel */ 1874 0 stevel encrypt_send_keyid(TELNET_DIR_ENCRYPT, (uchar_t *)"\0", 1, 1); 1875 0 stevel 1876 0 stevel break; 1877 0 stevel case CFB64_IV_BAD: 1878 0 stevel /* 1879 0 stevel * Clear the ivec 1880 0 stevel */ 1881 0 stevel (void) memset(encr_data.encrypt.ivec, 0, sizeof (Block)); 1882 0 stevel lstate = ENCR_STATE_NOT_READY; 1883 0 stevel break; 1884 0 stevel default: 1885 0 stevel if (enc_debug) 1886 0 stevel (void) fprintf(stderr, 1887 0 stevel "\t(encrypt_reply) Got unknown IV value in " 1888 0 stevel "REPLY message\n"); 1889 0 stevel lstate = ENCR_STATE_NOT_READY; 1890 0 stevel break; 1891 0 stevel } 1892 0 stevel 1893 0 stevel encr_data.encrypt.state = lstate; 1894 0 stevel if (lstate == ENCR_STATE_NOT_READY) { 1895 0 stevel encr_data.encrypt.autoflag = 0; 1896 0 stevel encr_data.encrypt.type = ENCTYPE_NULL; 1897 0 stevel if (enc_debug) 1898 0 stevel (void) fprintf(stderr, 1899 0 stevel "\t(encrypt_reply) encrypt.autoflag = " 1900 0 stevel "OFF\n"); 1901 0 stevel } else { 1902 0 stevel encr_data.encrypt.type = type; 1903 0 stevel if ((lstate == ENCR_STATE_OK) && encr_data.encrypt.autoflag) 1904 0 stevel encrypt_start_output(); 1905 0 stevel } 1906 0 stevel 1907 0 stevel if (enc_debug) 1908 0 stevel (void) fprintf(stderr, 1909 0 stevel "\t(encrypt_reply) ENCRYPT final state = %d\n", 1910 0 stevel lstate); 1911 0 stevel } 1912 0 stevel 1913 0 stevel static void 1914 0 stevel encrypt_set_keyid_state(uchar_t *keyid, int *keyidlen, int dir) 1915 0 stevel { 1916 0 stevel int lstate; 1917 0 stevel 1918 0 stevel lstate = (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state : 1919 0 stevel encr_data.decrypt.state); 1920 0 stevel 1921 0 stevel if (enc_debug) 1922 0 stevel (void) fprintf(stderr, 1923 0 stevel "\t(set_keyid_state) %s initial state = %d\n", 1924 0 stevel (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : 1925 0 stevel "DECRYPT"), lstate); 1926 0 stevel 1927 0 stevel /* 1928 0 stevel * Currently, we only support using the default keyid, 1929 0 stevel * so it should be an error if the len > 1 or the keyid != 0. 1930 0 stevel */ 1931 0 stevel if (*keyidlen != 1 || (*keyid != '\0')) { 1932 0 stevel if (enc_debug) 1933 0 stevel (void) fprintf(stderr, 1934 0 stevel "\t(set_keyid_state) unexpected keyid: " 1935 0 stevel "len=%d value=%d\n", *keyidlen, *keyid); 1936 0 stevel *keyidlen = 0; 1937 0 stevel syslog(LOG_ERR, "rcvd unexpected keyid %d - only keyid of 0 " 1938 0 stevel "is supported", *keyid); 1939 0 stevel } else { 1940 0 stevel /* 1941 0 stevel * We move to the "IN_PROGRESS" state. 1942 0 stevel */ 1943 0 stevel if (lstate == ENCR_STATE_NOT_READY) 1944 0 stevel lstate = ENCR_STATE_IN_PROGRESS; 1945 0 stevel /* 1946 0 stevel * Clear the NO_KEYID bit because we now have a valid keyid 1947 0 stevel */ 1948 0 stevel lstate &= ~ENCR_STATE_NO_KEYID; 1949 0 stevel } 1950 0 stevel 1951 0 stevel if (enc_debug) 1952 0 stevel (void) fprintf(stderr, 1953 0 stevel "\t(set_keyid_state) %s final state = %d\n", 1954 0 stevel (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : 1955 0 stevel "DECRYPT"), lstate); 1956 0 stevel 1957 0 stevel if (dir == TELNET_DIR_ENCRYPT) 1958 0 stevel encr_data.encrypt.state = lstate; 1959 0 stevel else 1960 0 stevel encr_data.decrypt.state = lstate; 1961 0 stevel } 1962 0 stevel 1963 0 stevel /* 1964 0 stevel * encrypt_keyid 1965 0 stevel * 1966 0 stevel * Set the keyid value in the key_info structure. 1967 0 stevel * if necessary send a response to the sender 1968 0 stevel */ 1969 0 stevel static void 1970 0 stevel encrypt_keyid(uchar_t *newkeyid, int *keyidlen, uchar_t *keyid, 1971 0 stevel int len, int dir) 1972 0 stevel { 1973 0 stevel if (len > TELNET_MAXNUMKEYS) { 1974 0 stevel if (enc_debug) 1975 0 stevel (void) fprintf(stderr, 1976 0 stevel "\t(keyid) keylen too big (%d)\n", len); 1977 0 stevel return; 1978 0 stevel } 1979 0 stevel 1980 0 stevel if (enc_debug) { 1981 0 stevel (void) fprintf(stderr, "\t(keyid) set KEYID for %s len = %d\n", 1982 0 stevel (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : 1983 0 stevel "DECRYPT"), len); 1984 0 stevel } 1985 0 stevel 1986 0 stevel if (len == 0) { 1987 0 stevel if (*keyidlen == 0) { 1988 0 stevel if (enc_debug) 1989 0 stevel (void) fprintf(stderr, 1990 0 stevel "\t(keyid) Got 0 length keyid - " 1991 0 stevel "failure\n"); 1992 0 stevel return; 1993 0 stevel } 1994 0 stevel *keyidlen = 0; 1995 0 stevel encrypt_set_keyid_state(newkeyid, keyidlen, dir); 1996 0 stevel 1997 0 stevel } else if (len != *keyidlen || memcmp(keyid, newkeyid, len)) { 1998 0 stevel if (enc_debug) 1999 0 stevel (void) fprintf(stderr, 2000 0 stevel "\t(keyid) Setting new key (%d bytes)\n", 2001 0 stevel len); 2002 0 stevel 2003 0 stevel *keyidlen = len; 2004 0 stevel (void) memcpy(newkeyid, keyid, len); 2005 0 stevel 2006 0 stevel encrypt_set_keyid_state(newkeyid, keyidlen, dir); 2007 0 stevel } else { 2008 0 stevel encrypt_set_keyid_state(newkeyid, keyidlen, dir); 2009 0 stevel 2010 0 stevel if (enc_debug) 2011 0 stevel (void) fprintf(stderr, 2012 0 stevel "\t(keyid) %s Key already in place," 2013 0 stevel "state = %d autoflag=%d\n", 2014 0 stevel (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT"), 2015 0 stevel (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state: 2016 0 stevel encr_data.decrypt.state), 2017 0 stevel (dir == TELNET_DIR_ENCRYPT ? 2018 0 stevel encr_data.encrypt.autoflag: 2019 0 stevel encr_data.decrypt.autoflag)); 2020 0 stevel 2021 0 stevel /* key already in place */ 2022 0 stevel if ((encr_data.encrypt.state == ENCR_STATE_OK) && 2023 0 stevel dir == TELNET_DIR_ENCRYPT && encr_data.encrypt.autoflag) { 2024 0 stevel encrypt_start_output(); 2025 0 stevel } 2026 0 stevel return; 2027 0 stevel } 2028 0 stevel 2029 0 stevel if (enc_debug) 2030 0 stevel (void) fprintf(stderr, "\t(keyid) %s final state = %d\n", 2031 0 stevel (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : 2032 0 stevel "DECRYPT"), 2033 0 stevel (dir == TELNET_DIR_ENCRYPT ? 2034 0 stevel encr_data.encrypt.state : 2035 0 stevel encr_data.decrypt.state)); 2036 0 stevel 2037 0 stevel encrypt_send_keyid(dir, newkeyid, *keyidlen, 0); 2038 0 stevel } 2039 0 stevel 2040 0 stevel /* 2041 0 stevel * encrypt_enc_keyid 2042 0 stevel * 2043 0 stevel * We received the ENC_KEYID message from a client indicating that 2044 0 stevel * the client wishes to verify that the indicated keyid maps to a 2045 0 stevel * valid key. 2046 0 stevel */ 2047 0 stevel static void 2048 0 stevel encrypt_enc_keyid(char *data, int cnt) 2049 0 stevel { 2050 0 stevel /* 2051 0 stevel * Verify the decrypt keyid is valid 2052 0 stevel */ 2053 0 stevel encrypt_keyid(encr_data.decrypt.keyid, &encr_data.decrypt.keyidlen, 2054 0 stevel (uchar_t *)data, cnt, TELNET_DIR_DECRYPT); 2055 0 stevel } 2056 0 stevel 2057 0 stevel /* 2058 0 stevel * encrypt_dec_keyid 2059 0 stevel * 2060 0 stevel * We received the DEC_KEYID message from a client indicating that 2061 0 stevel * the client wants to verify that the indicated keyid maps to a valid key. 2062 0 stevel */ 2063 0 stevel static void 2064 0 stevel encrypt_dec_keyid(char *data, int cnt) 2065 0 stevel { 2066 0 stevel encrypt_keyid(encr_data.encrypt.keyid, &encr_data.encrypt.keyidlen, 2067 0 stevel (uchar_t *)data, cnt, TELNET_DIR_ENCRYPT); 2068 0 stevel } 2069 0 stevel 2070 0 stevel /* 2071 0 stevel * encrypt_session_key 2072 0 stevel * 2073 0 stevel * Store the session key in the encryption data record 2074 0 stevel */ 2075 0 stevel static void 2076 0 stevel encrypt_session_key(Session_Key *key, cipher_info_t *cinfo) 2077 0 stevel { 2078 0 stevel if (key == NULL || key->type != SK_DES) { 2079 0 stevel if (enc_debug) 2080 0 stevel (void) fprintf(stderr, 2081 0 stevel "\t(session_key) Cannot set krb5 " 2082 0 stevel "session key (unknown type = %d)\n", 2083 0 stevel key ? key->type : -1); 2084 0 stevel } 2085 0 stevel if (enc_debug) 2086 0 stevel (void) fprintf(stderr, 2087 0 stevel "\t(session_key) Settting session key " 2088 0 stevel "for server\n"); 2089 0 stevel 2090 0 stevel /* store the key in the cipher info data struct */ 2091 0 stevel (void) memcpy(cinfo->krbdes_key, (void *)key->data, sizeof (Block)); 2092 0 stevel 2093 0 stevel /* 2094 0 stevel * Now look to see if we still need to send the key and start 2095 0 stevel * encrypting. 2096 0 stevel * 2097 0 stevel * If so, go ahead an call it now that we have the key. 2098 0 stevel */ 2099 0 stevel if (cinfo->need_start) { 2100 0 stevel if (encrypt_send_encrypt_is() == ENCR_STATE_OK) { 2101 0 stevel cinfo->need_start = 0; 2102 0 stevel } 2103 0 stevel } 2104 0 stevel } 2105 0 stevel 2106 0 stevel /* 2107 0 stevel * new_env 2108 0 stevel * 2109 0 stevel * Used to add an environment variable and value to the 2110 0 stevel * linked list structure. 2111 0 stevel */ 2112 0 stevel static int 2113 0 stevel new_env(const char *name, const char *value) 2114 0 stevel { 2115 0 stevel struct envlist *env; 2116 0 stevel 2117 0 stevel env = malloc(sizeof (struct envlist)); 2118 0 stevel if (env == NULL) 2119 0 stevel return (1); 2120 0 stevel if ((env->name = strdup(name)) == NULL) { 2121 0 stevel free(env); 2122 0 stevel return (1); 2123 0 stevel } 2124 0 stevel if ((env->value = strdup(value)) == NULL) { 2125 0 stevel free(env->name); 2126 0 stevel free(env); 2127 0 stevel return (1); 2128 0 stevel } 2129 0 stevel env->delete = 0; 2130 0 stevel env->next = envlist_head; 2131 0 stevel envlist_head = env; 2132 0 stevel return (0); 2133 0 stevel } 2134 0 stevel 2135 0 stevel /* 2136 0 stevel * del_env 2137 0 stevel * 2138 0 stevel * Used to delete an environment variable from the linked list 2139 0 stevel * structure. We just set a flag because we will delete the list 2140 0 stevel * anyway before we exec login. 2141 0 stevel */ 2142 0 stevel static int 2143 0 stevel del_env(const char *name) 2144 0 stevel { 2145 0 stevel struct envlist *env; 2146 0 stevel 2147 0 stevel for (env = envlist_head; env; env = env->next) { 2148 0 stevel if (strcmp(env->name, name) == 0) { 2149 0 stevel env->delete = 1; 2150 0 stevel break; 2151 0 stevel } 2152 0 stevel } 2153 0 stevel return (0); 2154 0 stevel } 2155 0 stevel 2156 0 stevel static int 2157 0 stevel issock(int fd) 2158 0 stevel { 2159 0 stevel struct stat stats; 2160 0 stevel 2161 0 stevel if (fstat(fd, &stats) == -1) 2162 0 stevel return (0); 2163 0 stevel return (S_ISSOCK(stats.st_mode)); 2164 0 stevel } 2165 0 stevel 2166 0 stevel /* 2167 0 stevel * audit_telnet_settid stores the terminal id while it is still 2168 0 stevel * available. Subsequent calls to adt_load_hostname() return 2169 0 stevel * the id which is stored here. 2170 0 stevel */ 2171 0 stevel static int 2172 0 stevel audit_telnet_settid(int sock) { 2173 0 stevel adt_session_data_t *ah; 2174 0 stevel adt_termid_t *termid; 2175 0 stevel int rc; 2176 0 stevel 2177 0 stevel if ((rc = adt_start_session(&ah, NULL, 0)) == 0) { 2178 0 stevel if ((rc = adt_load_termid(sock, &termid)) == 0) { 2179 0 stevel if ((rc = adt_set_user(ah, ADT_NO_AUDIT, 2180 0 stevel ADT_NO_AUDIT, 0, ADT_NO_AUDIT, 2181 0 stevel termid, ADT_SETTID)) == 0) 2182 0 stevel (void) adt_set_proc(ah); 2183 0 stevel free(termid); 2184 0 stevel } 2185 0 stevel (void) adt_end_session(ah); 2186 0 stevel } 2187 0 stevel return (rc); 2188 0 stevel } 2189 0 stevel 2190 0 stevel /* ARGSUSED */ 2191 0 stevel int 2192 0 stevel main(int argc, char *argv[]) 2193 0 stevel { 2194 0 stevel struct sockaddr_storage from; 2195 0 stevel int on = 1; 2196 0 stevel socklen_t fromlen; 2197 0 stevel int issocket; 2198 0 stevel #if defined(DEBUG) 2199 0 stevel ushort_t porttouse = 0; 2200 0 stevel boolean_t standalone = 0; 2201 0 stevel #endif /* defined(DEBUG) */ 2202 0 stevel extern char *optarg; 2203 0 stevel char c; 2204 0 stevel int tos = -1; 2205 0 stevel 2206 0 stevel while ((c = getopt(argc, argv, TELNETD_OPTS DEBUG_OPTS)) != -1) { 2207 0 stevel switch (c) { 2208 0 stevel #if defined(DEBUG) 2209 0 stevel case 'p': 2210 0 stevel /* 2211 0 stevel * note: alternative port number only used in 2212 0 stevel * standalone mode. 2213 0 stevel */ 2214 0 stevel porttouse = atoi(optarg); 2215 0 stevel standalone = 1; 2216 0 stevel break; 2217 0 stevel case 'e': 2218 0 stevel enc_debug = 1; 2219 0 stevel break; 2220 0 stevel #endif /* DEBUG */ 2221 0 stevel case 'a': 2222 0 stevel if (strcasecmp(optarg, "none") == 0) { 2223 0 stevel auth_level = 0; 2224 0 stevel } else if (strcasecmp(optarg, "user") == 0) { 2225 0 stevel auth_level = AUTH_USER; 2226 0 stevel } else if (strcasecmp(optarg, "valid") == 0) { 2227 0 stevel auth_level = AUTH_VALID; 2228 0 stevel } else if (strcasecmp(optarg, "off") == 0) { 2229 0 stevel auth_level = -1; 2230 0 stevel negotiate_auth_krb5 = 0; 2231 0 stevel } else if (strcasecmp(optarg, "debug") == 0) { 2232 0 stevel auth_debug = 1; 2233 0 stevel } else { 2234 0 stevel syslog(LOG_ERR, 2235 0 stevel "unknown authentication level specified " 2236 0 stevel "with \'-a\' option (%s)", optarg); 2237 0 stevel auth_level = AUTH_USER; 2238 0 stevel } 2239 0 stevel break; 2240 0 stevel case 'X': 2241 0 stevel /* disable authentication negotiation */ 2242 0 stevel negotiate_auth_krb5 = 0; 2243 0 stevel break; 2244 0 stevel case 'R': 2245 0 stevel case 'M': 2246 0 stevel if (optarg != NULL) { 2247 0 stevel int ret = krb5_init(); 2248 0 stevel if (ret) { 2249 0 stevel syslog(LOG_ERR, 2250 0 stevel "Unable to use Kerberos V5 as " 2251 0 stevel "requested, exiting"); 2252 0 stevel exit(1); 2253 0 stevel } 2254 0 stevel krb5_set_default_realm(telnet_context, optarg); 2255 0 stevel syslog(LOG_NOTICE, 2256 0 stevel "using %s as default KRB5 realm", optarg); 2257 0 stevel } 2258 0 stevel break; 2259 0 stevel case 'S': 2260 0 stevel telnet_srvtab = (char *)strdup(optarg); 2261 0 stevel break; 2262 0 stevel case 'E': /* disable automatic encryption */ 2263 0 stevel negotiate_encrypt = B_FALSE; 2264 0 stevel break; 2265 0 stevel case 'U': 2266 0 stevel resolve_hostname = 1; 2267 0 stevel break; 2268 0 stevel case 's': 2269 0 stevel if (optarg == NULL || (tos = atoi(optarg)) < 0 || 2270 0 stevel tos > 255) { 2271 0 stevel syslog(LOG_ERR, "telnetd: illegal tos value: " 2272 0 stevel "%s\n", optarg); 2273 0 stevel } else { 2274 0 stevel if (tos < 0) 2275 0 stevel tos = 020; 2276 0 stevel } 2277 0 stevel break; 2278 0 stevel case 'h': 2279 0 stevel show_hostinfo = 0; 2280 0 stevel break; 2281 0 stevel default: 2282 0 stevel syslog(LOG_ERR, "telnetd: illegal cmd line option %c", 2283 0 stevel c); 2284 0 stevel break; 2285 0 stevel } 2286 0 stevel } 2287 0 stevel 2288 0 stevel netibufsize = BUFSIZ; 2289 0 stevel if (!(netibuf = (char *)malloc(netibufsize))) 2290 0 stevel syslog(LOG_ERR, "netibuf malloc failed\n"); 2291 0 stevel (void) memset(netibuf, 0, netibufsize); 2292 0 stevel netip = netibuf; 2293 0 stevel 2294 0 stevel #if defined(DEBUG) 2295 0 stevel if (standalone) { 2296 0 stevel int s, ns, foo; 2297 0 stevel struct servent *sp; 2298 0 stevel static struct sockaddr_in6 sin6 = { AF_INET6 }; 2299 0 stevel int option = 1; 2300 0 stevel 2301 0 stevel if (porttouse) { 2302 0 stevel sin6.sin6_port = htons(porttouse); 2303 0 stevel } else { 2304 0 stevel sp = getservbyname("telnet", "tcp"); 2305 0 stevel if (sp == 0) { 2306 0 stevel (void) fprintf(stderr, 2307 0 stevel "telnetd: tcp/telnet: " 2308 0 stevel "unknown service\n"); 2309 0 stevel exit(EXIT_FAILURE); 2310 0 stevel } 2311 0 stevel sin6.sin6_port = sp->s_port; 2312 0 stevel } 2313 0 stevel 2314 0 stevel s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 2315 0 stevel if (s < 0) { 2316 0 stevel perror("telnetd: socket"); 2317 0 stevel exit(EXIT_FAILURE); 2318 0 stevel } 2319 0 stevel if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&option, 2320 0 stevel sizeof (option)) == -1) 2321 0 stevel perror("setsockopt SO_REUSEADDR"); 2322 0 stevel if (bind(s, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) { 2323 0 stevel perror("bind"); 2324 0 stevel exit(EXIT_FAILURE); 2325 0 stevel } 2326 0 stevel if (listen(s, 32) < 0) { 2327 0 stevel perror("listen"); 2328 0 stevel exit(EXIT_FAILURE); 2329 0 stevel } 2330 0 stevel 2331 0 stevel /* automatically reap all child processes */ 2332 0 stevel (void) signal(SIGCHLD, SIG_IGN); 2333 0 stevel 2334 0 stevel for (;;) { 2335 0 stevel pid_t pid; 2336 0 stevel 2337 0 stevel foo = sizeof (sin6); 2338 0 stevel ns = accept(s, (struct sockaddr *)&sin6, &foo); 2339 0 stevel if (ns < 0) { 2340 0 stevel perror("accept"); 2341 0 stevel exit(EXIT_FAILURE); 2342 0 stevel } 2343 0 stevel pid = fork(); 2344 0 stevel if (pid == -1) { 2345 0 stevel perror("fork"); 2346 0 stevel exit(EXIT_FAILURE); 2347 0 stevel } 2348 0 stevel if (pid == 0) { 2349 0 stevel (void) dup2(ns, 0); 2350 0 stevel (void) close(s); 2351 0 stevel (void) signal(SIGCHLD, SIG_DFL); 2352 0 stevel break; 2353 0 stevel } 2354 0 stevel (void) close(ns); 2355 0 stevel } 2356 0 stevel } 2357 0 stevel #endif /* defined(DEBUG) */ 2358 0 stevel 2359 0 stevel openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 2360 0 stevel 2361 0 stevel issocket = issock(0); 2362 0 stevel if (!issocket) 2363 0 stevel fatal(0, "stdin is not a socket file descriptor"); 2364 0 stevel 2365 0 stevel fromlen = (socklen_t)sizeof (from); 2366 0 stevel (void) memset((char *)&from, 0, sizeof (from)); 2367 0 stevel if (getpeername(0, (struct sockaddr *)&from, &fromlen) 2368 0 stevel < 0) { 2369 0 stevel (void) fprintf(stderr, "%s: ", argv[0]); 2370 0 stevel perror("getpeername"); 2371 0 stevel _exit(EXIT_FAILURE); 2372 0 stevel } 2373 0 stevel 2374 0 stevel if (audit_telnet_settid(0)) { /* set terminal ID */ 2375 0 stevel (void) fprintf(stderr, "%s: ", argv[0]); 2376 0 stevel perror("audit"); 2377 0 stevel exit(EXIT_FAILURE); 2378 0 stevel } 2379 0 stevel 2380 0 stevel if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on, 2381 0 stevel sizeof (on)) < 0) { 2382 0 stevel syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 2383 0 stevel } 2384 0 stevel 2385 0 stevel /* 2386 0 stevel * Set the TOS value 2387 0 stevel */ 2388 0 stevel if (tos != -1 && 2389 0 stevel setsockopt(0, IPPROTO_IP, IP_TOS, 2390 0 stevel (char *)&tos, sizeof (tos)) < 0 && 2391 0 stevel errno != ENOPROTOOPT) { 2392 0 stevel syslog(LOG_ERR, "setsockopt (IP_TOS %d): %m", tos); 2393 0 stevel } 2394 0 stevel 2395 0 stevel if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on, 2396 0 stevel sizeof (on)) < 0) { 2397 0 stevel syslog(LOG_WARNING, "setsockopt (SO_OOBINLINE): %m"); 2398 0 stevel } 2399 0 stevel 2400 0 stevel /* set the default PAM service name */ 2401 0 stevel (void) strcpy(pam_svc_name, "telnet"); 2402 0 stevel 2403 0 stevel doit(0, &from); 2404 0 stevel return (EXIT_SUCCESS); 2405 0 stevel } 2406 0 stevel 2407 0 stevel static char *terminaltype = 0; 2408 0 stevel 2409 0 stevel /* 2410 0 stevel * ttloop 2411 0 stevel * 2412 0 stevel * A small subroutine to flush the network output buffer, get some data 2413 0 stevel * from the network, and pass it through the telnet state machine. We 2414 0 stevel * also flush the pty input buffer (by dropping its data) if it becomes 2415 0 stevel * too full. 2416 0 stevel */ 2417 0 stevel static void 2418 0 stevel ttloop(void) 2419 0 stevel { 2420 0 stevel if (nfrontp-nbackp) { 2421 0 stevel netflush(); 2422 0 stevel } 2423 0 stevel read_again: 2424 0 stevel ncc = read(net, netibuf, netibufsize); 2425 0 stevel if (ncc < 0) { 2426 0 stevel if (errno == EINTR) 2427 0 stevel goto read_again; 2428 0 stevel syslog(LOG_INFO, "ttloop: read: %m"); 2429 0 stevel exit(EXIT_FAILURE); 2430 0 stevel } else if (ncc == 0) { 2431 0 stevel syslog(LOG_INFO, "ttloop: peer closed connection\n"); 2432 0 stevel exit(EXIT_FAILURE); 2433 0 stevel } 2434 0 stevel 2435 0 stevel netip = netibuf; 2436 0 stevel telrcv(); /* state machine */ 2437 0 stevel if (ncc > 0) { 2438 0 stevel pfrontp = pbackp = ptyobuf; 2439 0 stevel telrcv(); 2440 0 stevel } 2441 0 stevel } 2442 0 stevel 2443 0 stevel static void 2444 0 stevel send_do(int option) 2445 0 stevel { 2446 0 stevel write_data("%c%c%c", (uchar_t)IAC, (uchar_t)DO, (uchar_t)option); 2447 0 stevel } 2448 0 stevel 2449 0 stevel static void 2450 0 stevel send_will(int option) 2451 0 stevel { 2452 0 stevel write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WILL, (uchar_t)option); 2453 0 stevel } 2454 0 stevel 2455 0 stevel static void 2456 0 stevel send_wont(int option) 2457 0 stevel { 2458 0 stevel write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WONT, (uchar_t)option); 2459 0 stevel } 2460 0 stevel 2461 0 stevel 2462 0 stevel /* 2463 0 stevel * getauthtype 2464 0 stevel * 2465 0 stevel * Negotiate automatic authentication, is possible. 2466 0 stevel */ 2467 0 stevel static int 2468 0 stevel getauthtype(char *username, int *len) 2469 0 stevel { 2470 0 stevel int init_status = -1; 2471 0 stevel 2472 0 stevel init_status = krb5_init(); 2473 0 stevel 2474 0 stevel if (auth_level == -1 || init_status != 0) { 2475 0 stevel remopts[TELOPT_AUTHENTICATION] = OPT_NO; 2476 0 stevel myopts[TELOPT_AUTHENTICATION] = OPT_NO; 2477 0 stevel negotiate_auth_krb5 = B_FALSE; 2478 0 stevel negotiate_encrypt = B_FALSE; 2479 0 stevel return (AUTH_REJECT); 2480 0 stevel } 2481 0 stevel 2482 0 stevel if (init_status == 0 && auth_level != -1) { 2483 0 stevel if (negotiate_auth_krb5) { 2484 0 stevel /* 2485 0 stevel * Negotiate Authentication FIRST 2486 0 stevel */ 2487 0 stevel send_do(TELOPT_AUTHENTICATION); 2488 0 stevel remopts[TELOPT_AUTHENTICATION] = 2489 0 stevel OPT_YES_BUT_ALWAYS_LOOK; 2490 0 stevel } 2491 0 stevel while (sequenceIs(authopt, getauth)) 2492 0 stevel ttloop(); 2493 0 stevel 2494 0 stevel if (remopts[TELOPT_AUTHENTICATION] == OPT_YES) { 2495 0 stevel /* 2496 0 stevel * Request KRB5 Mutual authentication and if that fails, 2497 0 stevel * KRB5 1-way client authentication 2498 0 stevel */ 2499 0 stevel uchar_t sbbuf[MAXOPTLEN], *p; 2500 0 stevel p = sbbuf; 2501 0 stevel *p++ = (uchar_t)IAC; 2502 0 stevel *p++ = (uchar_t)SB; 2503 0 stevel *p++ = (uchar_t)TELOPT_AUTHENTICATION; 2504 0 stevel *p++ = (uchar_t)TELQUAL_SEND; 2505 0 stevel if (negotiate_auth_krb5) { 2506 0 stevel *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5; 2507 0 stevel *p++ = (uchar_t)(AUTH_WHO_CLIENT | 2508 0 stevel AUTH_HOW_MUTUAL | 2509 0 stevel AUTH_ENCRYPT_ON); 2510 0 stevel *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5; 2511 0 stevel *p++ = (uchar_t)(AUTH_WHO_CLIENT | 2512 0 stevel AUTH_HOW_MUTUAL); 2513 0 stevel *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5; 2514 0 stevel *p++ = (uchar_t)(AUTH_WHO_CLIENT| 2515 0 stevel AUTH_HOW_ONE_WAY); 2516 0 stevel } else { 2517 0 stevel *p++ = (uchar_t)AUTHTYPE_NULL; 2518 0 stevel } 2519 0 stevel *p++ = (uchar_t)IAC; 2520 0 stevel *p++ = (uchar_t)SE; 2521 0 stevel 2522 0 stevel write_data_len((const char *)sbbuf, 2523 0 stevel (size_t)(p - sbbuf)); 2524 0 stevel netflush(); 2525 0 stevel if (auth_debug) 2526 0 stevel (void) fprintf(stderr, 2527 0 stevel "SENT TELOPT_AUTHENTICATION " 2528 0 stevel "[data]\n"); 2529 0 stevel 2530 0 stevel /* auth_wait returns the authentication level */ 2531 0 stevel /* status = auth_wait(username, len); */ 2532 0 stevel while (sequenceIs(authdone, getauth)) 2533 0 stevel ttloop(); 2534 0 stevel /* 2535 0 stevel * Now check to see if the user is valid or not 2536 0 stevel */ 2537 0 stevel if (authenticated == NULL || authenticated == &NoAuth) 2538 0 stevel auth_status = AUTH_REJECT; 2539 0 stevel else { 2540 0 stevel /* 2541 0 stevel * We cant be VALID until the user status is 2542 0 stevel * checked. 2543 0 stevel */ 2544 0 stevel if (auth_status == AUTH_VALID) 2545 0 stevel auth_status = AUTH_USER; 2546 0 stevel 2547 0 stevel if (authenticated->AuthName == 2548 0 stevel AUTHTYPE_KERBEROS_V5) 2549 0 stevel auth_status = krb5_user_status( 2550 0 stevel username, *len, auth_status); 2551 0 stevel } 2552 0 stevel } 2553 0 stevel } 2554 0 stevel return (auth_status); 2555 0 stevel } 2556 0 stevel 2557 0 stevel static void 2558 0 stevel getencrtype(void) 2559 0 stevel { 2560 0 stevel if (krb5_privacy_allowed() && negotiate_encrypt) { 2561 0 stevel if (myopts[TELOPT_ENCRYPT] != OPT_YES) { 2562 0 stevel if (!sent_will_encrypt) { 2563 0 stevel send_will(TELOPT_ENCRYPT); 2564 0 stevel sent_will_encrypt = B_TRUE; 2565 0 stevel } 2566 0 stevel if (enc_debug) 2567 0 stevel (void) fprintf(stderr, "SENT WILL ENCRYPT\n"); 2568 0 stevel } 2569 0 stevel if (remopts[TELOPT_ENCRYPT] != OPT_YES) { 2570 0 stevel if (!sent_do_encrypt) { 2571 0 stevel send_do(TELOPT_ENCRYPT); 2572 0 stevel sent_do_encrypt = B_TRUE; 2573 93 ethindra remopts[TELOPT_ENCRYPT] = 2574 93 ethindra OPT_YES_BUT_ALWAYS_LOOK; 2575 0 stevel } 2576 0 stevel if (enc_debug) 2577 0 stevel (void) fprintf(stderr, "SENT DO ENCRYPT\n"); 2578 0 stevel } 2579 0 stevel myopts[TELOPT_ENCRYPT] = OPT_YES; 2580 0 stevel 2581 0 stevel while (sequenceIs(encropt, getencr)) 2582 0 stevel ttloop(); 2583 0 stevel 2584 0 stevel if (auth_status != AUTH_REJECT && 2585 0 stevel remopts[TELOPT_ENCRYPT] == OPT_YES && 2586 0 stevel myopts[TELOPT_ENCRYPT] == OPT_YES) { 2587 0 stevel 2588 0 stevel if (sent_encrypt_support == B_FALSE) { 2589 0 stevel write_data("%c%c%c%c%c%c%c", 2590 0 stevel (uchar_t)IAC, 2591 0 stevel (uchar_t)SB, 2592 0 stevel (uchar_t)TELOPT_ENCRYPT, 2593 0 stevel (uchar_t)ENCRYPT_SUPPORT, 2594 0 stevel (uchar_t)TELOPT_ENCTYPE_DES_CFB64, 2595 0 stevel (uchar_t)IAC, 2596 0 stevel (uchar_t)SE); 2597 0 stevel 2598 0 stevel netflush(); 2599 0 stevel } 2600 0 stevel /* 2601 0 stevel * Now wait for a response to these messages before 2602 0 stevel * continuing... 2603 0 stevel * Look for TELOPT_ENCRYPT suboptions 2604 0 stevel */ 2605 0 stevel while (sequenceIs(encr_support, getencr)) 2606 0 stevel ttloop(); 2607 0 stevel } 2608 0 stevel } else { 2609 0 stevel /* Dont need responses to these, so dont wait for them */ 2610 0 stevel settimer(encropt); 2611 0 stevel remopts[TELOPT_ENCRYPT] = OPT_NO; 2612 0 stevel myopts[TELOPT_ENCRYPT] = OPT_NO; 2613 0 stevel } 2614 0 stevel 2615 0 stevel } 2616 0 stevel 2617 0 stevel /* 2618 0 stevel * getterminaltype 2619 0 stevel * 2620 0 stevel * Ask the other end to send along its terminal type. 2621 0 stevel * Output is the variable terminaltype filled in. 2622 0 stevel */ 2623 0 stevel static void 2624 0 stevel getterminaltype(void) 2625 0 stevel { 2626 0 stevel /* 2627 0 stevel * The remote side may have already sent this info, so 2628 0 stevel * dont ask for these options if the other side already 2629 0 stevel * sent the information. 2630 0 stevel */ 2631 0 stevel if (sequenceIs(ttypeopt, getterminal)) { 2632 0 stevel send_do(TELOPT_TTYPE); 2633 0 stevel remopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK; 2634 0 stevel } 2635 0 stevel 2636 0 stevel if (sequenceIs(nawsopt, getterminal)) { 2637 0 stevel send_do(TELOPT_NAWS); 2638 0 stevel remopts[TELOPT_NAWS] = OPT_YES_BUT_ALWAYS_LOOK; 2639 0 stevel } 2640 0 stevel 2641 0 stevel if (sequenceIs(xdisplocopt, getterminal)) { 2642 0 stevel send_do(TELOPT_XDISPLOC); 2643 0 stevel remopts[TELOPT_XDISPLOC] = OPT_YES_BUT_ALWAYS_LOOK; 2644 0 stevel } 2645 0 stevel 2646 0 stevel if (sequenceIs(environopt, getterminal)) { 2647 0 stevel send_do(TELOPT_NEW_ENVIRON); 2648 0 stevel remopts[TELOPT_NEW_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK; 2649 0 stevel } 2650 0 stevel 2651 0 stevel if (sequenceIs(oenvironopt, getterminal)) { 2652 0 stevel send_do(TELOPT_OLD_ENVIRON); 2653 0 stevel remopts[TELOPT_OLD_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK; 2654 0 stevel } 2655 0 stevel 2656 0 stevel /* make sure encryption is started here */ 2657 0 stevel while (auth_status != AUTH_REJECT && 2658 0 stevel authenticated != &NoAuth && authenticated != NULL && 2659 0 stevel remopts[TELOPT_ENCRYPT] == OPT_YES && 2660 0 stevel encr_data.encrypt.autoflag && 2661 0 stevel encr_data.encrypt.state != ENCR_STATE_OK) { 2662 0 stevel if (enc_debug) 2663 0 stevel (void) fprintf(stderr, "getterminaltype() forcing encrypt\n"); 2664 0 stevel ttloop(); 2665 0 stevel } 2666 0 stevel 2667 0 stevel if (enc_debug) { 2668 0 stevel (void) fprintf(stderr, "getterminaltype() encryption %sstarted\n", 2669 0 stevel encr_data.encrypt.state == ENCR_STATE_OK ? "" : "not "); 2670 0 stevel } 2671 0 stevel 2672 0 stevel while (sequenceIs(ttypeopt, getterminal) || 2673 0 stevel sequenceIs(nawsopt, getterminal) || 2674 0 stevel sequenceIs(xdisplocopt, getterminal) || 2675 0 stevel sequenceIs(environopt, getterminal) || 2676 0 stevel sequenceIs(oenvironopt, getterminal)) { 2677 0 stevel ttloop(); 2678 0 stevel } 2679 0 stevel 2680 0 stevel 2681 0 stevel if (remopts[TELOPT_TTYPE] == OPT_YES) { 2682 0 stevel static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB, 2683 0 stevel (uchar_t)TELOPT_TTYPE, (uchar_t)TELQUAL_SEND, 2684 0 stevel (uchar_t)IAC, (uchar_t)SE }; 2685 0 stevel 2686 0 stevel write_data_len((const char *)sbbuf, sizeof (sbbuf)); 2687 0 stevel } 2688 0 stevel if (remopts[TELOPT_XDISPLOC] == OPT_YES) { 2689 0 stevel static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB, 2690 0 stevel (uchar_t)TELOPT_XDISPLOC, (uchar_t)TELQUAL_SEND, 2691 0 stevel (uchar_t)IAC, (uchar_t)SE }; 2692 0 stevel 2693 0 stevel write_data_len((const char *)sbbuf, sizeof (sbbuf)); 2694 0 stevel } 2695 0 stevel if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) { 2696 0 stevel static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB, 2697 0 stevel (uchar_t)TELOPT_NEW_ENVIRON, (uchar_t)TELQUAL_SEND, 2698 0 stevel (uchar_t)IAC, (uchar_t)SE }; 2699 0 stevel 2700 0 stevel write_data_len((const char *)sbbuf, sizeof (sbbuf)); 2701 0 stevel } 2702 0 stevel if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) { 2703 0 stevel static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB, 2704 0 stevel (uchar_t)TELOPT_OLD_ENVIRON, (uchar_t)TELQUAL_SEND, 2705 0 stevel (uchar_t)IAC, (uchar_t)SE }; 2706 0 stevel 2707 0 stevel write_data_len((const char *)sbbuf, sizeof (sbbuf)); 2708 0 stevel } 2709 0 stevel 2710 0 stevel if (remopts[TELOPT_TTYPE] == OPT_YES) { 2711 0 stevel while (sequenceIs(ttypesubopt, getterminal)) { 2712 0 stevel ttloop(); 2713 0 stevel } 2714 0 stevel } 2715 0 stevel if (remopts[TELOPT_XDISPLOC] == OPT_YES) { 2716 0 stevel while (sequenceIs(xdisplocsubopt, getterminal)) { 2717 0 stevel ttloop(); 2718 0 stevel } 2719 0 stevel } 2720 0 stevel if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) { 2721 0 stevel while (sequenceIs(environsubopt, getterminal)) { 2722 0 stevel ttloop(); 2723 0 stevel } 2724 0 stevel } 2725 0 stevel if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) { 2726 0 stevel while (sequenceIs(oenvironsubopt, getterminal)) { 2727 0 stevel ttloop(); 2728 0 stevel } 2729 0 stevel } 2730 0 stevel init_neg_done = 1; 2731 0 stevel } 2732 0 stevel 2733 0 stevel pid_t pid; 2734 0 stevel 2735 0 stevel /* 2736 0 stevel * Get a pty, scan input lines. 2737 0 stevel */ 2738 0 stevel static void 2739 0 stevel doit(int f, struct sockaddr_storage *who) 2740 0 stevel { 2741 0 stevel char *host; 2742 0 stevel char host_name[MAXHOSTNAMELEN]; 2743 0 stevel int p, t, tt; 2744 0 stevel struct sgttyb b; 2745 0 stevel int ptmfd; /* fd of logindmux connected to pty */ 2746 0 stevel int netfd; /* fd of logindmux connected to netf */ 2747 0 stevel struct stat buf; 2748 0 stevel struct protocol_arg telnetp; 2749 0 stevel struct strioctl telnetmod; 2750 0 stevel struct envlist *env, *next; 2751 0 stevel int nsize = 0; 2752 0 stevel char abuf[INET6_ADDRSTRLEN]; 2753 0 stevel struct sockaddr_in *sin; 2754 0 stevel struct sockaddr_in6 *sin6; 2755 0 stevel socklen_t wholen; 2756 0 stevel char username[MAXUSERNAMELEN]; 2757 0 stevel int len; 2758 0 stevel uchar_t passthru; 2759 0 stevel char *slavename; 2760 0 stevel 2761 0 stevel if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) { 2762 0 stevel fatalperror(f, "open /dev/ptmx", errno); 2763 0 stevel } 2764 0 stevel if (grantpt(p) == -1) 2765 0 stevel fatal(f, "could not grant slave pty"); 2766 0 stevel if (unlockpt(p) == -1) 2767 0 stevel fatal(f, "could not unlock slave pty"); 2768 0 stevel if ((slavename = ptsname(p)) == NULL) 2769 0 stevel fatal(f, "could not enable slave pty"); 2770 0 stevel (void) dup2(f, 0); 2771 0 stevel if ((t = open(slavename, O_RDWR | O_NOCTTY)) == -1) 2772 0 stevel fatal(f, "could not open slave pty"); 2773 0 stevel if (ioctl(t, I_PUSH, "ptem") == -1) 2774 0 stevel fatalperror(f, "ioctl I_PUSH ptem", errno); 2775 0 stevel if (ioctl(t, I_PUSH, "ldterm") == -1) 2776 0 stevel fatalperror(f, "ioctl I_PUSH ldterm", errno); 2777 0 stevel if (ioctl(t, I_PUSH, "ttcompat") == -1) 2778 0 stevel fatalperror(f, "ioctl I_PUSH ttcompat", errno); 2779 0 stevel 2780 0 stevel line = slavename; 2781 0 stevel 2782 0 stevel pty = t; 2783 0 stevel 2784 0 stevel if (ioctl(t, TIOCGETP, &b) == -1) 2785 0 stevel syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n"); 2786 0 stevel b.sg_flags = O_CRMOD|O_XTABS|O_ANYP; 2787 0 stevel /* XXX - ispeed and ospeed must be non-zero */ 2788 0 stevel b.sg_ispeed = B38400; 2789 0 stevel b.sg_ospeed = B38400; 2790 0 stevel if (ioctl(t, TIOCSETN, &b) == -1) 2791 0 stevel syslog(LOG_INFO, "ioctl TIOCSETN pty t: %m\n"); 2792 0 stevel if (ioctl(pty, TIOCGETP, &b) == -1) 2793 0 stevel syslog(LOG_INFO, "ioctl TIOCGETP pty pty: %m\n"); 2794 0 stevel b.sg_flags &= ~O_ECHO; 2795 0 stevel if (ioctl(pty, TIOCSETN, &b) == -1) 2796 0 stevel syslog(LOG_INFO, "ioctl TIOCSETN pty pty: %m\n"); 2797 0 stevel 2798 0 stevel if (who->ss_family == AF_INET) { 2799 0 stevel char *addrbuf = NULL; 2800 0 stevel char *portbuf = NULL; 2801 0 stevel 2802 0 stevel sin = (struct sockaddr_in *)who; 2803 0 stevel wholen = sizeof (struct sockaddr_in); 2804 0 stevel 2805 0 stevel addrbuf = (char *)malloc(wholen); 2806 0 stevel if (addrbuf == NULL) 2807 0 stevel fatal(f, "Cannot alloc memory for address info\n"); 2808 0 stevel portbuf = (char *)malloc(sizeof (sin->sin_port)); 2809 0 stevel if (portbuf == NULL) { 2810 0 stevel free(addrbuf); 2811 0 stevel fatal(f, "Cannot alloc memory for port info\n"); 2812 0 stevel } 2813 0 stevel 2814 0 stevel (void) memcpy(addrbuf, (const void *)&sin->sin_addr, wholen); 2815 0 stevel (void) memcpy(portbuf, (const void *)&sin->sin_port, 2816 0 stevel sizeof (sin->sin_port)); 2817 0 stevel 2818 0 stevel if (rsaddr.contents != NULL) 2819 0 stevel free(rsaddr.contents); 2820 0 stevel 2821 0 stevel rsaddr.contents = (krb5_octet *)addrbuf; 2822 0 stevel rsaddr.length = wholen; 2823 0 stevel rsaddr.addrtype = ADDRTYPE_INET; 2824 0 stevel 2825 0 stevel if (rsport.contents != NULL) 2826 0 stevel free(rsport.contents); 2827 0 stevel 2828 0 stevel rsport.contents = (krb5_octet *)portbuf; 2829 0 stevel rsport.length = sizeof (sin->sin_port); 2830 0 stevel rsport.addrtype = ADDRTYPE_IPPORT; 2831 0 stevel } else if (who->ss_family == AF_INET6) { 2832 0 stevel struct in_addr ipv4_addr; 2833 0 stevel char *addrbuf = NULL; 2834 0 stevel char *portbuf = NULL; 2835 0 stevel 2836 0 stevel sin6 = (struct sockaddr_in6 *)who; 2837 0 stevel wholen = sizeof (struct sockaddr_in6); 2838 0 stevel 2839 0 stevel IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr, 2840 0 stevel &ipv4_addr); 2841 0 stevel 2842 0 stevel addrbuf = (char *)malloc(wholen); 2843 0 stevel if (addrbuf == NULL) 2844 0 stevel fatal(f, "Cannot alloc memory for address info\n"); 2845 0 stevel 2846 0 stevel portbuf = (char *)malloc(sizeof (sin6->sin6_port)); 2847 0 stevel if (portbuf == NULL) { 2848 0 stevel free(addrbuf); 2849 0 stevel fatal(f, "Cannot alloc memory for port info\n"); 2850 0 stevel } 2851 0 stevel 2852 0 stevel (void) memcpy((void *) addrbuf, 2853 0 stevel (const void *)&ipv4_addr, 2854 0 stevel wholen); 2855 0 stevel /* 2856 0 stevel * If we already used rsaddr.contents, free the previous 2857 0 stevel * buffer. 2858 0 stevel */ 2859 0 stevel if (rsaddr.contents != NULL) 2860 0 stevel free(rsaddr.contents); 2861 0 stevel 2862 0 stevel rsaddr.contents = (krb5_octet *)addrbuf; 2863 0 stevel rsaddr.length = sizeof (ipv4_addr); 2864 0 stevel rsaddr.addrtype = ADDRTYPE_INET; 2865 0 stevel 2866 0 stevel (void) memcpy((void *) portbuf, (const void *)&sin6->sin6_port, 2867 0 stevel sizeof (sin6->sin6_port)); 2868 0 stevel 2869 0 stevel if (rsport.contents != NULL) 2870 0 stevel free(rsport.contents); 2871 0 stevel 2872 0 stevel rsport.contents = (krb5_octet *)portbuf; 2873 0 stevel rsport.length = sizeof (sin6->sin6_port); 2874 0 stevel rsport.addrtype = ADDRTYPE_IPPORT; 2875 0 stevel } else { 2876 0 stevel syslog(LOG_ERR, "unknown address family %d\n", 2877 0 stevel who->ss_family); 2878 0 stevel fatal(f, "getpeername: unknown address family\n"); 2879 0 stevel } 2880 0 stevel 2881 0 stevel if (getnameinfo((const struct sockaddr *) who, wholen, host_name, 2882 0 stevel sizeof (host_name), NULL, 0, 0) == 0) { 2883 0 stevel host = host_name; 2884 0 stevel } else { 2885 0 stevel /* 2886 0 stevel * If the '-U' option was given on the cmd line, we must 2887 0 stevel * be able to lookup the hostname 2888 0 stevel */ 2889 0 stevel if (resolve_hostname) { 2890 0 stevel fatal(f, "Couldn't resolve your address into a " 2891 0 stevel "host name.\r\nPlease contact your net " 2892 0 stevel "administrator"); 2893 0 stevel } 2894 0 stevel 2895 0 stevel if (who->ss_family == AF_INET6) { 2896 0 stevel if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 2897 0 stevel struct in_addr ipv4_addr; 2898 0 stevel 2899 0 stevel IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr, 2900 0 stevel &ipv4_addr); 2901 0 stevel host = (char *)inet_ntop(AF_INET, 2902 0 stevel &ipv4_addr, abuf, sizeof (abuf)); 2903 0 stevel } else { 2904 0 stevel host = (char *)inet_ntop(AF_INET6, 2905 0 stevel &sin6->sin6_addr, abuf, 2906 0 stevel sizeof (abuf)); 2907 0 stevel } 2908 0 stevel } else if (who->ss_family == AF_INET) { 2909 0 stevel host = (char *)inet_ntop(AF_INET, 2910 0 stevel &sin->sin_addr, abuf, sizeof (abuf)); 2911 0 stevel } 2912 0 stevel } 2913 0 stevel /* 2914 0 stevel * Note that sockmod has to be removed since readstream assumes 2915 0 stevel * a "raw" TPI endpoint (e.g. it uses getmsg). 2916 0 stevel */ 2917 0 stevel if (removemod(f, "sockmod") < 0) 2918 0 stevel fatalperror(f, "couldn't remove sockmod", errno); 2919 0 stevel 2920 0 stevel encrypt_init(); 2921 0 stevel 2922 0 stevel /* 2923 0 stevel * Push the crypto module on the stream before 'telmod' so it 2924 0 stevel * can encrypt/decrypt without interfering with telmod functionality 2925 0 stevel * We must push it now because many of the crypto options negotiated 2926 0 stevel * initially must be saved in the crypto module (via IOCTL calls). 2927 0 stevel */ 2928 0 stevel if (ioctl(f, I_PUSH, "cryptmod") < 0) 2929 0 stevel fatalperror(f, "ioctl I_PUSH cryptmod", errno); 2930 0 stevel 2931 0 stevel cryptmod_fd = f; 2932 0 stevel /* 2933 0 stevel * gotta set the encryption clock now because it is often negotiated 2934 0 stevel * immediately by the client, and if we wait till after we negotiate 2935 0 stevel * auth, it will be out of whack with when the WILL/WONT ENCRYPT 2936 0 stevel * option is received. 2937 0 stevel */ 2938 0 stevel settimer(getencr); 2939 0 stevel 2940 0 stevel /* 2941 0 stevel * get terminal type. 2942 0 stevel */ 2943 0 stevel username[0] = '\0'; 2944 0 stevel len = sizeof (username); 2945 0 stevel 2946 0 stevel settimer(getterminal); 2947 0 stevel settimer(getauth); 2948 0 stevel /* 2949 0 stevel * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942 2950 0 stevel */ 2951 0 stevel auth_status = getauthtype(username, &len); 2952 0 stevel /* 2953 0 stevel * Exchange TELOPT_ENCRYPT options per RFC 2946 2954 0 stevel */ 2955 0 stevel getencrtype(); 2956 0 stevel getterminaltype(); 2957 0 stevel 2958 0 stevel if (ioctl(f, I_PUSH, "telmod") < 0) 2959 0 stevel fatalperror(f, "ioctl I_PUSH telmod", errno); 2960 0 stevel 2961 0 stevel /* 2962 0 stevel * Make sure telmod will pass unrecognized IOCTLs to cryptmod 2963 0 stevel */ 2964 0 stevel passthru = 1; 2965 0 stevel 2966 0 stevel telnetmod.ic_cmd = CRYPTPASSTHRU; 2967 0 stevel telnetmod.ic_timout = -1; 2968 0 stevel telnetmod.ic_len = sizeof (uchar_t); 2969 0 stevel telnetmod.ic_dp = (char *)&passthru; 2970 0 stevel 2971 0 stevel if (ioctl(f, I_STR, &telnetmod) < 0) 2972 0 stevel fatal(f, "ioctl CRPASSTHRU failed\n"); 2973 0 stevel 2974 0 stevel if (!ncc) 2975 0 stevel netip = netibuf; 2976 0 stevel 2977 0 stevel /* 2978 0 stevel * readstream will do a getmsg till it receives M_PROTO type 2979 0 stevel * T_DATA_REQ from telnetmodopen(). This signals that all data 2980 0 stevel * in-flight before telmod was pushed has been received at the 2981 0 stevel * stream head. 2982 0 stevel */ 2983 0 stevel while ((nsize = readstream(f, netibuf, ncc + netip - netibuf)) > 0) { 2984 0 stevel ncc += nsize; 2985 0 stevel } 2986 0 stevel 2987 0 stevel if (nsize < 0) { 2988 0 stevel fatalperror(f, "readstream failed\n", errno); 2989 0 stevel } 2990 0 stevel 2991 0 stevel /* 2992 0 stevel * open logindmux drivers and link them with network and ptm 2993 0 stevel * file descriptors. 2994 0 stevel */ 2995 0 stevel if ((ptmfd = open("/dev/logindmux", O_RDWR)) == -1) { 2996 0 stevel fatalperror(f, "open /dev/logindmux", errno); 2997 0 stevel } 2998 0 stevel if ((netfd = open("/dev/logindmux", O_RDWR)) == -1) { 2999 0 stevel fatalperror(f, "open /dev/logindmux", errno); 3000 0 stevel } 3001 0 stevel 3002 0 stevel if (ioctl(ptmfd, I_LINK, p) < 0) 3003 0 stevel fatal(f, "ioctl I_LINK of /dev/ptmx failed\n"); 3004 0 stevel if (ioctl(netfd, I_LINK, f) < 0) 3005 0 stevel fatal(f, "ioctl I_LINK of tcp connection failed\n"); 3006 0 stevel 3007 0 stevel /* 3008 0 stevel * Figure out the device number of ptm's mux fd, and pass that 3009 0 stevel * to the net's mux. 3010 0 stevel */ 3011 0 stevel if (fstat(ptmfd, &buf) < 0) { 3012 0 stevel fatalperror(f, "fstat ptmfd failed", errno); 3013 0 stevel } 3014 0 stevel telnetp.dev = buf.st_rdev; 3015 0 stevel telnetp.flag = 0; 3016 0 stevel 3017 0 stevel telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE; 3018 0 stevel telnetmod.ic_timout = -1; 3019 0 stevel telnetmod.ic_len = sizeof (struct protocol_arg); 3020 0 stevel telnetmod.ic_dp = (char *)&telnetp; 3021 0 stevel 3022 0 stevel if (ioctl(netfd, I_STR, &telnetmod) < 0) 3023 0 stevel fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n"); 3024 0 stevel 3025 0 stevel /* 3026 0 stevel * Figure out the device number of the net's mux fd, and pass that 3027 0 stevel * to the ptm's mux. 3028 0 stevel */ 3029 0 stevel if (fstat(netfd, &buf) < 0) { 3030 0 stevel fatalperror(f, "fstat netfd failed", errno); 3031 0 stevel } 3032 0 stevel telnetp.dev = buf.st_rdev; 3033 0 stevel telnetp.flag = 1; 3034 0 stevel 3035 0 stevel telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE; 3036 0 stevel telnetmod.ic_timout = -1; 3037 0 stevel telnetmod.ic_len = sizeof (struct protocol_arg); 3038 0 stevel telnetmod.ic_dp = (char *)&telnetp; 3039 0 stevel 3040 0 stevel if (ioctl(ptmfd, I_STR, &telnetmod) < 0) 3041 0 stevel fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n"); 3042 0 stevel 3043 0 stevel net = netfd; 3044 0 stevel master = ptmfd; 3045 0 stevel cryptmod_fd = netfd; 3046 0 stevel 3047 0 stevel /* 3048 0 stevel * Show banner that getty never gave, but 3049 0 stevel * only if the user did not automatically authenticate. 3050 0 stevel */ 3051 0 stevel if (getenv("USER") == '\0' && auth_status < AUTH_USER) 3052 0 stevel showbanner(); 3053 0 stevel 3054 0 stevel /* 3055 0 stevel * If the user automatically authenticated with Kerberos 3056 0 stevel * we must set the service name that PAM will use. We 3057 0 stevel * need to do it BEFORE the child fork so that 'cleanup' 3058 0 stevel * in the parent can call the PAM cleanup stuff with the 3059 0 stevel * same PAM service that /bin/login will use to authenticate 3060 0 stevel * this session. 3061 0 stevel */ 3062 0 stevel if (auth_level >= 0 && auth_status >= AUTH_USER && 3063 0 stevel (AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) { 3064 0 stevel (void) strcpy(pam_svc_name, "ktelnet"); 3065 0 stevel } 3066 0 stevel /* 3067 0 stevel * Request to do suppress go ahead. 3068 0 stevel * 3069 0 stevel * Send this before sending the TELOPT_ECHO stuff below because 3070 0 stevel * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support 3071 0 stevel * that has them turn off local echo mode if SGA is not received first. 3072 0 stevel * This also has the odd side-effect of causing the client to enable 3073 0 stevel * encryption and then immediately disable it during the ECHO option 3074 0 stevel * negotiations. Its just better to to SGA first now that we support 3075 0 stevel * encryption. 3076 0 stevel */ 3077 0 stevel if (!myopts[TELOPT_SGA]) { 3078 0 stevel dooption(TELOPT_SGA); 3079 0 stevel } 3080 0 stevel 3081 0 stevel /* 3082 0 stevel * Pretend we got a DO ECHO from the client if we have not 3083 0 stevel * yet negotiated the ECHO. 3084 0 stevel */ 3085 0 stevel if (!myopts[TELOPT_ECHO]) { 3086 0 stevel dooption(TELOPT_ECHO); 3087 0 stevel } 3088 0 stevel 3089 0 stevel /* 3090 0 stevel * Is the client side a 4.2 (NOT 4.3) system? We need to know this 3091 0 stevel * because 4.2 clients are unable to deal with TCP urgent data. 3092 0 stevel * 3093 0 stevel * To find out, we send out a "DO ECHO". If the remote system 3094 0 stevel * answers "WILL ECHO" it is probably a 4.2 client, and we note 3095 0 stevel * that fact ("WILL ECHO" ==> that the client will echo what 3096 0 stevel * WE, the server, sends it; it does NOT mean that the client will 3097 0 stevel * echo the terminal input). 3098 0 stevel */ 3099 0 stevel send_do(TELOPT_ECHO); 3100 0 stevel remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK; 3101 0 stevel 3102 0 stevel if ((pid = fork()) < 0) 3103 0 stevel fatalperror(netfd, "fork", errno); 3104 0 stevel if (pid) 3105 0 stevel telnet(net, master); 3106 0 stevel /* 3107 0 stevel * The child process needs to be the session leader 3108 0 stevel * and have the pty as its controlling tty. Thus we need 3109 0 stevel * to re-open the slave side of the pty no without 3110 0 stevel * the O_NOCTTY flag that we have been careful to 3111 0 stevel * use up to this point. 3112 0 stevel */ 3113 0 stevel (void) setsid(); 3114 0 stevel 3115 0 stevel tt = open(line, O_RDWR); 3116 0 stevel if (tt < 0) 3117 0 stevel fatalperror(netfd, line, errno); 3118 0 stevel (void) close(netfd); 3119 0 stevel (void) close(ptmfd); 3120 0 stevel (void) close(f); 3121 0 stevel (void) close(p); 3122 0 stevel (void) close(t); 3123 0 stevel if (tt != 0) 3124 0 stevel (void) dup2(tt, 0); 3125 0 stevel if (tt != 1) 3126 0 stevel (void) dup2(tt, 1); 3127 0 stevel if (tt != 2) 3128 0 stevel (void) dup2(tt, 2); 3129 0 stevel if (tt > 2) 3130 0 stevel (void) close(tt); 3131 0 stevel 3132 0 stevel if (terminaltype) 3133 0 stevel (void) local_setenv("TERM", terminaltype+5, 1); 3134 0 stevel /* 3135 0 stevel * -h : pass on name of host. 3136 0 stevel * WARNING: -h is accepted by login if and only if 3137 0 stevel * getuid() == 0. 3138 0 stevel * -p : don't clobber the environment (so terminal type stays set). 3139 0 stevel */ 3140 0 stevel { 3141 0 stevel /* System V login expects a utmp entry to already be there */ 3142 0 stevel struct utmpx ut; 3143 0 stevel (void) memset((char *)&ut, 0, sizeof (ut)); 3144 0 <