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