dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / in.telnetd.c
blobd0d65f7aa28231212254a3a75e373b1a2d31af65
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
29 * All Rights Reserved.
33 * University Copyright- Copyright (c) 1982, 1986, 1988
34 * The Regents of the University of California.
35 * All Rights Reserved.
37 * University Acknowledgment- Portions of this document are derived from
38 * software developed by the University of California, Berkeley, and its
39 * contributors.
43 * Telnet server.
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/socket.h>
48 #include <sys/wait.h>
49 #include <sys/file.h>
50 #include <sys/stat.h>
51 #include <sys/filio.h>
52 #include <sys/time.h>
53 #include <sys/stropts.h>
54 #include <sys/stream.h>
55 #include <sys/tihdr.h>
56 #include <sys/utsname.h>
57 #include <unistd.h>
59 #include <netinet/in.h>
61 #define AUTHWHO_STR
62 #define AUTHTYPE_NAMES
63 #define AUTHHOW_NAMES
64 #define AUTHRSP_NAMES
65 #define ENCRYPT_NAMES
67 #include <arpa/telnet.h>
68 #include <arpa/inet.h>
69 #include <stdio.h>
70 #include <stdarg.h>
71 #include <signal.h>
72 #include <errno.h>
73 #include <netdb.h>
74 #include <syslog.h>
75 #include <ctype.h>
76 #include <fcntl.h>
77 #include <sac.h> /* for SC_WILDC */
78 #include <utmpx.h>
79 #include <sys/ttold.h>
80 #include <malloc.h>
81 #include <string.h>
82 #include <security/pam_appl.h>
83 #include <sys/tihdr.h>
84 #include <sys/logindmux.h>
85 #include <sys/telioctl.h>
86 #include <deflt.h>
87 #include <stdlib.h>
88 #include <string.h>
89 #include <stropts.h>
90 #include <termios.h>
92 #include <com_err.h>
93 #include <krb5.h>
94 #include <krb5_repository.h>
95 #include <des/des.h>
96 #include <rpc/des_crypt.h>
97 #include <sys/cryptmod.h>
98 #include <bsm/adt.h>
100 #define TELNETD_OPTS "Ss:a:dEXUhR:M:"
101 #ifdef DEBUG
102 #define DEBUG_OPTS "p:e"
103 #else
104 #define DEBUG_OPTS ""
105 #endif /* DEBUG */
107 #define OPT_NO 0 /* won't do this option */
108 #define OPT_YES 1 /* will do this option */
109 #define OPT_YES_BUT_ALWAYS_LOOK 2
110 #define OPT_NO_BUT_ALWAYS_LOOK 3
112 #define MAXOPTLEN 256
113 #define MAXUSERNAMELEN 256
115 static char remopts[MAXOPTLEN];
116 static char myopts[MAXOPTLEN];
117 static uchar_t doopt[] = { (uchar_t)IAC, (uchar_t)DO, '%', 'c', 0 };
118 static uchar_t dont[] = { (uchar_t)IAC, (uchar_t)DONT, '%', 'c', 0 };
119 static uchar_t will[] = { (uchar_t)IAC, (uchar_t)WILL, '%', 'c', 0 };
120 static uchar_t wont[] = { (uchar_t)IAC, (uchar_t)WONT, '%', 'c', 0 };
122 * I/O data buffers, pointers, and counters.
124 static char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
126 static char *netibuf, *netip;
127 static int netibufsize;
129 #define NIACCUM(c) { *netip++ = c; \
130 ncc++; \
133 static char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
134 static char *neturg = 0; /* one past last bye of urgent data */
135 /* the remote system seems to NOT be an old 4.2 */
136 static int not42 = 1;
137 static char defaultfile[] = "/etc/default/telnetd";
138 static char bannervar[] = "BANNER=";
140 static char BANNER1[] = "\r\n\r\n";
141 static char BANNER2[] = "\r\n\r\0\r\n\r\0";
144 * buffer for sub-options - enlarged to 4096 to handle credentials
145 * from AUTH options
147 static char subbuffer[4096], *subpointer = subbuffer, *subend = subbuffer;
148 #define SB_CLEAR() subpointer = subbuffer;
149 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
150 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof (subbuffer))) { \
151 *subpointer++ = (c); \
153 #define SB_GET() ((*subpointer++)&0xff)
154 #define SB_EOF() (subpointer >= subend)
155 #define SB_LEN() (subend - subpointer)
157 #define MAXERRSTRLEN 1024
158 #define MAXPRINCLEN 256
160 extern uint_t kwarn_add_warning(char *, int);
161 extern uint_t kwarn_del_warning(char *);
163 static boolean_t auth_debug = 0;
164 static boolean_t negotiate_auth_krb5 = 1;
165 static boolean_t auth_negotiated = 0;
166 static int auth_status = 0;
167 static int auth_level = 0;
168 static char *AuthenticatingUser = NULL;
169 static char *krb5_name = NULL;
171 static krb5_address rsaddr = { 0, 0, 0, NULL };
172 static krb5_address rsport = { 0, 0, 0, NULL };
174 static krb5_context telnet_context = 0;
175 static krb5_auth_context auth_context = 0;
177 /* telnetd gets session key from here */
178 static krb5_ticket *ticket = NULL;
179 static krb5_keyblock *session_key = NULL;
180 static char *telnet_srvtab = NULL;
182 typedef struct {
183 uchar_t AuthName;
184 uchar_t AuthHow;
185 char *AuthString;
186 } AuthInfo;
188 static AuthInfo auth_list[] = {
189 {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL |
190 AUTH_ENCRYPT_ON, "KRB5 MUTUAL CRYPTO"},
191 {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL,
192 "KRB5 MUTUAL" },
193 {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_ONE_WAY,
194 "KRB5 1-WAY" },
195 {0, 0, "NONE"}
198 static AuthInfo NoAuth = {0, 0, NULL};
200 static AuthInfo *authenticated = NULL;
202 #define PREAMBLE_SIZE 5 /* for auth_reply_str allocation */
203 #define POSTAMBLE_SIZE 5
204 #define STR_DATA_LEN(len) ((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE)
206 static void auth_name(uchar_t *, int);
207 static void auth_is(uchar_t *, int);
209 #define NO_ENCRYPTION 0x00
210 #define SEND_ENCRYPTED 0x01
211 #define RECV_ENCRYPTED 0x02
212 #define ENCRYPT_BOTH_WAYS (SEND_ENCRYPTED | RECV_ENCRYPTED)
214 static telnet_enc_data_t encr_data;
215 static boolean_t negotiate_encrypt = B_TRUE;
216 static boolean_t sent_encrypt_support = B_FALSE;
217 static boolean_t sent_will_encrypt = B_FALSE;
218 static boolean_t sent_do_encrypt = B_FALSE;
219 static boolean_t enc_debug = 0;
221 static void encrypt_session_key(Session_Key *key, cipher_info_t *cinfo);
222 static int encrypt_send_encrypt_is();
224 extern void mit_des_fixup_key_parity(Block);
225 extern int krb5_setenv(const char *, const char *, int);
226 /* need to know what FD to use to talk to the crypto module */
227 static int cryptmod_fd = -1;
229 #define LOGIN_PROGRAM "/bin/login"
232 * State for recv fsm
234 #define TS_DATA 0 /* base state */
235 #define TS_IAC 1 /* look for double IAC's */
236 #define TS_CR 2 /* CR-LF ->'s CR */
237 #define TS_SB 3 /* throw away begin's... */
238 #define TS_SE 4 /* ...end's (suboption negotiation) */
239 #define TS_WILL 5 /* will option negotiation */
240 #define TS_WONT 6 /* wont " */
241 #define TS_DO 7 /* do " */
242 #define TS_DONT 8 /* dont " */
244 static int ncc;
245 static int master; /* master side of pty */
246 static int pty; /* side of pty that gets ioctls */
247 static int net;
248 static int inter;
249 extern char **environ;
250 static char *line;
251 static int SYNCHing = 0; /* we are in TELNET SYNCH mode */
252 static int state = TS_DATA;
254 static int env_ovar = -1; /* XXX.sparker */
255 static int env_ovalue = -1; /* XXX.sparker */
256 static char pam_svc_name[64];
257 static boolean_t telmod_init_done = B_FALSE;
259 static void doit(int, struct sockaddr_storage *);
260 static void willoption(int);
261 static void wontoption(int);
262 static void dooption(int);
263 static void dontoption(int);
264 static void fatal(int, char *);
265 static void fatalperror(int, char *, int);
266 static void mode(int, int);
267 static void interrupt(void);
268 static void drainstream(int);
269 static int readstream(int, char *, int);
270 static int send_oob(int fd, char *ptr, int count);
271 static int local_setenv(const char *name, const char *value, int rewrite);
272 static void local_unsetenv(const char *name);
273 static void suboption(void);
274 static int removemod(int f, char *modname);
275 static void willoption(int option);
276 static void wontoption(int option);
277 static void dooption(int option);
278 static void dontoption(int option);
279 static void write_data(const char *, ...);
280 static void write_data_len(const char *, int);
281 static void rmut(void);
282 static void cleanup(int);
283 static void telnet(int, int);
284 static void telrcv(void);
285 static void sendbrk(void);
286 static void ptyflush(void);
287 static void netclear(void);
288 static void netflush(void);
289 static void showbanner(void);
290 static void map_banner(char *);
291 static void defbanner(void);
292 static void ttloop(void);
295 * The env_list linked list is used to store the environment variables
296 * until the final exec of login. A malevolent client might try to
297 * send an environment variable intended to affect the telnet daemon's
298 * execution. Right now the BANNER expansion is the only instance.
299 * Note that it is okay to pass the environment variables to login
300 * because login protects itself against environment variables mischief.
303 struct envlist {
304 struct envlist *next;
305 char *name;
306 char *value;
307 int delete;
310 static struct envlist *envlist_head = NULL;
313 * The following are some clocks used to decide how to interpret
314 * the relationship between various variables.
317 static struct {
319 system, /* what the current time is */
320 echotoggle, /* last time user entered echo character */
321 modenegotiated, /* last time operating mode negotiated */
322 didnetreceive, /* last time we read data from network */
323 ttypeopt, /* ttype will/won't received */
324 ttypesubopt, /* ttype subopt is received */
325 getterminal, /* time started to get terminal information */
326 xdisplocopt, /* xdisploc will/wont received */
327 xdisplocsubopt, /* xdisploc suboption received */
328 nawsopt, /* window size will/wont received */
329 nawssubopt, /* window size received */
330 environopt, /* environment option will/wont received */
331 oenvironopt, /* "old" environ option will/wont received */
332 environsubopt, /* environment option suboption received */
333 oenvironsubopt, /* "old environ option suboption received */
334 gotDM; /* when did we last see a data mark */
336 int getauth;
337 int authopt; /* Authentication option negotiated */
338 int authdone;
340 int getencr;
341 int encropt;
342 int encr_support;
343 } clocks;
345 static int init_neg_done = 0;
346 static boolean_t resolve_hostname = 0;
347 static boolean_t show_hostinfo = 1;
349 #define settimer(x) (clocks.x = ++clocks.system)
350 #define sequenceIs(x, y) (clocks.x < clocks.y)
352 static void send_will(int);
353 static void send_wont(int);
354 static void send_do(int);
355 static char *__findenv(const char *name, int *offset);
357 /* ARGSUSED */
358 static void
359 auth_finished(AuthInfo *ap, int result)
361 if ((authenticated = ap) == NULL) {
362 authenticated = &NoAuth;
363 if (myopts[TELOPT_ENCRYPT] == OPT_YES)
364 send_wont(TELOPT_ENCRYPT);
365 myopts[TELOPT_ENCRYPT] = remopts[TELOPT_ENCRYPT] = OPT_NO;
366 encr_data.encrypt.autoflag = 0;
367 } else if (result != AUTH_REJECT &&
368 myopts[TELOPT_ENCRYPT] == OPT_YES &&
369 remopts[TELOPT_ENCRYPT] == OPT_YES) {
372 * Authentication successful, so we have a session key, and
373 * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT.
375 * Can't have sent ENCRYPT SUPPORT yet! And if we're sending it
376 * now it's really only because we did the DO ENCRYPT/WILL
377 * ENCRYPT dance before authentication, which is ok, but not too
378 * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT
379 * dance if authentication fails, though clients typically just
380 * don't care.
382 write_data("%c%c%c%c%c%c%c",
383 (uchar_t)IAC,
384 (uchar_t)SB,
385 (uchar_t)TELOPT_ENCRYPT,
386 (uchar_t)ENCRYPT_SUPPORT,
387 (uchar_t)TELOPT_ENCTYPE_DES_CFB64,
388 (uchar_t)IAC,
389 (uchar_t)SE);
391 netflush();
393 sent_encrypt_support = B_TRUE;
395 if (enc_debug)
396 (void) fprintf(stderr,
397 "SENT ENCRYPT SUPPORT\n");
399 (void) encrypt_send_encrypt_is();
402 auth_status = result;
404 settimer(authdone);
407 static void
408 reply_to_client(AuthInfo *ap, int type, void *data, int len)
410 uchar_t reply[BUFSIZ];
411 uchar_t *p = reply;
412 uchar_t *cd = (uchar_t *)data;
414 if (len == -1 && data != NULL)
415 len = strlen((char *)data);
416 else if (len > (sizeof (reply) - 9)) {
417 syslog(LOG_ERR,
418 "krb5 auth reply length too large (%d)", len);
419 if (auth_debug)
420 (void) fprintf(stderr,
421 "krb5 auth reply length too large (%d)\n",
422 len);
423 return;
424 } else if (data == NULL)
425 len = 0;
427 *p++ = IAC;
428 *p++ = SB;
429 *p++ = TELOPT_AUTHENTICATION;
430 *p++ = AUTHTYPE_KERBEROS_V5;
431 *p++ = ap->AuthName;
432 *p++ = ap->AuthHow; /* MUTUAL, ONE-WAY, etc */
433 *p++ = type; /* RESPONSE or ACCEPT */
434 while (len-- > 0) {
435 if ((*p++ = *cd++) == IAC)
436 *p++ = IAC;
438 *p++ = IAC;
439 *p++ = SE;
441 /* queue the data to be sent */
442 write_data_len((const char *)reply, p-reply);
444 #if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\
445 defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES)
446 if (auth_debug) {
447 (void) fprintf(stderr, "SENT TELOPT_AUTHENTICATION REPLY "
448 "%s %s|%s %s\n",
449 AUTHTYPE_NAME(ap->AuthName),
450 AUTHWHO_NAME(ap->AuthHow & AUTH_WHO_MASK),
451 AUTHHOW_NAME(ap->AuthHow & AUTH_HOW_MASK),
452 AUTHRSP_NAME(type));
454 #endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */
456 netflush();
459 /* Decode, decrypt and store the forwarded creds in the local ccache. */
460 static krb5_error_code
461 rd_and_store_forwarded_creds(krb5_context context,
462 krb5_auth_context auth_context,
463 krb5_data *inbuf, krb5_ticket *ticket,
464 char *username)
466 krb5_creds **creds;
467 krb5_error_code retval;
468 char ccname[MAXPATHLEN];
469 krb5_ccache ccache = NULL;
470 char *client_name = NULL;
472 if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))
473 return (retval);
475 (void) sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", getpid());
476 (void) krb5_setenv("KRB5CCNAME", ccname, 1);
478 if ((retval = krb5_cc_default(context, &ccache)))
479 goto cleanup;
481 if ((retval = krb5_cc_initialize(context, ccache,
482 ticket->enc_part2->client)) != 0)
483 goto cleanup;
485 if ((retval = krb5_cc_store_cred(context, ccache, *creds)) != 0)
486 goto cleanup;
488 if ((retval = krb5_cc_close(context, ccache)) != 0)
489 goto cleanup;
491 /* Register with ktkt_warnd(1M) */
492 if ((retval = krb5_unparse_name(context, (*creds)->client,
493 &client_name)) != 0)
494 goto cleanup;
495 (void) kwarn_del_warning(client_name);
496 if (kwarn_add_warning(client_name, (*creds)->times.endtime) != 0) {
497 syslog(LOG_AUTH|LOG_NOTICE,
498 "rd_and_store_forwarded_creds: kwarn_add_warning"
499 " failed: ktkt_warnd(1M) down? ");
500 if (auth_debug)
501 (void) fprintf(stderr,
502 "kwarn_add_warning failed:"
503 " ktkt_warnd(1M) down?\n");
505 free(client_name);
506 client_name = NULL;
508 if (username != NULL) {
510 * This verifies that the user is valid on the local system,
511 * maps the username from KerberosV5 to unix,
512 * and moves the KRB5CCNAME file to the correct place
513 * /tmp/krb5cc_[uid] with correct ownership (0600 uid gid).
515 * NOTE: the user must be in the gsscred table in order to map
516 * from KRB5 to Unix.
518 (void) krb5_kuserok(context, ticket->enc_part2->client,
519 username);
521 if (auth_debug)
522 (void) fprintf(stderr,
523 "Successfully stored forwarded creds\n");
525 cleanup:
526 krb5_free_creds(context, *creds);
527 return (retval);
530 static void
531 kerberos5_is(AuthInfo *ap, uchar_t *data, int cnt)
533 krb5_error_code err = 0;
534 krb5_principal server;
535 krb5_keyblock *newkey = NULL;
536 krb5_keytab keytabid = 0;
537 krb5_data outbuf;
538 krb5_data inbuf;
539 krb5_authenticator *authenticator;
540 char errbuf[MAXERRSTRLEN];
541 char *name;
542 krb5_data auth;
544 Session_Key skey;
546 if (cnt-- < 1)
547 return;
548 switch (*data++) {
549 case KRB_AUTH:
550 auth.data = (char *)data;
551 auth.length = cnt;
553 if (auth_context == NULL) {
554 err = krb5_auth_con_init(telnet_context, &auth_context);
555 if (err)
556 syslog(LOG_ERR,
557 "Error getting krb5 auth "
558 "context: %s", error_message(err));
560 if (!err) {
561 krb5_rcache rcache;
563 err = krb5_auth_con_getrcache(telnet_context,
564 auth_context,
565 &rcache);
566 if (!err && !rcache) {
567 err = krb5_sname_to_principal(telnet_context,
568 0, 0,
569 KRB5_NT_SRV_HST,
570 &server);
571 if (!err) {
572 err = krb5_get_server_rcache(
573 telnet_context,
574 krb5_princ_component(
575 telnet_context,
576 server, 0),
577 &rcache);
579 krb5_free_principal(telnet_context,
580 server);
583 if (err)
584 syslog(LOG_ERR,
585 "Error allocating krb5 replay cache: %s",
586 error_message(err));
587 else {
588 err = krb5_auth_con_setrcache(telnet_context,
589 auth_context,
590 rcache);
591 if (err)
592 syslog(LOG_ERR,
593 "Error creating krb5 "
594 "replay cache: %s",
595 error_message(err));
598 if (!err && telnet_srvtab != NULL)
599 err = krb5_kt_resolve(telnet_context,
600 telnet_srvtab, &keytabid);
601 if (!err)
602 err = krb5_rd_req(telnet_context, &auth_context, &auth,
603 NULL, keytabid, NULL, &ticket);
604 if (err) {
605 (void) snprintf(errbuf, sizeof (errbuf),
606 "Error reading krb5 auth information:"
607 " %s", error_message(err));
608 goto errout;
612 * Verify that the correct principal was used
614 if (krb5_princ_component(telnet_context,
615 ticket->server, 0)->length < MAXPRINCLEN) {
616 char princ[MAXPRINCLEN];
617 (void) strncpy(princ,
618 krb5_princ_component(telnet_context,
619 ticket->server, 0)->data,
620 krb5_princ_component(telnet_context,
621 ticket->server, 0)->length);
622 princ[krb5_princ_component(telnet_context,
623 ticket->server, 0)->length] = '\0';
624 if (strcmp("host", princ)) {
625 if (strlen(princ) < sizeof (errbuf) - 39) {
626 (void) snprintf(errbuf, sizeof (errbuf),
627 "incorrect service "
628 "name: \"%s\" != "
629 "\"host\"",
630 princ);
631 } else {
632 (void) strncpy(errbuf,
633 "incorrect service "
634 "name: principal != "
635 "\"host\"",
636 sizeof (errbuf));
638 goto errout;
640 } else {
641 (void) strlcpy(errbuf, "service name too long",
642 sizeof (errbuf));
643 goto errout;
646 err = krb5_auth_con_getauthenticator(telnet_context,
647 auth_context,
648 &authenticator);
649 if (err) {
650 (void) snprintf(errbuf, sizeof (errbuf),
651 "Failed to get authenticator: %s",
652 error_message(err));
653 goto errout;
655 if ((ap->AuthHow & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
656 !authenticator->checksum) {
657 (void) strlcpy(errbuf,
658 "authenticator is missing checksum",
659 sizeof (errbuf));
660 goto errout;
662 if (authenticator->checksum) {
663 char type_check[2];
664 krb5_checksum *cksum = authenticator->checksum;
665 krb5_keyblock *key;
666 krb5_data input;
667 krb5_boolean valid;
669 type_check[0] = ap->AuthName;
670 type_check[1] = ap->AuthHow;
672 err = krb5_auth_con_getkey(telnet_context,
673 auth_context, &key);
674 if (err) {
675 (void) snprintf(errbuf, sizeof (errbuf),
676 "Failed to get key from "
677 "authenticator: %s",
678 error_message(err));
679 goto errout;
682 input.data = type_check;
683 input.length = 2;
684 err = krb5_c_verify_checksum(telnet_context,
685 key, 0,
686 &input,
687 cksum,
688 &valid);
689 if (!err && !valid)
690 err = KRB5KRB_AP_ERR_BAD_INTEGRITY;
692 if (err) {
693 (void) snprintf(errbuf, sizeof (errbuf),
694 "Kerberos checksum "
695 "verification failed: "
696 "%s",
697 error_message(err));
698 goto errout;
700 krb5_free_keyblock(telnet_context, key);
703 krb5_free_authenticator(telnet_context, authenticator);
704 if ((ap->AuthHow & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
705 /* do ap_rep stuff here */
706 if ((err = krb5_mk_rep(telnet_context, auth_context,
707 &outbuf))) {
708 (void) snprintf(errbuf, sizeof (errbuf),
709 "Failed to make "
710 "Kerberos auth reply: "
711 "%s",
712 error_message(err));
713 goto errout;
715 reply_to_client(ap, KRB_RESPONSE, outbuf.data,
716 outbuf.length);
718 if (krb5_unparse_name(telnet_context,
719 ticket->enc_part2->client,
720 &name))
721 name = 0;
722 reply_to_client(ap, KRB_ACCEPT, name, name ? -1 : 0);
723 if (auth_debug) {
724 syslog(LOG_NOTICE,
725 "\tKerberos5 identifies user as ``%s''\r\n",
726 name ? name : "");
728 if (name != NULL) {
729 krb5_name = (char *)strdup(name);
731 auth_finished(ap, AUTH_USER);
733 free(name);
734 (void) krb5_auth_con_getremotesubkey(telnet_context,
735 auth_context, &newkey);
736 if (session_key != NULL) {
737 krb5_free_keyblock(telnet_context, session_key);
738 session_key = 0;
740 if (newkey != NULL) {
741 (void) krb5_copy_keyblock(telnet_context,
742 newkey, &session_key);
743 krb5_free_keyblock(telnet_context, newkey);
744 } else {
745 (void) krb5_copy_keyblock(telnet_context,
746 ticket->enc_part2->session, &session_key);
750 * Initialize encryption stuff. Currently, we are only
751 * supporting 8 byte keys and blocks. Check for this later.
753 skey.type = SK_DES;
754 skey.length = DES_BLOCKSIZE;
755 skey.data = session_key->contents;
756 encrypt_session_key(&skey, &encr_data.encrypt);
757 encrypt_session_key(&skey, &encr_data.decrypt);
758 break;
759 case KRB_FORWARD:
760 inbuf.length = cnt;
761 inbuf.data = (char *)data;
762 if (auth_debug)
763 (void) fprintf(stderr,
764 "RCVD KRB_FORWARD data (%d bytes)\n", cnt);
766 if (auth_context != NULL) {
767 krb5_rcache rcache;
769 err = krb5_auth_con_getrcache(telnet_context,
770 auth_context, &rcache);
771 if (!err && !rcache) {
772 err = krb5_sname_to_principal(telnet_context,
773 0, 0, KRB5_NT_SRV_HST, &server);
774 if (!err) {
775 err = krb5_get_server_rcache(
776 telnet_context,
777 krb5_princ_component(
778 telnet_context,
779 server, 0),
780 &rcache);
781 krb5_free_principal(telnet_context,
782 server);
785 if (err) {
786 syslog(LOG_ERR,
787 "Error allocating krb5 replay cache: %s",
788 error_message(err));
789 } else {
790 err = krb5_auth_con_setrcache(telnet_context,
791 auth_context, rcache);
792 if (err)
793 syslog(LOG_ERR,
794 "Error creating krb5 replay cache:"
795 " %s",
796 error_message(err));
800 * Use the 'rsaddr' and 'rsport' (remote service addr/port)
801 * from the original connection. This data is used to
802 * verify the forwarded credentials.
804 if (!(err = krb5_auth_con_setaddrs(telnet_context, auth_context,
805 NULL, &rsaddr)))
806 err = krb5_auth_con_setports(telnet_context,
807 auth_context, NULL, &rsport);
809 if (err == 0)
811 * If all is well, store the forwarded creds in
812 * the users local credential cache.
814 err = rd_and_store_forwarded_creds(telnet_context,
815 auth_context, &inbuf,
816 ticket,
817 AuthenticatingUser);
818 if (err) {
819 (void) snprintf(errbuf, sizeof (errbuf),
820 "Read forwarded creds failed: %s",
821 error_message(err));
822 syslog(LOG_ERR, "%s", errbuf);
824 reply_to_client(ap, KRB_FORWARD_REJECT, errbuf, -1);
825 if (auth_debug)
826 (void) fprintf(stderr,
827 "\tCould not read "
828 "forwarded credentials\r\n");
829 } else
830 reply_to_client(ap, KRB_FORWARD_ACCEPT, NULL, 0);
832 free(rsaddr.contents);
834 free(rsport.contents);
836 if (auth_debug)
837 (void) fprintf(stderr, "\tForwarded "
838 "credentials obtained\r\n");
839 break;
840 default:
841 if (auth_debug)
842 (void) fprintf(stderr,
843 "\tUnknown Kerberos option %d\r\n",
844 data[-1]);
845 reply_to_client(ap, KRB_REJECT, NULL, 0);
846 break;
848 return;
850 errout:
851 reply_to_client(ap, KRB_REJECT, errbuf, -1);
853 if (auth_debug)
854 (void) fprintf(stderr, "\tKerberos V5 error: %s\r\n", errbuf);
856 syslog(LOG_ERR, "%s", errbuf);
858 if (auth_context != NULL) {
859 (void) krb5_auth_con_free(telnet_context, auth_context);
860 auth_context = 0;
864 static int
865 krb5_init()
867 int code = 0;
869 if (telnet_context == NULL) {
870 code = krb5_init_context(&telnet_context);
871 if (code != 0 && auth_debug)
872 syslog(LOG_NOTICE,
873 "Cannot initialize Kerberos V5: %s",
874 error_message(code));
877 return (code);
880 static void
881 auth_name(uchar_t *data, int cnt)
883 char namebuf[MAXPRINCLEN];
885 if (cnt < 1) {
886 if (auth_debug)
887 (void) fprintf(stderr,
888 "\t(auth_name) Empty NAME in auth "
889 "reply\n");
890 return;
892 if (cnt > sizeof (namebuf)-1) {
893 if (auth_debug)
894 (void) fprintf(stderr,
895 "\t(auth_name) NAME exceeds %d bytes\n",
896 sizeof (namebuf)-1);
897 return;
899 (void) memcpy((void *)namebuf, (void *)data, cnt);
900 namebuf[cnt] = 0;
901 if (auth_debug)
902 (void) fprintf(stderr, "\t(auth_name) name [%s]\n", namebuf);
903 AuthenticatingUser = (char *)strdup(namebuf);
906 static void
907 auth_is(uchar_t *data, int cnt)
909 AuthInfo *aptr = auth_list;
911 if (cnt < 2)
912 return;
915 * We failed to negoiate secure authentication
917 if (data[0] == AUTHTYPE_NULL) {
918 auth_finished(0, AUTH_REJECT);
919 return;
922 while (aptr->AuthName != 0 &&
923 (aptr->AuthName != data[0] || aptr->AuthHow != data[1]))
924 aptr++;
926 if (aptr != NULL) {
927 if (auth_debug)
928 (void) fprintf(stderr, "\t(auth_is) auth type is %s "
929 "(%d bytes)\n", aptr->AuthString, cnt);
931 if (aptr->AuthName == AUTHTYPE_KERBEROS_V5)
932 kerberos5_is(aptr, data+2, cnt-2);
936 static int
937 krb5_user_status(char *name, int namelen, int level)
939 int retval = AUTH_USER;
941 if (auth_debug)
942 (void) fprintf(stderr, "\t(krb5_user_status) level = %d "
943 "auth_level = %d user = %s\n",
944 level, auth_level,
945 (AuthenticatingUser != NULL ? AuthenticatingUser : ""));
947 if (level < AUTH_USER)
948 return (level);
950 if (AuthenticatingUser != NULL &&
951 (retval = krb5_kuserok(telnet_context, ticket->enc_part2->client,
952 AuthenticatingUser))) {
953 (void) strncpy(name, AuthenticatingUser, namelen);
954 return (AUTH_VALID);
955 } else {
956 if (!retval)
957 syslog(LOG_ERR,
958 "Krb5 principal lacks permission to "
959 "access local account for %s",
960 AuthenticatingUser);
961 return (AUTH_USER);
966 * Wrapper around /dev/urandom
968 static int
969 getrandom(char *buf, int buflen)
971 static int devrandom = -1;
973 if (devrandom == -1 &&
974 (devrandom = open("/dev/urandom", O_RDONLY)) == -1) {
975 fatalperror(net, "Unable to open /dev/urandom: ",
976 errno);
977 return (-1);
980 if (read(devrandom, buf, buflen) == -1) {
981 fatalperror(net, "Unable to read from /dev/urandom: ",
982 errno);
983 return (-1);
986 return (0);
990 * encrypt_init
992 * Initialize the encryption data structures
994 static void
995 encrypt_init()
997 (void) memset(&encr_data.encrypt, 0, sizeof (cipher_info_t));
998 (void) memset(&encr_data.decrypt, 0, sizeof (cipher_info_t));
1000 encr_data.encrypt.state = ENCR_STATE_NOT_READY;
1001 encr_data.decrypt.state = ENCR_STATE_NOT_READY;
1005 * encrypt_send_request_start
1007 * Request that the remote side automatically start sending
1008 * encrypted output
1010 static void
1011 encrypt_send_request_start()
1013 uchar_t buf[6+TELNET_MAXKEYIDLEN], *p;
1015 p = buf;
1017 *p++ = IAC;
1018 *p++ = SB;
1019 *p++ = TELOPT_ENCRYPT;
1020 *p++ = ENCRYPT_REQSTART;
1022 * We are telling the remote side which
1023 * decrypt key we will use so that it may
1024 * encrypt in the same key.
1026 (void) memcpy(p, encr_data.decrypt.keyid, encr_data.decrypt.keyidlen);
1027 p += encr_data.decrypt.keyidlen;
1029 *p++ = IAC;
1030 *p++ = SE;
1032 write_data_len((const char *)buf, p-buf);
1033 netflush();
1034 if (enc_debug)
1035 (void) fprintf(stderr,
1036 "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
1040 * encrypt_is
1042 * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
1043 * message, the client is telling us that it will be sending
1044 * encrypted data using the indicated cipher.
1045 * We must initialize the read (decrypt) side of our connection
1047 static void
1048 encrypt_is(uchar_t *data, int cnt)
1050 register int type;
1051 register int iv_status = CFB64_IV_OK;
1052 register int lstate = 0;
1054 uchar_t sbbuf[] = {
1055 (uchar_t)IAC,
1056 (uchar_t)SB,
1057 (uchar_t)TELOPT_ENCRYPT,
1058 (uchar_t)ENCRYPT_REPLY,
1059 (uchar_t)0, /* placeholder: sbbuf[4] */
1060 (uchar_t)CFB64_IV_OK, /* placeholder: sbbuf[5] */
1061 (uchar_t)IAC,
1062 (uchar_t)SE,
1065 if (--cnt < 0)
1066 return;
1068 type = sbbuf[4] = *data++;
1071 * Steps to take:
1072 * 1. Create the proper stream Initialization vector
1073 * - copy the correct 'seed' to IV and output blocks
1074 * - set the correct key schedule
1075 * 2. Generate reply for the other side:
1076 * IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
1077 * [ data ... ] IAC SE
1078 * 3. Tell crypto module: method, direction, IV
1080 switch (type) {
1081 case TELOPT_ENCTYPE_DES_CFB64:
1082 encr_data.decrypt.type = type;
1084 lstate = encr_data.decrypt.state;
1085 if (enc_debug)
1086 (void) fprintf(stderr,
1087 "\t(encrypt_is) initial state = %d\n",
1088 lstate);
1090 * Before we extract the IV bytes, make sure we got
1091 * enough data.
1093 if (cnt < sizeof (Block)) {
1094 iv_status = CFB64_IV_BAD;
1095 if (enc_debug)
1096 (void) fprintf(stderr,
1097 "\t(encrypt_is) Not enough "
1098 "IV bytes\n");
1099 lstate = ENCR_STATE_NOT_READY;
1100 } else {
1101 data++; /* skip over the CFB64_IV byte */
1102 (void) memcpy(encr_data.decrypt.ivec, data,
1103 sizeof (Block));
1104 lstate = ENCR_STATE_IN_PROGRESS;
1106 break;
1107 case TELOPT_ENCTYPE_NULL:
1108 encr_data.decrypt.type = type;
1109 lstate &= ~ENCR_STATE_NO_RECV_IV;
1110 lstate &= ~ENCR_STATE_NO_SEND_IV;
1111 if (enc_debug)
1112 (void) fprintf(stderr,
1113 "\t(encrypt_is) We accept NULL encr\n");
1114 break;
1115 default:
1116 iv_status = CFB64_IV_BAD;
1117 encr_data.decrypt.type = 0;
1118 if (enc_debug)
1119 (void) fprintf(stderr,
1120 "\t(encrypt_is) Can't find type (%d) "
1121 "for initial negotiation\r\n",
1122 type);
1123 lstate = ENCR_STATE_NOT_READY;
1124 break;
1127 sbbuf[5] = (uchar_t)iv_status; /* either CFB64_IV_OK or BAD */
1129 if (iv_status == CFB64_IV_OK) {
1131 * send IV to crypto module and indicate it is for
1132 * decrypt only
1134 lstate &= ~ENCR_STATE_NO_RECV_IV; /* we received an OK IV */
1135 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont send an IV */
1136 } else {
1137 /* tell crypto module to disable crypto on "read" stream */
1138 lstate = ENCR_STATE_NOT_READY;
1141 write_data_len((const char *)sbbuf, sizeof (sbbuf));
1142 netflush();
1143 #ifdef ENCRYPT_NAMES
1144 if (enc_debug)
1145 (void) fprintf(stderr,
1146 "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
1147 ENCTYPE_NAME(type),
1148 (iv_status == CFB64_IV_OK ? "CFB64_IV_OK" :
1149 "CFB64_IV_BAD"));
1150 #endif /* ENCRYPT_NAMES */
1151 /* Update the state of the decryption negotiation */
1152 encr_data.decrypt.state = lstate;
1154 if (lstate == ENCR_STATE_NOT_READY)
1155 encr_data.decrypt.autoflag = 0;
1156 else {
1157 if (lstate == ENCR_STATE_OK && encr_data.decrypt.autoflag)
1158 encrypt_send_request_start();
1160 if (enc_debug)
1161 (void) fprintf(stderr,
1162 "\t(encrypt_is) final DECRYPT state = %d\n",
1163 encr_data.decrypt.state);
1167 * encrypt_send_encrypt_is
1169 * Tell the client what encryption we will use
1170 * and what our IV will be.
1172 static int
1173 encrypt_send_encrypt_is()
1175 register int lstate;
1176 krb5_error_code kret;
1177 uchar_t sbbuf[MAXOPTLEN], *p;
1178 int i;
1180 lstate = encr_data.encrypt.state;
1182 if (encr_data.encrypt.type == ENCTYPE_NULL) {
1184 * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
1185 * on a cipher.
1187 return (lstate);
1191 * - Create a random DES key
1193 * - DES ECB encrypt
1194 * encrypt the IV using itself as the key.
1196 * - Send response
1197 * IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
1198 * IAC SE
1201 if (lstate == ENCR_STATE_NOT_READY)
1202 lstate = ENCR_STATE_IN_PROGRESS;
1203 else if ((lstate & ENCR_STATE_NO_SEND_IV) == 0) {
1204 if (enc_debug)
1205 (void) fprintf(stderr,
1206 "\t(encrypt_send_is) IV already sent,"
1207 " state = %d\n", lstate);
1208 return (lstate);
1211 if (!VALIDKEY(encr_data.encrypt.krbdes_key)) {
1213 * Invalid key, set flag so we try again later
1214 * when we get a good one
1216 encr_data.encrypt.need_start = 1;
1217 if (enc_debug)
1218 (void) fprintf(stderr,
1219 "\t(encrypt_send_is) No Key, cannot "
1220 "start encryption yet\n");
1221 return (lstate);
1223 if (enc_debug)
1224 (void) fprintf(stderr,
1225 "\t(encrypt_send_is) Creating new feed\n");
1228 * Create a random feed and send it over.
1230 * Use the /dev/[u]random interface to generate
1231 * our encryption IV.
1233 kret = getrandom((char *)encr_data.encrypt.ivec, sizeof (Block));
1235 if (kret) {
1236 if (enc_debug)
1237 (void) fprintf(stderr,
1238 "\t(encrypt_send_is) error from "
1239 "getrandom: %d\n", kret);
1240 syslog(LOG_ERR, "Failed to create encryption key (err %d)\n");
1241 encr_data.encrypt.type = ENCTYPE_NULL;
1242 } else {
1243 mit_des_fixup_key_parity(encr_data.encrypt.ivec);
1246 p = sbbuf;
1247 *p++ = IAC;
1248 *p++ = SB;
1249 *p++ = TELOPT_ENCRYPT;
1250 *p++ = ENCRYPT_IS;
1251 *p++ = encr_data.encrypt.type;
1252 *p++ = CFB64_IV;
1255 * Copy the IV bytes individually so that when a
1256 * 255 (telnet IAC) is used, it can be "escaped" by
1257 * adding it twice (telnet RFC 854).
1259 for (i = 0; i < sizeof (Block); i++)
1260 if ((*p++ = encr_data.encrypt.ivec[i]) == IAC)
1261 *p++ = IAC;
1263 *p++ = IAC;
1264 *p++ = SE;
1265 write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1266 netflush();
1268 if (!kret) {
1269 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we sent our IV */
1270 lstate &= ~ENCR_STATE_NO_SEND_IV; /* dont need decrypt IV */
1272 encr_data.encrypt.state = lstate;
1274 if (enc_debug) {
1275 int i;
1276 (void) fprintf(stderr,
1277 "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
1278 encr_data.encrypt.type);
1279 for (i = 0; i < (p-sbbuf); i++)
1280 (void) fprintf(stderr, "%d ", (int)sbbuf[i]);
1281 (void) fprintf(stderr, "\n");
1284 return (lstate);
1288 * stop_stream
1290 * Utility routine to send a CRIOCSTOP ioctl to the
1291 * crypto module (cryptmod).
1293 static void
1294 stop_stream(int fd, int dir)
1296 struct strioctl crioc;
1297 uint32_t stopdir = dir;
1299 crioc.ic_cmd = CRYPTIOCSTOP;
1300 crioc.ic_timout = -1;
1301 crioc.ic_len = sizeof (stopdir);
1302 crioc.ic_dp = (char *)&stopdir;
1304 if (ioctl(fd, I_STR, &crioc)) {
1305 syslog(LOG_ERR, "Error sending CRYPTIOCSTOP ioctl: %m");
1310 * start_stream
1312 * Utility routine to send a CRYPTIOCSTART ioctl to the
1313 * crypto module (cryptmod). This routine may contain optional
1314 * payload data that the cryptmod will interpret as bytes that
1315 * need to be decrypted and sent back up to the application
1316 * via the data stream.
1318 static void
1319 start_stream(int fd, int dir, int datalen, char *data)
1321 struct strioctl crioc;
1323 crioc.ic_cmd = (dir == CRYPT_ENCRYPT ? CRYPTIOCSTARTENC :
1324 CRYPTIOCSTARTDEC);
1325 crioc.ic_timout = -1;
1326 crioc.ic_len = datalen;
1327 crioc.ic_dp = data;
1329 if (ioctl(fd, I_STR, &crioc)) {
1330 syslog(LOG_ERR, "Error sending CRYPTIOCSTART ioctl: %m");
1335 * encrypt_start_output
1337 * Tell the other side to start encrypting its data
1339 static void
1340 encrypt_start_output()
1342 int lstate;
1343 uchar_t *p;
1344 uchar_t sbbuf[MAXOPTLEN];
1345 struct strioctl crioc;
1346 struct cr_info_t cki;
1349 * Initialize crypto and send the ENCRYPT_IS msg
1351 lstate = encrypt_send_encrypt_is();
1353 if (lstate != ENCR_STATE_OK) {
1354 if (enc_debug)
1355 (void) fprintf(stderr,
1356 "\t(encrypt_start_output) ENCRYPT state "
1357 "= %d\n", lstate);
1358 return;
1361 p = sbbuf;
1363 *p++ = IAC;
1364 *p++ = SB;
1365 *p++ = TELOPT_ENCRYPT;
1366 *p++ = ENCRYPT_START;
1368 (void) memcpy(p, encr_data.encrypt.keyid, encr_data.encrypt.keyidlen);
1369 p += encr_data.encrypt.keyidlen;
1371 *p++ = IAC;
1372 *p++ = SE;
1374 /* Flush this data out before we start encrypting */
1375 write_data_len((const char *)sbbuf, (int)(p-sbbuf));
1376 netflush();
1378 if (enc_debug)
1379 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
1380 "(lstate = %d) data waiting = %d\n",
1381 (int)encr_data.encrypt.keyid[0],
1382 lstate, nfrontp-nbackp);
1384 encr_data.encrypt.state = lstate;
1387 * tell crypto module what key to use for encrypting
1388 * Note that the ENCRYPT has not yet been enabled, but we
1389 * need to first set the crypto key to use.
1391 cki.direction_mask = CRYPT_ENCRYPT;
1393 if (encr_data.encrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1394 cki.crypto_method = CRYPT_METHOD_DES_CFB;
1395 } else {
1396 if (enc_debug)
1397 (void) fprintf(stderr,
1398 "\t(encrypt_start_output) - unknown "
1399 "crypto_method %d\n",
1400 encr_data.encrypt.type);
1401 syslog(LOG_ERR, "unrecognized crypto encrypt method: %d",
1402 encr_data.encrypt.type);
1404 return;
1408 * If we previously configured this crypto method, we dont want to
1409 * overwrite the key or ivec information already given to the crypto
1410 * module as it will cause the cipher data between the client and server
1411 * to become out of synch and impossible to decipher.
1413 if (encr_data.encrypt.setup == cki.crypto_method) {
1414 cki.keylen = 0;
1415 cki.iveclen = 0;
1416 } else {
1417 cki.keylen = DES_BLOCKSIZE;
1418 (void) memcpy(cki.key, (void *)encr_data.encrypt.krbdes_key,
1419 DES_BLOCKSIZE);
1421 cki.iveclen = DES_BLOCKSIZE;
1422 (void) memcpy(cki.ivec, (void *)encr_data.encrypt.ivec,
1423 DES_BLOCKSIZE);
1425 cki.ivec_usage = IVEC_ONETIME;
1428 cki.option_mask = 0;
1430 /* Stop encrypt side prior to setup so we dont lose data */
1431 stop_stream(cryptmod_fd, CRYPT_ENCRYPT);
1433 crioc.ic_cmd = CRYPTIOCSETUP;
1434 crioc.ic_timout = -1;
1435 crioc.ic_len = sizeof (struct cr_info_t);
1436 crioc.ic_dp = (char *)&cki;
1438 if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1439 perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
1440 } else {
1441 /* Setup completed OK */
1442 encr_data.encrypt.setup = cki.crypto_method;
1446 * We do not check for "stuck" data when setting up the
1447 * outbound "encrypt" channel. Any data queued prior to
1448 * this IOCTL will get processed correctly without our help.
1450 start_stream(cryptmod_fd, CRYPT_ENCRYPT, 0, NULL);
1453 * tell crypto module to start encrypting
1455 if (enc_debug)
1456 (void) fprintf(stderr,
1457 "\t(encrypt_start_output) Encrypting output\n");
1461 * encrypt_request_start
1463 * The client requests that we start encryption immediately after
1464 * successful negotiation
1466 static void
1467 encrypt_request_start(void)
1469 if (encr_data.encrypt.type == ENCTYPE_NULL) {
1470 encr_data.encrypt.autoflag = 1;
1471 if (enc_debug)
1472 (void) fprintf(stderr, "\t(encrypt_request_start) "
1473 "autoencrypt = ON\n");
1474 } else {
1475 encrypt_start_output();
1480 * encrypt_end
1482 * ENCRYPT END received, stop decrypting the read stream
1484 static void
1485 encrypt_end(int direction)
1487 struct cr_info_t cki;
1488 struct strioctl crioc;
1489 uint32_t stopdir;
1491 stopdir = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1492 CRYPT_ENCRYPT);
1494 stop_stream(cryptmod_fd, stopdir);
1497 * Call this function when we wish to disable crypto in
1498 * either direction (ENCRYPT or DECRYPT)
1500 cki.direction_mask = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1501 CRYPT_ENCRYPT);
1502 cki.crypto_method = CRYPT_METHOD_NONE;
1503 cki.option_mask = 0;
1505 cki.keylen = 0;
1506 cki.iveclen = 0;
1507 cki.ivec_usage = IVEC_ONETIME;
1509 crioc.ic_cmd = CRYPTIOCSETUP;
1510 crioc.ic_timout = -1;
1511 crioc.ic_len = sizeof (cki);
1512 crioc.ic_dp = (char *)&cki;
1514 if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1515 perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
1518 start_stream(cryptmod_fd, stopdir, 0, NULL);
1522 * encrypt_request_end
1524 * When we receive a REQEND from the client, it means
1525 * that we are supposed to stop encrypting
1527 static void
1528 encrypt_request_end()
1531 * Tell the other side we are done encrypting
1534 write_data("%c%c%c%c%c%c",
1535 (uchar_t)IAC,
1536 (uchar_t)SB,
1537 (uchar_t)TELOPT_ENCRYPT,
1538 (uchar_t)ENCRYPT_END,
1539 (uchar_t)IAC,
1540 (uchar_t)SE);
1541 netflush();
1542 if (enc_debug)
1543 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
1546 * Turn off encryption of the write stream
1548 encrypt_end(TELNET_DIR_ENCRYPT);
1552 * encrypt_send_request_end
1554 * We stop encrypting the write stream and tell the other side about it.
1556 static void
1557 encrypt_send_request_end()
1559 write_data("%c%c%c%c%c%c",
1560 (uchar_t)IAC,
1561 (uchar_t)SB,
1562 (uchar_t)TELOPT_ENCRYPT,
1563 (uchar_t)ENCRYPT_REQEND,
1564 (uchar_t)IAC,
1565 (uchar_t)SE);
1566 netflush();
1567 if (enc_debug)
1568 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
1572 * encrypt_start
1574 * The client is going to start sending encrypted data
1575 * using the previously negotiated cipher (see what we set
1576 * when we did the REPLY in encrypt_is).
1578 static void
1579 encrypt_start(void)
1581 struct cr_info_t cki;
1582 struct strioctl crioc;
1583 int bytes = 0;
1584 char *dataptr = NULL;
1586 if (encr_data.decrypt.type == ENCTYPE_NULL) {
1587 if (enc_debug)
1588 (void) fprintf(stderr,
1589 "\t(encrypt_start) No DECRYPT method "
1590 "defined yet\n");
1591 encrypt_send_request_end();
1592 return;
1595 cki.direction_mask = CRYPT_DECRYPT;
1597 if (encr_data.decrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1598 cki.crypto_method = CRYPT_METHOD_DES_CFB;
1599 } else {
1600 if (enc_debug)
1601 (void) fprintf(stderr,
1602 "\t(encrypt_start) - unknown "
1603 "crypto_method %d\n", encr_data.decrypt.type);
1605 syslog(LOG_ERR, "unrecognized crypto decrypt method: %d",
1606 encr_data.decrypt.type);
1608 return;
1612 * Don't overwrite previously configured key and ivec info
1614 if (encr_data.decrypt.setup != cki.crypto_method) {
1615 (void) memcpy(cki.key, (void *)encr_data.decrypt.krbdes_key,
1616 DES_BLOCKSIZE);
1617 (void) memcpy(cki.ivec, (void *)encr_data.decrypt.ivec,
1618 DES_BLOCKSIZE);
1620 cki.keylen = DES_BLOCKSIZE;
1621 cki.iveclen = DES_BLOCKSIZE;
1622 cki.ivec_usage = IVEC_ONETIME;
1623 } else {
1624 cki.keylen = 0;
1625 cki.iveclen = 0;
1627 cki.option_mask = 0;
1629 stop_stream(cryptmod_fd, CRYPT_DECRYPT);
1631 crioc.ic_cmd = CRYPTIOCSETUP;
1632 crioc.ic_timout = -1;
1633 crioc.ic_len = sizeof (struct cr_info_t);
1634 crioc.ic_dp = (char *)&cki;
1636 if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1637 syslog(LOG_ERR, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
1638 "error: %m");
1639 } else {
1640 encr_data.decrypt.setup = cki.crypto_method;
1642 if (enc_debug)
1643 (void) fprintf(stderr,
1644 "\t(encrypt_start) called CRYPTIOCSETUP for "
1645 "decrypt side\n");
1648 * Read any data stuck between the cryptmod and the application
1649 * so we can pass it back down to be properly decrypted after
1650 * this operation finishes.
1652 if (ioctl(cryptmod_fd, I_NREAD, &bytes) < 0) {
1653 syslog(LOG_ERR, "I_NREAD returned error %m");
1654 bytes = 0;
1658 * Any data which was read AFTER the ENCRYPT START message
1659 * must be sent back down to be decrypted properly.
1661 * 'ncc' is the number of bytes that have been read but
1662 * not yet processed by the telnet state machine.
1664 * 'bytes' is the number of bytes waiting to be read from
1665 * the stream.
1667 * If either one is a positive value, then those bytes
1668 * must be pulled up and sent back down to be decrypted.
1670 if (ncc || bytes) {
1671 drainstream(bytes);
1672 if (enc_debug)
1673 (void) fprintf(stderr,
1674 "\t(encrypt_start) after drainstream, "
1675 "ncc=%d bytes = %d\n", ncc, bytes);
1676 bytes += ncc;
1677 dataptr = netip;
1680 start_stream(cryptmod_fd, CRYPT_DECRYPT, bytes, dataptr);
1683 * The bytes putback into the stream are no longer
1684 * available to be read by the server, so adjust the
1685 * counter accordingly.
1687 ncc = 0;
1688 netip = netibuf;
1689 (void) memset(netip, 0, netibufsize);
1691 #ifdef ENCRYPT_NAMES
1692 if (enc_debug) {
1693 (void) fprintf(stderr,
1694 "\t(encrypt_start) Start DECRYPT using %s\n",
1695 ENCTYPE_NAME(encr_data.decrypt.type));
1697 #endif /* ENCRYPT_NAMES */
1701 * encrypt_support
1703 * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
1704 * message from a client.
1706 * Choose an agreeable method (DES_CFB64) and
1707 * respond with TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
1709 * from: RFC 2946
1711 static void
1712 encrypt_support(char *data, int cnt)
1714 int lstate = ENCR_STATE_NOT_READY;
1715 int type, use_type = 0;
1717 while (cnt-- > 0 && use_type == 0) {
1718 type = *data++;
1719 #ifdef ENCRYPT_NAMES
1720 if (enc_debug)
1721 (void) fprintf(stderr,
1722 "RCVD ENCRYPT SUPPORT %s\n",
1723 ENCTYPE_NAME(type));
1724 #endif /* ENCRYPT_NAMES */
1726 * Prefer CFB64
1728 if (type == TELOPT_ENCTYPE_DES_CFB64) {
1729 use_type = type;
1732 encr_data.encrypt.type = use_type;
1734 if (use_type != TELOPT_ENCTYPE_NULL &&
1735 authenticated != NULL && authenticated != &NoAuth &&
1736 auth_status != AUTH_REJECT) {
1738 /* Authenticated -> have session key -> send ENCRYPT IS */
1739 lstate = encrypt_send_encrypt_is();
1740 if (lstate == ENCR_STATE_OK)
1741 encrypt_start_output();
1742 } else if (use_type == TELOPT_ENCTYPE_NULL) {
1743 if (enc_debug)
1744 (void) fprintf(stderr,
1745 "\t(encrypt_support) Cannot agree "
1746 "on crypto algorithm, output encryption "
1747 "disabled.\n");
1750 * Cannot agree on crypto algorithm
1751 * RFC 2946 sez:
1752 * send "IAC SB ENCRYPT IS NULL IAC SE"
1753 * optionally, also send IAC WONT ENCRYPT
1755 write_data("%c%c%c%c%c%c%c",
1756 (uchar_t)IAC,
1757 (uchar_t)SB,
1758 (uchar_t)TELOPT_ENCRYPT,
1759 (uchar_t)ENCRYPT_IS,
1760 (uchar_t)TELOPT_ENCTYPE_NULL,
1761 (uchar_t)IAC,
1762 (uchar_t)SE);
1763 send_wont(TELOPT_ENCRYPT);
1764 netflush();
1765 if (enc_debug)
1766 (void) fprintf(stderr,
1767 "SENT TELOPT_ENCRYPT ENCRYPT_IS "
1768 "[NULL]\n");
1770 remopts[TELOPT_ENCRYPT] = OPT_NO;
1772 settimer(encr_support);
1776 * encrypt_send_keyid
1778 * Sent the key id we will use to the client
1780 static void
1781 encrypt_send_keyid(int dir, uchar_t *keyid, int keylen, boolean_t saveit)
1783 uchar_t sbbuf[128], *p;
1785 p = sbbuf;
1787 *p++ = IAC;
1788 *p++ = SB;
1789 *p++ = TELOPT_ENCRYPT;
1790 *p++ = (dir == TELNET_DIR_ENCRYPT ? ENCRYPT_ENC_KEYID :
1791 ENCRYPT_DEC_KEYID);
1792 if (saveit) {
1793 if (enc_debug)
1794 (void) fprintf(stderr,
1795 "\t(send_keyid) store %d byte %s keyid\n",
1796 keylen,
1797 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1798 "DECRYPT"));
1800 if (dir == TELNET_DIR_ENCRYPT) {
1801 (void) memcpy(encr_data.encrypt.keyid, keyid, keylen);
1802 encr_data.encrypt.keyidlen = keylen;
1803 } else {
1804 (void) memcpy(encr_data.decrypt.keyid, keyid, keylen);
1805 encr_data.decrypt.keyidlen = keylen;
1808 (void) memcpy(p, keyid, keylen);
1809 p += keylen;
1811 *p++ = IAC;
1812 *p++ = SE;
1813 write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1814 netflush();
1816 if (enc_debug)
1817 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT %s %d\n",
1818 (dir == TELNET_DIR_ENCRYPT ? "ENC_KEYID" :
1819 "DEC_KEYID"), keyid[0]);
1823 * encrypt_reply
1825 * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
1826 * message, process it accordingly.
1827 * If the vector is acceptable, tell client we are encrypting and
1828 * enable encryption on our write stream.
1830 * Negotiate the KEYID next..
1831 * RFC 2946, 2952
1833 static void
1834 encrypt_reply(char *data, int len)
1836 uchar_t type = (uchar_t)(*data++);
1837 uchar_t result = (uchar_t)(*data);
1838 int lstate;
1840 #ifdef ENCRYPT_NAMES
1841 if (enc_debug)
1842 (void) fprintf(stderr,
1843 "\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
1844 ENCRYPT_NAME(type),
1845 (result == CFB64_IV_OK ? "CFB64_IV_OK" :
1846 "CFB64_IV_BAD"), len);
1847 #endif /* ENCRYPT_NAMES */
1849 lstate = encr_data.encrypt.state;
1850 if (enc_debug)
1851 (void) fprintf(stderr,
1852 "\t(encrypt_reply) initial ENCRYPT state = %d\n",
1853 lstate);
1854 switch (result) {
1855 case CFB64_IV_OK:
1856 if (lstate == ENCR_STATE_NOT_READY)
1857 lstate = ENCR_STATE_IN_PROGRESS;
1858 lstate &= ~ENCR_STATE_NO_RECV_IV; /* we got the IV */
1859 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont need to send IV */
1862 * The correct response here is to send the encryption key id
1863 * RFC 2752.
1865 * Send keyid 0 to indicate that we will just use default
1866 * keys.
1868 encrypt_send_keyid(TELNET_DIR_ENCRYPT, (uchar_t *)"\0", 1, 1);
1870 break;
1871 case CFB64_IV_BAD:
1873 * Clear the ivec
1875 (void) memset(encr_data.encrypt.ivec, 0, sizeof (Block));
1876 lstate = ENCR_STATE_NOT_READY;
1877 break;
1878 default:
1879 if (enc_debug)
1880 (void) fprintf(stderr,
1881 "\t(encrypt_reply) Got unknown IV value in "
1882 "REPLY message\n");
1883 lstate = ENCR_STATE_NOT_READY;
1884 break;
1887 encr_data.encrypt.state = lstate;
1888 if (lstate == ENCR_STATE_NOT_READY) {
1889 encr_data.encrypt.autoflag = 0;
1890 encr_data.encrypt.type = ENCTYPE_NULL;
1891 if (enc_debug)
1892 (void) fprintf(stderr,
1893 "\t(encrypt_reply) encrypt.autoflag = "
1894 "OFF\n");
1895 } else {
1896 encr_data.encrypt.type = type;
1897 if ((lstate == ENCR_STATE_OK) && encr_data.encrypt.autoflag)
1898 encrypt_start_output();
1901 if (enc_debug)
1902 (void) fprintf(stderr,
1903 "\t(encrypt_reply) ENCRYPT final state = %d\n",
1904 lstate);
1907 static void
1908 encrypt_set_keyid_state(uchar_t *keyid, int *keyidlen, int dir)
1910 int lstate;
1912 lstate = (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state :
1913 encr_data.decrypt.state);
1915 if (enc_debug)
1916 (void) fprintf(stderr,
1917 "\t(set_keyid_state) %s initial state = %d\n",
1918 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1919 "DECRYPT"), lstate);
1922 * Currently, we only support using the default keyid,
1923 * so it should be an error if the len > 1 or the keyid != 0.
1925 if (*keyidlen != 1 || (*keyid != '\0')) {
1926 if (enc_debug)
1927 (void) fprintf(stderr,
1928 "\t(set_keyid_state) unexpected keyid: "
1929 "len=%d value=%d\n", *keyidlen, *keyid);
1930 *keyidlen = 0;
1931 syslog(LOG_ERR, "rcvd unexpected keyid %d - only keyid of 0 "
1932 "is supported", *keyid);
1933 } else {
1935 * We move to the "IN_PROGRESS" state.
1937 if (lstate == ENCR_STATE_NOT_READY)
1938 lstate = ENCR_STATE_IN_PROGRESS;
1940 * Clear the NO_KEYID bit because we now have a valid keyid
1942 lstate &= ~ENCR_STATE_NO_KEYID;
1945 if (enc_debug)
1946 (void) fprintf(stderr,
1947 "\t(set_keyid_state) %s final state = %d\n",
1948 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1949 "DECRYPT"), lstate);
1951 if (dir == TELNET_DIR_ENCRYPT)
1952 encr_data.encrypt.state = lstate;
1953 else
1954 encr_data.decrypt.state = lstate;
1958 * encrypt_keyid
1960 * Set the keyid value in the key_info structure.
1961 * if necessary send a response to the sender
1963 static void
1964 encrypt_keyid(uchar_t *newkeyid, int *keyidlen, uchar_t *keyid,
1965 int len, int dir)
1967 if (len > TELNET_MAXNUMKEYS) {
1968 if (enc_debug)
1969 (void) fprintf(stderr,
1970 "\t(keyid) keylen too big (%d)\n", len);
1971 return;
1974 if (enc_debug) {
1975 (void) fprintf(stderr, "\t(keyid) set KEYID for %s len = %d\n",
1976 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1977 "DECRYPT"), len);
1980 if (len == 0) {
1981 if (*keyidlen == 0) {
1982 if (enc_debug)
1983 (void) fprintf(stderr,
1984 "\t(keyid) Got 0 length keyid - "
1985 "failure\n");
1986 return;
1988 *keyidlen = 0;
1989 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
1991 } else if (len != *keyidlen || memcmp(keyid, newkeyid, len)) {
1992 if (enc_debug)
1993 (void) fprintf(stderr,
1994 "\t(keyid) Setting new key (%d bytes)\n",
1995 len);
1997 *keyidlen = len;
1998 (void) memcpy(newkeyid, keyid, len);
2000 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2001 } else {
2002 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2004 if (enc_debug)
2005 (void) fprintf(stderr,
2006 "\t(keyid) %s Key already in place,"
2007 "state = %d autoflag=%d\n",
2008 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT"),
2009 (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state:
2010 encr_data.decrypt.state),
2011 (dir == TELNET_DIR_ENCRYPT ?
2012 encr_data.encrypt.autoflag:
2013 encr_data.decrypt.autoflag));
2015 /* key already in place */
2016 if ((encr_data.encrypt.state == ENCR_STATE_OK) &&
2017 dir == TELNET_DIR_ENCRYPT && encr_data.encrypt.autoflag) {
2018 encrypt_start_output();
2020 return;
2023 if (enc_debug)
2024 (void) fprintf(stderr, "\t(keyid) %s final state = %d\n",
2025 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
2026 "DECRYPT"),
2027 (dir == TELNET_DIR_ENCRYPT ?
2028 encr_data.encrypt.state :
2029 encr_data.decrypt.state));
2031 encrypt_send_keyid(dir, newkeyid, *keyidlen, 0);
2035 * encrypt_enc_keyid
2037 * We received the ENC_KEYID message from a client indicating that
2038 * the client wishes to verify that the indicated keyid maps to a
2039 * valid key.
2041 static void
2042 encrypt_enc_keyid(char *data, int cnt)
2045 * Verify the decrypt keyid is valid
2047 encrypt_keyid(encr_data.decrypt.keyid, &encr_data.decrypt.keyidlen,
2048 (uchar_t *)data, cnt, TELNET_DIR_DECRYPT);
2052 * encrypt_dec_keyid
2054 * We received the DEC_KEYID message from a client indicating that
2055 * the client wants to verify that the indicated keyid maps to a valid key.
2057 static void
2058 encrypt_dec_keyid(char *data, int cnt)
2060 encrypt_keyid(encr_data.encrypt.keyid, &encr_data.encrypt.keyidlen,
2061 (uchar_t *)data, cnt, TELNET_DIR_ENCRYPT);
2065 * encrypt_session_key
2067 * Store the session key in the encryption data record
2069 static void
2070 encrypt_session_key(Session_Key *key, cipher_info_t *cinfo)
2072 if (key == NULL || key->type != SK_DES) {
2073 if (enc_debug)
2074 (void) fprintf(stderr,
2075 "\t(session_key) Cannot set krb5 "
2076 "session key (unknown type = %d)\n",
2077 key ? key->type : -1);
2079 if (enc_debug)
2080 (void) fprintf(stderr,
2081 "\t(session_key) Settting session key "
2082 "for server\n");
2084 /* store the key in the cipher info data struct */
2085 (void) memcpy(cinfo->krbdes_key, (void *)key->data, sizeof (Block));
2088 * Now look to see if we still need to send the key and start
2089 * encrypting.
2091 * If so, go ahead an call it now that we have the key.
2093 if (cinfo->need_start) {
2094 if (encrypt_send_encrypt_is() == ENCR_STATE_OK) {
2095 cinfo->need_start = 0;
2101 * new_env
2103 * Used to add an environment variable and value to the
2104 * linked list structure.
2106 static int
2107 new_env(const char *name, const char *value)
2109 struct envlist *env;
2111 env = malloc(sizeof (struct envlist));
2112 if (env == NULL)
2113 return (1);
2114 if ((env->name = strdup(name)) == NULL) {
2115 free(env);
2116 return (1);
2118 if ((env->value = strdup(value)) == NULL) {
2119 free(env->name);
2120 free(env);
2121 return (1);
2123 env->delete = 0;
2124 env->next = envlist_head;
2125 envlist_head = env;
2126 return (0);
2130 * del_env
2132 * Used to delete an environment variable from the linked list
2133 * structure. We just set a flag because we will delete the list
2134 * anyway before we exec login.
2136 static int
2137 del_env(const char *name)
2139 struct envlist *env;
2141 for (env = envlist_head; env; env = env->next) {
2142 if (strcmp(env->name, name) == 0) {
2143 env->delete = 1;
2144 break;
2147 return (0);
2150 static int
2151 issock(int fd)
2153 struct stat stats;
2155 if (fstat(fd, &stats) == -1)
2156 return (0);
2157 return (S_ISSOCK(stats.st_mode));
2161 * audit_telnet_settid stores the terminal id while it is still
2162 * available. Subsequent calls to adt_load_hostname() return
2163 * the id which is stored here.
2165 static int
2166 audit_telnet_settid(int sock) {
2167 adt_session_data_t *ah;
2168 adt_termid_t *termid;
2169 int rc;
2171 if ((rc = adt_start_session(&ah, NULL, 0)) == 0) {
2172 if ((rc = adt_load_termid(sock, &termid)) == 0) {
2173 if ((rc = adt_set_user(ah, ADT_NO_AUDIT,
2174 ADT_NO_AUDIT, 0, ADT_NO_AUDIT,
2175 termid, ADT_SETTID)) == 0)
2176 (void) adt_set_proc(ah);
2177 free(termid);
2179 (void) adt_end_session(ah);
2181 return (rc);
2184 /* ARGSUSED */
2186 main(int argc, char *argv[])
2188 struct sockaddr_storage from;
2189 int on = 1;
2190 socklen_t fromlen;
2191 int issocket;
2192 #if defined(DEBUG)
2193 ushort_t porttouse = 0;
2194 boolean_t standalone = 0;
2195 #endif /* defined(DEBUG) */
2196 extern char *optarg;
2197 char c;
2198 int tos = -1;
2200 while ((c = getopt(argc, argv, TELNETD_OPTS DEBUG_OPTS)) != -1) {
2201 switch (c) {
2202 #if defined(DEBUG)
2203 case 'p':
2205 * note: alternative port number only used in
2206 * standalone mode.
2208 porttouse = atoi(optarg);
2209 standalone = 1;
2210 break;
2211 case 'e':
2212 enc_debug = 1;
2213 break;
2214 #endif /* DEBUG */
2215 case 'a':
2216 if (strcasecmp(optarg, "none") == 0) {
2217 auth_level = 0;
2218 } else if (strcasecmp(optarg, "user") == 0) {
2219 auth_level = AUTH_USER;
2220 } else if (strcasecmp(optarg, "valid") == 0) {
2221 auth_level = AUTH_VALID;
2222 } else if (strcasecmp(optarg, "off") == 0) {
2223 auth_level = -1;
2224 negotiate_auth_krb5 = 0;
2225 } else if (strcasecmp(optarg, "debug") == 0) {
2226 auth_debug = 1;
2227 } else {
2228 syslog(LOG_ERR,
2229 "unknown authentication level specified "
2230 "with \'-a\' option (%s)", optarg);
2231 auth_level = AUTH_USER;
2233 break;
2234 case 'X':
2235 /* disable authentication negotiation */
2236 negotiate_auth_krb5 = 0;
2237 break;
2238 case 'R':
2239 case 'M':
2240 if (optarg != NULL) {
2241 int ret = krb5_init();
2242 if (ret) {
2243 syslog(LOG_ERR,
2244 "Unable to use Kerberos V5 as "
2245 "requested, exiting");
2246 exit(1);
2248 (void) krb5_set_default_realm(telnet_context,
2249 optarg);
2250 syslog(LOG_NOTICE,
2251 "using %s as default KRB5 realm", optarg);
2253 break;
2254 case 'S':
2255 telnet_srvtab = (char *)strdup(optarg);
2256 break;
2257 case 'E': /* disable automatic encryption */
2258 negotiate_encrypt = B_FALSE;
2259 break;
2260 case 'U':
2261 resolve_hostname = 1;
2262 break;
2263 case 's':
2264 if (optarg == NULL || (tos = atoi(optarg)) < 0 ||
2265 tos > 255) {
2266 syslog(LOG_ERR, "telnetd: illegal tos value: "
2267 "%s\n", optarg);
2268 } else {
2269 if (tos < 0)
2270 tos = 020;
2272 break;
2273 case 'h':
2274 show_hostinfo = 0;
2275 break;
2276 default:
2277 syslog(LOG_ERR, "telnetd: illegal cmd line option %c",
2279 break;
2283 netibufsize = BUFSIZ;
2284 if (!(netibuf = (char *)malloc(netibufsize)))
2285 syslog(LOG_ERR, "netibuf malloc failed\n");
2286 (void) memset(netibuf, 0, netibufsize);
2287 netip = netibuf;
2289 #if defined(DEBUG)
2290 if (standalone) {
2291 int s, ns, foo;
2292 struct servent *sp;
2293 static struct sockaddr_in6 sin6 = { AF_INET6 };
2294 int option = 1;
2296 if (porttouse) {
2297 sin6.sin6_port = htons(porttouse);
2298 } else {
2299 sp = getservbyname("telnet", "tcp");
2300 if (sp == 0) {
2301 (void) fprintf(stderr,
2302 "telnetd: tcp/telnet: "
2303 "unknown service\n");
2304 exit(EXIT_FAILURE);
2306 sin6.sin6_port = sp->s_port;
2309 s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
2310 if (s < 0) {
2311 perror("telnetd: socket");
2312 exit(EXIT_FAILURE);
2314 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&option,
2315 sizeof (option)) == -1)
2316 perror("setsockopt SO_REUSEADDR");
2317 if (bind(s, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) {
2318 perror("bind");
2319 exit(EXIT_FAILURE);
2321 if (listen(s, 32) < 0) {
2322 perror("listen");
2323 exit(EXIT_FAILURE);
2326 /* automatically reap all child processes */
2327 (void) signal(SIGCHLD, SIG_IGN);
2329 for (;;) {
2330 pid_t pid;
2332 foo = sizeof (sin6);
2333 ns = accept(s, (struct sockaddr *)&sin6, &foo);
2334 if (ns < 0) {
2335 perror("accept");
2336 exit(EXIT_FAILURE);
2338 pid = fork();
2339 if (pid == -1) {
2340 perror("fork");
2341 exit(EXIT_FAILURE);
2343 if (pid == 0) {
2344 (void) dup2(ns, 0);
2345 (void) close(s);
2346 (void) signal(SIGCHLD, SIG_DFL);
2347 break;
2349 (void) close(ns);
2352 #endif /* defined(DEBUG) */
2354 openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
2356 issocket = issock(0);
2357 if (!issocket)
2358 fatal(0, "stdin is not a socket file descriptor");
2360 fromlen = (socklen_t)sizeof (from);
2361 (void) memset((char *)&from, 0, sizeof (from));
2362 if (getpeername(0, (struct sockaddr *)&from, &fromlen)
2363 < 0) {
2364 (void) fprintf(stderr, "%s: ", argv[0]);
2365 perror("getpeername");
2366 _exit(EXIT_FAILURE);
2369 if (audit_telnet_settid(0)) { /* set terminal ID */
2370 (void) fprintf(stderr, "%s: ", argv[0]);
2371 perror("audit");
2372 exit(EXIT_FAILURE);
2375 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on,
2376 sizeof (on)) < 0) {
2377 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
2381 * Set the TOS value
2383 if (tos != -1 &&
2384 setsockopt(0, IPPROTO_IP, IP_TOS,
2385 (char *)&tos, sizeof (tos)) < 0 &&
2386 errno != ENOPROTOOPT) {
2387 syslog(LOG_ERR, "setsockopt (IP_TOS %d): %m", tos);
2390 if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on,
2391 sizeof (on)) < 0) {
2392 syslog(LOG_WARNING, "setsockopt (SO_OOBINLINE): %m");
2395 /* set the default PAM service name */
2396 (void) strcpy(pam_svc_name, "telnet");
2398 doit(0, &from);
2399 return (EXIT_SUCCESS);
2402 static char *terminaltype = 0;
2405 * ttloop
2407 * A small subroutine to flush the network output buffer, get some data
2408 * from the network, and pass it through the telnet state machine. We
2409 * also flush the pty input buffer (by dropping its data) if it becomes
2410 * too full.
2412 static void
2413 ttloop(void)
2415 if (nfrontp-nbackp) {
2416 netflush();
2418 read_again:
2419 ncc = read(net, netibuf, netibufsize);
2420 if (ncc < 0) {
2421 if (errno == EINTR)
2422 goto read_again;
2423 syslog(LOG_INFO, "ttloop: read: %m");
2424 exit(EXIT_FAILURE);
2425 } else if (ncc == 0) {
2426 syslog(LOG_INFO, "ttloop: peer closed connection\n");
2427 exit(EXIT_FAILURE);
2430 netip = netibuf;
2431 telrcv(); /* state machine */
2432 if (ncc > 0) {
2433 pfrontp = pbackp = ptyobuf;
2434 telrcv();
2438 static void
2439 send_do(int option)
2441 write_data("%c%c%c", (uchar_t)IAC, (uchar_t)DO, (uchar_t)option);
2444 static void
2445 send_will(int option)
2447 write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WILL, (uchar_t)option);
2450 static void
2451 send_wont(int option)
2453 write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WONT, (uchar_t)option);
2458 * getauthtype
2460 * Negotiate automatic authentication, is possible.
2462 static int
2463 getauthtype(char *username, int *len)
2465 int init_status = -1;
2467 init_status = krb5_init();
2469 if (auth_level == -1 || init_status != 0) {
2470 remopts[TELOPT_AUTHENTICATION] = OPT_NO;
2471 myopts[TELOPT_AUTHENTICATION] = OPT_NO;
2472 negotiate_auth_krb5 = B_FALSE;
2473 negotiate_encrypt = B_FALSE;
2474 return (AUTH_REJECT);
2477 if (init_status == 0 && auth_level != -1) {
2478 if (negotiate_auth_krb5) {
2480 * Negotiate Authentication FIRST
2482 send_do(TELOPT_AUTHENTICATION);
2483 remopts[TELOPT_AUTHENTICATION] =
2484 OPT_YES_BUT_ALWAYS_LOOK;
2486 while (sequenceIs(authopt, getauth))
2487 ttloop();
2489 if (remopts[TELOPT_AUTHENTICATION] == OPT_YES) {
2491 * Request KRB5 Mutual authentication and if that fails,
2492 * KRB5 1-way client authentication
2494 uchar_t sbbuf[MAXOPTLEN], *p;
2495 p = sbbuf;
2496 *p++ = (uchar_t)IAC;
2497 *p++ = (uchar_t)SB;
2498 *p++ = (uchar_t)TELOPT_AUTHENTICATION;
2499 *p++ = (uchar_t)TELQUAL_SEND;
2500 if (negotiate_auth_krb5) {
2501 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2502 *p++ = (uchar_t)(AUTH_WHO_CLIENT |
2503 AUTH_HOW_MUTUAL |
2504 AUTH_ENCRYPT_ON);
2505 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2506 *p++ = (uchar_t)(AUTH_WHO_CLIENT |
2507 AUTH_HOW_MUTUAL);
2508 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2509 *p++ = (uchar_t)(AUTH_WHO_CLIENT|
2510 AUTH_HOW_ONE_WAY);
2511 } else {
2512 *p++ = (uchar_t)AUTHTYPE_NULL;
2514 *p++ = (uchar_t)IAC;
2515 *p++ = (uchar_t)SE;
2517 write_data_len((const char *)sbbuf,
2518 (size_t)(p - sbbuf));
2519 netflush();
2520 if (auth_debug)
2521 (void) fprintf(stderr,
2522 "SENT TELOPT_AUTHENTICATION "
2523 "[data]\n");
2525 /* auth_wait returns the authentication level */
2526 /* status = auth_wait(username, len); */
2527 while (sequenceIs(authdone, getauth))
2528 ttloop();
2530 * Now check to see if the user is valid or not
2532 if (authenticated == NULL || authenticated == &NoAuth)
2533 auth_status = AUTH_REJECT;
2534 else {
2536 * We cant be VALID until the user status is
2537 * checked.
2539 if (auth_status == AUTH_VALID)
2540 auth_status = AUTH_USER;
2542 if (authenticated->AuthName ==
2543 AUTHTYPE_KERBEROS_V5)
2544 auth_status = krb5_user_status(
2545 username, *len, auth_status);
2549 return (auth_status);
2552 static void
2553 getencrtype(void)
2555 if (krb5_privacy_allowed() && negotiate_encrypt) {
2556 if (myopts[TELOPT_ENCRYPT] != OPT_YES) {
2557 if (!sent_will_encrypt) {
2558 send_will(TELOPT_ENCRYPT);
2559 sent_will_encrypt = B_TRUE;
2561 if (enc_debug)
2562 (void) fprintf(stderr, "SENT WILL ENCRYPT\n");
2564 if (remopts[TELOPT_ENCRYPT] != OPT_YES) {
2565 if (!sent_do_encrypt) {
2566 send_do(TELOPT_ENCRYPT);
2567 sent_do_encrypt = B_TRUE;
2568 remopts[TELOPT_ENCRYPT] =
2569 OPT_YES_BUT_ALWAYS_LOOK;
2571 if (enc_debug)
2572 (void) fprintf(stderr, "SENT DO ENCRYPT\n");
2574 myopts[TELOPT_ENCRYPT] = OPT_YES;
2576 while (sequenceIs(encropt, getencr))
2577 ttloop();
2579 if (auth_status != AUTH_REJECT &&
2580 remopts[TELOPT_ENCRYPT] == OPT_YES &&
2581 myopts[TELOPT_ENCRYPT] == OPT_YES) {
2583 if (sent_encrypt_support == B_FALSE) {
2584 write_data("%c%c%c%c%c%c%c",
2585 (uchar_t)IAC,
2586 (uchar_t)SB,
2587 (uchar_t)TELOPT_ENCRYPT,
2588 (uchar_t)ENCRYPT_SUPPORT,
2589 (uchar_t)TELOPT_ENCTYPE_DES_CFB64,
2590 (uchar_t)IAC,
2591 (uchar_t)SE);
2593 netflush();
2596 * Now wait for a response to these messages before
2597 * continuing...
2598 * Look for TELOPT_ENCRYPT suboptions
2600 while (sequenceIs(encr_support, getencr))
2601 ttloop();
2603 } else {
2604 /* Dont need responses to these, so dont wait for them */
2605 settimer(encropt);
2606 remopts[TELOPT_ENCRYPT] = OPT_NO;
2607 myopts[TELOPT_ENCRYPT] = OPT_NO;
2613 * getterminaltype
2615 * Ask the other end to send along its terminal type.
2616 * Output is the variable terminaltype filled in.
2618 static void
2619 getterminaltype(void)
2622 * The remote side may have already sent this info, so
2623 * dont ask for these options if the other side already
2624 * sent the information.
2626 if (sequenceIs(ttypeopt, getterminal)) {
2627 send_do(TELOPT_TTYPE);
2628 remopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK;
2631 if (sequenceIs(nawsopt, getterminal)) {
2632 send_do(TELOPT_NAWS);
2633 remopts[TELOPT_NAWS] = OPT_YES_BUT_ALWAYS_LOOK;
2636 if (sequenceIs(xdisplocopt, getterminal)) {
2637 send_do(TELOPT_XDISPLOC);
2638 remopts[TELOPT_XDISPLOC] = OPT_YES_BUT_ALWAYS_LOOK;
2641 if (sequenceIs(environopt, getterminal)) {
2642 send_do(TELOPT_NEW_ENVIRON);
2643 remopts[TELOPT_NEW_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2646 if (sequenceIs(oenvironopt, getterminal)) {
2647 send_do(TELOPT_OLD_ENVIRON);
2648 remopts[TELOPT_OLD_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2651 /* make sure encryption is started here */
2652 while (auth_status != AUTH_REJECT &&
2653 authenticated != &NoAuth && authenticated != NULL &&
2654 remopts[TELOPT_ENCRYPT] == OPT_YES &&
2655 encr_data.encrypt.autoflag &&
2656 encr_data.encrypt.state != ENCR_STATE_OK) {
2657 if (enc_debug)
2658 (void) fprintf(stderr, "getterminaltype() forcing encrypt\n");
2659 ttloop();
2662 if (enc_debug) {
2663 (void) fprintf(stderr, "getterminaltype() encryption %sstarted\n",
2664 encr_data.encrypt.state == ENCR_STATE_OK ? "" : "not ");
2667 while (sequenceIs(ttypeopt, getterminal) ||
2668 sequenceIs(nawsopt, getterminal) ||
2669 sequenceIs(xdisplocopt, getterminal) ||
2670 sequenceIs(environopt, getterminal) ||
2671 sequenceIs(oenvironopt, getterminal)) {
2672 ttloop();
2676 if (remopts[TELOPT_TTYPE] == OPT_YES) {
2677 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2678 (uchar_t)TELOPT_TTYPE, (uchar_t)TELQUAL_SEND,
2679 (uchar_t)IAC, (uchar_t)SE };
2681 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2683 if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2684 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2685 (uchar_t)TELOPT_XDISPLOC, (uchar_t)TELQUAL_SEND,
2686 (uchar_t)IAC, (uchar_t)SE };
2688 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2690 if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2691 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2692 (uchar_t)TELOPT_NEW_ENVIRON, (uchar_t)TELQUAL_SEND,
2693 (uchar_t)IAC, (uchar_t)SE };
2695 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2697 if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2698 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2699 (uchar_t)TELOPT_OLD_ENVIRON, (uchar_t)TELQUAL_SEND,
2700 (uchar_t)IAC, (uchar_t)SE };
2702 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2705 if (remopts[TELOPT_TTYPE] == OPT_YES) {
2706 while (sequenceIs(ttypesubopt, getterminal)) {
2707 ttloop();
2710 if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2711 while (sequenceIs(xdisplocsubopt, getterminal)) {
2712 ttloop();
2715 if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2716 while (sequenceIs(environsubopt, getterminal)) {
2717 ttloop();
2720 if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2721 while (sequenceIs(oenvironsubopt, getterminal)) {
2722 ttloop();
2725 init_neg_done = 1;
2728 pid_t pid;
2731 * Get a pty, scan input lines.
2733 static void
2734 doit(int f, struct sockaddr_storage *who)
2736 char *host;
2737 char host_name[MAXHOSTNAMELEN];
2738 int p, t, tt;
2739 struct sgttyb b;
2740 int ptmfd; /* fd of logindmux connected to pty */
2741 int netfd; /* fd of logindmux connected to netf */
2742 struct stat buf;
2743 struct protocol_arg telnetp;
2744 struct strioctl telnetmod;
2745 struct envlist *env, *next;
2746 int nsize = 0;
2747 char abuf[INET6_ADDRSTRLEN];
2748 struct sockaddr_in *sin;
2749 struct sockaddr_in6 *sin6;
2750 socklen_t wholen;
2751 char username[MAXUSERNAMELEN];
2752 int len;
2753 uchar_t passthru;
2754 char *slavename;
2756 if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) {
2757 fatalperror(f, "open /dev/ptmx", errno);
2759 if (grantpt(p) == -1)
2760 fatal(f, "could not grant slave pty");
2761 if (unlockpt(p) == -1)
2762 fatal(f, "could not unlock slave pty");
2763 if ((slavename = ptsname(p)) == NULL)
2764 fatal(f, "could not enable slave pty");
2765 (void) dup2(f, 0);
2766 if ((t = open(slavename, O_RDWR | O_NOCTTY)) == -1)
2767 fatal(f, "could not open slave pty");
2768 if (ioctl(t, I_PUSH, "ptem") == -1)
2769 fatalperror(f, "ioctl I_PUSH ptem", errno);
2770 if (ioctl(t, I_PUSH, "ldterm") == -1)
2771 fatalperror(f, "ioctl I_PUSH ldterm", errno);
2772 if (ioctl(t, I_PUSH, "ttcompat") == -1)
2773 fatalperror(f, "ioctl I_PUSH ttcompat", errno);
2775 line = slavename;
2777 pty = t;
2779 if (ioctl(t, TIOCGETP, &b) == -1)
2780 syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n");
2781 b.sg_flags = O_CRMOD|O_XTABS|O_ANYP;
2782 /* XXX - ispeed and ospeed must be non-zero */
2783 b.sg_ispeed = B38400;
2784 b.sg_ospeed = B38400;
2785 if (ioctl(t, TIOCSETN, &b) == -1)
2786 syslog(LOG_INFO, "ioctl TIOCSETN pty t: %m\n");
2787 if (ioctl(pty, TIOCGETP, &b) == -1)
2788 syslog(LOG_INFO, "ioctl TIOCGETP pty pty: %m\n");
2789 b.sg_flags &= ~O_ECHO;
2790 if (ioctl(pty, TIOCSETN, &b) == -1)
2791 syslog(LOG_INFO, "ioctl TIOCSETN pty pty: %m\n");
2793 if (who->ss_family == AF_INET) {
2794 char *addrbuf = NULL;
2795 char *portbuf = NULL;
2797 sin = (struct sockaddr_in *)who;
2798 wholen = sizeof (struct sockaddr_in);
2800 addrbuf = (char *)malloc(wholen);
2801 if (addrbuf == NULL)
2802 fatal(f, "Cannot alloc memory for address info\n");
2803 portbuf = (char *)malloc(sizeof (sin->sin_port));
2804 if (portbuf == NULL) {
2805 free(addrbuf);
2806 fatal(f, "Cannot alloc memory for port info\n");
2809 (void) memcpy(addrbuf, (const void *)&sin->sin_addr, wholen);
2810 (void) memcpy(portbuf, (const void *)&sin->sin_port,
2811 sizeof (sin->sin_port));
2813 free(rsaddr.contents);
2815 rsaddr.contents = (krb5_octet *)addrbuf;
2816 rsaddr.length = wholen;
2817 rsaddr.addrtype = ADDRTYPE_INET;
2819 free(rsport.contents);
2821 rsport.contents = (krb5_octet *)portbuf;
2822 rsport.length = sizeof (sin->sin_port);
2823 rsport.addrtype = ADDRTYPE_IPPORT;
2824 } else if (who->ss_family == AF_INET6) {
2825 struct in_addr ipv4_addr;
2826 char *addrbuf = NULL;
2827 char *portbuf = NULL;
2829 sin6 = (struct sockaddr_in6 *)who;
2830 wholen = sizeof (struct sockaddr_in6);
2832 IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2833 &ipv4_addr);
2835 addrbuf = (char *)malloc(wholen);
2836 if (addrbuf == NULL)
2837 fatal(f, "Cannot alloc memory for address info\n");
2839 portbuf = (char *)malloc(sizeof (sin6->sin6_port));
2840 if (portbuf == NULL) {
2841 free(addrbuf);
2842 fatal(f, "Cannot alloc memory for port info\n");
2845 (void) memcpy((void *) addrbuf,
2846 (const void *)&ipv4_addr,
2847 wholen);
2849 * If we already used rsaddr.contents, free the previous
2850 * buffer.
2852 free(rsaddr.contents);
2854 rsaddr.contents = (krb5_octet *)addrbuf;
2855 rsaddr.length = sizeof (ipv4_addr);
2856 rsaddr.addrtype = ADDRTYPE_INET;
2858 (void) memcpy((void *) portbuf, (const void *)&sin6->sin6_port,
2859 sizeof (sin6->sin6_port));
2861 free(rsport.contents);
2863 rsport.contents = (krb5_octet *)portbuf;
2864 rsport.length = sizeof (sin6->sin6_port);
2865 rsport.addrtype = ADDRTYPE_IPPORT;
2866 } else {
2867 syslog(LOG_ERR, "unknown address family %d\n",
2868 who->ss_family);
2869 fatal(f, "getpeername: unknown address family\n");
2872 if (getnameinfo((const struct sockaddr *) who, wholen, host_name,
2873 sizeof (host_name), NULL, 0, 0) == 0) {
2874 host = host_name;
2875 } else {
2877 * If the '-U' option was given on the cmd line, we must
2878 * be able to lookup the hostname
2880 if (resolve_hostname) {
2881 fatal(f, "Couldn't resolve your address into a "
2882 "host name.\r\nPlease contact your net "
2883 "administrator");
2886 if (who->ss_family == AF_INET6) {
2887 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2888 struct in_addr ipv4_addr;
2890 IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2891 &ipv4_addr);
2892 host = (char *)inet_ntop(AF_INET,
2893 &ipv4_addr, abuf, sizeof (abuf));
2894 } else {
2895 host = (char *)inet_ntop(AF_INET6,
2896 &sin6->sin6_addr, abuf,
2897 sizeof (abuf));
2899 } else if (who->ss_family == AF_INET) {
2900 host = (char *)inet_ntop(AF_INET,
2901 &sin->sin_addr, abuf, sizeof (abuf));
2905 * Note that sockmod has to be removed since readstream assumes
2906 * a "raw" TPI endpoint (e.g. it uses getmsg).
2908 if (removemod(f, "sockmod") < 0)
2909 fatalperror(f, "couldn't remove sockmod", errno);
2911 encrypt_init();
2914 * Push the crypto module on the stream before 'telmod' so it
2915 * can encrypt/decrypt without interfering with telmod functionality
2916 * We must push it now because many of the crypto options negotiated
2917 * initially must be saved in the crypto module (via IOCTL calls).
2919 if (ioctl(f, I_PUSH, "cryptmod") < 0)
2920 fatalperror(f, "ioctl I_PUSH cryptmod", errno);
2922 cryptmod_fd = f;
2924 * gotta set the encryption clock now because it is often negotiated
2925 * immediately by the client, and if we wait till after we negotiate
2926 * auth, it will be out of whack with when the WILL/WONT ENCRYPT
2927 * option is received.
2929 settimer(getencr);
2932 * get terminal type.
2934 username[0] = '\0';
2935 len = sizeof (username);
2937 settimer(getterminal);
2938 settimer(getauth);
2940 * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
2942 auth_status = getauthtype(username, &len);
2944 * Exchange TELOPT_ENCRYPT options per RFC 2946
2946 getencrtype();
2947 getterminaltype();
2949 if (ioctl(f, I_PUSH, "telmod") < 0)
2950 fatalperror(f, "ioctl I_PUSH telmod", errno);
2953 * Make sure telmod will pass unrecognized IOCTLs to cryptmod
2955 passthru = 1;
2957 telnetmod.ic_cmd = CRYPTPASSTHRU;
2958 telnetmod.ic_timout = -1;
2959 telnetmod.ic_len = sizeof (uchar_t);
2960 telnetmod.ic_dp = (char *)&passthru;
2962 if (ioctl(f, I_STR, &telnetmod) < 0)
2963 fatal(f, "ioctl CRPASSTHRU failed\n");
2965 if (!ncc)
2966 netip = netibuf;
2969 * readstream will do a getmsg till it receives M_PROTO type
2970 * T_DATA_REQ from telnetmodopen(). This signals that all data
2971 * in-flight before telmod was pushed has been received at the
2972 * stream head.
2974 while ((nsize = readstream(f, netibuf, ncc + netip - netibuf)) > 0) {
2975 ncc += nsize;
2978 if (nsize < 0) {
2979 fatalperror(f, "readstream failed\n", errno);
2983 * open logindmux drivers and link them with network and ptm
2984 * file descriptors.
2986 if ((ptmfd = open("/dev/logindmux", O_RDWR)) == -1) {
2987 fatalperror(f, "open /dev/logindmux", errno);
2989 if ((netfd = open("/dev/logindmux", O_RDWR)) == -1) {
2990 fatalperror(f, "open /dev/logindmux", errno);
2993 if (ioctl(ptmfd, I_LINK, p) < 0)
2994 fatal(f, "ioctl I_LINK of /dev/ptmx failed\n");
2995 if (ioctl(netfd, I_LINK, f) < 0)
2996 fatal(f, "ioctl I_LINK of tcp connection failed\n");
2999 * Figure out the device number of ptm's mux fd, and pass that
3000 * to the net's mux.
3002 if (fstat(ptmfd, &buf) < 0) {
3003 fatalperror(f, "fstat ptmfd failed", errno);
3005 telnetp.dev = buf.st_rdev;
3006 telnetp.flag = 0;
3008 telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
3009 telnetmod.ic_timout = -1;
3010 telnetmod.ic_len = sizeof (struct protocol_arg);
3011 telnetmod.ic_dp = (char *)&telnetp;
3013 if (ioctl(netfd, I_STR, &telnetmod) < 0)
3014 fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
3017 * Figure out the device number of the net's mux fd, and pass that
3018 * to the ptm's mux.
3020 if (fstat(netfd, &buf) < 0) {
3021 fatalperror(f, "fstat netfd failed", errno);
3023 telnetp.dev = buf.st_rdev;
3024 telnetp.flag = 1;
3026 telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
3027 telnetmod.ic_timout = -1;
3028 telnetmod.ic_len = sizeof (struct protocol_arg);
3029 telnetmod.ic_dp = (char *)&telnetp;
3031 if (ioctl(ptmfd, I_STR, &telnetmod) < 0)
3032 fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
3034 net = netfd;
3035 master = ptmfd;
3036 cryptmod_fd = netfd;
3039 * Show banner that getty never gave, but
3040 * only if the user did not automatically authenticate.
3042 if (getenv("USER") == '\0' && auth_status < AUTH_USER)
3043 showbanner();
3046 * If the user automatically authenticated with Kerberos
3047 * we must set the service name that PAM will use. We
3048 * need to do it BEFORE the child fork so that 'cleanup'
3049 * in the parent can call the PAM cleanup stuff with the
3050 * same PAM service that /bin/login will use to authenticate
3051 * this session.
3053 if (auth_level >= 0 && auth_status >= AUTH_USER &&
3054 (AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) {
3055 (void) strcpy(pam_svc_name, "ktelnet");
3058 * Request to do suppress go ahead.
3060 * Send this before sending the TELOPT_ECHO stuff below because
3061 * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
3062 * that has them turn off local echo mode if SGA is not received first.
3063 * This also has the odd side-effect of causing the client to enable
3064 * encryption and then immediately disable it during the ECHO option
3065 * negotiations. Its just better to to SGA first now that we support
3066 * encryption.
3068 if (!myopts[TELOPT_SGA]) {
3069 dooption(TELOPT_SGA);
3073 * Pretend we got a DO ECHO from the client if we have not
3074 * yet negotiated the ECHO.
3076 if (!myopts[TELOPT_ECHO]) {
3077 dooption(TELOPT_ECHO);
3081 * Is the client side a 4.2 (NOT 4.3) system? We need to know this
3082 * because 4.2 clients are unable to deal with TCP urgent data.
3084 * To find out, we send out a "DO ECHO". If the remote system
3085 * answers "WILL ECHO" it is probably a 4.2 client, and we note
3086 * that fact ("WILL ECHO" ==> that the client will echo what
3087 * WE, the server, sends it; it does NOT mean that the client will
3088 * echo the terminal input).
3090 send_do(TELOPT_ECHO);
3091 remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;
3093 if ((pid = fork()) < 0)
3094 fatalperror(netfd, "fork", errno);
3095 if (pid)
3096 telnet(net, master);
3098 * The child process needs to be the session leader
3099 * and have the pty as its controlling tty. Thus we need
3100 * to re-open the slave side of the pty no without
3101 * the O_NOCTTY flag that we have been careful to
3102 * use up to this point.
3104 (void) setsid();
3106 tt = open(line, O_RDWR);
3107 if (tt < 0)
3108 fatalperror(netfd, line, errno);
3109 (void) close(netfd);
3110 (void) close(ptmfd);
3111 (void) close(f);
3112 (void) close(p);
3113 (void) close(t);
3114 if (tt != 0)
3115 (void) dup2(tt, 0);
3116 if (tt != 1)
3117 (void) dup2(tt, 1);
3118 if (tt != 2)
3119 (void) dup2(tt, 2);
3120 if (tt > 2)
3121 (void) close(tt);
3123 if (terminaltype)
3124 (void) local_setenv("TERM", terminaltype+5, 1);
3126 * -h : pass on name of host.
3127 * WARNING: -h is accepted by login if and only if
3128 * getuid() == 0.
3129 * -p : don't clobber the environment (so terminal type stays set).
3132 /* System V login expects a utmp entry to already be there */
3133 struct utmpx ut;
3134 (void) memset((char *)&ut, 0, sizeof (ut));
3135 (void) strncpy(ut.ut_user, ".telnet", sizeof (ut.ut_user));
3136 (void) strncpy(ut.ut_line, line, sizeof (ut.ut_line));
3137 ut.ut_pid = getpid();
3138 ut.ut_id[0] = 't';
3139 ut.ut_id[1] = (char)SC_WILDC;
3140 ut.ut_id[2] = (char)SC_WILDC;
3141 ut.ut_id[3] = (char)SC_WILDC;
3142 ut.ut_type = LOGIN_PROCESS;
3143 ut.ut_exit.e_termination = 0;
3144 ut.ut_exit.e_exit = 0;
3145 (void) time(&ut.ut_tv.tv_sec);
3146 if (makeutx(&ut) == NULL)
3147 syslog(LOG_INFO, "in.telnetd:\tmakeutx failed");
3151 * Load in the cached environment variables and either
3152 * set/unset them in the environment.
3154 for (next = envlist_head; next; ) {
3155 env = next;
3156 if (env->delete)
3157 (void) local_unsetenv(env->name);
3158 else
3159 (void) local_setenv(env->name, env->value, 1);
3160 free(env->name);
3161 free(env->value);
3162 next = env->next;
3163 free(env);
3166 if (!username || !username[0])
3167 auth_status = AUTH_REJECT; /* we dont know who this is */
3169 /* If the current auth status is less than the required level, exit */
3170 if (auth_status < auth_level) {
3171 fatal(net, "Authentication failed\n");
3172 exit(EXIT_FAILURE);
3176 * If AUTH_VALID (proper authentication REQUIRED and we have
3177 * a krb5_name), exec '/bin/login', make sure it uses the
3178 * correct PAM service name (pam_svc_name). If possible,
3179 * make sure the krb5 authenticated user's name (krb5_name)
3180 * is in the PAM REPOSITORY for krb5.
3182 if (auth_level >= 0 &&
3183 (auth_status == AUTH_VALID || auth_status == AUTH_USER) &&
3184 ((krb5_name != NULL) && strlen(krb5_name)) &&
3185 ((AuthenticatingUser != NULL) && strlen(AuthenticatingUser))) {
3186 (void) execl(LOGIN_PROGRAM, "login",
3187 "-p",
3188 "-d", slavename,
3189 "-h", host,
3190 "-u", krb5_name,
3191 "-s", pam_svc_name,
3192 "-R", KRB5_REPOSITORY_NAME,
3193 AuthenticatingUser, 0);
3194 } else if (auth_level >= 0 &&
3195 auth_status >= AUTH_USER &&
3196 (((AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) ||
3197 getenv("USER"))) {
3199 * If we only know the name but not the principal,
3200 * login will have to authenticate further.
3202 (void) execl(LOGIN_PROGRAM, "login",
3203 "-p",
3204 "-d", slavename,
3205 "-h", host,
3206 "-s", pam_svc_name, "--",
3207 (AuthenticatingUser != NULL ? AuthenticatingUser :
3208 getenv("USER")), 0);
3210 } else /* default, no auth. info available, login does it all */ {
3211 (void) execl(LOGIN_PROGRAM, "login",
3212 "-p", "-h", host, "-d", slavename, "--",
3213 getenv("USER"), 0);
3216 fatalperror(netfd, LOGIN_PROGRAM, errno);
3217 /*NOTREACHED*/
3220 static void
3221 fatal(int f, char *msg)
3223 char buf[BUFSIZ];
3225 (void) snprintf(buf, sizeof (buf), "telnetd: %s.\r\n", msg);
3226 (void) write(f, buf, strlen(buf));
3227 exit(EXIT_FAILURE);
3228 /*NOTREACHED*/
3231 static void
3232 fatalperror(int f, char *msg, int errnum)
3234 char buf[BUFSIZ];
3236 (void) snprintf(buf, sizeof (buf),
3237 "%s: %s\r\n", msg, strerror(errnum));
3238 fatal(f, buf);
3239 /*NOTREACHED*/
3243 * Main loop. Select from pty and network, and
3244 * hand data to telnet receiver finite state machine
3245 * when it receives telnet protocol. Regular data
3246 * flow between pty and network takes place through
3247 * inkernel telnet streams module (telmod).
3249 static void
3250 telnet(int net, int master)
3252 int on = 1;
3253 char mode;
3254 struct strioctl telnetmod;
3255 int nsize = 0;
3256 char binary_in = 0;
3257 char binary_out = 0;
3259 if (ioctl(net, FIONBIO, &on) == -1)
3260 syslog(LOG_INFO, "ioctl FIONBIO net: %m\n");
3261 if (ioctl(master, FIONBIO, &on) == -1)
3262 syslog(LOG_INFO, "ioctl FIONBIO pty p: %m\n");
3263 (void) signal(SIGTSTP, SIG_IGN);
3264 (void) signal(SIGCHLD, (void (*)())cleanup);
3265 (void) setpgrp();
3268 * Call telrcv() once to pick up anything received during
3269 * terminal type negotiation.
3271 telrcv();
3273 netflush();
3274 ptyflush();
3276 for (;;) {
3277 fd_set ibits, obits, xbits;
3278 int c;
3280 if (ncc < 0)
3281 break;
3283 FD_ZERO(&ibits);
3284 FD_ZERO(&obits);
3285 FD_ZERO(&xbits);
3288 * If we couldn't flush all our output to the network,
3289 * keep checking for when we can.
3291 if (nfrontp - nbackp)
3292 FD_SET(net, &obits);
3294 * Never look for input if there's still
3295 * stuff in the corresponding output buffer
3297 if (pfrontp - pbackp) {
3298 FD_SET(master, &obits);
3299 } else {
3300 FD_SET(net, &ibits);
3302 if (!SYNCHing) {
3303 FD_SET(net, &xbits);
3306 #define max(x, y) (((x) < (y)) ? (y) : (x))
3309 * make an ioctl to telnet module (net side) to send
3310 * binary mode of telnet daemon. binary_in and
3311 * binary_out are 0 if not in binary mode.
3313 if (binary_in != myopts[TELOPT_BINARY] ||
3314 binary_out != remopts[TELOPT_BINARY]) {
3316 mode = 0;
3317 if (myopts[TELOPT_BINARY] != OPT_NO)
3318 mode |= TEL_BINARY_IN;
3320 if (remopts[TELOPT_BINARY] != OPT_NO)
3321 mode |= TEL_BINARY_OUT;
3323 telnetmod.ic_cmd = TEL_IOC_MODE;
3324 telnetmod.ic_timout = -1;
3325 telnetmod.ic_len = 1;
3326 telnetmod.ic_dp = &mode;
3328 syslog(LOG_DEBUG, "TEL_IOC_MODE binary has changed\n");
3330 if (ioctl(net, I_STR, &telnetmod) < 0)
3331 fatal(net, "ioctl TEL_IOC_MODE failed\n");
3332 binary_in = myopts[TELOPT_BINARY];
3333 binary_out = remopts[TELOPT_BINARY];
3335 if (state == TS_DATA) {
3336 if ((nfrontp == nbackp) &&
3337 (pfrontp == pbackp)) {
3338 if (ioctl(net, I_NREAD, &nsize) < 0)
3339 fatalperror(net,
3340 "ioctl I_NREAD failed\n", errno);
3341 if (nsize)
3342 drainstream(nsize);
3345 * make an ioctl to reinsert remaining data at
3346 * streamhead. After this, ioctl reenables the
3347 * telnet lower put queue. This queue was
3348 * noenabled by telnet module after sending
3349 * protocol/urgent data to telnetd.
3352 telnetmod.ic_cmd = TEL_IOC_ENABLE;
3353 telnetmod.ic_timout = -1;
3354 if (ncc || nsize) {
3355 telnetmod.ic_len = ncc + nsize;
3356 telnetmod.ic_dp = netip;
3357 } else {
3358 telnetmod.ic_len = 0;
3359 telnetmod.ic_dp = NULL;
3361 if (ioctl(net, I_STR, &telnetmod) < 0)
3362 fatal(net, "ioctl TEL_IOC_ENABLE \
3363 failed\n");
3365 telmod_init_done = B_TRUE;
3367 netip = netibuf;
3368 (void) memset(netibuf, 0, netibufsize);
3370 ncc = 0;
3372 } else {
3374 * state not changed to TS_DATA and hence, more to read
3375 * send ioctl to get one more message block.
3377 telnetmod.ic_cmd = TEL_IOC_GETBLK;
3378 telnetmod.ic_timout = -1;
3379 telnetmod.ic_len = 0;
3380 telnetmod.ic_dp = NULL;
3382 if (ioctl(net, I_STR, &telnetmod) < 0)
3383 fatal(net, "ioctl TEL_IOC_GETBLK failed\n");
3386 if ((c = select(max(net, master) + 1, &ibits, &obits, &xbits,
3387 NULL)) < 1) {
3388 if (c == -1) {
3389 if (errno == EINTR) {
3390 continue;
3393 (void) sleep(5);
3394 continue;
3398 * Any urgent data?
3400 if (FD_ISSET(net, &xbits)) {
3401 SYNCHing = 1;
3405 * Something to read from the network...
3407 if (FD_ISSET(net, &ibits)) {
3408 ncc = read(net, netibuf, netibufsize);
3409 if (ncc < 0 && errno == EWOULDBLOCK)
3410 ncc = 0;
3411 else {
3412 if (ncc <= 0) {
3413 break;
3415 netip = netibuf;
3419 if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0)
3420 netflush();
3421 if (ncc > 0)
3422 telrcv();
3423 if (FD_ISSET(master, &obits) && (pfrontp - pbackp) > 0)
3424 ptyflush();
3426 cleanup(0);
3429 static void
3430 telrcv(void)
3432 int c;
3434 while (ncc > 0) {
3435 if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
3436 return;
3437 c = *netip & 0377;
3439 * Once we hit data, we want to transition back to
3440 * in-kernel processing. However, this code is shared
3441 * by getterminaltype()/ttloop() which run before the
3442 * in-kernel plumbing is available. So if we are still
3443 * processing the initial option negotiation, even TS_DATA
3444 * must be processed here.
3446 if (c != IAC && state == TS_DATA && init_neg_done) {
3447 break;
3449 netip++;
3450 ncc--;
3451 switch (state) {
3453 case TS_CR:
3454 state = TS_DATA;
3455 /* Strip off \n or \0 after a \r */
3456 if ((c == 0) || (c == '\n')) {
3457 break;
3459 /* FALLTHRU */
3461 case TS_DATA:
3462 if (c == IAC) {
3463 state = TS_IAC;
3464 break;
3466 if (inter > 0)
3467 break;
3469 * We map \r\n ==> \r, since
3470 * We now map \r\n ==> \r for pragmatic reasons.
3471 * Many client implementations send \r\n when
3472 * the user hits the CarriageReturn key.
3474 * We USED to map \r\n ==> \n, since \r\n says
3475 * that we want to be in column 1 of the next
3476 * line.
3478 if (c == '\r' && (myopts[TELOPT_BINARY] == OPT_NO)) {
3479 state = TS_CR;
3481 *pfrontp++ = c;
3482 break;
3484 case TS_IAC:
3485 switch (c) {
3488 * Send the process on the pty side an
3489 * interrupt. Do this with a NULL or
3490 * interrupt char; depending on the tty mode.
3492 case IP:
3493 interrupt();
3494 break;
3496 case BREAK:
3497 sendbrk();
3498 break;
3501 * Are You There?
3503 case AYT:
3504 write_data_len("\r\n[Yes]\r\n", 9);
3505 break;
3508 * Abort Output
3510 case AO: {
3511 struct ltchars tmpltc;
3513 ptyflush(); /* half-hearted */
3514 if (ioctl(pty, TIOCGLTC, &tmpltc) == -1)
3515 syslog(LOG_INFO,
3516 "ioctl TIOCGLTC: %m\n");
3517 if (tmpltc.t_flushc != '\377') {
3518 *pfrontp++ = tmpltc.t_flushc;
3520 netclear(); /* clear buffer back */
3521 write_data("%c%c", (uchar_t)IAC,
3522 (uchar_t)DM);
3524 neturg = nfrontp-1; /* off by one XXX */
3525 netflush();
3526 netflush(); /* XXX.sparker */
3527 break;
3531 * Erase Character and
3532 * Erase Line
3534 case EC:
3535 case EL: {
3536 struct sgttyb b;
3537 char ch;
3539 ptyflush(); /* half-hearted */
3540 if (ioctl(pty, TIOCGETP, &b) == -1)
3541 syslog(LOG_INFO,
3542 "ioctl TIOCGETP: %m\n");
3543 ch = (c == EC) ?
3544 b.sg_erase : b.sg_kill;
3545 if (ch != '\377') {
3546 *pfrontp++ = ch;
3548 break;
3552 * Check for urgent data...
3554 case DM:
3555 break;
3558 * Begin option subnegotiation...
3560 case SB:
3561 state = TS_SB;
3562 SB_CLEAR();
3563 continue;
3565 case WILL:
3566 state = TS_WILL;
3567 continue;
3569 case WONT:
3570 state = TS_WONT;
3571 continue;
3573 case DO:
3574 state = TS_DO;
3575 continue;
3577 case DONT:
3578 state = TS_DONT;
3579 continue;
3581 case IAC:
3582 *pfrontp++ = c;
3583 break;
3585 state = TS_DATA;
3586 break;
3587 case TS_SB:
3588 if (c == IAC) {
3589 state = TS_SE;
3590 } else {
3591 SB_ACCUM(c);
3593 break;
3594 case TS_SE:
3595 if (c != SE) {
3596 if (c != IAC) {
3597 SB_ACCUM((uchar_t)IAC);
3599 SB_ACCUM(c);
3600 state = TS_SB;
3602 } else {
3603 SB_TERM();
3604 suboption(); /* handle sub-option */
3605 state = TS_DATA;
3607 break;
3609 case TS_WILL:
3610 if (remopts[c] != OPT_YES)
3611 willoption(c);
3612 state = TS_DATA;
3613 continue;
3615 case TS_WONT:
3616 if (remopts[c] != OPT_NO)
3617 wontoption(c);
3618 state = TS_DATA;
3619 continue;
3621 case TS_DO:
3622 if (myopts[c] != OPT_YES)
3623 dooption(c);
3624 state = TS_DATA;
3625 continue;
3627 case TS_DONT:
3628 if (myopts[c] != OPT_NO) {
3629 dontoption(c);
3631 state = TS_DATA;
3632 continue;
3634 default:
3635 syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
3636 (void) printf("telnetd: panic state=%d\n", state);
3637 exit(EXIT_FAILURE);
3642 static void
3643 willoption(int option)
3645 uchar_t *fmt;
3646 boolean_t send_reply = B_TRUE;
3648 switch (option) {
3649 case TELOPT_BINARY:
3650 mode(O_RAW, 0);
3651 fmt = doopt;
3652 break;
3654 case TELOPT_ECHO:
3655 not42 = 0; /* looks like a 4.2 system */
3657 * Now, in a 4.2 system, to break them out of ECHOing
3658 * (to the terminal) mode, we need to send a "WILL ECHO".
3659 * Kludge upon kludge!
3661 if (myopts[TELOPT_ECHO] == OPT_YES) {
3662 dooption(TELOPT_ECHO);
3664 fmt = dont;
3665 break;
3666 case TELOPT_TTYPE:
3667 settimer(ttypeopt);
3668 goto common;
3670 case TELOPT_NAWS:
3671 settimer(nawsopt);
3672 goto common;
3674 case TELOPT_XDISPLOC:
3675 settimer(xdisplocopt);
3676 goto common;
3678 case TELOPT_NEW_ENVIRON:
3679 settimer(environopt);
3680 goto common;
3682 case TELOPT_AUTHENTICATION:
3683 settimer(authopt);
3684 if (remopts[option] == OPT_NO ||
3685 negotiate_auth_krb5 == 0)
3686 fmt = dont;
3687 else
3688 fmt = doopt;
3689 break;
3691 case TELOPT_OLD_ENVIRON:
3692 settimer(oenvironopt);
3693 goto common;
3694 common:
3695 if (remopts[option] == OPT_YES_BUT_ALWAYS_LOOK) {
3696 remopts[option] = OPT_YES;
3697 return;
3699 /*FALLTHRU*/
3700 case TELOPT_SGA:
3701 fmt = doopt;
3702 break;
3704 case TELOPT_TM:
3705 fmt = dont;
3706 break;
3708 case TELOPT_ENCRYPT:
3709 settimer(encropt); /* got response to do/dont */
3710 if (enc_debug)
3711 (void) fprintf(stderr,
3712 "RCVD IAC WILL TELOPT_ENCRYPT\n");
3713 if (krb5_privacy_allowed()) {
3714 fmt = doopt;
3715 if (sent_do_encrypt)
3716 send_reply = B_FALSE;
3717 else
3718 sent_do_encrypt = B_TRUE;
3719 } else {
3720 fmt = dont;
3722 break;
3724 default:
3725 fmt = dont;
3726 break;
3728 if (fmt == doopt) {
3729 remopts[option] = OPT_YES;
3730 } else {
3731 remopts[option] = OPT_NO;
3733 if (send_reply) {
3734 write_data((const char *)fmt, option);
3735 netflush();
3739 static void
3740 wontoption(int option)
3742 uchar_t *fmt;
3743 int send_reply = 1;
3745 switch (option) {
3746 case TELOPT_ECHO:
3747 not42 = 1; /* doesn't seem to be a 4.2 system */
3748 break;
3750 case TELOPT_BINARY:
3751 mode(0, O_RAW);
3752 break;
3754 case TELOPT_TTYPE:
3755 settimer(ttypeopt);
3756 break;
3758 case TELOPT_NAWS:
3759 settimer(nawsopt);
3760 break;
3762 case TELOPT_XDISPLOC:
3763 settimer(xdisplocopt);
3764 break;
3766 case TELOPT_NEW_ENVIRON:
3767 settimer(environopt);
3768 break;
3770 case TELOPT_OLD_ENVIRON:
3771 settimer(oenvironopt);
3772 break;
3774 case TELOPT_AUTHENTICATION:
3775 settimer(authopt);
3776 auth_finished(0, AUTH_REJECT);
3777 if (auth_debug)
3778 (void) fprintf(stderr,
3779 "RCVD WONT TELOPT_AUTHENTICATE\n");
3781 remopts[option] = OPT_NO;
3782 send_reply = 0;
3783 break;
3785 case TELOPT_ENCRYPT:
3786 if (enc_debug)
3787 (void) fprintf(stderr,
3788 "RCVD IAC WONT TELOPT_ENCRYPT\n");
3789 settimer(encropt); /* got response to will/wont */
3791 * Remote side cannot send encryption. No reply necessary
3792 * Treat this as if "IAC SB ENCRYPT END IAC SE" were
3793 * received (RFC 2946) and disable crypto.
3795 encrypt_end(TELNET_DIR_DECRYPT);
3796 send_reply = 0;
3797 break;
3800 fmt = dont;
3801 remopts[option] = OPT_NO;
3802 if (send_reply) {
3803 write_data((const char *)fmt, option);
3808 * We received an "IAC DO ..." message from the client, change our state
3809 * to OPT_YES.
3811 static void
3812 dooption(int option)
3814 uchar_t *fmt;
3815 boolean_t send_reply = B_TRUE;
3817 switch (option) {
3819 case TELOPT_TM:
3820 fmt = wont;
3821 break;
3823 case TELOPT_ECHO:
3824 mode(O_ECHO|O_CRMOD, 0);
3825 fmt = will;
3826 break;
3828 case TELOPT_BINARY:
3829 mode(O_RAW, 0);
3830 fmt = will;
3831 break;
3833 case TELOPT_SGA:
3834 fmt = will;
3835 break;
3837 case TELOPT_LOGOUT:
3839 * Options don't get much easier. Acknowledge the option,
3840 * and then clean up and exit.
3842 write_data((const char *)will, option);
3843 netflush();
3844 cleanup(0);
3845 /*NOTREACHED*/
3847 case TELOPT_ENCRYPT:
3848 if (enc_debug)
3849 (void) fprintf(stderr, "RCVD DO TELOPT_ENCRYPT\n");
3850 settimer(encropt);
3852 * We received a "DO". This indicates that the other side
3853 * wants us to encrypt our data (pending negotiatoin).
3854 * reply with "IAC WILL ENCRYPT" if we are able to send
3855 * encrypted data.
3857 if (krb5_privacy_allowed() && negotiate_encrypt) {
3858 fmt = will;
3859 if (sent_will_encrypt)
3860 send_reply = B_FALSE;
3861 else
3862 sent_will_encrypt = B_TRUE;
3863 /* return if we already sent "WILL ENCRYPT" */
3864 if (myopts[option] == OPT_YES)
3865 return;
3866 } else {
3867 fmt = wont;
3869 break;
3871 case TELOPT_AUTHENTICATION:
3872 if (auth_debug) {
3873 (void) fprintf(stderr,
3874 "RCVD DO TELOPT_AUTHENTICATION\n");
3877 * RFC 2941 - only the server can send
3878 * "DO TELOPT_AUTHENTICATION".
3879 * if a server receives this, it must respond with WONT...
3881 fmt = wont;
3882 break;
3884 default:
3885 fmt = wont;
3886 break;
3888 if (fmt == will) {
3889 myopts[option] = OPT_YES;
3890 } else {
3891 myopts[option] = OPT_NO;
3893 if (send_reply) {
3894 write_data((const char *)fmt, option);
3895 netflush();
3900 * We received an "IAC DONT ..." message from client.
3901 * Client does not agree with the option so act accordingly.
3903 static void
3904 dontoption(int option)
3906 int send_reply = 1;
3907 switch (option) {
3908 case TELOPT_ECHO:
3910 * we should stop echoing, since the client side will be doing
3911 * it, but keep mapping CR since CR-LF will be mapped to it.
3913 mode(0, O_ECHO);
3914 break;
3916 case TELOPT_ENCRYPT:
3917 if (enc_debug)
3918 (void) fprintf(stderr, "RCVD IAC DONT ENCRYPT\n");
3919 settimer(encropt);
3921 * Remote side cannot receive any encrypted data,
3922 * so dont send any. No reply necessary.
3924 send_reply = 0;
3925 break;
3927 default:
3928 break;
3931 myopts[option] = OPT_NO;
3933 if (send_reply) {
3934 write_data((const char *)wont, option);
3939 * suboption()
3941 * Look at the sub-option buffer, and try to be helpful to the other
3942 * side.
3945 static void
3946 suboption(void)
3948 int subchar;
3950 switch (subchar = SB_GET()) {
3951 case TELOPT_TTYPE: { /* Yaaaay! */
3952 static char terminalname[5+41] = "TERM=";
3954 settimer(ttypesubopt);
3956 if (SB_GET() != TELQUAL_IS) {
3957 return; /* ??? XXX but, this is the most robust */
3960 terminaltype = terminalname+strlen(terminalname);
3962 while (terminaltype < (terminalname + sizeof (terminalname) -
3963 1) && !SB_EOF()) {
3964 int c;
3966 c = SB_GET();
3967 if (isupper(c)) {
3968 c = tolower(c);
3970 *terminaltype++ = c; /* accumulate name */
3972 *terminaltype = 0;
3973 terminaltype = terminalname;
3974 break;
3977 case TELOPT_NAWS: {
3978 struct winsize ws;
3980 if (SB_EOF()) {
3981 return;
3983 ws.ws_col = SB_GET() << 8;
3984 if (SB_EOF()) {
3985 return;
3987 ws.ws_col |= SB_GET();
3988 if (SB_EOF()) {
3989 return;
3991 ws.ws_row = SB_GET() << 8;
3992 if (SB_EOF()) {
3993 return;
3995 ws.ws_row |= SB_GET();
3996 ws.ws_xpixel = 0; ws.ws_ypixel = 0;
3997 (void) ioctl(pty, TIOCSWINSZ, &ws);
3998 settimer(nawsopt);
3999 break;
4002 case TELOPT_XDISPLOC: {
4003 if (SB_EOF() || SB_GET() != TELQUAL_IS) {
4004 return;
4006 settimer(xdisplocsubopt);
4007 subpointer[SB_LEN()] = '\0';
4008 if ((new_env("DISPLAY", subpointer)) == 1)
4009 perror("malloc");
4010 break;
4013 case TELOPT_NEW_ENVIRON:
4014 case TELOPT_OLD_ENVIRON: {
4015 int c;
4016 char *cp, *varp, *valp;
4018 if (SB_EOF())
4019 return;
4020 c = SB_GET();
4021 if (c == TELQUAL_IS) {
4022 if (subchar == TELOPT_OLD_ENVIRON)
4023 settimer(oenvironsubopt);
4024 else
4025 settimer(environsubopt);
4026 } else if (c != TELQUAL_INFO) {
4027 return;
4030 if (subchar == TELOPT_NEW_ENVIRON) {
4031 while (!SB_EOF()) {
4032 c = SB_GET();
4033 if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
4034 break;
4036 } else
4038 while (!SB_EOF()) {
4039 c = SB_GET();
4040 if ((c == env_ovar) || (c == ENV_USERVAR))
4041 break;
4045 if (SB_EOF())
4046 return;
4048 cp = varp = (char *)subpointer;
4049 valp = 0;
4051 while (!SB_EOF()) {
4052 c = SB_GET();
4053 if (subchar == TELOPT_OLD_ENVIRON) {
4054 if (c == env_ovar)
4055 c = NEW_ENV_VAR;
4056 else if (c == env_ovalue)
4057 c = NEW_ENV_VALUE;
4059 switch (c) {
4061 case NEW_ENV_VALUE:
4062 *cp = '\0';
4063 cp = valp = (char *)subpointer;
4064 break;
4066 case NEW_ENV_VAR:
4067 case ENV_USERVAR:
4068 *cp = '\0';
4069 if (valp) {
4070 if ((new_env(varp, valp)) == 1) {
4071 perror("malloc");
4073 } else {
4074 (void) del_env(varp);
4076 cp = varp = (char *)subpointer;
4077 valp = 0;
4078 break;
4080 case ENV_ESC:
4081 if (SB_EOF())
4082 break;
4083 c = SB_GET();
4084 /* FALL THROUGH */
4085 default:
4086 *cp++ = c;
4087 break;
4090 *cp = '\0';
4091 if (valp) {
4092 if ((new_env(varp, valp)) == 1) {
4093 perror("malloc");
4095 } else {
4096 (void) del_env(varp);
4098 break;
4099 } /* end of case TELOPT_NEW_ENVIRON */
4101 case TELOPT_AUTHENTICATION:
4102 if (SB_EOF())
4103 break;
4104 switch (SB_GET()) {
4105 case TELQUAL_SEND:
4106 case TELQUAL_REPLY:
4108 * These are sent server only and cannot be sent by the
4109 * client.
4111 break;
4112 case TELQUAL_IS:
4113 if (auth_debug)
4114 (void) fprintf(stderr,
4115 "RCVD AUTHENTICATION IS "
4116 "(%d bytes)\n",
4117 SB_LEN());
4118 if (!auth_negotiated)
4119 auth_is((uchar_t *)subpointer, SB_LEN());
4120 break;
4121 case TELQUAL_NAME:
4122 if (auth_debug)
4123 (void) fprintf(stderr,
4124 "RCVD AUTHENTICATION NAME "
4125 "(%d bytes)\n",
4126 SB_LEN());
4127 if (!auth_negotiated)
4128 auth_name((uchar_t *)subpointer, SB_LEN());
4129 break;
4131 break;
4133 case TELOPT_ENCRYPT: {
4134 int c;
4135 if (SB_EOF())
4136 break;
4137 c = SB_GET();
4138 #ifdef ENCRYPT_NAMES
4139 if (enc_debug)
4140 (void) fprintf(stderr, "RCVD ENCRYPT %s\n",
4141 ENCRYPT_NAME(c));
4142 #endif /* ENCRYPT_NAMES */
4143 switch (c) {
4144 case ENCRYPT_SUPPORT:
4145 encrypt_support(subpointer, SB_LEN());
4146 break;
4147 case ENCRYPT_IS:
4148 encrypt_is((uchar_t *)subpointer, SB_LEN());
4149 break;
4150 case ENCRYPT_REPLY:
4151 (void) encrypt_reply(subpointer, SB_LEN());
4152 break;
4153 case ENCRYPT_START:
4154 encrypt_start();
4155 break;
4156 case ENCRYPT_END:
4157 encrypt_end(TELNET_DIR_DECRYPT);
4158 break;
4159 case ENCRYPT_REQSTART:
4160 encrypt_request_start();
4161 break;
4162 case ENCRYPT_REQEND:
4164 * We can always send an REQEND so that we cannot
4165 * get stuck encrypting. We should only get this
4166 * if we have been able to get in the correct mode
4167 * anyhow.
4169 encrypt_request_end();
4170 break;
4171 case ENCRYPT_ENC_KEYID:
4172 encrypt_enc_keyid(subpointer, SB_LEN());
4173 break;
4174 case ENCRYPT_DEC_KEYID:
4175 encrypt_dec_keyid(subpointer, SB_LEN());
4176 break;
4177 default:
4178 break;
4181 break;
4183 default:
4184 break;
4188 static void
4189 mode(int on, int off)
4191 struct termios tios;
4193 ptyflush();
4194 if (tcgetattr(pty, &tios) < 0)
4195 syslog(LOG_INFO, "tcgetattr: %m\n");
4197 if (on & O_RAW) {
4198 tios.c_cflag |= CS8;
4199 tios.c_iflag &= ~IUCLC;
4200 tios.c_lflag &= ~(XCASE|IEXTEN);
4202 if (off & O_RAW) {
4203 if ((tios.c_cflag & PARENB) != 0)
4204 tios.c_cflag &= ~CS8;
4205 tios.c_lflag |= IEXTEN;
4208 if (on & O_ECHO)
4209 tios.c_lflag |= ECHO;
4210 if (off & O_ECHO)
4211 tios.c_lflag &= ~ECHO;
4213 if (on & O_CRMOD) {
4214 tios.c_iflag |= ICRNL;
4215 tios.c_oflag |= ONLCR;
4218 * Because "O_CRMOD" will never be set in "off" we don't have to
4219 * handle this case here.
4222 if (tcsetattr(pty, TCSANOW, &tios) < 0)
4223 syslog(LOG_INFO, "tcsetattr: %m\n");
4227 * Send interrupt to process on other side of pty.
4228 * If it is in raw mode, just write NULL;
4229 * otherwise, write intr char.
4231 static void
4232 interrupt(void)
4234 struct sgttyb b;
4235 struct tchars tchars;
4237 ptyflush(); /* half-hearted */
4238 if (ioctl(pty, TIOCGETP, &b) == -1)
4239 syslog(LOG_INFO, "ioctl TIOCGETP: %m\n");
4240 if (b.sg_flags & O_RAW) {
4241 *pfrontp++ = '\0';
4242 return;
4244 *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4245 '\177' : tchars.t_intrc;
4249 * Send quit to process on other side of pty.
4250 * If it is in raw mode, just write NULL;
4251 * otherwise, write quit char.
4253 static void
4254 sendbrk(void)
4256 struct sgttyb b;
4257 struct tchars tchars;
4259 ptyflush(); /* half-hearted */
4260 (void) ioctl(pty, TIOCGETP, &b);
4261 if (b.sg_flags & O_RAW) {
4262 *pfrontp++ = '\0';
4263 return;
4265 *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4266 '\034' : tchars.t_quitc;
4269 static void
4270 ptyflush(void)
4272 int n;
4274 if ((n = pfrontp - pbackp) > 0)
4275 n = write(master, pbackp, n);
4276 if (n < 0)
4277 return;
4278 pbackp += n;
4279 if (pbackp == pfrontp)
4280 pbackp = pfrontp = ptyobuf;
4284 * nextitem()
4286 * Return the address of the next "item" in the TELNET data
4287 * stream. This will be the address of the next character if
4288 * the current address is a user data character, or it will
4289 * be the address of the character following the TELNET command
4290 * if the current address is a TELNET IAC ("I Am a Command")
4291 * character.
4294 static char *
4295 nextitem(char *current)
4297 if ((*current&0xff) != IAC) {
4298 return (current+1);
4300 switch (*(current+1)&0xff) {
4301 case DO:
4302 case DONT:
4303 case WILL:
4304 case WONT:
4305 return (current+3);
4306 case SB: /* loop forever looking for the SE */
4308 char *look = current+2;
4310 for (;;) {
4311 if ((*look++&0xff) == IAC) {
4312 if ((*look++&0xff) == SE) {
4313 return (look);
4318 default:
4319 return (current+2);
4325 * netclear()
4327 * We are about to do a TELNET SYNCH operation. Clear
4328 * the path to the network.
4330 * Things are a bit tricky since we may have sent the first
4331 * byte or so of a previous TELNET command into the network.
4332 * So, we have to scan the network buffer from the beginning
4333 * until we are up to where we want to be.
4335 * A side effect of what we do, just to keep things
4336 * simple, is to clear the urgent data pointer. The principal
4337 * caller should be setting the urgent data pointer AFTER calling
4338 * us in any case.
4340 static void
4341 netclear(void)
4343 char *thisitem, *next;
4344 char *good;
4345 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
4346 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
4348 thisitem = netobuf;
4350 while ((next = nextitem(thisitem)) <= nbackp) {
4351 thisitem = next;
4354 /* Now, thisitem is first before/at boundary. */
4356 good = netobuf; /* where the good bytes go */
4358 while (nfrontp > thisitem) {
4359 if (wewant(thisitem)) {
4360 int length;
4362 next = thisitem;
4363 do {
4364 next = nextitem(next);
4365 } while (wewant(next) && (nfrontp > next));
4366 length = next-thisitem;
4367 (void) memmove(good, thisitem, length);
4368 good += length;
4369 thisitem = next;
4370 } else {
4371 thisitem = nextitem(thisitem);
4375 nbackp = netobuf;
4376 nfrontp = good; /* next byte to be sent */
4377 neturg = 0;
4382 * netflush
4383 * Send as much data as possible to the network,
4384 * handling requests for urgent data.
4386 static void
4387 netflush(void)
4389 int n;
4391 if ((n = nfrontp - nbackp) > 0) {
4393 * if no urgent data, or if the other side appears to be an
4394 * old 4.2 client (and thus unable to survive TCP urgent data),
4395 * write the entire buffer in non-OOB mode.
4397 if ((neturg == 0) || (not42 == 0)) {
4398 n = write(net, nbackp, n); /* normal write */
4399 } else {
4400 n = neturg - nbackp;
4402 * In 4.2 (and 4.3) systems, there is some question
4403 * about what byte in a sendOOB operation is the "OOB"
4404 * data. To make ourselves compatible, we only send ONE
4405 * byte out of band, the one WE THINK should be OOB
4406 * (though we really have more the TCP philosophy of
4407 * urgent data rather than the Unix philosophy of OOB
4408 * data).
4410 if (n > 1) {
4411 /* send URGENT all by itself */
4412 n = write(net, nbackp, n-1);
4413 } else {
4414 /* URGENT data */
4415 n = send_oob(net, nbackp, n);
4419 if (n < 0) {
4420 if (errno == EWOULDBLOCK)
4421 return;
4422 /* should blow this guy away... */
4423 return;
4426 nbackp += n;
4428 if (nbackp >= neturg) {
4429 neturg = 0;
4431 if (nbackp == nfrontp) {
4432 nbackp = nfrontp = netobuf;
4436 /* ARGSUSED */
4437 static void
4438 cleanup(int signum)
4441 * If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
4442 * handle closing differently. We close "net" first and then
4443 * "master" in that order. We do close(net) first because
4444 * we have no other way to disconnect forwarding between the network
4445 * and master. So by issuing the close()'s we ensure that no further
4446 * data rises from TCP. A more complex fix would be adding proper
4447 * support for throwing a "stop" switch for forwarding data between
4448 * logindmux peers. It's possible to block in the close of the tty
4449 * while the network still receives data and the telmod module is
4450 * TEL_STOPPED. A denial-of-service attack generates this case,
4451 * see 4102102.
4454 if (!telmod_init_done) {
4455 (void) close(net);
4456 (void) close(master);
4458 rmut();
4460 exit(EXIT_FAILURE);
4463 static void
4464 rmut(void)
4466 pam_handle_t *pamh;
4467 struct utmpx *up;
4468 char user[sizeof (up->ut_user) + 1];
4469 char ttyn[sizeof (up->ut_line) + 1];
4470 char rhost[sizeof (up->ut_host) + 1];
4472 /* while cleaning up don't allow disruption */
4473 (void) signal(SIGCHLD, SIG_IGN);
4475 setutxent();
4476 while (up = getutxent()) {
4477 if (up->ut_pid == pid) {
4478 if (up->ut_type == DEAD_PROCESS) {
4480 * Cleaned up elsewhere.
4482 break;
4486 * call pam_close_session if login changed
4487 * the utmpx user entry from type LOGIN_PROCESS
4488 * to type USER_PROCESS, which happens
4489 * after pam_open_session is called.
4491 if (up->ut_type == USER_PROCESS) {
4492 (void) strlcpy(user, up->ut_user,
4493 sizeof (user));
4494 (void) strlcpy(ttyn, up->ut_line,
4495 sizeof (ttyn));
4496 (void) strlcpy(rhost, up->ut_host,
4497 sizeof (rhost));
4498 if ((pam_start("telnet", user, NULL, &pamh)) ==
4499 PAM_SUCCESS) {
4500 (void) pam_set_item(pamh, PAM_TTY,
4501 ttyn);
4502 (void) pam_set_item(pamh, PAM_RHOST,
4503 rhost);
4504 (void) pam_close_session(pamh, 0);
4505 (void) pam_end(pamh, PAM_SUCCESS);
4509 up->ut_type = DEAD_PROCESS;
4510 up->ut_exit.e_termination = WTERMSIG(0);
4511 up->ut_exit.e_exit = WEXITSTATUS(0);
4512 (void) time(&up->ut_tv.tv_sec);
4514 if (modutx(up) == NULL) {
4516 * Since modutx failed we'll
4517 * write out the new entry
4518 * ourselves.
4520 (void) pututxline(up);
4521 updwtmpx("wtmpx", up);
4523 break;
4527 endutxent();
4529 (void) signal(SIGCHLD, (void (*)())cleanup);
4532 static int
4533 readstream(int fd, char *buf, int offset)
4535 struct strbuf ctlbuf, datbuf;
4536 union T_primitives tpi;
4537 int ret = 0;
4538 int flags = 0;
4539 int bytes_avail, count;
4541 (void) memset((char *)&ctlbuf, 0, sizeof (ctlbuf));
4542 (void) memset((char *)&datbuf, 0, sizeof (datbuf));
4544 ctlbuf.buf = (char *)&tpi;
4545 ctlbuf.maxlen = sizeof (tpi);
4547 if (ioctl(fd, I_NREAD, &bytes_avail) < 0) {
4548 syslog(LOG_ERR, "I_NREAD returned error %m");
4549 return (-1);
4551 if (bytes_avail > netibufsize - offset) {
4552 count = netip - netibuf;
4553 netibuf = (char *)realloc(netibuf,
4554 (unsigned)netibufsize + bytes_avail);
4555 if (netibuf == NULL) {
4556 fatal(net, "netibuf realloc failed\n");
4558 netibufsize += bytes_avail;
4559 netip = netibuf + count;
4560 buf = netibuf;
4562 datbuf.buf = buf + offset;
4563 datbuf.maxlen = netibufsize;
4564 ret = getmsg(fd, &ctlbuf, &datbuf, &flags);
4565 if (ret < 0) {
4566 syslog(LOG_ERR, "getmsg returned -1, errno %d\n",
4567 errno);
4568 return (-1);
4570 if (ctlbuf.len <= 0) {
4571 return (datbuf.len);
4574 if (tpi.type == T_DATA_REQ) {
4575 return (0);
4578 if ((tpi.type == T_ORDREL_IND) || (tpi.type == T_DISCON_IND))
4579 cleanup(0);
4580 fatal(fd, "no data or protocol element recognized");
4581 return (0);
4584 static void
4585 drainstream(int size)
4587 int nbytes;
4588 int tsize;
4590 tsize = netip - netibuf;
4592 if ((tsize + ncc + size) > netibufsize) {
4593 if (!(netibuf = (char *)realloc(netibuf,
4594 (unsigned)tsize + ncc + size)))
4595 fatalperror(net, "netibuf realloc failed\n", errno);
4596 netibufsize = tsize + ncc + size;
4598 netip = netibuf + tsize;
4601 if ((nbytes = read(net, (char *)netip + ncc, size)) != size)
4602 syslog(LOG_ERR, "read %d bytes\n", nbytes);
4606 * TPI style replacement for socket send() primitive, so we don't require
4607 * sockmod to be on the stream.
4609 static int
4610 send_oob(int fd, char *ptr, int count)
4612 struct T_exdata_req exd_req;
4613 struct strbuf hdr, dat;
4614 int ret;
4616 exd_req.PRIM_type = T_EXDATA_REQ;
4617 exd_req.MORE_flag = 0;
4619 hdr.buf = (char *)&exd_req;
4620 hdr.len = sizeof (exd_req);
4622 dat.buf = ptr;
4623 dat.len = count;
4625 ret = putmsg(fd, &hdr, &dat, 0);
4626 if (ret == 0) {
4627 ret = count;
4629 return (ret);
4634 * local_setenv --
4635 * Set the value of the environmental variable "name" to be
4636 * "value". If rewrite is set, replace any current value.
4638 static int
4639 local_setenv(const char *name, const char *value, int rewrite)
4641 static int alloced; /* if allocated space before */
4642 char *c;
4643 int l_value, offset;
4646 * Do not allow environment variables which begin with LD_ to be
4647 * inserted into the environment. While normally the dynamic linker
4648 * protects the login program, that is based on the assumption hostile
4649 * invocation of login are from non-root users. However, since telnetd
4650 * runs as root, this cannot be utilized. So instead we simply
4651 * prevent LD_* from being inserted into the environment.
4652 * This also applies to other environment variables that
4653 * are to be ignored in setugid apps.
4654 * Note that at this point name can contain '='!
4655 * Also, do not allow TTYPROMPT to be passed along here.
4657 if (strncmp(name, "LD_", 3) == 0 ||
4658 strncmp(name, "NLSPATH", 7) == 0 ||
4659 (strncmp(name, "TTYPROMPT", 9) == 0 &&
4660 (name[9] == '\0' || name[9] == '='))) {
4661 return (-1);
4663 if (*value == '=') /* no `=' in value */
4664 ++value;
4665 l_value = strlen(value);
4666 if ((c = __findenv(name, &offset))) { /* find if already exists */
4667 if (!rewrite)
4668 return (0);
4669 if ((int)strlen(c) >= l_value) { /* old larger; copy over */
4670 while (*c++ = *value++)
4672 return (0);
4674 } else { /* create new slot */
4675 int cnt;
4676 char **p;
4678 for (p = environ, cnt = 0; *p; ++p, ++cnt)
4680 if (alloced) { /* just increase size */
4681 environ = (char **)realloc((char *)environ,
4682 (size_t)(sizeof (char *) * (cnt + 2)));
4683 if (!environ)
4684 return (-1);
4685 } else { /* get new space */
4686 alloced = 1; /* copy old entries into it */
4687 p = (char **)malloc((size_t)(sizeof (char *)*
4688 (cnt + 2)));
4689 if (!p)
4690 return (-1);
4691 (void) memcpy(p, environ, cnt * sizeof (char *));
4692 environ = p;
4694 environ[cnt + 1] = NULL;
4695 offset = cnt;
4697 for (c = (char *)name; *c && *c != '='; ++c) /* no `=' in name */
4699 if (!(environ[offset] = /* name + `=' + value */
4700 malloc((size_t)((int)(c - name) + l_value + 2))))
4701 return (-1);
4702 for (c = environ[offset]; ((*c = *name++) != 0) && (*c != '='); ++c)
4704 for (*c++ = '='; *c++ = *value++; )
4706 return (0);
4710 * local_unsetenv(name) --
4711 * Delete environmental variable "name".
4713 static void
4714 local_unsetenv(const char *name)
4716 char **p;
4717 int offset;
4719 while (__findenv(name, &offset)) /* if set multiple times */
4720 for (p = &environ[offset]; ; ++p)
4721 if ((*p = *(p + 1)) == 0)
4722 break;
4726 * __findenv --
4727 * Returns pointer to value associated with name, if any, else NULL.
4728 * Sets offset to be the offset of the name/value combination in the
4729 * environmental array, for use by local_setenv() and local_unsetenv().
4730 * Explicitly removes '=' in argument name.
4732 static char *
4733 __findenv(const char *name, int *offset)
4735 extern char **environ;
4736 int len;
4737 const char *np;
4738 char **p, *c;
4740 if (name == NULL || environ == NULL)
4741 return (NULL);
4742 for (np = name; *np && *np != '='; ++np)
4743 continue;
4744 len = np - name;
4745 for (p = environ; (c = *p) != NULL; ++p)
4746 if (strncmp(c, name, len) == 0 && c[len] == '=') {
4747 *offset = p - environ;
4748 return (c + len + 1);
4750 return (NULL);
4753 static void
4754 showbanner(void)
4756 char *cp;
4757 char evalbuf[BUFSIZ];
4759 if (defopen(defaultfile) == 0) {
4760 int flags;
4762 /* ignore case */
4763 flags = defcntl(DC_GETFLAGS, 0);
4764 TURNOFF(flags, DC_CASE);
4765 (void) defcntl(DC_SETFLAGS, flags);
4766 if (cp = defread(bannervar)) {
4767 FILE *fp;
4769 if (strlen(cp) + strlen("eval echo '") + strlen("'\n")
4770 + 1 < sizeof (evalbuf)) {
4771 (void) strlcpy(evalbuf, "eval echo '",
4772 sizeof (evalbuf));
4773 (void) strlcat(evalbuf, cp, sizeof (evalbuf));
4774 (void) strlcat(evalbuf, "'\n",
4775 sizeof (evalbuf));
4777 if (fp = popen(evalbuf, "r")) {
4778 char buf[BUFSIZ];
4779 size_t size;
4782 * Pipe I/O atomicity guarantees we
4783 * need only one read.
4785 if ((size = fread(buf, 1,
4786 sizeof (buf) - 1,
4787 fp)) != 0) {
4788 char *p;
4789 buf[size] = '\0';
4790 p = strrchr(buf, '\n');
4791 if (p != NULL)
4792 *p = '\0';
4793 if (strlen(buf)) {
4794 map_banner(buf);
4795 netflush();
4798 (void) pclose(fp);
4799 /* close default file */
4800 (void) defopen(NULL);
4801 return;
4805 (void) defopen(NULL); /* close default file */
4808 defbanner();
4809 netflush();
4812 static void
4813 map_banner(char *p)
4815 char *q;
4818 * Map the banner: "\n" -> "\r\n" and "\r" -> "\r\0"
4820 for (q = nfrontp; p && *p && q < nfrontp + sizeof (netobuf) - 1; )
4821 if (*p == '\n') {
4822 *q++ = '\r';
4823 *q++ = '\n';
4824 p++;
4825 } else if (*p == '\r') {
4826 *q++ = '\r';
4827 *q++ = '\0';
4828 p++;
4829 } else
4830 *q++ = *p++;
4832 nfrontp += q - netobuf;
4836 * Show banner that getty never gave. By default, this is `uname -sr`.
4838 * The banner includes some null's (for TELNET CR disambiguation),
4839 * so we have to be somewhat complicated.
4841 static void
4842 defbanner(void)
4844 struct utsname u;
4847 * Dont show this if the '-h' option was present
4849 if (!show_hostinfo)
4850 return;
4852 if (uname(&u) == -1)
4853 return;
4855 write_data_len((const char *) BANNER1, sizeof (BANNER1) - 1);
4856 write_data_len(u.sysname, strlen(u.sysname));
4857 write_data_len(" ", 1);
4858 write_data_len(u.release, strlen(u.release));
4859 write_data_len((const char *)BANNER2, sizeof (BANNER2) - 1);
4863 * Verify that the named module is at the top of the stream
4864 * and then pop it off.
4866 static int
4867 removemod(int f, char *modname)
4869 char topmodname[BUFSIZ];
4871 if (ioctl(f, I_LOOK, topmodname) < 0)
4872 return (-1);
4873 if (strcmp(modname, topmodname) != 0) {
4874 errno = ENXIO;
4875 return (-1);
4877 if (ioctl(f, I_POP, 0) < 0)
4878 return (-1);
4879 return (0);
4882 static void
4883 write_data(const char *format, ...)
4885 va_list args;
4886 int len;
4887 char argp[BUFSIZ];
4889 va_start(args, format);
4891 if ((len = vsnprintf(argp, sizeof (argp), format, args)) == -1)
4892 return;
4894 write_data_len(argp, len);
4895 va_end(args);
4898 static void
4899 write_data_len(const char *buf, int len)
4901 int remaining, copied;
4903 remaining = BUFSIZ - (nfrontp - netobuf);
4904 while (len > 0) {
4906 * If there's not enough space in netobuf then
4907 * try to make some.
4909 if ((len > BUFSIZ ? BUFSIZ : len) > remaining) {
4910 netflush();
4911 remaining = BUFSIZ - (nfrontp - netobuf);
4913 /* Copy as much as we can */
4914 copied = remaining > len ? len : remaining;
4915 (void) memmove(nfrontp, buf, copied);
4916 nfrontp += copied;
4917 len -= copied;
4918 remaining -= copied;
4919 buf += copied;