cmd-inet/usr.sbin: remove -Wno-implicit-function-declaration
[unleashed.git] / usr / src / cmd / cmd-inet / usr.sbin / in.telnetd.c
blob6c9d50a2374560581a6068d79a2e70166ced58e4
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>
99 #define TELNETD_OPTS "Ss:a:dEXUhR:M:"
100 #ifdef DEBUG
101 #define DEBUG_OPTS "p:e"
102 #else
103 #define DEBUG_OPTS ""
104 #endif /* DEBUG */
106 #define OPT_NO 0 /* won't do this option */
107 #define OPT_YES 1 /* will do this option */
108 #define OPT_YES_BUT_ALWAYS_LOOK 2
109 #define OPT_NO_BUT_ALWAYS_LOOK 3
111 #define MAXOPTLEN 256
112 #define MAXUSERNAMELEN 256
114 static char remopts[MAXOPTLEN];
115 static char myopts[MAXOPTLEN];
116 static uchar_t doopt[] = { (uchar_t)IAC, (uchar_t)DO, '%', 'c', 0 };
117 static uchar_t dont[] = { (uchar_t)IAC, (uchar_t)DONT, '%', 'c', 0 };
118 static uchar_t will[] = { (uchar_t)IAC, (uchar_t)WILL, '%', 'c', 0 };
119 static uchar_t wont[] = { (uchar_t)IAC, (uchar_t)WONT, '%', 'c', 0 };
121 * I/O data buffers, pointers, and counters.
123 static char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
125 static char *netibuf, *netip;
126 static int netibufsize;
128 #define NIACCUM(c) { *netip++ = c; \
129 ncc++; \
132 static char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
133 static char *neturg = 0; /* one past last bye of urgent data */
134 /* the remote system seems to NOT be an old 4.2 */
135 static int not42 = 1;
136 static char defaultfile[] = "/etc/default/telnetd";
137 static char bannervar[] = "BANNER=";
139 static char BANNER1[] = "\r\n\r\n";
140 static char BANNER2[] = "\r\n\r\0\r\n\r\0";
143 * buffer for sub-options - enlarged to 4096 to handle credentials
144 * from AUTH options
146 static char subbuffer[4096], *subpointer = subbuffer, *subend = subbuffer;
147 #define SB_CLEAR() subpointer = subbuffer;
148 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
149 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof (subbuffer))) { \
150 *subpointer++ = (c); \
152 #define SB_GET() ((*subpointer++)&0xff)
153 #define SB_EOF() (subpointer >= subend)
154 #define SB_LEN() (subend - subpointer)
156 #define MAXERRSTRLEN 1024
157 #define MAXPRINCLEN 256
159 extern uint_t kwarn_add_warning(char *, int);
160 extern uint_t kwarn_del_warning(char *);
162 static boolean_t auth_debug = 0;
163 static boolean_t negotiate_auth_krb5 = 1;
164 static boolean_t auth_negotiated = 0;
165 static int auth_status = 0;
166 static int auth_level = 0;
167 static char *AuthenticatingUser = NULL;
168 static char *krb5_name = NULL;
170 static krb5_address rsaddr = { 0, 0, 0, NULL };
171 static krb5_address rsport = { 0, 0, 0, NULL };
173 static krb5_context telnet_context = 0;
174 static krb5_auth_context auth_context = 0;
176 /* telnetd gets session key from here */
177 static krb5_ticket *ticket = NULL;
178 static krb5_keyblock *session_key = NULL;
179 static char *telnet_srvtab = NULL;
181 typedef struct {
182 uchar_t AuthName;
183 uchar_t AuthHow;
184 char *AuthString;
185 } AuthInfo;
187 static AuthInfo auth_list[] = {
188 {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL |
189 AUTH_ENCRYPT_ON, "KRB5 MUTUAL CRYPTO"},
190 {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL,
191 "KRB5 MUTUAL" },
192 {AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_ONE_WAY,
193 "KRB5 1-WAY" },
194 {0, 0, "NONE"}
197 static AuthInfo NoAuth = {0, 0, NULL};
199 static AuthInfo *authenticated = NULL;
201 #define PREAMBLE_SIZE 5 /* for auth_reply_str allocation */
202 #define POSTAMBLE_SIZE 5
203 #define STR_DATA_LEN(len) ((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE)
205 static void auth_name(uchar_t *, int);
206 static void auth_is(uchar_t *, int);
208 #define NO_ENCRYPTION 0x00
209 #define SEND_ENCRYPTED 0x01
210 #define RECV_ENCRYPTED 0x02
211 #define ENCRYPT_BOTH_WAYS (SEND_ENCRYPTED | RECV_ENCRYPTED)
213 static telnet_enc_data_t encr_data;
214 static boolean_t negotiate_encrypt = B_TRUE;
215 static boolean_t sent_encrypt_support = B_FALSE;
216 static boolean_t sent_will_encrypt = B_FALSE;
217 static boolean_t sent_do_encrypt = B_FALSE;
218 static boolean_t enc_debug = 0;
220 static void encrypt_session_key(Session_Key *key, cipher_info_t *cinfo);
221 static int encrypt_send_encrypt_is();
223 extern void mit_des_fixup_key_parity(Block);
224 extern int krb5_setenv(const char *, const char *, int);
225 /* need to know what FD to use to talk to the crypto module */
226 static int cryptmod_fd = -1;
228 #define LOGIN_PROGRAM "/bin/login"
231 * State for recv fsm
233 #define TS_DATA 0 /* base state */
234 #define TS_IAC 1 /* look for double IAC's */
235 #define TS_CR 2 /* CR-LF ->'s CR */
236 #define TS_SB 3 /* throw away begin's... */
237 #define TS_SE 4 /* ...end's (suboption negotiation) */
238 #define TS_WILL 5 /* will option negotiation */
239 #define TS_WONT 6 /* wont " */
240 #define TS_DO 7 /* do " */
241 #define TS_DONT 8 /* dont " */
243 static int ncc;
244 static int master; /* master side of pty */
245 static int pty; /* side of pty that gets ioctls */
246 static int net;
247 static int inter;
248 extern char **environ;
249 static char *line;
250 static int SYNCHing = 0; /* we are in TELNET SYNCH mode */
251 static int state = TS_DATA;
253 static int env_ovar = -1; /* XXX.sparker */
254 static int env_ovalue = -1; /* XXX.sparker */
255 static char pam_svc_name[64];
256 static boolean_t telmod_init_done = B_FALSE;
258 static void doit(int, struct sockaddr_storage *);
259 static void willoption(int);
260 static void wontoption(int);
261 static void dooption(int);
262 static void dontoption(int);
263 static void fatal(int, char *);
264 static void fatalperror(int, char *, int);
265 static void mode(int, int);
266 static void interrupt(void);
267 static void drainstream(int);
268 static int readstream(int, char *, int);
269 static int send_oob(int fd, char *ptr, int count);
270 static int local_setenv(const char *name, const char *value, int rewrite);
271 static void local_unsetenv(const char *name);
272 static void suboption(void);
273 static int removemod(int f, char *modname);
274 static void willoption(int option);
275 static void wontoption(int option);
276 static void dooption(int option);
277 static void dontoption(int option);
278 static void write_data(const char *, ...);
279 static void write_data_len(const char *, int);
280 static void rmut(void);
281 static void cleanup(int);
282 static void telnet(int, int);
283 static void telrcv(void);
284 static void sendbrk(void);
285 static void ptyflush(void);
286 static void netclear(void);
287 static void netflush(void);
288 static void showbanner(void);
289 static void map_banner(char *);
290 static void defbanner(void);
291 static void ttloop(void);
294 * The env_list linked list is used to store the environment variables
295 * until the final exec of login. A malevolent client might try to
296 * send an environment variable intended to affect the telnet daemon's
297 * execution. Right now the BANNER expansion is the only instance.
298 * Note that it is okay to pass the environment variables to login
299 * because login protects itself against environment variables mischief.
302 struct envlist {
303 struct envlist *next;
304 char *name;
305 char *value;
306 int delete;
309 static struct envlist *envlist_head = NULL;
312 * The following are some clocks used to decide how to interpret
313 * the relationship between various variables.
316 static struct {
318 system, /* what the current time is */
319 echotoggle, /* last time user entered echo character */
320 modenegotiated, /* last time operating mode negotiated */
321 didnetreceive, /* last time we read data from network */
322 ttypeopt, /* ttype will/won't received */
323 ttypesubopt, /* ttype subopt is received */
324 getterminal, /* time started to get terminal information */
325 xdisplocopt, /* xdisploc will/wont received */
326 xdisplocsubopt, /* xdisploc suboption received */
327 nawsopt, /* window size will/wont received */
328 nawssubopt, /* window size received */
329 environopt, /* environment option will/wont received */
330 oenvironopt, /* "old" environ option will/wont received */
331 environsubopt, /* environment option suboption received */
332 oenvironsubopt, /* "old environ option suboption received */
333 gotDM; /* when did we last see a data mark */
335 int getauth;
336 int authopt; /* Authentication option negotiated */
337 int authdone;
339 int getencr;
340 int encropt;
341 int encr_support;
342 } clocks;
344 static int init_neg_done = 0;
345 static boolean_t resolve_hostname = 0;
346 static boolean_t show_hostinfo = 1;
348 #define settimer(x) (clocks.x = ++clocks.system)
349 #define sequenceIs(x, y) (clocks.x < clocks.y)
351 static void send_will(int);
352 static void send_wont(int);
353 static void send_do(int);
354 static char *__findenv(const char *name, int *offset);
356 /* ARGSUSED */
357 static void
358 auth_finished(AuthInfo *ap, int result)
360 if ((authenticated = ap) == NULL) {
361 authenticated = &NoAuth;
362 if (myopts[TELOPT_ENCRYPT] == OPT_YES)
363 send_wont(TELOPT_ENCRYPT);
364 myopts[TELOPT_ENCRYPT] = remopts[TELOPT_ENCRYPT] = OPT_NO;
365 encr_data.encrypt.autoflag = 0;
366 } else if (result != AUTH_REJECT &&
367 myopts[TELOPT_ENCRYPT] == OPT_YES &&
368 remopts[TELOPT_ENCRYPT] == OPT_YES) {
371 * Authentication successful, so we have a session key, and
372 * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT.
374 * Can't have sent ENCRYPT SUPPORT yet! And if we're sending it
375 * now it's really only because we did the DO ENCRYPT/WILL
376 * ENCRYPT dance before authentication, which is ok, but not too
377 * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT
378 * dance if authentication fails, though clients typically just
379 * don't care.
381 write_data("%c%c%c%c%c%c%c",
382 (uchar_t)IAC,
383 (uchar_t)SB,
384 (uchar_t)TELOPT_ENCRYPT,
385 (uchar_t)ENCRYPT_SUPPORT,
386 (uchar_t)TELOPT_ENCTYPE_DES_CFB64,
387 (uchar_t)IAC,
388 (uchar_t)SE);
390 netflush();
392 sent_encrypt_support = B_TRUE;
394 if (enc_debug)
395 (void) fprintf(stderr,
396 "SENT ENCRYPT SUPPORT\n");
398 (void) encrypt_send_encrypt_is();
401 auth_status = result;
403 settimer(authdone);
406 static void
407 reply_to_client(AuthInfo *ap, int type, void *data, int len)
409 uchar_t reply[BUFSIZ];
410 uchar_t *p = reply;
411 uchar_t *cd = (uchar_t *)data;
413 if (len == -1 && data != NULL)
414 len = strlen((char *)data);
415 else if (len > (sizeof (reply) - 9)) {
416 syslog(LOG_ERR,
417 "krb5 auth reply length too large (%d)", len);
418 if (auth_debug)
419 (void) fprintf(stderr,
420 "krb5 auth reply length too large (%d)\n",
421 len);
422 return;
423 } else if (data == NULL)
424 len = 0;
426 *p++ = IAC;
427 *p++ = SB;
428 *p++ = TELOPT_AUTHENTICATION;
429 *p++ = AUTHTYPE_KERBEROS_V5;
430 *p++ = ap->AuthName;
431 *p++ = ap->AuthHow; /* MUTUAL, ONE-WAY, etc */
432 *p++ = type; /* RESPONSE or ACCEPT */
433 while (len-- > 0) {
434 if ((*p++ = *cd++) == IAC)
435 *p++ = IAC;
437 *p++ = IAC;
438 *p++ = SE;
440 /* queue the data to be sent */
441 write_data_len((const char *)reply, p-reply);
443 #if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\
444 defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES)
445 if (auth_debug) {
446 (void) fprintf(stderr, "SENT TELOPT_AUTHENTICATION REPLY "
447 "%s %s|%s %s\n",
448 AUTHTYPE_NAME(ap->AuthName),
449 AUTHWHO_NAME(ap->AuthHow & AUTH_WHO_MASK),
450 AUTHHOW_NAME(ap->AuthHow & AUTH_HOW_MASK),
451 AUTHRSP_NAME(type));
453 #endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */
455 netflush();
458 /* Decode, decrypt and store the forwarded creds in the local ccache. */
459 static krb5_error_code
460 rd_and_store_forwarded_creds(krb5_context context,
461 krb5_auth_context auth_context,
462 krb5_data *inbuf, krb5_ticket *ticket,
463 char *username)
465 krb5_creds **creds;
466 krb5_error_code retval;
467 char ccname[MAXPATHLEN];
468 krb5_ccache ccache = NULL;
469 char *client_name = NULL;
471 if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))
472 return (retval);
474 (void) sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", getpid());
475 (void) krb5_setenv("KRB5CCNAME", ccname, 1);
477 if ((retval = krb5_cc_default(context, &ccache)))
478 goto cleanup;
480 if ((retval = krb5_cc_initialize(context, ccache,
481 ticket->enc_part2->client)) != 0)
482 goto cleanup;
484 if ((retval = krb5_cc_store_cred(context, ccache, *creds)) != 0)
485 goto cleanup;
487 if ((retval = krb5_cc_close(context, ccache)) != 0)
488 goto cleanup;
490 /* Register with ktkt_warnd(8) */
491 if ((retval = krb5_unparse_name(context, (*creds)->client,
492 &client_name)) != 0)
493 goto cleanup;
494 (void) kwarn_del_warning(client_name);
495 if (kwarn_add_warning(client_name, (*creds)->times.endtime) != 0) {
496 syslog(LOG_AUTH|LOG_NOTICE,
497 "rd_and_store_forwarded_creds: kwarn_add_warning"
498 " failed: ktkt_warnd(8) down? ");
499 if (auth_debug)
500 (void) fprintf(stderr,
501 "kwarn_add_warning failed:"
502 " ktkt_warnd(8) down?\n");
504 free(client_name);
505 client_name = NULL;
507 if (username != NULL) {
509 * This verifies that the user is valid on the local system,
510 * maps the username from KerberosV5 to unix,
511 * and moves the KRB5CCNAME file to the correct place
512 * /tmp/krb5cc_[uid] with correct ownership (0600 uid gid).
514 * NOTE: the user must be in the gsscred table in order to map
515 * from KRB5 to Unix.
517 (void) krb5_kuserok(context, ticket->enc_part2->client,
518 username);
520 if (auth_debug)
521 (void) fprintf(stderr,
522 "Successfully stored forwarded creds\n");
524 cleanup:
525 krb5_free_creds(context, *creds);
526 return (retval);
529 static void
530 kerberos5_is(AuthInfo *ap, uchar_t *data, int cnt)
532 krb5_error_code err = 0;
533 krb5_principal server;
534 krb5_keyblock *newkey = NULL;
535 krb5_keytab keytabid = 0;
536 krb5_data outbuf;
537 krb5_data inbuf;
538 krb5_authenticator *authenticator;
539 char errbuf[MAXERRSTRLEN];
540 char *name;
541 krb5_data auth;
543 Session_Key skey;
545 if (cnt-- < 1)
546 return;
547 switch (*data++) {
548 case KRB_AUTH:
549 auth.data = (char *)data;
550 auth.length = cnt;
552 if (auth_context == NULL) {
553 err = krb5_auth_con_init(telnet_context, &auth_context);
554 if (err)
555 syslog(LOG_ERR,
556 "Error getting krb5 auth "
557 "context: %s", error_message(err));
559 if (!err) {
560 krb5_rcache rcache;
562 err = krb5_auth_con_getrcache(telnet_context,
563 auth_context,
564 &rcache);
565 if (!err && !rcache) {
566 err = krb5_sname_to_principal(telnet_context,
567 0, 0,
568 KRB5_NT_SRV_HST,
569 &server);
570 if (!err) {
571 err = krb5_get_server_rcache(
572 telnet_context,
573 krb5_princ_component(
574 telnet_context,
575 server, 0),
576 &rcache);
578 krb5_free_principal(telnet_context,
579 server);
582 if (err)
583 syslog(LOG_ERR,
584 "Error allocating krb5 replay cache: %s",
585 error_message(err));
586 else {
587 err = krb5_auth_con_setrcache(telnet_context,
588 auth_context,
589 rcache);
590 if (err)
591 syslog(LOG_ERR,
592 "Error creating krb5 "
593 "replay cache: %s",
594 error_message(err));
597 if (!err && telnet_srvtab != NULL)
598 err = krb5_kt_resolve(telnet_context,
599 telnet_srvtab, &keytabid);
600 if (!err)
601 err = krb5_rd_req(telnet_context, &auth_context, &auth,
602 NULL, keytabid, NULL, &ticket);
603 if (err) {
604 (void) snprintf(errbuf, sizeof (errbuf),
605 "Error reading krb5 auth information:"
606 " %s", error_message(err));
607 goto errout;
611 * Verify that the correct principal was used
613 if (krb5_princ_component(telnet_context,
614 ticket->server, 0)->length < MAXPRINCLEN) {
615 char princ[MAXPRINCLEN];
616 (void) strncpy(princ,
617 krb5_princ_component(telnet_context,
618 ticket->server, 0)->data,
619 krb5_princ_component(telnet_context,
620 ticket->server, 0)->length);
621 princ[krb5_princ_component(telnet_context,
622 ticket->server, 0)->length] = '\0';
623 if (strcmp("host", princ)) {
624 if (strlen(princ) < sizeof (errbuf) - 39) {
625 (void) snprintf(errbuf, sizeof (errbuf),
626 "incorrect service "
627 "name: \"%s\" != "
628 "\"host\"",
629 princ);
630 } else {
631 (void) strncpy(errbuf,
632 "incorrect service "
633 "name: principal != "
634 "\"host\"",
635 sizeof (errbuf));
637 goto errout;
639 } else {
640 (void) strlcpy(errbuf, "service name too long",
641 sizeof (errbuf));
642 goto errout;
645 err = krb5_auth_con_getauthenticator(telnet_context,
646 auth_context,
647 &authenticator);
648 if (err) {
649 (void) snprintf(errbuf, sizeof (errbuf),
650 "Failed to get authenticator: %s",
651 error_message(err));
652 goto errout;
654 if ((ap->AuthHow & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
655 !authenticator->checksum) {
656 (void) strlcpy(errbuf,
657 "authenticator is missing checksum",
658 sizeof (errbuf));
659 goto errout;
661 if (authenticator->checksum) {
662 char type_check[2];
663 krb5_checksum *cksum = authenticator->checksum;
664 krb5_keyblock *key;
665 krb5_data input;
666 krb5_boolean valid;
668 type_check[0] = ap->AuthName;
669 type_check[1] = ap->AuthHow;
671 err = krb5_auth_con_getkey(telnet_context,
672 auth_context, &key);
673 if (err) {
674 (void) snprintf(errbuf, sizeof (errbuf),
675 "Failed to get key from "
676 "authenticator: %s",
677 error_message(err));
678 goto errout;
681 input.data = type_check;
682 input.length = 2;
683 err = krb5_c_verify_checksum(telnet_context,
684 key, 0,
685 &input,
686 cksum,
687 &valid);
688 if (!err && !valid)
689 err = KRB5KRB_AP_ERR_BAD_INTEGRITY;
691 if (err) {
692 (void) snprintf(errbuf, sizeof (errbuf),
693 "Kerberos checksum "
694 "verification failed: "
695 "%s",
696 error_message(err));
697 goto errout;
699 krb5_free_keyblock(telnet_context, key);
702 krb5_free_authenticator(telnet_context, authenticator);
703 if ((ap->AuthHow & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
704 /* do ap_rep stuff here */
705 if ((err = krb5_mk_rep(telnet_context, auth_context,
706 &outbuf))) {
707 (void) snprintf(errbuf, sizeof (errbuf),
708 "Failed to make "
709 "Kerberos auth reply: "
710 "%s",
711 error_message(err));
712 goto errout;
714 reply_to_client(ap, KRB_RESPONSE, outbuf.data,
715 outbuf.length);
717 if (krb5_unparse_name(telnet_context,
718 ticket->enc_part2->client,
719 &name))
720 name = 0;
721 reply_to_client(ap, KRB_ACCEPT, name, name ? -1 : 0);
722 if (auth_debug) {
723 syslog(LOG_NOTICE,
724 "\tKerberos5 identifies user as ``%s''\r\n",
725 name ? name : "");
727 if (name != NULL) {
728 krb5_name = (char *)strdup(name);
730 auth_finished(ap, AUTH_USER);
732 free(name);
733 (void) krb5_auth_con_getremotesubkey(telnet_context,
734 auth_context, &newkey);
735 if (session_key != NULL) {
736 krb5_free_keyblock(telnet_context, session_key);
737 session_key = 0;
739 if (newkey != NULL) {
740 (void) krb5_copy_keyblock(telnet_context,
741 newkey, &session_key);
742 krb5_free_keyblock(telnet_context, newkey);
743 } else {
744 (void) krb5_copy_keyblock(telnet_context,
745 ticket->enc_part2->session, &session_key);
749 * Initialize encryption stuff. Currently, we are only
750 * supporting 8 byte keys and blocks. Check for this later.
752 skey.type = SK_DES;
753 skey.length = DES_BLOCKSIZE;
754 skey.data = session_key->contents;
755 encrypt_session_key(&skey, &encr_data.encrypt);
756 encrypt_session_key(&skey, &encr_data.decrypt);
757 break;
758 case KRB_FORWARD:
759 inbuf.length = cnt;
760 inbuf.data = (char *)data;
761 if (auth_debug)
762 (void) fprintf(stderr,
763 "RCVD KRB_FORWARD data (%d bytes)\n", cnt);
765 if (auth_context != NULL) {
766 krb5_rcache rcache;
768 err = krb5_auth_con_getrcache(telnet_context,
769 auth_context, &rcache);
770 if (!err && !rcache) {
771 err = krb5_sname_to_principal(telnet_context,
772 0, 0, KRB5_NT_SRV_HST, &server);
773 if (!err) {
774 err = krb5_get_server_rcache(
775 telnet_context,
776 krb5_princ_component(
777 telnet_context,
778 server, 0),
779 &rcache);
780 krb5_free_principal(telnet_context,
781 server);
784 if (err) {
785 syslog(LOG_ERR,
786 "Error allocating krb5 replay cache: %s",
787 error_message(err));
788 } else {
789 err = krb5_auth_con_setrcache(telnet_context,
790 auth_context, rcache);
791 if (err)
792 syslog(LOG_ERR,
793 "Error creating krb5 replay cache:"
794 " %s",
795 error_message(err));
799 * Use the 'rsaddr' and 'rsport' (remote service addr/port)
800 * from the original connection. This data is used to
801 * verify the forwarded credentials.
803 if (!(err = krb5_auth_con_setaddrs(telnet_context, auth_context,
804 NULL, &rsaddr)))
805 err = krb5_auth_con_setports(telnet_context,
806 auth_context, NULL, &rsport);
808 if (err == 0)
810 * If all is well, store the forwarded creds in
811 * the users local credential cache.
813 err = rd_and_store_forwarded_creds(telnet_context,
814 auth_context, &inbuf,
815 ticket,
816 AuthenticatingUser);
817 if (err) {
818 (void) snprintf(errbuf, sizeof (errbuf),
819 "Read forwarded creds failed: %s",
820 error_message(err));
821 syslog(LOG_ERR, "%s", errbuf);
823 reply_to_client(ap, KRB_FORWARD_REJECT, errbuf, -1);
824 if (auth_debug)
825 (void) fprintf(stderr,
826 "\tCould not read "
827 "forwarded credentials\r\n");
828 } else
829 reply_to_client(ap, KRB_FORWARD_ACCEPT, NULL, 0);
831 free(rsaddr.contents);
833 free(rsport.contents);
835 if (auth_debug)
836 (void) fprintf(stderr, "\tForwarded "
837 "credentials obtained\r\n");
838 break;
839 default:
840 if (auth_debug)
841 (void) fprintf(stderr,
842 "\tUnknown Kerberos option %d\r\n",
843 data[-1]);
844 reply_to_client(ap, KRB_REJECT, NULL, 0);
845 break;
847 return;
849 errout:
850 reply_to_client(ap, KRB_REJECT, errbuf, -1);
852 if (auth_debug)
853 (void) fprintf(stderr, "\tKerberos V5 error: %s\r\n", errbuf);
855 syslog(LOG_ERR, "%s", errbuf);
857 if (auth_context != NULL) {
858 (void) krb5_auth_con_free(telnet_context, auth_context);
859 auth_context = 0;
863 static int
864 krb5_init()
866 int code = 0;
868 if (telnet_context == NULL) {
869 code = krb5_init_context(&telnet_context);
870 if (code != 0 && auth_debug)
871 syslog(LOG_NOTICE,
872 "Cannot initialize Kerberos V5: %s",
873 error_message(code));
876 return (code);
879 static void
880 auth_name(uchar_t *data, int cnt)
882 char namebuf[MAXPRINCLEN];
884 if (cnt < 1) {
885 if (auth_debug)
886 (void) fprintf(stderr,
887 "\t(auth_name) Empty NAME in auth "
888 "reply\n");
889 return;
891 if (cnt > sizeof (namebuf)-1) {
892 if (auth_debug)
893 (void) fprintf(stderr,
894 "\t(auth_name) NAME exceeds %d bytes\n",
895 sizeof (namebuf)-1);
896 return;
898 (void) memcpy((void *)namebuf, (void *)data, cnt);
899 namebuf[cnt] = 0;
900 if (auth_debug)
901 (void) fprintf(stderr, "\t(auth_name) name [%s]\n", namebuf);
902 AuthenticatingUser = (char *)strdup(namebuf);
905 static void
906 auth_is(uchar_t *data, int cnt)
908 AuthInfo *aptr = auth_list;
910 if (cnt < 2)
911 return;
914 * We failed to negoiate secure authentication
916 if (data[0] == AUTHTYPE_NULL) {
917 auth_finished(0, AUTH_REJECT);
918 return;
921 while (aptr->AuthName != 0 &&
922 (aptr->AuthName != data[0] || aptr->AuthHow != data[1]))
923 aptr++;
925 if (aptr != NULL) {
926 if (auth_debug)
927 (void) fprintf(stderr, "\t(auth_is) auth type is %s "
928 "(%d bytes)\n", aptr->AuthString, cnt);
930 if (aptr->AuthName == AUTHTYPE_KERBEROS_V5)
931 kerberos5_is(aptr, data+2, cnt-2);
935 static int
936 krb5_user_status(char *name, int namelen, int level)
938 int retval = AUTH_USER;
940 if (auth_debug)
941 (void) fprintf(stderr, "\t(krb5_user_status) level = %d "
942 "auth_level = %d user = %s\n",
943 level, auth_level,
944 (AuthenticatingUser != NULL ? AuthenticatingUser : ""));
946 if (level < AUTH_USER)
947 return (level);
949 if (AuthenticatingUser != NULL &&
950 (retval = krb5_kuserok(telnet_context, ticket->enc_part2->client,
951 AuthenticatingUser))) {
952 (void) strncpy(name, AuthenticatingUser, namelen);
953 return (AUTH_VALID);
954 } else {
955 if (!retval)
956 syslog(LOG_ERR,
957 "Krb5 principal lacks permission to "
958 "access local account for %s",
959 AuthenticatingUser);
960 return (AUTH_USER);
965 * Wrapper around /dev/urandom
967 static int
968 getrandom(char *buf, int buflen)
970 static int devrandom = -1;
972 if (devrandom == -1 &&
973 (devrandom = open("/dev/urandom", O_RDONLY)) == -1) {
974 fatalperror(net, "Unable to open /dev/urandom: ",
975 errno);
976 return (-1);
979 if (read(devrandom, buf, buflen) == -1) {
980 fatalperror(net, "Unable to read from /dev/urandom: ",
981 errno);
982 return (-1);
985 return (0);
989 * encrypt_init
991 * Initialize the encryption data structures
993 static void
994 encrypt_init()
996 (void) memset(&encr_data.encrypt, 0, sizeof (cipher_info_t));
997 (void) memset(&encr_data.decrypt, 0, sizeof (cipher_info_t));
999 encr_data.encrypt.state = ENCR_STATE_NOT_READY;
1000 encr_data.decrypt.state = ENCR_STATE_NOT_READY;
1004 * encrypt_send_request_start
1006 * Request that the remote side automatically start sending
1007 * encrypted output
1009 static void
1010 encrypt_send_request_start()
1012 uchar_t buf[6+TELNET_MAXKEYIDLEN], *p;
1014 p = buf;
1016 *p++ = IAC;
1017 *p++ = SB;
1018 *p++ = TELOPT_ENCRYPT;
1019 *p++ = ENCRYPT_REQSTART;
1021 * We are telling the remote side which
1022 * decrypt key we will use so that it may
1023 * encrypt in the same key.
1025 (void) memcpy(p, encr_data.decrypt.keyid, encr_data.decrypt.keyidlen);
1026 p += encr_data.decrypt.keyidlen;
1028 *p++ = IAC;
1029 *p++ = SE;
1031 write_data_len((const char *)buf, p-buf);
1032 netflush();
1033 if (enc_debug)
1034 (void) fprintf(stderr,
1035 "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
1039 * encrypt_is
1041 * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
1042 * message, the client is telling us that it will be sending
1043 * encrypted data using the indicated cipher.
1044 * We must initialize the read (decrypt) side of our connection
1046 static void
1047 encrypt_is(uchar_t *data, int cnt)
1049 register int type;
1050 register int iv_status = CFB64_IV_OK;
1051 register int lstate = 0;
1053 uchar_t sbbuf[] = {
1054 (uchar_t)IAC,
1055 (uchar_t)SB,
1056 (uchar_t)TELOPT_ENCRYPT,
1057 (uchar_t)ENCRYPT_REPLY,
1058 (uchar_t)0, /* placeholder: sbbuf[4] */
1059 (uchar_t)CFB64_IV_OK, /* placeholder: sbbuf[5] */
1060 (uchar_t)IAC,
1061 (uchar_t)SE,
1064 if (--cnt < 0)
1065 return;
1067 type = sbbuf[4] = *data++;
1070 * Steps to take:
1071 * 1. Create the proper stream Initialization vector
1072 * - copy the correct 'seed' to IV and output blocks
1073 * - set the correct key schedule
1074 * 2. Generate reply for the other side:
1075 * IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
1076 * [ data ... ] IAC SE
1077 * 3. Tell crypto module: method, direction, IV
1079 switch (type) {
1080 case TELOPT_ENCTYPE_DES_CFB64:
1081 encr_data.decrypt.type = type;
1083 lstate = encr_data.decrypt.state;
1084 if (enc_debug)
1085 (void) fprintf(stderr,
1086 "\t(encrypt_is) initial state = %d\n",
1087 lstate);
1089 * Before we extract the IV bytes, make sure we got
1090 * enough data.
1092 if (cnt < sizeof (Block)) {
1093 iv_status = CFB64_IV_BAD;
1094 if (enc_debug)
1095 (void) fprintf(stderr,
1096 "\t(encrypt_is) Not enough "
1097 "IV bytes\n");
1098 lstate = ENCR_STATE_NOT_READY;
1099 } else {
1100 data++; /* skip over the CFB64_IV byte */
1101 (void) memcpy(encr_data.decrypt.ivec, data,
1102 sizeof (Block));
1103 lstate = ENCR_STATE_IN_PROGRESS;
1105 break;
1106 case TELOPT_ENCTYPE_NULL:
1107 encr_data.decrypt.type = type;
1108 lstate &= ~ENCR_STATE_NO_RECV_IV;
1109 lstate &= ~ENCR_STATE_NO_SEND_IV;
1110 if (enc_debug)
1111 (void) fprintf(stderr,
1112 "\t(encrypt_is) We accept NULL encr\n");
1113 break;
1114 default:
1115 iv_status = CFB64_IV_BAD;
1116 encr_data.decrypt.type = 0;
1117 if (enc_debug)
1118 (void) fprintf(stderr,
1119 "\t(encrypt_is) Can't find type (%d) "
1120 "for initial negotiation\r\n",
1121 type);
1122 lstate = ENCR_STATE_NOT_READY;
1123 break;
1126 sbbuf[5] = (uchar_t)iv_status; /* either CFB64_IV_OK or BAD */
1128 if (iv_status == CFB64_IV_OK) {
1130 * send IV to crypto module and indicate it is for
1131 * decrypt only
1133 lstate &= ~ENCR_STATE_NO_RECV_IV; /* we received an OK IV */
1134 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont send an IV */
1135 } else {
1136 /* tell crypto module to disable crypto on "read" stream */
1137 lstate = ENCR_STATE_NOT_READY;
1140 write_data_len((const char *)sbbuf, sizeof (sbbuf));
1141 netflush();
1142 #ifdef ENCRYPT_NAMES
1143 if (enc_debug)
1144 (void) fprintf(stderr,
1145 "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
1146 ENCTYPE_NAME(type),
1147 (iv_status == CFB64_IV_OK ? "CFB64_IV_OK" :
1148 "CFB64_IV_BAD"));
1149 #endif /* ENCRYPT_NAMES */
1150 /* Update the state of the decryption negotiation */
1151 encr_data.decrypt.state = lstate;
1153 if (lstate == ENCR_STATE_NOT_READY)
1154 encr_data.decrypt.autoflag = 0;
1155 else {
1156 if (lstate == ENCR_STATE_OK && encr_data.decrypt.autoflag)
1157 encrypt_send_request_start();
1159 if (enc_debug)
1160 (void) fprintf(stderr,
1161 "\t(encrypt_is) final DECRYPT state = %d\n",
1162 encr_data.decrypt.state);
1166 * encrypt_send_encrypt_is
1168 * Tell the client what encryption we will use
1169 * and what our IV will be.
1171 static int
1172 encrypt_send_encrypt_is()
1174 register int lstate;
1175 krb5_error_code kret;
1176 uchar_t sbbuf[MAXOPTLEN], *p;
1177 int i;
1179 lstate = encr_data.encrypt.state;
1181 if (encr_data.encrypt.type == ENCTYPE_NULL) {
1183 * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
1184 * on a cipher.
1186 return (lstate);
1190 * - Create a random DES key
1192 * - DES ECB encrypt
1193 * encrypt the IV using itself as the key.
1195 * - Send response
1196 * IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
1197 * IAC SE
1200 if (lstate == ENCR_STATE_NOT_READY)
1201 lstate = ENCR_STATE_IN_PROGRESS;
1202 else if ((lstate & ENCR_STATE_NO_SEND_IV) == 0) {
1203 if (enc_debug)
1204 (void) fprintf(stderr,
1205 "\t(encrypt_send_is) IV already sent,"
1206 " state = %d\n", lstate);
1207 return (lstate);
1210 if (!VALIDKEY(encr_data.encrypt.krbdes_key)) {
1212 * Invalid key, set flag so we try again later
1213 * when we get a good one
1215 encr_data.encrypt.need_start = 1;
1216 if (enc_debug)
1217 (void) fprintf(stderr,
1218 "\t(encrypt_send_is) No Key, cannot "
1219 "start encryption yet\n");
1220 return (lstate);
1222 if (enc_debug)
1223 (void) fprintf(stderr,
1224 "\t(encrypt_send_is) Creating new feed\n");
1227 * Create a random feed and send it over.
1229 * Use the /dev/[u]random interface to generate
1230 * our encryption IV.
1232 kret = getrandom((char *)encr_data.encrypt.ivec, sizeof (Block));
1234 if (kret) {
1235 if (enc_debug)
1236 (void) fprintf(stderr,
1237 "\t(encrypt_send_is) error from "
1238 "getrandom: %d\n", kret);
1239 syslog(LOG_ERR, "Failed to create encryption key (err %d)\n");
1240 encr_data.encrypt.type = ENCTYPE_NULL;
1241 } else {
1242 mit_des_fixup_key_parity(encr_data.encrypt.ivec);
1245 p = sbbuf;
1246 *p++ = IAC;
1247 *p++ = SB;
1248 *p++ = TELOPT_ENCRYPT;
1249 *p++ = ENCRYPT_IS;
1250 *p++ = encr_data.encrypt.type;
1251 *p++ = CFB64_IV;
1254 * Copy the IV bytes individually so that when a
1255 * 255 (telnet IAC) is used, it can be "escaped" by
1256 * adding it twice (telnet RFC 854).
1258 for (i = 0; i < sizeof (Block); i++)
1259 if ((*p++ = encr_data.encrypt.ivec[i]) == IAC)
1260 *p++ = IAC;
1262 *p++ = IAC;
1263 *p++ = SE;
1264 write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1265 netflush();
1267 if (!kret) {
1268 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we sent our IV */
1269 lstate &= ~ENCR_STATE_NO_SEND_IV; /* dont need decrypt IV */
1271 encr_data.encrypt.state = lstate;
1273 if (enc_debug) {
1274 int i;
1275 (void) fprintf(stderr,
1276 "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
1277 encr_data.encrypt.type);
1278 for (i = 0; i < (p-sbbuf); i++)
1279 (void) fprintf(stderr, "%d ", (int)sbbuf[i]);
1280 (void) fprintf(stderr, "\n");
1283 return (lstate);
1287 * stop_stream
1289 * Utility routine to send a CRIOCSTOP ioctl to the
1290 * crypto module (cryptmod).
1292 static void
1293 stop_stream(int fd, int dir)
1295 struct strioctl crioc;
1296 uint32_t stopdir = dir;
1298 crioc.ic_cmd = CRYPTIOCSTOP;
1299 crioc.ic_timout = -1;
1300 crioc.ic_len = sizeof (stopdir);
1301 crioc.ic_dp = (char *)&stopdir;
1303 if (ioctl(fd, I_STR, &crioc)) {
1304 syslog(LOG_ERR, "Error sending CRYPTIOCSTOP ioctl: %m");
1309 * start_stream
1311 * Utility routine to send a CRYPTIOCSTART ioctl to the
1312 * crypto module (cryptmod). This routine may contain optional
1313 * payload data that the cryptmod will interpret as bytes that
1314 * need to be decrypted and sent back up to the application
1315 * via the data stream.
1317 static void
1318 start_stream(int fd, int dir, int datalen, char *data)
1320 struct strioctl crioc;
1322 crioc.ic_cmd = (dir == CRYPT_ENCRYPT ? CRYPTIOCSTARTENC :
1323 CRYPTIOCSTARTDEC);
1324 crioc.ic_timout = -1;
1325 crioc.ic_len = datalen;
1326 crioc.ic_dp = data;
1328 if (ioctl(fd, I_STR, &crioc)) {
1329 syslog(LOG_ERR, "Error sending CRYPTIOCSTART ioctl: %m");
1334 * encrypt_start_output
1336 * Tell the other side to start encrypting its data
1338 static void
1339 encrypt_start_output()
1341 int lstate;
1342 uchar_t *p;
1343 uchar_t sbbuf[MAXOPTLEN];
1344 struct strioctl crioc;
1345 struct cr_info_t cki;
1348 * Initialize crypto and send the ENCRYPT_IS msg
1350 lstate = encrypt_send_encrypt_is();
1352 if (lstate != ENCR_STATE_OK) {
1353 if (enc_debug)
1354 (void) fprintf(stderr,
1355 "\t(encrypt_start_output) ENCRYPT state "
1356 "= %d\n", lstate);
1357 return;
1360 p = sbbuf;
1362 *p++ = IAC;
1363 *p++ = SB;
1364 *p++ = TELOPT_ENCRYPT;
1365 *p++ = ENCRYPT_START;
1367 (void) memcpy(p, encr_data.encrypt.keyid, encr_data.encrypt.keyidlen);
1368 p += encr_data.encrypt.keyidlen;
1370 *p++ = IAC;
1371 *p++ = SE;
1373 /* Flush this data out before we start encrypting */
1374 write_data_len((const char *)sbbuf, (int)(p-sbbuf));
1375 netflush();
1377 if (enc_debug)
1378 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
1379 "(lstate = %d) data waiting = %d\n",
1380 (int)encr_data.encrypt.keyid[0],
1381 lstate, nfrontp-nbackp);
1383 encr_data.encrypt.state = lstate;
1386 * tell crypto module what key to use for encrypting
1387 * Note that the ENCRYPT has not yet been enabled, but we
1388 * need to first set the crypto key to use.
1390 cki.direction_mask = CRYPT_ENCRYPT;
1392 if (encr_data.encrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1393 cki.crypto_method = CRYPT_METHOD_DES_CFB;
1394 } else {
1395 if (enc_debug)
1396 (void) fprintf(stderr,
1397 "\t(encrypt_start_output) - unknown "
1398 "crypto_method %d\n",
1399 encr_data.encrypt.type);
1400 syslog(LOG_ERR, "unrecognized crypto encrypt method: %d",
1401 encr_data.encrypt.type);
1403 return;
1407 * If we previously configured this crypto method, we dont want to
1408 * overwrite the key or ivec information already given to the crypto
1409 * module as it will cause the cipher data between the client and server
1410 * to become out of synch and impossible to decipher.
1412 if (encr_data.encrypt.setup == cki.crypto_method) {
1413 cki.keylen = 0;
1414 cki.iveclen = 0;
1415 } else {
1416 cki.keylen = DES_BLOCKSIZE;
1417 (void) memcpy(cki.key, (void *)encr_data.encrypt.krbdes_key,
1418 DES_BLOCKSIZE);
1420 cki.iveclen = DES_BLOCKSIZE;
1421 (void) memcpy(cki.ivec, (void *)encr_data.encrypt.ivec,
1422 DES_BLOCKSIZE);
1424 cki.ivec_usage = IVEC_ONETIME;
1427 cki.option_mask = 0;
1429 /* Stop encrypt side prior to setup so we dont lose data */
1430 stop_stream(cryptmod_fd, CRYPT_ENCRYPT);
1432 crioc.ic_cmd = CRYPTIOCSETUP;
1433 crioc.ic_timout = -1;
1434 crioc.ic_len = sizeof (struct cr_info_t);
1435 crioc.ic_dp = (char *)&cki;
1437 if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1438 perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
1439 } else {
1440 /* Setup completed OK */
1441 encr_data.encrypt.setup = cki.crypto_method;
1445 * We do not check for "stuck" data when setting up the
1446 * outbound "encrypt" channel. Any data queued prior to
1447 * this IOCTL will get processed correctly without our help.
1449 start_stream(cryptmod_fd, CRYPT_ENCRYPT, 0, NULL);
1452 * tell crypto module to start encrypting
1454 if (enc_debug)
1455 (void) fprintf(stderr,
1456 "\t(encrypt_start_output) Encrypting output\n");
1460 * encrypt_request_start
1462 * The client requests that we start encryption immediately after
1463 * successful negotiation
1465 static void
1466 encrypt_request_start(void)
1468 if (encr_data.encrypt.type == ENCTYPE_NULL) {
1469 encr_data.encrypt.autoflag = 1;
1470 if (enc_debug)
1471 (void) fprintf(stderr, "\t(encrypt_request_start) "
1472 "autoencrypt = ON\n");
1473 } else {
1474 encrypt_start_output();
1479 * encrypt_end
1481 * ENCRYPT END received, stop decrypting the read stream
1483 static void
1484 encrypt_end(int direction)
1486 struct cr_info_t cki;
1487 struct strioctl crioc;
1488 uint32_t stopdir;
1490 stopdir = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1491 CRYPT_ENCRYPT);
1493 stop_stream(cryptmod_fd, stopdir);
1496 * Call this function when we wish to disable crypto in
1497 * either direction (ENCRYPT or DECRYPT)
1499 cki.direction_mask = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1500 CRYPT_ENCRYPT);
1501 cki.crypto_method = CRYPT_METHOD_NONE;
1502 cki.option_mask = 0;
1504 cki.keylen = 0;
1505 cki.iveclen = 0;
1506 cki.ivec_usage = IVEC_ONETIME;
1508 crioc.ic_cmd = CRYPTIOCSETUP;
1509 crioc.ic_timout = -1;
1510 crioc.ic_len = sizeof (cki);
1511 crioc.ic_dp = (char *)&cki;
1513 if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1514 perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
1517 start_stream(cryptmod_fd, stopdir, 0, NULL);
1521 * encrypt_request_end
1523 * When we receive a REQEND from the client, it means
1524 * that we are supposed to stop encrypting
1526 static void
1527 encrypt_request_end()
1530 * Tell the other side we are done encrypting
1533 write_data("%c%c%c%c%c%c",
1534 (uchar_t)IAC,
1535 (uchar_t)SB,
1536 (uchar_t)TELOPT_ENCRYPT,
1537 (uchar_t)ENCRYPT_END,
1538 (uchar_t)IAC,
1539 (uchar_t)SE);
1540 netflush();
1541 if (enc_debug)
1542 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
1545 * Turn off encryption of the write stream
1547 encrypt_end(TELNET_DIR_ENCRYPT);
1551 * encrypt_send_request_end
1553 * We stop encrypting the write stream and tell the other side about it.
1555 static void
1556 encrypt_send_request_end()
1558 write_data("%c%c%c%c%c%c",
1559 (uchar_t)IAC,
1560 (uchar_t)SB,
1561 (uchar_t)TELOPT_ENCRYPT,
1562 (uchar_t)ENCRYPT_REQEND,
1563 (uchar_t)IAC,
1564 (uchar_t)SE);
1565 netflush();
1566 if (enc_debug)
1567 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
1571 * encrypt_start
1573 * The client is going to start sending encrypted data
1574 * using the previously negotiated cipher (see what we set
1575 * when we did the REPLY in encrypt_is).
1577 static void
1578 encrypt_start(void)
1580 struct cr_info_t cki;
1581 struct strioctl crioc;
1582 int bytes = 0;
1583 char *dataptr = NULL;
1585 if (encr_data.decrypt.type == ENCTYPE_NULL) {
1586 if (enc_debug)
1587 (void) fprintf(stderr,
1588 "\t(encrypt_start) No DECRYPT method "
1589 "defined yet\n");
1590 encrypt_send_request_end();
1591 return;
1594 cki.direction_mask = CRYPT_DECRYPT;
1596 if (encr_data.decrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1597 cki.crypto_method = CRYPT_METHOD_DES_CFB;
1598 } else {
1599 if (enc_debug)
1600 (void) fprintf(stderr,
1601 "\t(encrypt_start) - unknown "
1602 "crypto_method %d\n", encr_data.decrypt.type);
1604 syslog(LOG_ERR, "unrecognized crypto decrypt method: %d",
1605 encr_data.decrypt.type);
1607 return;
1611 * Don't overwrite previously configured key and ivec info
1613 if (encr_data.decrypt.setup != cki.crypto_method) {
1614 (void) memcpy(cki.key, (void *)encr_data.decrypt.krbdes_key,
1615 DES_BLOCKSIZE);
1616 (void) memcpy(cki.ivec, (void *)encr_data.decrypt.ivec,
1617 DES_BLOCKSIZE);
1619 cki.keylen = DES_BLOCKSIZE;
1620 cki.iveclen = DES_BLOCKSIZE;
1621 cki.ivec_usage = IVEC_ONETIME;
1622 } else {
1623 cki.keylen = 0;
1624 cki.iveclen = 0;
1626 cki.option_mask = 0;
1628 stop_stream(cryptmod_fd, CRYPT_DECRYPT);
1630 crioc.ic_cmd = CRYPTIOCSETUP;
1631 crioc.ic_timout = -1;
1632 crioc.ic_len = sizeof (struct cr_info_t);
1633 crioc.ic_dp = (char *)&cki;
1635 if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1636 syslog(LOG_ERR, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
1637 "error: %m");
1638 } else {
1639 encr_data.decrypt.setup = cki.crypto_method;
1641 if (enc_debug)
1642 (void) fprintf(stderr,
1643 "\t(encrypt_start) called CRYPTIOCSETUP for "
1644 "decrypt side\n");
1647 * Read any data stuck between the cryptmod and the application
1648 * so we can pass it back down to be properly decrypted after
1649 * this operation finishes.
1651 if (ioctl(cryptmod_fd, I_NREAD, &bytes) < 0) {
1652 syslog(LOG_ERR, "I_NREAD returned error %m");
1653 bytes = 0;
1657 * Any data which was read AFTER the ENCRYPT START message
1658 * must be sent back down to be decrypted properly.
1660 * 'ncc' is the number of bytes that have been read but
1661 * not yet processed by the telnet state machine.
1663 * 'bytes' is the number of bytes waiting to be read from
1664 * the stream.
1666 * If either one is a positive value, then those bytes
1667 * must be pulled up and sent back down to be decrypted.
1669 if (ncc || bytes) {
1670 drainstream(bytes);
1671 if (enc_debug)
1672 (void) fprintf(stderr,
1673 "\t(encrypt_start) after drainstream, "
1674 "ncc=%d bytes = %d\n", ncc, bytes);
1675 bytes += ncc;
1676 dataptr = netip;
1679 start_stream(cryptmod_fd, CRYPT_DECRYPT, bytes, dataptr);
1682 * The bytes putback into the stream are no longer
1683 * available to be read by the server, so adjust the
1684 * counter accordingly.
1686 ncc = 0;
1687 netip = netibuf;
1688 (void) memset(netip, 0, netibufsize);
1690 #ifdef ENCRYPT_NAMES
1691 if (enc_debug) {
1692 (void) fprintf(stderr,
1693 "\t(encrypt_start) Start DECRYPT using %s\n",
1694 ENCTYPE_NAME(encr_data.decrypt.type));
1696 #endif /* ENCRYPT_NAMES */
1700 * encrypt_support
1702 * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
1703 * message from a client.
1705 * Choose an agreeable method (DES_CFB64) and
1706 * respond with TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
1708 * from: RFC 2946
1710 static void
1711 encrypt_support(char *data, int cnt)
1713 int lstate = ENCR_STATE_NOT_READY;
1714 int type, use_type = 0;
1716 while (cnt-- > 0 && use_type == 0) {
1717 type = *data++;
1718 #ifdef ENCRYPT_NAMES
1719 if (enc_debug)
1720 (void) fprintf(stderr,
1721 "RCVD ENCRYPT SUPPORT %s\n",
1722 ENCTYPE_NAME(type));
1723 #endif /* ENCRYPT_NAMES */
1725 * Prefer CFB64
1727 if (type == TELOPT_ENCTYPE_DES_CFB64) {
1728 use_type = type;
1731 encr_data.encrypt.type = use_type;
1733 if (use_type != TELOPT_ENCTYPE_NULL &&
1734 authenticated != NULL && authenticated != &NoAuth &&
1735 auth_status != AUTH_REJECT) {
1737 /* Authenticated -> have session key -> send ENCRYPT IS */
1738 lstate = encrypt_send_encrypt_is();
1739 if (lstate == ENCR_STATE_OK)
1740 encrypt_start_output();
1741 } else if (use_type == TELOPT_ENCTYPE_NULL) {
1742 if (enc_debug)
1743 (void) fprintf(stderr,
1744 "\t(encrypt_support) Cannot agree "
1745 "on crypto algorithm, output encryption "
1746 "disabled.\n");
1749 * Cannot agree on crypto algorithm
1750 * RFC 2946 sez:
1751 * send "IAC SB ENCRYPT IS NULL IAC SE"
1752 * optionally, also send IAC WONT ENCRYPT
1754 write_data("%c%c%c%c%c%c%c",
1755 (uchar_t)IAC,
1756 (uchar_t)SB,
1757 (uchar_t)TELOPT_ENCRYPT,
1758 (uchar_t)ENCRYPT_IS,
1759 (uchar_t)TELOPT_ENCTYPE_NULL,
1760 (uchar_t)IAC,
1761 (uchar_t)SE);
1762 send_wont(TELOPT_ENCRYPT);
1763 netflush();
1764 if (enc_debug)
1765 (void) fprintf(stderr,
1766 "SENT TELOPT_ENCRYPT ENCRYPT_IS "
1767 "[NULL]\n");
1769 remopts[TELOPT_ENCRYPT] = OPT_NO;
1771 settimer(encr_support);
1775 * encrypt_send_keyid
1777 * Sent the key id we will use to the client
1779 static void
1780 encrypt_send_keyid(int dir, uchar_t *keyid, int keylen, boolean_t saveit)
1782 uchar_t sbbuf[128], *p;
1784 p = sbbuf;
1786 *p++ = IAC;
1787 *p++ = SB;
1788 *p++ = TELOPT_ENCRYPT;
1789 *p++ = (dir == TELNET_DIR_ENCRYPT ? ENCRYPT_ENC_KEYID :
1790 ENCRYPT_DEC_KEYID);
1791 if (saveit) {
1792 if (enc_debug)
1793 (void) fprintf(stderr,
1794 "\t(send_keyid) store %d byte %s keyid\n",
1795 keylen,
1796 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1797 "DECRYPT"));
1799 if (dir == TELNET_DIR_ENCRYPT) {
1800 (void) memcpy(encr_data.encrypt.keyid, keyid, keylen);
1801 encr_data.encrypt.keyidlen = keylen;
1802 } else {
1803 (void) memcpy(encr_data.decrypt.keyid, keyid, keylen);
1804 encr_data.decrypt.keyidlen = keylen;
1807 (void) memcpy(p, keyid, keylen);
1808 p += keylen;
1810 *p++ = IAC;
1811 *p++ = SE;
1812 write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1813 netflush();
1815 if (enc_debug)
1816 (void) fprintf(stderr, "SENT TELOPT_ENCRYPT %s %d\n",
1817 (dir == TELNET_DIR_ENCRYPT ? "ENC_KEYID" :
1818 "DEC_KEYID"), keyid[0]);
1822 * encrypt_reply
1824 * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
1825 * message, process it accordingly.
1826 * If the vector is acceptable, tell client we are encrypting and
1827 * enable encryption on our write stream.
1829 * Negotiate the KEYID next..
1830 * RFC 2946, 2952
1832 static void
1833 encrypt_reply(char *data, int len)
1835 uchar_t type = (uchar_t)(*data++);
1836 uchar_t result = (uchar_t)(*data);
1837 int lstate;
1839 #ifdef ENCRYPT_NAMES
1840 if (enc_debug)
1841 (void) fprintf(stderr,
1842 "\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
1843 ENCRYPT_NAME(type),
1844 (result == CFB64_IV_OK ? "CFB64_IV_OK" :
1845 "CFB64_IV_BAD"), len);
1846 #endif /* ENCRYPT_NAMES */
1848 lstate = encr_data.encrypt.state;
1849 if (enc_debug)
1850 (void) fprintf(stderr,
1851 "\t(encrypt_reply) initial ENCRYPT state = %d\n",
1852 lstate);
1853 switch (result) {
1854 case CFB64_IV_OK:
1855 if (lstate == ENCR_STATE_NOT_READY)
1856 lstate = ENCR_STATE_IN_PROGRESS;
1857 lstate &= ~ENCR_STATE_NO_RECV_IV; /* we got the IV */
1858 lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont need to send IV */
1861 * The correct response here is to send the encryption key id
1862 * RFC 2752.
1864 * Send keyid 0 to indicate that we will just use default
1865 * keys.
1867 encrypt_send_keyid(TELNET_DIR_ENCRYPT, (uchar_t *)"\0", 1, 1);
1869 break;
1870 case CFB64_IV_BAD:
1872 * Clear the ivec
1874 (void) memset(encr_data.encrypt.ivec, 0, sizeof (Block));
1875 lstate = ENCR_STATE_NOT_READY;
1876 break;
1877 default:
1878 if (enc_debug)
1879 (void) fprintf(stderr,
1880 "\t(encrypt_reply) Got unknown IV value in "
1881 "REPLY message\n");
1882 lstate = ENCR_STATE_NOT_READY;
1883 break;
1886 encr_data.encrypt.state = lstate;
1887 if (lstate == ENCR_STATE_NOT_READY) {
1888 encr_data.encrypt.autoflag = 0;
1889 encr_data.encrypt.type = ENCTYPE_NULL;
1890 if (enc_debug)
1891 (void) fprintf(stderr,
1892 "\t(encrypt_reply) encrypt.autoflag = "
1893 "OFF\n");
1894 } else {
1895 encr_data.encrypt.type = type;
1896 if ((lstate == ENCR_STATE_OK) && encr_data.encrypt.autoflag)
1897 encrypt_start_output();
1900 if (enc_debug)
1901 (void) fprintf(stderr,
1902 "\t(encrypt_reply) ENCRYPT final state = %d\n",
1903 lstate);
1906 static void
1907 encrypt_set_keyid_state(uchar_t *keyid, int *keyidlen, int dir)
1909 int lstate;
1911 lstate = (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state :
1912 encr_data.decrypt.state);
1914 if (enc_debug)
1915 (void) fprintf(stderr,
1916 "\t(set_keyid_state) %s initial state = %d\n",
1917 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1918 "DECRYPT"), lstate);
1921 * Currently, we only support using the default keyid,
1922 * so it should be an error if the len > 1 or the keyid != 0.
1924 if (*keyidlen != 1 || (*keyid != '\0')) {
1925 if (enc_debug)
1926 (void) fprintf(stderr,
1927 "\t(set_keyid_state) unexpected keyid: "
1928 "len=%d value=%d\n", *keyidlen, *keyid);
1929 *keyidlen = 0;
1930 syslog(LOG_ERR, "rcvd unexpected keyid %d - only keyid of 0 "
1931 "is supported", *keyid);
1932 } else {
1934 * We move to the "IN_PROGRESS" state.
1936 if (lstate == ENCR_STATE_NOT_READY)
1937 lstate = ENCR_STATE_IN_PROGRESS;
1939 * Clear the NO_KEYID bit because we now have a valid keyid
1941 lstate &= ~ENCR_STATE_NO_KEYID;
1944 if (enc_debug)
1945 (void) fprintf(stderr,
1946 "\t(set_keyid_state) %s final state = %d\n",
1947 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1948 "DECRYPT"), lstate);
1950 if (dir == TELNET_DIR_ENCRYPT)
1951 encr_data.encrypt.state = lstate;
1952 else
1953 encr_data.decrypt.state = lstate;
1957 * encrypt_keyid
1959 * Set the keyid value in the key_info structure.
1960 * if necessary send a response to the sender
1962 static void
1963 encrypt_keyid(uchar_t *newkeyid, int *keyidlen, uchar_t *keyid,
1964 int len, int dir)
1966 if (len > TELNET_MAXNUMKEYS) {
1967 if (enc_debug)
1968 (void) fprintf(stderr,
1969 "\t(keyid) keylen too big (%d)\n", len);
1970 return;
1973 if (enc_debug) {
1974 (void) fprintf(stderr, "\t(keyid) set KEYID for %s len = %d\n",
1975 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1976 "DECRYPT"), len);
1979 if (len == 0) {
1980 if (*keyidlen == 0) {
1981 if (enc_debug)
1982 (void) fprintf(stderr,
1983 "\t(keyid) Got 0 length keyid - "
1984 "failure\n");
1985 return;
1987 *keyidlen = 0;
1988 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
1990 } else if (len != *keyidlen || memcmp(keyid, newkeyid, len)) {
1991 if (enc_debug)
1992 (void) fprintf(stderr,
1993 "\t(keyid) Setting new key (%d bytes)\n",
1994 len);
1996 *keyidlen = len;
1997 (void) memcpy(newkeyid, keyid, len);
1999 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2000 } else {
2001 encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2003 if (enc_debug)
2004 (void) fprintf(stderr,
2005 "\t(keyid) %s Key already in place,"
2006 "state = %d autoflag=%d\n",
2007 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT"),
2008 (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state:
2009 encr_data.decrypt.state),
2010 (dir == TELNET_DIR_ENCRYPT ?
2011 encr_data.encrypt.autoflag:
2012 encr_data.decrypt.autoflag));
2014 /* key already in place */
2015 if ((encr_data.encrypt.state == ENCR_STATE_OK) &&
2016 dir == TELNET_DIR_ENCRYPT && encr_data.encrypt.autoflag) {
2017 encrypt_start_output();
2019 return;
2022 if (enc_debug)
2023 (void) fprintf(stderr, "\t(keyid) %s final state = %d\n",
2024 (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
2025 "DECRYPT"),
2026 (dir == TELNET_DIR_ENCRYPT ?
2027 encr_data.encrypt.state :
2028 encr_data.decrypt.state));
2030 encrypt_send_keyid(dir, newkeyid, *keyidlen, 0);
2034 * encrypt_enc_keyid
2036 * We received the ENC_KEYID message from a client indicating that
2037 * the client wishes to verify that the indicated keyid maps to a
2038 * valid key.
2040 static void
2041 encrypt_enc_keyid(char *data, int cnt)
2044 * Verify the decrypt keyid is valid
2046 encrypt_keyid(encr_data.decrypt.keyid, &encr_data.decrypt.keyidlen,
2047 (uchar_t *)data, cnt, TELNET_DIR_DECRYPT);
2051 * encrypt_dec_keyid
2053 * We received the DEC_KEYID message from a client indicating that
2054 * the client wants to verify that the indicated keyid maps to a valid key.
2056 static void
2057 encrypt_dec_keyid(char *data, int cnt)
2059 encrypt_keyid(encr_data.encrypt.keyid, &encr_data.encrypt.keyidlen,
2060 (uchar_t *)data, cnt, TELNET_DIR_ENCRYPT);
2064 * encrypt_session_key
2066 * Store the session key in the encryption data record
2068 static void
2069 encrypt_session_key(Session_Key *key, cipher_info_t *cinfo)
2071 if (key == NULL || key->type != SK_DES) {
2072 if (enc_debug)
2073 (void) fprintf(stderr,
2074 "\t(session_key) Cannot set krb5 "
2075 "session key (unknown type = %d)\n",
2076 key ? key->type : -1);
2078 if (enc_debug)
2079 (void) fprintf(stderr,
2080 "\t(session_key) Settting session key "
2081 "for server\n");
2083 /* store the key in the cipher info data struct */
2084 (void) memcpy(cinfo->krbdes_key, (void *)key->data, sizeof (Block));
2087 * Now look to see if we still need to send the key and start
2088 * encrypting.
2090 * If so, go ahead an call it now that we have the key.
2092 if (cinfo->need_start) {
2093 if (encrypt_send_encrypt_is() == ENCR_STATE_OK) {
2094 cinfo->need_start = 0;
2100 * new_env
2102 * Used to add an environment variable and value to the
2103 * linked list structure.
2105 static int
2106 new_env(const char *name, const char *value)
2108 struct envlist *env;
2110 env = malloc(sizeof (struct envlist));
2111 if (env == NULL)
2112 return (1);
2113 if ((env->name = strdup(name)) == NULL) {
2114 free(env);
2115 return (1);
2117 if ((env->value = strdup(value)) == NULL) {
2118 free(env->name);
2119 free(env);
2120 return (1);
2122 env->delete = 0;
2123 env->next = envlist_head;
2124 envlist_head = env;
2125 return (0);
2129 * del_env
2131 * Used to delete an environment variable from the linked list
2132 * structure. We just set a flag because we will delete the list
2133 * anyway before we exec login.
2135 static int
2136 del_env(const char *name)
2138 struct envlist *env;
2140 for (env = envlist_head; env; env = env->next) {
2141 if (strcmp(env->name, name) == 0) {
2142 env->delete = 1;
2143 break;
2146 return (0);
2149 static int
2150 issock(int fd)
2152 struct stat stats;
2154 if (fstat(fd, &stats) == -1)
2155 return (0);
2156 return (S_ISSOCK(stats.st_mode));
2159 /* ARGSUSED */
2161 main(int argc, char *argv[])
2163 struct sockaddr_storage from;
2164 int on = 1;
2165 socklen_t fromlen;
2166 int issocket;
2167 #if defined(DEBUG)
2168 ushort_t porttouse = 0;
2169 boolean_t standalone = 0;
2170 #endif /* defined(DEBUG) */
2171 extern char *optarg;
2172 char c;
2173 int tos = -1;
2175 while ((c = getopt(argc, argv, TELNETD_OPTS DEBUG_OPTS)) != -1) {
2176 switch (c) {
2177 #if defined(DEBUG)
2178 case 'p':
2180 * note: alternative port number only used in
2181 * standalone mode.
2183 porttouse = atoi(optarg);
2184 standalone = 1;
2185 break;
2186 case 'e':
2187 enc_debug = 1;
2188 break;
2189 #endif /* DEBUG */
2190 case 'a':
2191 if (strcasecmp(optarg, "none") == 0) {
2192 auth_level = 0;
2193 } else if (strcasecmp(optarg, "user") == 0) {
2194 auth_level = AUTH_USER;
2195 } else if (strcasecmp(optarg, "valid") == 0) {
2196 auth_level = AUTH_VALID;
2197 } else if (strcasecmp(optarg, "off") == 0) {
2198 auth_level = -1;
2199 negotiate_auth_krb5 = 0;
2200 } else if (strcasecmp(optarg, "debug") == 0) {
2201 auth_debug = 1;
2202 } else {
2203 syslog(LOG_ERR,
2204 "unknown authentication level specified "
2205 "with \'-a\' option (%s)", optarg);
2206 auth_level = AUTH_USER;
2208 break;
2209 case 'X':
2210 /* disable authentication negotiation */
2211 negotiate_auth_krb5 = 0;
2212 break;
2213 case 'R':
2214 case 'M':
2215 if (optarg != NULL) {
2216 int ret = krb5_init();
2217 if (ret) {
2218 syslog(LOG_ERR,
2219 "Unable to use Kerberos V5 as "
2220 "requested, exiting");
2221 exit(1);
2223 (void) krb5_set_default_realm(telnet_context,
2224 optarg);
2225 syslog(LOG_NOTICE,
2226 "using %s as default KRB5 realm", optarg);
2228 break;
2229 case 'S':
2230 telnet_srvtab = (char *)strdup(optarg);
2231 break;
2232 case 'E': /* disable automatic encryption */
2233 negotiate_encrypt = B_FALSE;
2234 break;
2235 case 'U':
2236 resolve_hostname = 1;
2237 break;
2238 case 's':
2239 if (optarg == NULL || (tos = atoi(optarg)) < 0 ||
2240 tos > 255) {
2241 syslog(LOG_ERR, "telnetd: illegal tos value: "
2242 "%s\n", optarg);
2243 } else {
2244 if (tos < 0)
2245 tos = 020;
2247 break;
2248 case 'h':
2249 show_hostinfo = 0;
2250 break;
2251 default:
2252 syslog(LOG_ERR, "telnetd: illegal cmd line option %c",
2254 break;
2258 netibufsize = BUFSIZ;
2259 if (!(netibuf = (char *)malloc(netibufsize)))
2260 syslog(LOG_ERR, "netibuf malloc failed\n");
2261 (void) memset(netibuf, 0, netibufsize);
2262 netip = netibuf;
2264 #if defined(DEBUG)
2265 if (standalone) {
2266 int s, ns, foo;
2267 struct servent *sp;
2268 static struct sockaddr_in6 sin6 = { AF_INET6 };
2269 int option = 1;
2271 if (porttouse) {
2272 sin6.sin6_port = htons(porttouse);
2273 } else {
2274 sp = getservbyname("telnet", "tcp");
2275 if (sp == 0) {
2276 (void) fprintf(stderr,
2277 "telnetd: tcp/telnet: "
2278 "unknown service\n");
2279 exit(EXIT_FAILURE);
2281 sin6.sin6_port = sp->s_port;
2284 s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
2285 if (s < 0) {
2286 perror("telnetd: socket");
2287 exit(EXIT_FAILURE);
2289 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&option,
2290 sizeof (option)) == -1)
2291 perror("setsockopt SO_REUSEADDR");
2292 if (bind(s, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) {
2293 perror("bind");
2294 exit(EXIT_FAILURE);
2296 if (listen(s, 32) < 0) {
2297 perror("listen");
2298 exit(EXIT_FAILURE);
2301 /* automatically reap all child processes */
2302 (void) signal(SIGCHLD, SIG_IGN);
2304 for (;;) {
2305 pid_t pid;
2307 foo = sizeof (sin6);
2308 ns = accept(s, (struct sockaddr *)&sin6, &foo);
2309 if (ns < 0) {
2310 perror("accept");
2311 exit(EXIT_FAILURE);
2313 pid = fork();
2314 if (pid == -1) {
2315 perror("fork");
2316 exit(EXIT_FAILURE);
2318 if (pid == 0) {
2319 (void) dup2(ns, 0);
2320 (void) close(s);
2321 (void) signal(SIGCHLD, SIG_DFL);
2322 break;
2324 (void) close(ns);
2327 #endif /* defined(DEBUG) */
2329 openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
2331 issocket = issock(0);
2332 if (!issocket)
2333 fatal(0, "stdin is not a socket file descriptor");
2335 fromlen = (socklen_t)sizeof (from);
2336 (void) memset((char *)&from, 0, sizeof (from));
2337 if (getpeername(0, (struct sockaddr *)&from, &fromlen)
2338 < 0) {
2339 (void) fprintf(stderr, "%s: ", argv[0]);
2340 perror("getpeername");
2341 _exit(EXIT_FAILURE);
2344 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on,
2345 sizeof (on)) < 0) {
2346 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
2350 * Set the TOS value
2352 if (tos != -1 &&
2353 setsockopt(0, IPPROTO_IP, IP_TOS,
2354 (char *)&tos, sizeof (tos)) < 0 &&
2355 errno != ENOPROTOOPT) {
2356 syslog(LOG_ERR, "setsockopt (IP_TOS %d): %m", tos);
2359 if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on,
2360 sizeof (on)) < 0) {
2361 syslog(LOG_WARNING, "setsockopt (SO_OOBINLINE): %m");
2364 /* set the default PAM service name */
2365 (void) strcpy(pam_svc_name, "telnet");
2367 doit(0, &from);
2368 return (EXIT_SUCCESS);
2371 static char *terminaltype = 0;
2374 * ttloop
2376 * A small subroutine to flush the network output buffer, get some data
2377 * from the network, and pass it through the telnet state machine. We
2378 * also flush the pty input buffer (by dropping its data) if it becomes
2379 * too full.
2381 static void
2382 ttloop(void)
2384 if (nfrontp-nbackp) {
2385 netflush();
2387 read_again:
2388 ncc = read(net, netibuf, netibufsize);
2389 if (ncc < 0) {
2390 if (errno == EINTR)
2391 goto read_again;
2392 syslog(LOG_INFO, "ttloop: read: %m");
2393 exit(EXIT_FAILURE);
2394 } else if (ncc == 0) {
2395 syslog(LOG_INFO, "ttloop: peer closed connection\n");
2396 exit(EXIT_FAILURE);
2399 netip = netibuf;
2400 telrcv(); /* state machine */
2401 if (ncc > 0) {
2402 pfrontp = pbackp = ptyobuf;
2403 telrcv();
2407 static void
2408 send_do(int option)
2410 write_data("%c%c%c", (uchar_t)IAC, (uchar_t)DO, (uchar_t)option);
2413 static void
2414 send_will(int option)
2416 write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WILL, (uchar_t)option);
2419 static void
2420 send_wont(int option)
2422 write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WONT, (uchar_t)option);
2427 * getauthtype
2429 * Negotiate automatic authentication, is possible.
2431 static int
2432 getauthtype(char *username, int *len)
2434 int init_status = -1;
2436 init_status = krb5_init();
2438 if (auth_level == -1 || init_status != 0) {
2439 remopts[TELOPT_AUTHENTICATION] = OPT_NO;
2440 myopts[TELOPT_AUTHENTICATION] = OPT_NO;
2441 negotiate_auth_krb5 = B_FALSE;
2442 negotiate_encrypt = B_FALSE;
2443 return (AUTH_REJECT);
2446 if (init_status == 0 && auth_level != -1) {
2447 if (negotiate_auth_krb5) {
2449 * Negotiate Authentication FIRST
2451 send_do(TELOPT_AUTHENTICATION);
2452 remopts[TELOPT_AUTHENTICATION] =
2453 OPT_YES_BUT_ALWAYS_LOOK;
2455 while (sequenceIs(authopt, getauth))
2456 ttloop();
2458 if (remopts[TELOPT_AUTHENTICATION] == OPT_YES) {
2460 * Request KRB5 Mutual authentication and if that fails,
2461 * KRB5 1-way client authentication
2463 uchar_t sbbuf[MAXOPTLEN], *p;
2464 p = sbbuf;
2465 *p++ = (uchar_t)IAC;
2466 *p++ = (uchar_t)SB;
2467 *p++ = (uchar_t)TELOPT_AUTHENTICATION;
2468 *p++ = (uchar_t)TELQUAL_SEND;
2469 if (negotiate_auth_krb5) {
2470 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2471 *p++ = (uchar_t)(AUTH_WHO_CLIENT |
2472 AUTH_HOW_MUTUAL |
2473 AUTH_ENCRYPT_ON);
2474 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2475 *p++ = (uchar_t)(AUTH_WHO_CLIENT |
2476 AUTH_HOW_MUTUAL);
2477 *p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2478 *p++ = (uchar_t)(AUTH_WHO_CLIENT|
2479 AUTH_HOW_ONE_WAY);
2480 } else {
2481 *p++ = (uchar_t)AUTHTYPE_NULL;
2483 *p++ = (uchar_t)IAC;
2484 *p++ = (uchar_t)SE;
2486 write_data_len((const char *)sbbuf,
2487 (size_t)(p - sbbuf));
2488 netflush();
2489 if (auth_debug)
2490 (void) fprintf(stderr,
2491 "SENT TELOPT_AUTHENTICATION "
2492 "[data]\n");
2494 /* auth_wait returns the authentication level */
2495 /* status = auth_wait(username, len); */
2496 while (sequenceIs(authdone, getauth))
2497 ttloop();
2499 * Now check to see if the user is valid or not
2501 if (authenticated == NULL || authenticated == &NoAuth)
2502 auth_status = AUTH_REJECT;
2503 else {
2505 * We cant be VALID until the user status is
2506 * checked.
2508 if (auth_status == AUTH_VALID)
2509 auth_status = AUTH_USER;
2511 if (authenticated->AuthName ==
2512 AUTHTYPE_KERBEROS_V5)
2513 auth_status = krb5_user_status(
2514 username, *len, auth_status);
2518 return (auth_status);
2521 static void
2522 getencrtype(void)
2524 if (krb5_privacy_allowed() && negotiate_encrypt) {
2525 if (myopts[TELOPT_ENCRYPT] != OPT_YES) {
2526 if (!sent_will_encrypt) {
2527 send_will(TELOPT_ENCRYPT);
2528 sent_will_encrypt = B_TRUE;
2530 if (enc_debug)
2531 (void) fprintf(stderr, "SENT WILL ENCRYPT\n");
2533 if (remopts[TELOPT_ENCRYPT] != OPT_YES) {
2534 if (!sent_do_encrypt) {
2535 send_do(TELOPT_ENCRYPT);
2536 sent_do_encrypt = B_TRUE;
2537 remopts[TELOPT_ENCRYPT] =
2538 OPT_YES_BUT_ALWAYS_LOOK;
2540 if (enc_debug)
2541 (void) fprintf(stderr, "SENT DO ENCRYPT\n");
2543 myopts[TELOPT_ENCRYPT] = OPT_YES;
2545 while (sequenceIs(encropt, getencr))
2546 ttloop();
2548 if (auth_status != AUTH_REJECT &&
2549 remopts[TELOPT_ENCRYPT] == OPT_YES &&
2550 myopts[TELOPT_ENCRYPT] == OPT_YES) {
2552 if (sent_encrypt_support == B_FALSE) {
2553 write_data("%c%c%c%c%c%c%c",
2554 (uchar_t)IAC,
2555 (uchar_t)SB,
2556 (uchar_t)TELOPT_ENCRYPT,
2557 (uchar_t)ENCRYPT_SUPPORT,
2558 (uchar_t)TELOPT_ENCTYPE_DES_CFB64,
2559 (uchar_t)IAC,
2560 (uchar_t)SE);
2562 netflush();
2565 * Now wait for a response to these messages before
2566 * continuing...
2567 * Look for TELOPT_ENCRYPT suboptions
2569 while (sequenceIs(encr_support, getencr))
2570 ttloop();
2572 } else {
2573 /* Dont need responses to these, so dont wait for them */
2574 settimer(encropt);
2575 remopts[TELOPT_ENCRYPT] = OPT_NO;
2576 myopts[TELOPT_ENCRYPT] = OPT_NO;
2582 * getterminaltype
2584 * Ask the other end to send along its terminal type.
2585 * Output is the variable terminaltype filled in.
2587 static void
2588 getterminaltype(void)
2591 * The remote side may have already sent this info, so
2592 * dont ask for these options if the other side already
2593 * sent the information.
2595 if (sequenceIs(ttypeopt, getterminal)) {
2596 send_do(TELOPT_TTYPE);
2597 remopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK;
2600 if (sequenceIs(nawsopt, getterminal)) {
2601 send_do(TELOPT_NAWS);
2602 remopts[TELOPT_NAWS] = OPT_YES_BUT_ALWAYS_LOOK;
2605 if (sequenceIs(xdisplocopt, getterminal)) {
2606 send_do(TELOPT_XDISPLOC);
2607 remopts[TELOPT_XDISPLOC] = OPT_YES_BUT_ALWAYS_LOOK;
2610 if (sequenceIs(environopt, getterminal)) {
2611 send_do(TELOPT_NEW_ENVIRON);
2612 remopts[TELOPT_NEW_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2615 if (sequenceIs(oenvironopt, getterminal)) {
2616 send_do(TELOPT_OLD_ENVIRON);
2617 remopts[TELOPT_OLD_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2620 /* make sure encryption is started here */
2621 while (auth_status != AUTH_REJECT &&
2622 authenticated != &NoAuth && authenticated != NULL &&
2623 remopts[TELOPT_ENCRYPT] == OPT_YES &&
2624 encr_data.encrypt.autoflag &&
2625 encr_data.encrypt.state != ENCR_STATE_OK) {
2626 if (enc_debug)
2627 (void) fprintf(stderr, "getterminaltype() forcing encrypt\n");
2628 ttloop();
2631 if (enc_debug) {
2632 (void) fprintf(stderr, "getterminaltype() encryption %sstarted\n",
2633 encr_data.encrypt.state == ENCR_STATE_OK ? "" : "not ");
2636 while (sequenceIs(ttypeopt, getterminal) ||
2637 sequenceIs(nawsopt, getterminal) ||
2638 sequenceIs(xdisplocopt, getterminal) ||
2639 sequenceIs(environopt, getterminal) ||
2640 sequenceIs(oenvironopt, getterminal)) {
2641 ttloop();
2645 if (remopts[TELOPT_TTYPE] == OPT_YES) {
2646 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2647 (uchar_t)TELOPT_TTYPE, (uchar_t)TELQUAL_SEND,
2648 (uchar_t)IAC, (uchar_t)SE };
2650 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2652 if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2653 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2654 (uchar_t)TELOPT_XDISPLOC, (uchar_t)TELQUAL_SEND,
2655 (uchar_t)IAC, (uchar_t)SE };
2657 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2659 if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2660 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2661 (uchar_t)TELOPT_NEW_ENVIRON, (uchar_t)TELQUAL_SEND,
2662 (uchar_t)IAC, (uchar_t)SE };
2664 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2666 if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2667 static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2668 (uchar_t)TELOPT_OLD_ENVIRON, (uchar_t)TELQUAL_SEND,
2669 (uchar_t)IAC, (uchar_t)SE };
2671 write_data_len((const char *)sbbuf, sizeof (sbbuf));
2674 if (remopts[TELOPT_TTYPE] == OPT_YES) {
2675 while (sequenceIs(ttypesubopt, getterminal)) {
2676 ttloop();
2679 if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2680 while (sequenceIs(xdisplocsubopt, getterminal)) {
2681 ttloop();
2684 if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2685 while (sequenceIs(environsubopt, getterminal)) {
2686 ttloop();
2689 if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2690 while (sequenceIs(oenvironsubopt, getterminal)) {
2691 ttloop();
2694 init_neg_done = 1;
2697 pid_t pid;
2700 * Get a pty, scan input lines.
2702 static void
2703 doit(int f, struct sockaddr_storage *who)
2705 char *host;
2706 char host_name[MAXHOSTNAMELEN];
2707 int p, t, tt;
2708 struct sgttyb b;
2709 int ptmfd; /* fd of logindmux connected to pty */
2710 int netfd; /* fd of logindmux connected to netf */
2711 struct stat buf;
2712 struct protocol_arg telnetp;
2713 struct strioctl telnetmod;
2714 struct envlist *env, *next;
2715 int nsize = 0;
2716 char abuf[INET6_ADDRSTRLEN];
2717 struct sockaddr_in *sin;
2718 struct sockaddr_in6 *sin6;
2719 socklen_t wholen;
2720 char username[MAXUSERNAMELEN];
2721 int len;
2722 uchar_t passthru;
2723 char *slavename;
2725 if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) {
2726 fatalperror(f, "open /dev/ptmx", errno);
2728 if (grantpt(p) == -1)
2729 fatal(f, "could not grant slave pty");
2730 if (unlockpt(p) == -1)
2731 fatal(f, "could not unlock slave pty");
2732 if ((slavename = ptsname(p)) == NULL)
2733 fatal(f, "could not enable slave pty");
2734 (void) dup2(f, 0);
2735 if ((t = open(slavename, O_RDWR | O_NOCTTY)) == -1)
2736 fatal(f, "could not open slave pty");
2737 if (ioctl(t, I_PUSH, "ptem") == -1)
2738 fatalperror(f, "ioctl I_PUSH ptem", errno);
2739 if (ioctl(t, I_PUSH, "ldterm") == -1)
2740 fatalperror(f, "ioctl I_PUSH ldterm", errno);
2741 if (ioctl(t, I_PUSH, "ttcompat") == -1)
2742 fatalperror(f, "ioctl I_PUSH ttcompat", errno);
2744 line = slavename;
2746 pty = t;
2748 if (ioctl(t, TIOCGETP, &b) == -1)
2749 syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n");
2750 b.sg_flags = O_CRMOD|O_XTABS|O_ANYP;
2751 /* XXX - ispeed and ospeed must be non-zero */
2752 b.sg_ispeed = B38400;
2753 b.sg_ospeed = B38400;
2754 if (ioctl(t, TIOCSETN, &b) == -1)
2755 syslog(LOG_INFO, "ioctl TIOCSETN pty t: %m\n");
2756 if (ioctl(pty, TIOCGETP, &b) == -1)
2757 syslog(LOG_INFO, "ioctl TIOCGETP pty pty: %m\n");
2758 b.sg_flags &= ~O_ECHO;
2759 if (ioctl(pty, TIOCSETN, &b) == -1)
2760 syslog(LOG_INFO, "ioctl TIOCSETN pty pty: %m\n");
2762 if (who->ss_family == AF_INET) {
2763 char *addrbuf = NULL;
2764 char *portbuf = NULL;
2766 sin = (struct sockaddr_in *)who;
2767 wholen = sizeof (struct sockaddr_in);
2769 addrbuf = (char *)malloc(wholen);
2770 if (addrbuf == NULL)
2771 fatal(f, "Cannot alloc memory for address info\n");
2772 portbuf = (char *)malloc(sizeof (sin->sin_port));
2773 if (portbuf == NULL) {
2774 free(addrbuf);
2775 fatal(f, "Cannot alloc memory for port info\n");
2778 (void) memcpy(addrbuf, (const void *)&sin->sin_addr, wholen);
2779 (void) memcpy(portbuf, (const void *)&sin->sin_port,
2780 sizeof (sin->sin_port));
2782 free(rsaddr.contents);
2784 rsaddr.contents = (krb5_octet *)addrbuf;
2785 rsaddr.length = wholen;
2786 rsaddr.addrtype = ADDRTYPE_INET;
2788 free(rsport.contents);
2790 rsport.contents = (krb5_octet *)portbuf;
2791 rsport.length = sizeof (sin->sin_port);
2792 rsport.addrtype = ADDRTYPE_IPPORT;
2793 } else if (who->ss_family == AF_INET6) {
2794 struct in_addr ipv4_addr;
2795 char *addrbuf = NULL;
2796 char *portbuf = NULL;
2798 sin6 = (struct sockaddr_in6 *)who;
2799 wholen = sizeof (struct sockaddr_in6);
2801 IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2802 &ipv4_addr);
2804 addrbuf = (char *)malloc(wholen);
2805 if (addrbuf == NULL)
2806 fatal(f, "Cannot alloc memory for address info\n");
2808 portbuf = (char *)malloc(sizeof (sin6->sin6_port));
2809 if (portbuf == NULL) {
2810 free(addrbuf);
2811 fatal(f, "Cannot alloc memory for port info\n");
2814 (void) memcpy((void *) addrbuf,
2815 (const void *)&ipv4_addr,
2816 wholen);
2818 * If we already used rsaddr.contents, free the previous
2819 * buffer.
2821 free(rsaddr.contents);
2823 rsaddr.contents = (krb5_octet *)addrbuf;
2824 rsaddr.length = sizeof (ipv4_addr);
2825 rsaddr.addrtype = ADDRTYPE_INET;
2827 (void) memcpy((void *) portbuf, (const void *)&sin6->sin6_port,
2828 sizeof (sin6->sin6_port));
2830 free(rsport.contents);
2832 rsport.contents = (krb5_octet *)portbuf;
2833 rsport.length = sizeof (sin6->sin6_port);
2834 rsport.addrtype = ADDRTYPE_IPPORT;
2835 } else {
2836 syslog(LOG_ERR, "unknown address family %d\n",
2837 who->ss_family);
2838 fatal(f, "getpeername: unknown address family\n");
2841 if (getnameinfo((const struct sockaddr *) who, wholen, host_name,
2842 sizeof (host_name), NULL, 0, 0) == 0) {
2843 host = host_name;
2844 } else {
2846 * If the '-U' option was given on the cmd line, we must
2847 * be able to lookup the hostname
2849 if (resolve_hostname) {
2850 fatal(f, "Couldn't resolve your address into a "
2851 "host name.\r\nPlease contact your net "
2852 "administrator");
2855 if (who->ss_family == AF_INET6) {
2856 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2857 struct in_addr ipv4_addr;
2859 IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2860 &ipv4_addr);
2861 host = (char *)inet_ntop(AF_INET,
2862 &ipv4_addr, abuf, sizeof (abuf));
2863 } else {
2864 host = (char *)inet_ntop(AF_INET6,
2865 &sin6->sin6_addr, abuf,
2866 sizeof (abuf));
2868 } else if (who->ss_family == AF_INET) {
2869 host = (char *)inet_ntop(AF_INET,
2870 &sin->sin_addr, abuf, sizeof (abuf));
2874 * Note that sockmod has to be removed since readstream assumes
2875 * a "raw" TPI endpoint (e.g. it uses getmsg).
2877 if (removemod(f, "sockmod") < 0)
2878 fatalperror(f, "couldn't remove sockmod", errno);
2880 encrypt_init();
2883 * Push the crypto module on the stream before 'telmod' so it
2884 * can encrypt/decrypt without interfering with telmod functionality
2885 * We must push it now because many of the crypto options negotiated
2886 * initially must be saved in the crypto module (via IOCTL calls).
2888 if (ioctl(f, I_PUSH, "cryptmod") < 0)
2889 fatalperror(f, "ioctl I_PUSH cryptmod", errno);
2891 cryptmod_fd = f;
2893 * gotta set the encryption clock now because it is often negotiated
2894 * immediately by the client, and if we wait till after we negotiate
2895 * auth, it will be out of whack with when the WILL/WONT ENCRYPT
2896 * option is received.
2898 settimer(getencr);
2901 * get terminal type.
2903 username[0] = '\0';
2904 len = sizeof (username);
2906 settimer(getterminal);
2907 settimer(getauth);
2909 * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
2911 auth_status = getauthtype(username, &len);
2913 * Exchange TELOPT_ENCRYPT options per RFC 2946
2915 getencrtype();
2916 getterminaltype();
2918 if (ioctl(f, I_PUSH, "telmod") < 0)
2919 fatalperror(f, "ioctl I_PUSH telmod", errno);
2922 * Make sure telmod will pass unrecognized IOCTLs to cryptmod
2924 passthru = 1;
2926 telnetmod.ic_cmd = CRYPTPASSTHRU;
2927 telnetmod.ic_timout = -1;
2928 telnetmod.ic_len = sizeof (uchar_t);
2929 telnetmod.ic_dp = (char *)&passthru;
2931 if (ioctl(f, I_STR, &telnetmod) < 0)
2932 fatal(f, "ioctl CRPASSTHRU failed\n");
2934 if (!ncc)
2935 netip = netibuf;
2938 * readstream will do a getmsg till it receives M_PROTO type
2939 * T_DATA_REQ from telnetmodopen(). This signals that all data
2940 * in-flight before telmod was pushed has been received at the
2941 * stream head.
2943 while ((nsize = readstream(f, netibuf, ncc + netip - netibuf)) > 0) {
2944 ncc += nsize;
2947 if (nsize < 0) {
2948 fatalperror(f, "readstream failed\n", errno);
2952 * open logindmux drivers and link them with network and ptm
2953 * file descriptors.
2955 if ((ptmfd = open("/dev/logindmux", O_RDWR)) == -1) {
2956 fatalperror(f, "open /dev/logindmux", errno);
2958 if ((netfd = open("/dev/logindmux", O_RDWR)) == -1) {
2959 fatalperror(f, "open /dev/logindmux", errno);
2962 if (ioctl(ptmfd, I_LINK, p) < 0)
2963 fatal(f, "ioctl I_LINK of /dev/ptmx failed\n");
2964 if (ioctl(netfd, I_LINK, f) < 0)
2965 fatal(f, "ioctl I_LINK of tcp connection failed\n");
2968 * Figure out the device number of ptm's mux fd, and pass that
2969 * to the net's mux.
2971 if (fstat(ptmfd, &buf) < 0) {
2972 fatalperror(f, "fstat ptmfd failed", errno);
2974 telnetp.dev = buf.st_rdev;
2975 telnetp.flag = 0;
2977 telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
2978 telnetmod.ic_timout = -1;
2979 telnetmod.ic_len = sizeof (struct protocol_arg);
2980 telnetmod.ic_dp = (char *)&telnetp;
2982 if (ioctl(netfd, I_STR, &telnetmod) < 0)
2983 fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
2986 * Figure out the device number of the net's mux fd, and pass that
2987 * to the ptm's mux.
2989 if (fstat(netfd, &buf) < 0) {
2990 fatalperror(f, "fstat netfd failed", errno);
2992 telnetp.dev = buf.st_rdev;
2993 telnetp.flag = 1;
2995 telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
2996 telnetmod.ic_timout = -1;
2997 telnetmod.ic_len = sizeof (struct protocol_arg);
2998 telnetmod.ic_dp = (char *)&telnetp;
3000 if (ioctl(ptmfd, I_STR, &telnetmod) < 0)
3001 fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
3003 net = netfd;
3004 master = ptmfd;
3005 cryptmod_fd = netfd;
3008 * Show banner that getty never gave, but
3009 * only if the user did not automatically authenticate.
3011 if (getenv("USER") == NULL && auth_status < AUTH_USER)
3012 showbanner();
3015 * If the user automatically authenticated with Kerberos
3016 * we must set the service name that PAM will use. We
3017 * need to do it BEFORE the child fork so that 'cleanup'
3018 * in the parent can call the PAM cleanup stuff with the
3019 * same PAM service that /bin/login will use to authenticate
3020 * this session.
3022 if (auth_level >= 0 && auth_status >= AUTH_USER &&
3023 (AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) {
3024 (void) strcpy(pam_svc_name, "ktelnet");
3027 * Request to do suppress go ahead.
3029 * Send this before sending the TELOPT_ECHO stuff below because
3030 * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
3031 * that has them turn off local echo mode if SGA is not received first.
3032 * This also has the odd side-effect of causing the client to enable
3033 * encryption and then immediately disable it during the ECHO option
3034 * negotiations. Its just better to to SGA first now that we support
3035 * encryption.
3037 if (!myopts[TELOPT_SGA]) {
3038 dooption(TELOPT_SGA);
3042 * Pretend we got a DO ECHO from the client if we have not
3043 * yet negotiated the ECHO.
3045 if (!myopts[TELOPT_ECHO]) {
3046 dooption(TELOPT_ECHO);
3050 * Is the client side a 4.2 (NOT 4.3) system? We need to know this
3051 * because 4.2 clients are unable to deal with TCP urgent data.
3053 * To find out, we send out a "DO ECHO". If the remote system
3054 * answers "WILL ECHO" it is probably a 4.2 client, and we note
3055 * that fact ("WILL ECHO" ==> that the client will echo what
3056 * WE, the server, sends it; it does NOT mean that the client will
3057 * echo the terminal input).
3059 send_do(TELOPT_ECHO);
3060 remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;
3062 if ((pid = fork()) < 0)
3063 fatalperror(netfd, "fork", errno);
3064 if (pid)
3065 telnet(net, master);
3067 * The child process needs to be the session leader
3068 * and have the pty as its controlling tty. Thus we need
3069 * to re-open the slave side of the pty no without
3070 * the O_NOCTTY flag that we have been careful to
3071 * use up to this point.
3073 (void) setsid();
3075 tt = open(line, O_RDWR);
3076 if (tt < 0)
3077 fatalperror(netfd, line, errno);
3078 (void) close(netfd);
3079 (void) close(ptmfd);
3080 (void) close(f);
3081 (void) close(p);
3082 (void) close(t);
3083 if (tt != 0)
3084 (void) dup2(tt, 0);
3085 if (tt != 1)
3086 (void) dup2(tt, 1);
3087 if (tt != 2)
3088 (void) dup2(tt, 2);
3089 if (tt > 2)
3090 (void) close(tt);
3092 if (terminaltype)
3093 (void) local_setenv("TERM", terminaltype+5, 1);
3095 * -h : pass on name of host.
3096 * WARNING: -h is accepted by login if and only if
3097 * getuid() == 0.
3098 * -p : don't clobber the environment (so terminal type stays set).
3101 /* System V login expects a utmp entry to already be there */
3102 struct utmpx ut;
3103 (void) memset((char *)&ut, 0, sizeof (ut));
3104 (void) strncpy(ut.ut_user, ".telnet", sizeof (ut.ut_user));
3105 (void) strncpy(ut.ut_line, line, sizeof (ut.ut_line));
3106 ut.ut_pid = getpid();
3107 ut.ut_id[0] = 't';
3108 ut.ut_id[1] = (char)SC_WILDC;
3109 ut.ut_id[2] = (char)SC_WILDC;
3110 ut.ut_id[3] = (char)SC_WILDC;
3111 ut.ut_type = LOGIN_PROCESS;
3112 ut.ut_exit.e_termination = 0;
3113 ut.ut_exit.e_exit = 0;
3114 (void) time(&ut.ut_tv.tv_sec);
3115 if (makeutx(&ut) == NULL)
3116 syslog(LOG_INFO, "in.telnetd:\tmakeutx failed");
3120 * Load in the cached environment variables and either
3121 * set/unset them in the environment.
3123 for (next = envlist_head; next; ) {
3124 env = next;
3125 if (env->delete)
3126 (void) local_unsetenv(env->name);
3127 else
3128 (void) local_setenv(env->name, env->value, 1);
3129 free(env->name);
3130 free(env->value);
3131 next = env->next;
3132 free(env);
3135 if (!username || !username[0])
3136 auth_status = AUTH_REJECT; /* we dont know who this is */
3138 /* If the current auth status is less than the required level, exit */
3139 if (auth_status < auth_level) {
3140 fatal(net, "Authentication failed\n");
3141 exit(EXIT_FAILURE);
3145 * If AUTH_VALID (proper authentication REQUIRED and we have
3146 * a krb5_name), exec '/bin/login', make sure it uses the
3147 * correct PAM service name (pam_svc_name). If possible,
3148 * make sure the krb5 authenticated user's name (krb5_name)
3149 * is in the PAM REPOSITORY for krb5.
3151 if (auth_level >= 0 &&
3152 (auth_status == AUTH_VALID || auth_status == AUTH_USER) &&
3153 ((krb5_name != NULL) && strlen(krb5_name)) &&
3154 ((AuthenticatingUser != NULL) && strlen(AuthenticatingUser))) {
3155 (void) execl(LOGIN_PROGRAM, "login",
3156 "-p",
3157 "-d", slavename,
3158 "-h", host,
3159 "-u", krb5_name,
3160 "-s", pam_svc_name,
3161 "-R", KRB5_REPOSITORY_NAME,
3162 AuthenticatingUser, 0);
3163 } else if (auth_level >= 0 &&
3164 auth_status >= AUTH_USER &&
3165 (((AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) ||
3166 getenv("USER"))) {
3168 * If we only know the name but not the principal,
3169 * login will have to authenticate further.
3171 (void) execl(LOGIN_PROGRAM, "login",
3172 "-p",
3173 "-d", slavename,
3174 "-h", host,
3175 "-s", pam_svc_name, "--",
3176 (AuthenticatingUser != NULL ? AuthenticatingUser :
3177 getenv("USER")), 0);
3179 } else /* default, no auth. info available, login does it all */ {
3180 (void) execl(LOGIN_PROGRAM, "login",
3181 "-p", "-h", host, "-d", slavename, "--",
3182 getenv("USER"), 0);
3185 fatalperror(netfd, LOGIN_PROGRAM, errno);
3186 /*NOTREACHED*/
3189 static void
3190 fatal(int f, char *msg)
3192 char buf[BUFSIZ];
3194 (void) snprintf(buf, sizeof (buf), "telnetd: %s.\r\n", msg);
3195 (void) write(f, buf, strlen(buf));
3196 exit(EXIT_FAILURE);
3197 /*NOTREACHED*/
3200 static void
3201 fatalperror(int f, char *msg, int errnum)
3203 char buf[BUFSIZ];
3205 (void) snprintf(buf, sizeof (buf),
3206 "%s: %s\r\n", msg, strerror(errnum));
3207 fatal(f, buf);
3208 /*NOTREACHED*/
3212 * Main loop. Select from pty and network, and
3213 * hand data to telnet receiver finite state machine
3214 * when it receives telnet protocol. Regular data
3215 * flow between pty and network takes place through
3216 * inkernel telnet streams module (telmod).
3218 static void
3219 telnet(int net, int master)
3221 int on = 1;
3222 char mode;
3223 struct strioctl telnetmod;
3224 int nsize = 0;
3225 char binary_in = 0;
3226 char binary_out = 0;
3228 if (ioctl(net, FIONBIO, &on) == -1)
3229 syslog(LOG_INFO, "ioctl FIONBIO net: %m\n");
3230 if (ioctl(master, FIONBIO, &on) == -1)
3231 syslog(LOG_INFO, "ioctl FIONBIO pty p: %m\n");
3232 (void) signal(SIGTSTP, SIG_IGN);
3233 (void) signal(SIGCHLD, (void (*)())cleanup);
3234 (void) setpgrp();
3237 * Call telrcv() once to pick up anything received during
3238 * terminal type negotiation.
3240 telrcv();
3242 netflush();
3243 ptyflush();
3245 for (;;) {
3246 fd_set ibits, obits, xbits;
3247 int c;
3249 if (ncc < 0)
3250 break;
3252 FD_ZERO(&ibits);
3253 FD_ZERO(&obits);
3254 FD_ZERO(&xbits);
3257 * If we couldn't flush all our output to the network,
3258 * keep checking for when we can.
3260 if (nfrontp - nbackp)
3261 FD_SET(net, &obits);
3263 * Never look for input if there's still
3264 * stuff in the corresponding output buffer
3266 if (pfrontp - pbackp) {
3267 FD_SET(master, &obits);
3268 } else {
3269 FD_SET(net, &ibits);
3271 if (!SYNCHing) {
3272 FD_SET(net, &xbits);
3275 #define max(x, y) (((x) < (y)) ? (y) : (x))
3278 * make an ioctl to telnet module (net side) to send
3279 * binary mode of telnet daemon. binary_in and
3280 * binary_out are 0 if not in binary mode.
3282 if (binary_in != myopts[TELOPT_BINARY] ||
3283 binary_out != remopts[TELOPT_BINARY]) {
3285 mode = 0;
3286 if (myopts[TELOPT_BINARY] != OPT_NO)
3287 mode |= TEL_BINARY_IN;
3289 if (remopts[TELOPT_BINARY] != OPT_NO)
3290 mode |= TEL_BINARY_OUT;
3292 telnetmod.ic_cmd = TEL_IOC_MODE;
3293 telnetmod.ic_timout = -1;
3294 telnetmod.ic_len = 1;
3295 telnetmod.ic_dp = &mode;
3297 syslog(LOG_DEBUG, "TEL_IOC_MODE binary has changed\n");
3299 if (ioctl(net, I_STR, &telnetmod) < 0)
3300 fatal(net, "ioctl TEL_IOC_MODE failed\n");
3301 binary_in = myopts[TELOPT_BINARY];
3302 binary_out = remopts[TELOPT_BINARY];
3304 if (state == TS_DATA) {
3305 if ((nfrontp == nbackp) &&
3306 (pfrontp == pbackp)) {
3307 if (ioctl(net, I_NREAD, &nsize) < 0)
3308 fatalperror(net,
3309 "ioctl I_NREAD failed\n", errno);
3310 if (nsize)
3311 drainstream(nsize);
3314 * make an ioctl to reinsert remaining data at
3315 * streamhead. After this, ioctl reenables the
3316 * telnet lower put queue. This queue was
3317 * noenabled by telnet module after sending
3318 * protocol/urgent data to telnetd.
3321 telnetmod.ic_cmd = TEL_IOC_ENABLE;
3322 telnetmod.ic_timout = -1;
3323 if (ncc || nsize) {
3324 telnetmod.ic_len = ncc + nsize;
3325 telnetmod.ic_dp = netip;
3326 } else {
3327 telnetmod.ic_len = 0;
3328 telnetmod.ic_dp = NULL;
3330 if (ioctl(net, I_STR, &telnetmod) < 0)
3331 fatal(net, "ioctl TEL_IOC_ENABLE \
3332 failed\n");
3334 telmod_init_done = B_TRUE;
3336 netip = netibuf;
3337 (void) memset(netibuf, 0, netibufsize);
3339 ncc = 0;
3341 } else {
3343 * state not changed to TS_DATA and hence, more to read
3344 * send ioctl to get one more message block.
3346 telnetmod.ic_cmd = TEL_IOC_GETBLK;
3347 telnetmod.ic_timout = -1;
3348 telnetmod.ic_len = 0;
3349 telnetmod.ic_dp = NULL;
3351 if (ioctl(net, I_STR, &telnetmod) < 0)
3352 fatal(net, "ioctl TEL_IOC_GETBLK failed\n");
3355 if ((c = select(max(net, master) + 1, &ibits, &obits, &xbits,
3356 NULL)) < 1) {
3357 if (c == -1) {
3358 if (errno == EINTR) {
3359 continue;
3362 (void) sleep(5);
3363 continue;
3367 * Any urgent data?
3369 if (FD_ISSET(net, &xbits)) {
3370 SYNCHing = 1;
3374 * Something to read from the network...
3376 if (FD_ISSET(net, &ibits)) {
3377 ncc = read(net, netibuf, netibufsize);
3378 if (ncc < 0 && errno == EWOULDBLOCK)
3379 ncc = 0;
3380 else {
3381 if (ncc <= 0) {
3382 break;
3384 netip = netibuf;
3388 if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0)
3389 netflush();
3390 if (ncc > 0)
3391 telrcv();
3392 if (FD_ISSET(master, &obits) && (pfrontp - pbackp) > 0)
3393 ptyflush();
3395 cleanup(0);
3398 static void
3399 telrcv(void)
3401 int c;
3403 while (ncc > 0) {
3404 if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
3405 return;
3406 c = *netip & 0377;
3408 * Once we hit data, we want to transition back to
3409 * in-kernel processing. However, this code is shared
3410 * by getterminaltype()/ttloop() which run before the
3411 * in-kernel plumbing is available. So if we are still
3412 * processing the initial option negotiation, even TS_DATA
3413 * must be processed here.
3415 if (c != IAC && state == TS_DATA && init_neg_done) {
3416 break;
3418 netip++;
3419 ncc--;
3420 switch (state) {
3422 case TS_CR:
3423 state = TS_DATA;
3424 /* Strip off \n or \0 after a \r */
3425 if ((c == 0) || (c == '\n')) {
3426 break;
3428 /* FALLTHRU */
3430 case TS_DATA:
3431 if (c == IAC) {
3432 state = TS_IAC;
3433 break;
3435 if (inter > 0)
3436 break;
3438 * We map \r\n ==> \r, since
3439 * We now map \r\n ==> \r for pragmatic reasons.
3440 * Many client implementations send \r\n when
3441 * the user hits the CarriageReturn key.
3443 * We USED to map \r\n ==> \n, since \r\n says
3444 * that we want to be in column 1 of the next
3445 * line.
3447 if (c == '\r' && (myopts[TELOPT_BINARY] == OPT_NO)) {
3448 state = TS_CR;
3450 *pfrontp++ = c;
3451 break;
3453 case TS_IAC:
3454 switch (c) {
3457 * Send the process on the pty side an
3458 * interrupt. Do this with a NULL or
3459 * interrupt char; depending on the tty mode.
3461 case IP:
3462 interrupt();
3463 break;
3465 case BREAK:
3466 sendbrk();
3467 break;
3470 * Are You There?
3472 case AYT:
3473 write_data_len("\r\n[Yes]\r\n", 9);
3474 break;
3477 * Abort Output
3479 case AO: {
3480 struct ltchars tmpltc;
3482 ptyflush(); /* half-hearted */
3483 if (ioctl(pty, TIOCGLTC, &tmpltc) == -1)
3484 syslog(LOG_INFO,
3485 "ioctl TIOCGLTC: %m\n");
3486 if (tmpltc.t_flushc != '\377') {
3487 *pfrontp++ = tmpltc.t_flushc;
3489 netclear(); /* clear buffer back */
3490 write_data("%c%c", (uchar_t)IAC,
3491 (uchar_t)DM);
3493 neturg = nfrontp-1; /* off by one XXX */
3494 netflush();
3495 netflush(); /* XXX.sparker */
3496 break;
3500 * Erase Character and
3501 * Erase Line
3503 case EC:
3504 case EL: {
3505 struct sgttyb b;
3506 char ch;
3508 ptyflush(); /* half-hearted */
3509 if (ioctl(pty, TIOCGETP, &b) == -1)
3510 syslog(LOG_INFO,
3511 "ioctl TIOCGETP: %m\n");
3512 ch = (c == EC) ?
3513 b.sg_erase : b.sg_kill;
3514 if (ch != '\377') {
3515 *pfrontp++ = ch;
3517 break;
3521 * Check for urgent data...
3523 case DM:
3524 break;
3527 * Begin option subnegotiation...
3529 case SB:
3530 state = TS_SB;
3531 SB_CLEAR();
3532 continue;
3534 case WILL:
3535 state = TS_WILL;
3536 continue;
3538 case WONT:
3539 state = TS_WONT;
3540 continue;
3542 case DO:
3543 state = TS_DO;
3544 continue;
3546 case DONT:
3547 state = TS_DONT;
3548 continue;
3550 case IAC:
3551 *pfrontp++ = c;
3552 break;
3554 state = TS_DATA;
3555 break;
3556 case TS_SB:
3557 if (c == IAC) {
3558 state = TS_SE;
3559 } else {
3560 SB_ACCUM(c);
3562 break;
3563 case TS_SE:
3564 if (c != SE) {
3565 if (c != IAC) {
3566 SB_ACCUM((uchar_t)IAC);
3568 SB_ACCUM(c);
3569 state = TS_SB;
3571 } else {
3572 SB_TERM();
3573 suboption(); /* handle sub-option */
3574 state = TS_DATA;
3576 break;
3578 case TS_WILL:
3579 if (remopts[c] != OPT_YES)
3580 willoption(c);
3581 state = TS_DATA;
3582 continue;
3584 case TS_WONT:
3585 if (remopts[c] != OPT_NO)
3586 wontoption(c);
3587 state = TS_DATA;
3588 continue;
3590 case TS_DO:
3591 if (myopts[c] != OPT_YES)
3592 dooption(c);
3593 state = TS_DATA;
3594 continue;
3596 case TS_DONT:
3597 if (myopts[c] != OPT_NO) {
3598 dontoption(c);
3600 state = TS_DATA;
3601 continue;
3603 default:
3604 syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
3605 (void) printf("telnetd: panic state=%d\n", state);
3606 exit(EXIT_FAILURE);
3611 static void
3612 willoption(int option)
3614 uchar_t *fmt;
3615 boolean_t send_reply = B_TRUE;
3617 switch (option) {
3618 case TELOPT_BINARY:
3619 mode(O_RAW, 0);
3620 fmt = doopt;
3621 break;
3623 case TELOPT_ECHO:
3624 not42 = 0; /* looks like a 4.2 system */
3626 * Now, in a 4.2 system, to break them out of ECHOing
3627 * (to the terminal) mode, we need to send a "WILL ECHO".
3628 * Kludge upon kludge!
3630 if (myopts[TELOPT_ECHO] == OPT_YES) {
3631 dooption(TELOPT_ECHO);
3633 fmt = dont;
3634 break;
3635 case TELOPT_TTYPE:
3636 settimer(ttypeopt);
3637 goto common;
3639 case TELOPT_NAWS:
3640 settimer(nawsopt);
3641 goto common;
3643 case TELOPT_XDISPLOC:
3644 settimer(xdisplocopt);
3645 goto common;
3647 case TELOPT_NEW_ENVIRON:
3648 settimer(environopt);
3649 goto common;
3651 case TELOPT_AUTHENTICATION:
3652 settimer(authopt);
3653 if (remopts[option] == OPT_NO ||
3654 negotiate_auth_krb5 == 0)
3655 fmt = dont;
3656 else
3657 fmt = doopt;
3658 break;
3660 case TELOPT_OLD_ENVIRON:
3661 settimer(oenvironopt);
3662 goto common;
3663 common:
3664 if (remopts[option] == OPT_YES_BUT_ALWAYS_LOOK) {
3665 remopts[option] = OPT_YES;
3666 return;
3668 /*FALLTHRU*/
3669 case TELOPT_SGA:
3670 fmt = doopt;
3671 break;
3673 case TELOPT_TM:
3674 fmt = dont;
3675 break;
3677 case TELOPT_ENCRYPT:
3678 settimer(encropt); /* got response to do/dont */
3679 if (enc_debug)
3680 (void) fprintf(stderr,
3681 "RCVD IAC WILL TELOPT_ENCRYPT\n");
3682 if (krb5_privacy_allowed()) {
3683 fmt = doopt;
3684 if (sent_do_encrypt)
3685 send_reply = B_FALSE;
3686 else
3687 sent_do_encrypt = B_TRUE;
3688 } else {
3689 fmt = dont;
3691 break;
3693 default:
3694 fmt = dont;
3695 break;
3697 if (fmt == doopt) {
3698 remopts[option] = OPT_YES;
3699 } else {
3700 remopts[option] = OPT_NO;
3702 if (send_reply) {
3703 write_data((const char *)fmt, option);
3704 netflush();
3708 static void
3709 wontoption(int option)
3711 uchar_t *fmt;
3712 int send_reply = 1;
3714 switch (option) {
3715 case TELOPT_ECHO:
3716 not42 = 1; /* doesn't seem to be a 4.2 system */
3717 break;
3719 case TELOPT_BINARY:
3720 mode(0, O_RAW);
3721 break;
3723 case TELOPT_TTYPE:
3724 settimer(ttypeopt);
3725 break;
3727 case TELOPT_NAWS:
3728 settimer(nawsopt);
3729 break;
3731 case TELOPT_XDISPLOC:
3732 settimer(xdisplocopt);
3733 break;
3735 case TELOPT_NEW_ENVIRON:
3736 settimer(environopt);
3737 break;
3739 case TELOPT_OLD_ENVIRON:
3740 settimer(oenvironopt);
3741 break;
3743 case TELOPT_AUTHENTICATION:
3744 settimer(authopt);
3745 auth_finished(0, AUTH_REJECT);
3746 if (auth_debug)
3747 (void) fprintf(stderr,
3748 "RCVD WONT TELOPT_AUTHENTICATE\n");
3750 remopts[option] = OPT_NO;
3751 send_reply = 0;
3752 break;
3754 case TELOPT_ENCRYPT:
3755 if (enc_debug)
3756 (void) fprintf(stderr,
3757 "RCVD IAC WONT TELOPT_ENCRYPT\n");
3758 settimer(encropt); /* got response to will/wont */
3760 * Remote side cannot send encryption. No reply necessary
3761 * Treat this as if "IAC SB ENCRYPT END IAC SE" were
3762 * received (RFC 2946) and disable crypto.
3764 encrypt_end(TELNET_DIR_DECRYPT);
3765 send_reply = 0;
3766 break;
3769 fmt = dont;
3770 remopts[option] = OPT_NO;
3771 if (send_reply) {
3772 write_data((const char *)fmt, option);
3777 * We received an "IAC DO ..." message from the client, change our state
3778 * to OPT_YES.
3780 static void
3781 dooption(int option)
3783 uchar_t *fmt;
3784 boolean_t send_reply = B_TRUE;
3786 switch (option) {
3788 case TELOPT_TM:
3789 fmt = wont;
3790 break;
3792 case TELOPT_ECHO:
3793 mode(O_ECHO|O_CRMOD, 0);
3794 fmt = will;
3795 break;
3797 case TELOPT_BINARY:
3798 mode(O_RAW, 0);
3799 fmt = will;
3800 break;
3802 case TELOPT_SGA:
3803 fmt = will;
3804 break;
3806 case TELOPT_LOGOUT:
3808 * Options don't get much easier. Acknowledge the option,
3809 * and then clean up and exit.
3811 write_data((const char *)will, option);
3812 netflush();
3813 cleanup(0);
3814 /*NOTREACHED*/
3816 case TELOPT_ENCRYPT:
3817 if (enc_debug)
3818 (void) fprintf(stderr, "RCVD DO TELOPT_ENCRYPT\n");
3819 settimer(encropt);
3821 * We received a "DO". This indicates that the other side
3822 * wants us to encrypt our data (pending negotiatoin).
3823 * reply with "IAC WILL ENCRYPT" if we are able to send
3824 * encrypted data.
3826 if (krb5_privacy_allowed() && negotiate_encrypt) {
3827 fmt = will;
3828 if (sent_will_encrypt)
3829 send_reply = B_FALSE;
3830 else
3831 sent_will_encrypt = B_TRUE;
3832 /* return if we already sent "WILL ENCRYPT" */
3833 if (myopts[option] == OPT_YES)
3834 return;
3835 } else {
3836 fmt = wont;
3838 break;
3840 case TELOPT_AUTHENTICATION:
3841 if (auth_debug) {
3842 (void) fprintf(stderr,
3843 "RCVD DO TELOPT_AUTHENTICATION\n");
3846 * RFC 2941 - only the server can send
3847 * "DO TELOPT_AUTHENTICATION".
3848 * if a server receives this, it must respond with WONT...
3850 fmt = wont;
3851 break;
3853 default:
3854 fmt = wont;
3855 break;
3857 if (fmt == will) {
3858 myopts[option] = OPT_YES;
3859 } else {
3860 myopts[option] = OPT_NO;
3862 if (send_reply) {
3863 write_data((const char *)fmt, option);
3864 netflush();
3869 * We received an "IAC DONT ..." message from client.
3870 * Client does not agree with the option so act accordingly.
3872 static void
3873 dontoption(int option)
3875 int send_reply = 1;
3876 switch (option) {
3877 case TELOPT_ECHO:
3879 * we should stop echoing, since the client side will be doing
3880 * it, but keep mapping CR since CR-LF will be mapped to it.
3882 mode(0, O_ECHO);
3883 break;
3885 case TELOPT_ENCRYPT:
3886 if (enc_debug)
3887 (void) fprintf(stderr, "RCVD IAC DONT ENCRYPT\n");
3888 settimer(encropt);
3890 * Remote side cannot receive any encrypted data,
3891 * so dont send any. No reply necessary.
3893 send_reply = 0;
3894 break;
3896 default:
3897 break;
3900 myopts[option] = OPT_NO;
3902 if (send_reply) {
3903 write_data((const char *)wont, option);
3908 * suboption()
3910 * Look at the sub-option buffer, and try to be helpful to the other
3911 * side.
3914 static void
3915 suboption(void)
3917 int subchar;
3919 switch (subchar = SB_GET()) {
3920 case TELOPT_TTYPE: { /* Yaaaay! */
3921 static char terminalname[5+41] = "TERM=";
3923 settimer(ttypesubopt);
3925 if (SB_GET() != TELQUAL_IS) {
3926 return; /* ??? XXX but, this is the most robust */
3929 terminaltype = terminalname+strlen(terminalname);
3931 while (terminaltype < (terminalname + sizeof (terminalname) -
3932 1) && !SB_EOF()) {
3933 int c;
3935 c = SB_GET();
3936 if (isupper(c)) {
3937 c = tolower(c);
3939 *terminaltype++ = c; /* accumulate name */
3941 *terminaltype = 0;
3942 terminaltype = terminalname;
3943 break;
3946 case TELOPT_NAWS: {
3947 struct winsize ws;
3949 if (SB_EOF()) {
3950 return;
3952 ws.ws_col = SB_GET() << 8;
3953 if (SB_EOF()) {
3954 return;
3956 ws.ws_col |= SB_GET();
3957 if (SB_EOF()) {
3958 return;
3960 ws.ws_row = SB_GET() << 8;
3961 if (SB_EOF()) {
3962 return;
3964 ws.ws_row |= SB_GET();
3965 ws.ws_xpixel = 0; ws.ws_ypixel = 0;
3966 (void) ioctl(pty, TIOCSWINSZ, &ws);
3967 settimer(nawsopt);
3968 break;
3971 case TELOPT_XDISPLOC: {
3972 if (SB_EOF() || SB_GET() != TELQUAL_IS) {
3973 return;
3975 settimer(xdisplocsubopt);
3976 subpointer[SB_LEN()] = '\0';
3977 if ((new_env("DISPLAY", subpointer)) == 1)
3978 perror("malloc");
3979 break;
3982 case TELOPT_NEW_ENVIRON:
3983 case TELOPT_OLD_ENVIRON: {
3984 int c;
3985 char *cp, *varp, *valp;
3987 if (SB_EOF())
3988 return;
3989 c = SB_GET();
3990 if (c == TELQUAL_IS) {
3991 if (subchar == TELOPT_OLD_ENVIRON)
3992 settimer(oenvironsubopt);
3993 else
3994 settimer(environsubopt);
3995 } else if (c != TELQUAL_INFO) {
3996 return;
3999 if (subchar == TELOPT_NEW_ENVIRON) {
4000 while (!SB_EOF()) {
4001 c = SB_GET();
4002 if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
4003 break;
4005 } else
4007 while (!SB_EOF()) {
4008 c = SB_GET();
4009 if ((c == env_ovar) || (c == ENV_USERVAR))
4010 break;
4014 if (SB_EOF())
4015 return;
4017 cp = varp = (char *)subpointer;
4018 valp = 0;
4020 while (!SB_EOF()) {
4021 c = SB_GET();
4022 if (subchar == TELOPT_OLD_ENVIRON) {
4023 if (c == env_ovar)
4024 c = NEW_ENV_VAR;
4025 else if (c == env_ovalue)
4026 c = NEW_ENV_VALUE;
4028 switch (c) {
4030 case NEW_ENV_VALUE:
4031 *cp = '\0';
4032 cp = valp = (char *)subpointer;
4033 break;
4035 case NEW_ENV_VAR:
4036 case ENV_USERVAR:
4037 *cp = '\0';
4038 if (valp) {
4039 if ((new_env(varp, valp)) == 1) {
4040 perror("malloc");
4042 } else {
4043 (void) del_env(varp);
4045 cp = varp = (char *)subpointer;
4046 valp = 0;
4047 break;
4049 case ENV_ESC:
4050 if (SB_EOF())
4051 break;
4052 c = SB_GET();
4053 /* FALL THROUGH */
4054 default:
4055 *cp++ = c;
4056 break;
4059 *cp = '\0';
4060 if (valp) {
4061 if ((new_env(varp, valp)) == 1) {
4062 perror("malloc");
4064 } else {
4065 (void) del_env(varp);
4067 break;
4068 } /* end of case TELOPT_NEW_ENVIRON */
4070 case TELOPT_AUTHENTICATION:
4071 if (SB_EOF())
4072 break;
4073 switch (SB_GET()) {
4074 case TELQUAL_SEND:
4075 case TELQUAL_REPLY:
4077 * These are sent server only and cannot be sent by the
4078 * client.
4080 break;
4081 case TELQUAL_IS:
4082 if (auth_debug)
4083 (void) fprintf(stderr,
4084 "RCVD AUTHENTICATION IS "
4085 "(%d bytes)\n",
4086 SB_LEN());
4087 if (!auth_negotiated)
4088 auth_is((uchar_t *)subpointer, SB_LEN());
4089 break;
4090 case TELQUAL_NAME:
4091 if (auth_debug)
4092 (void) fprintf(stderr,
4093 "RCVD AUTHENTICATION NAME "
4094 "(%d bytes)\n",
4095 SB_LEN());
4096 if (!auth_negotiated)
4097 auth_name((uchar_t *)subpointer, SB_LEN());
4098 break;
4100 break;
4102 case TELOPT_ENCRYPT: {
4103 int c;
4104 if (SB_EOF())
4105 break;
4106 c = SB_GET();
4107 #ifdef ENCRYPT_NAMES
4108 if (enc_debug)
4109 (void) fprintf(stderr, "RCVD ENCRYPT %s\n",
4110 ENCRYPT_NAME(c));
4111 #endif /* ENCRYPT_NAMES */
4112 switch (c) {
4113 case ENCRYPT_SUPPORT:
4114 encrypt_support(subpointer, SB_LEN());
4115 break;
4116 case ENCRYPT_IS:
4117 encrypt_is((uchar_t *)subpointer, SB_LEN());
4118 break;
4119 case ENCRYPT_REPLY:
4120 (void) encrypt_reply(subpointer, SB_LEN());
4121 break;
4122 case ENCRYPT_START:
4123 encrypt_start();
4124 break;
4125 case ENCRYPT_END:
4126 encrypt_end(TELNET_DIR_DECRYPT);
4127 break;
4128 case ENCRYPT_REQSTART:
4129 encrypt_request_start();
4130 break;
4131 case ENCRYPT_REQEND:
4133 * We can always send an REQEND so that we cannot
4134 * get stuck encrypting. We should only get this
4135 * if we have been able to get in the correct mode
4136 * anyhow.
4138 encrypt_request_end();
4139 break;
4140 case ENCRYPT_ENC_KEYID:
4141 encrypt_enc_keyid(subpointer, SB_LEN());
4142 break;
4143 case ENCRYPT_DEC_KEYID:
4144 encrypt_dec_keyid(subpointer, SB_LEN());
4145 break;
4146 default:
4147 break;
4150 break;
4152 default:
4153 break;
4157 static void
4158 mode(int on, int off)
4160 struct termios tios;
4162 ptyflush();
4163 if (tcgetattr(pty, &tios) < 0)
4164 syslog(LOG_INFO, "tcgetattr: %m\n");
4166 if (on & O_RAW) {
4167 tios.c_cflag |= CS8;
4168 tios.c_iflag &= ~IUCLC;
4169 tios.c_lflag &= ~(XCASE|IEXTEN);
4171 if (off & O_RAW) {
4172 if ((tios.c_cflag & PARENB) != 0)
4173 tios.c_cflag &= ~CS8;
4174 tios.c_lflag |= IEXTEN;
4177 if (on & O_ECHO)
4178 tios.c_lflag |= ECHO;
4179 if (off & O_ECHO)
4180 tios.c_lflag &= ~ECHO;
4182 if (on & O_CRMOD) {
4183 tios.c_iflag |= ICRNL;
4184 tios.c_oflag |= ONLCR;
4187 * Because "O_CRMOD" will never be set in "off" we don't have to
4188 * handle this case here.
4191 if (tcsetattr(pty, TCSANOW, &tios) < 0)
4192 syslog(LOG_INFO, "tcsetattr: %m\n");
4196 * Send interrupt to process on other side of pty.
4197 * If it is in raw mode, just write NULL;
4198 * otherwise, write intr char.
4200 static void
4201 interrupt(void)
4203 struct sgttyb b;
4204 struct tchars tchars;
4206 ptyflush(); /* half-hearted */
4207 if (ioctl(pty, TIOCGETP, &b) == -1)
4208 syslog(LOG_INFO, "ioctl TIOCGETP: %m\n");
4209 if (b.sg_flags & O_RAW) {
4210 *pfrontp++ = '\0';
4211 return;
4213 *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4214 '\177' : tchars.t_intrc;
4218 * Send quit to process on other side of pty.
4219 * If it is in raw mode, just write NULL;
4220 * otherwise, write quit char.
4222 static void
4223 sendbrk(void)
4225 struct sgttyb b;
4226 struct tchars tchars;
4228 ptyflush(); /* half-hearted */
4229 (void) ioctl(pty, TIOCGETP, &b);
4230 if (b.sg_flags & O_RAW) {
4231 *pfrontp++ = '\0';
4232 return;
4234 *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4235 '\034' : tchars.t_quitc;
4238 static void
4239 ptyflush(void)
4241 int n;
4243 if ((n = pfrontp - pbackp) > 0)
4244 n = write(master, pbackp, n);
4245 if (n < 0)
4246 return;
4247 pbackp += n;
4248 if (pbackp == pfrontp)
4249 pbackp = pfrontp = ptyobuf;
4253 * nextitem()
4255 * Return the address of the next "item" in the TELNET data
4256 * stream. This will be the address of the next character if
4257 * the current address is a user data character, or it will
4258 * be the address of the character following the TELNET command
4259 * if the current address is a TELNET IAC ("I Am a Command")
4260 * character.
4263 static char *
4264 nextitem(char *current)
4266 if ((*current&0xff) != IAC) {
4267 return (current+1);
4269 switch (*(current+1)&0xff) {
4270 case DO:
4271 case DONT:
4272 case WILL:
4273 case WONT:
4274 return (current+3);
4275 case SB: /* loop forever looking for the SE */
4277 char *look = current+2;
4279 for (;;) {
4280 if ((*look++&0xff) == IAC) {
4281 if ((*look++&0xff) == SE) {
4282 return (look);
4287 default:
4288 return (current+2);
4294 * netclear()
4296 * We are about to do a TELNET SYNCH operation. Clear
4297 * the path to the network.
4299 * Things are a bit tricky since we may have sent the first
4300 * byte or so of a previous TELNET command into the network.
4301 * So, we have to scan the network buffer from the beginning
4302 * until we are up to where we want to be.
4304 * A side effect of what we do, just to keep things
4305 * simple, is to clear the urgent data pointer. The principal
4306 * caller should be setting the urgent data pointer AFTER calling
4307 * us in any case.
4309 static void
4310 netclear(void)
4312 char *thisitem, *next;
4313 char *good;
4314 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
4315 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
4317 thisitem = netobuf;
4319 while ((next = nextitem(thisitem)) <= nbackp) {
4320 thisitem = next;
4323 /* Now, thisitem is first before/at boundary. */
4325 good = netobuf; /* where the good bytes go */
4327 while (nfrontp > thisitem) {
4328 if (wewant(thisitem)) {
4329 int length;
4331 next = thisitem;
4332 do {
4333 next = nextitem(next);
4334 } while (wewant(next) && (nfrontp > next));
4335 length = next-thisitem;
4336 (void) memmove(good, thisitem, length);
4337 good += length;
4338 thisitem = next;
4339 } else {
4340 thisitem = nextitem(thisitem);
4344 nbackp = netobuf;
4345 nfrontp = good; /* next byte to be sent */
4346 neturg = 0;
4351 * netflush
4352 * Send as much data as possible to the network,
4353 * handling requests for urgent data.
4355 static void
4356 netflush(void)
4358 int n;
4360 if ((n = nfrontp - nbackp) > 0) {
4362 * if no urgent data, or if the other side appears to be an
4363 * old 4.2 client (and thus unable to survive TCP urgent data),
4364 * write the entire buffer in non-OOB mode.
4366 if ((neturg == 0) || (not42 == 0)) {
4367 n = write(net, nbackp, n); /* normal write */
4368 } else {
4369 n = neturg - nbackp;
4371 * In 4.2 (and 4.3) systems, there is some question
4372 * about what byte in a sendOOB operation is the "OOB"
4373 * data. To make ourselves compatible, we only send ONE
4374 * byte out of band, the one WE THINK should be OOB
4375 * (though we really have more the TCP philosophy of
4376 * urgent data rather than the Unix philosophy of OOB
4377 * data).
4379 if (n > 1) {
4380 /* send URGENT all by itself */
4381 n = write(net, nbackp, n-1);
4382 } else {
4383 /* URGENT data */
4384 n = send_oob(net, nbackp, n);
4388 if (n < 0) {
4389 if (errno == EWOULDBLOCK)
4390 return;
4391 /* should blow this guy away... */
4392 return;
4395 nbackp += n;
4397 if (nbackp >= neturg) {
4398 neturg = 0;
4400 if (nbackp == nfrontp) {
4401 nbackp = nfrontp = netobuf;
4405 /* ARGSUSED */
4406 static void
4407 cleanup(int signum)
4410 * If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
4411 * handle closing differently. We close "net" first and then
4412 * "master" in that order. We do close(net) first because
4413 * we have no other way to disconnect forwarding between the network
4414 * and master. So by issuing the close()'s we ensure that no further
4415 * data rises from TCP. A more complex fix would be adding proper
4416 * support for throwing a "stop" switch for forwarding data between
4417 * logindmux peers. It's possible to block in the close of the tty
4418 * while the network still receives data and the telmod module is
4419 * TEL_STOPPED. A denial-of-service attack generates this case,
4420 * see 4102102.
4423 if (!telmod_init_done) {
4424 (void) close(net);
4425 (void) close(master);
4427 rmut();
4429 exit(EXIT_FAILURE);
4432 static void
4433 rmut(void)
4435 pam_handle_t *pamh;
4436 struct utmpx *up;
4437 char user[sizeof (up->ut_user) + 1];
4438 char ttyn[sizeof (up->ut_line) + 1];
4439 char rhost[sizeof (up->ut_host) + 1];
4441 /* while cleaning up don't allow disruption */
4442 (void) signal(SIGCHLD, SIG_IGN);
4444 setutxent();
4445 while (up = getutxent()) {
4446 if (up->ut_pid == pid) {
4447 if (up->ut_type == DEAD_PROCESS) {
4449 * Cleaned up elsewhere.
4451 break;
4455 * call pam_close_session if login changed
4456 * the utmpx user entry from type LOGIN_PROCESS
4457 * to type USER_PROCESS, which happens
4458 * after pam_open_session is called.
4460 if (up->ut_type == USER_PROCESS) {
4461 (void) strlcpy(user, up->ut_user,
4462 sizeof (user));
4463 (void) strlcpy(ttyn, up->ut_line,
4464 sizeof (ttyn));
4465 (void) strlcpy(rhost, up->ut_host,
4466 sizeof (rhost));
4467 if ((pam_start("telnet", user, NULL, &pamh)) ==
4468 PAM_SUCCESS) {
4469 (void) pam_set_item(pamh, PAM_TTY,
4470 ttyn);
4471 (void) pam_set_item(pamh, PAM_RHOST,
4472 rhost);
4473 (void) pam_close_session(pamh, 0);
4474 (void) pam_end(pamh, PAM_SUCCESS);
4478 up->ut_type = DEAD_PROCESS;
4479 up->ut_exit.e_termination = WTERMSIG(0);
4480 up->ut_exit.e_exit = WEXITSTATUS(0);
4481 (void) time(&up->ut_tv.tv_sec);
4483 if (modutx(up) == NULL) {
4485 * Since modutx failed we'll
4486 * write out the new entry
4487 * ourselves.
4489 (void) pututxline(up);
4490 updwtmpx("wtmpx", up);
4492 break;
4496 endutxent();
4498 (void) signal(SIGCHLD, (void (*)())cleanup);
4501 static int
4502 readstream(int fd, char *buf, int offset)
4504 struct strbuf ctlbuf, datbuf;
4505 union T_primitives tpi;
4506 int ret = 0;
4507 int flags = 0;
4508 int bytes_avail, count;
4510 (void) memset((char *)&ctlbuf, 0, sizeof (ctlbuf));
4511 (void) memset((char *)&datbuf, 0, sizeof (datbuf));
4513 ctlbuf.buf = (char *)&tpi;
4514 ctlbuf.maxlen = sizeof (tpi);
4516 if (ioctl(fd, I_NREAD, &bytes_avail) < 0) {
4517 syslog(LOG_ERR, "I_NREAD returned error %m");
4518 return (-1);
4520 if (bytes_avail > netibufsize - offset) {
4521 count = netip - netibuf;
4522 netibuf = (char *)realloc(netibuf,
4523 (unsigned)netibufsize + bytes_avail);
4524 if (netibuf == NULL) {
4525 fatal(net, "netibuf realloc failed\n");
4527 netibufsize += bytes_avail;
4528 netip = netibuf + count;
4529 buf = netibuf;
4531 datbuf.buf = buf + offset;
4532 datbuf.maxlen = netibufsize;
4533 ret = getmsg(fd, &ctlbuf, &datbuf, &flags);
4534 if (ret < 0) {
4535 syslog(LOG_ERR, "getmsg returned -1, errno %d\n",
4536 errno);
4537 return (-1);
4539 if (ctlbuf.len <= 0) {
4540 return (datbuf.len);
4543 if (tpi.type == T_DATA_REQ) {
4544 return (0);
4547 if ((tpi.type == T_ORDREL_IND) || (tpi.type == T_DISCON_IND))
4548 cleanup(0);
4549 fatal(fd, "no data or protocol element recognized");
4550 return (0);
4553 static void
4554 drainstream(int size)
4556 int nbytes;
4557 int tsize;
4559 tsize = netip - netibuf;
4561 if ((tsize + ncc + size) > netibufsize) {
4562 if (!(netibuf = (char *)realloc(netibuf,
4563 (unsigned)tsize + ncc + size)))
4564 fatalperror(net, "netibuf realloc failed\n", errno);
4565 netibufsize = tsize + ncc + size;
4567 netip = netibuf + tsize;
4570 if ((nbytes = read(net, (char *)netip + ncc, size)) != size)
4571 syslog(LOG_ERR, "read %d bytes\n", nbytes);
4575 * TPI style replacement for socket send() primitive, so we don't require
4576 * sockmod to be on the stream.
4578 static int
4579 send_oob(int fd, char *ptr, int count)
4581 struct T_exdata_req exd_req;
4582 struct strbuf hdr, dat;
4583 int ret;
4585 exd_req.PRIM_type = T_EXDATA_REQ;
4586 exd_req.MORE_flag = 0;
4588 hdr.buf = (char *)&exd_req;
4589 hdr.len = sizeof (exd_req);
4591 dat.buf = ptr;
4592 dat.len = count;
4594 ret = putmsg(fd, &hdr, &dat, 0);
4595 if (ret == 0) {
4596 ret = count;
4598 return (ret);
4603 * local_setenv --
4604 * Set the value of the environmental variable "name" to be
4605 * "value". If rewrite is set, replace any current value.
4607 static int
4608 local_setenv(const char *name, const char *value, int rewrite)
4610 static int alloced; /* if allocated space before */
4611 char *c;
4612 int l_value, offset;
4615 * Do not allow environment variables which begin with LD_ to be
4616 * inserted into the environment. While normally the dynamic linker
4617 * protects the login program, that is based on the assumption hostile
4618 * invocation of login are from non-root users. However, since telnetd
4619 * runs as root, this cannot be utilized. So instead we simply
4620 * prevent LD_* from being inserted into the environment.
4621 * This also applies to other environment variables that
4622 * are to be ignored in setugid apps.
4623 * Note that at this point name can contain '='!
4624 * Also, do not allow TTYPROMPT to be passed along here.
4626 if (strncmp(name, "LD_", 3) == 0 ||
4627 strncmp(name, "NLSPATH", 7) == 0 ||
4628 (strncmp(name, "TTYPROMPT", 9) == 0 &&
4629 (name[9] == '\0' || name[9] == '='))) {
4630 return (-1);
4632 if (*value == '=') /* no `=' in value */
4633 ++value;
4634 l_value = strlen(value);
4635 if ((c = __findenv(name, &offset))) { /* find if already exists */
4636 if (!rewrite)
4637 return (0);
4638 if ((int)strlen(c) >= l_value) { /* old larger; copy over */
4639 while (*c++ = *value++)
4641 return (0);
4643 } else { /* create new slot */
4644 int cnt;
4645 char **p;
4647 for (p = environ, cnt = 0; *p; ++p, ++cnt)
4649 if (alloced) { /* just increase size */
4650 environ = (char **)realloc((char *)environ,
4651 (size_t)(sizeof (char *) * (cnt + 2)));
4652 if (!environ)
4653 return (-1);
4654 } else { /* get new space */
4655 alloced = 1; /* copy old entries into it */
4656 p = (char **)malloc((size_t)(sizeof (char *)*
4657 (cnt + 2)));
4658 if (!p)
4659 return (-1);
4660 (void) memcpy(p, environ, cnt * sizeof (char *));
4661 environ = p;
4663 environ[cnt + 1] = NULL;
4664 offset = cnt;
4666 for (c = (char *)name; *c && *c != '='; ++c) /* no `=' in name */
4668 if (!(environ[offset] = /* name + `=' + value */
4669 malloc((size_t)((int)(c - name) + l_value + 2))))
4670 return (-1);
4671 for (c = environ[offset]; ((*c = *name++) != 0) && (*c != '='); ++c)
4673 for (*c++ = '='; *c++ = *value++; )
4675 return (0);
4679 * local_unsetenv(name) --
4680 * Delete environmental variable "name".
4682 static void
4683 local_unsetenv(const char *name)
4685 char **p;
4686 int offset;
4688 while (__findenv(name, &offset)) /* if set multiple times */
4689 for (p = &environ[offset]; ; ++p)
4690 if ((*p = *(p + 1)) == 0)
4691 break;
4695 * __findenv --
4696 * Returns pointer to value associated with name, if any, else NULL.
4697 * Sets offset to be the offset of the name/value combination in the
4698 * environmental array, for use by local_setenv() and local_unsetenv().
4699 * Explicitly removes '=' in argument name.
4701 static char *
4702 __findenv(const char *name, int *offset)
4704 extern char **environ;
4705 int len;
4706 const char *np;
4707 char **p, *c;
4709 if (name == NULL || environ == NULL)
4710 return (NULL);
4711 for (np = name; *np && *np != '='; ++np)
4712 continue;
4713 len = np - name;
4714 for (p = environ; (c = *p) != NULL; ++p)
4715 if (strncmp(c, name, len) == 0 && c[len] == '=') {
4716 *offset = p - environ;
4717 return (c + len + 1);
4719 return (NULL);
4722 static void
4723 showbanner(void)
4725 char *cp;
4726 char evalbuf[BUFSIZ];
4728 if (defopen(defaultfile) == 0) {
4729 int flags;
4731 /* ignore case */
4732 flags = defcntl(DC_GETFLAGS, 0);
4733 TURNOFF(flags, DC_CASE);
4734 (void) defcntl(DC_SETFLAGS, flags);
4735 if (cp = defread(bannervar)) {
4736 FILE *fp;
4738 if (strlen(cp) + strlen("eval echo '") + strlen("'\n")
4739 + 1 < sizeof (evalbuf)) {
4740 (void) strlcpy(evalbuf, "eval echo '",
4741 sizeof (evalbuf));
4742 (void) strlcat(evalbuf, cp, sizeof (evalbuf));
4743 (void) strlcat(evalbuf, "'\n",
4744 sizeof (evalbuf));
4746 if (fp = popen(evalbuf, "r")) {
4747 char buf[BUFSIZ];
4748 size_t size;
4751 * Pipe I/O atomicity guarantees we
4752 * need only one read.
4754 if ((size = fread(buf, 1,
4755 sizeof (buf) - 1,
4756 fp)) != 0) {
4757 char *p;
4758 buf[size] = '\0';
4759 p = strrchr(buf, '\n');
4760 if (p != NULL)
4761 *p = '\0';
4762 if (strlen(buf)) {
4763 map_banner(buf);
4764 netflush();
4767 (void) pclose(fp);
4768 /* close default file */
4769 (void) defopen(NULL);
4770 return;
4774 (void) defopen(NULL); /* close default file */
4777 defbanner();
4778 netflush();
4781 static void
4782 map_banner(char *p)
4784 char *q;
4787 * Map the banner: "\n" -> "\r\n" and "\r" -> "\r\0"
4789 for (q = nfrontp; p && *p && q < nfrontp + sizeof (netobuf) - 1; )
4790 if (*p == '\n') {
4791 *q++ = '\r';
4792 *q++ = '\n';
4793 p++;
4794 } else if (*p == '\r') {
4795 *q++ = '\r';
4796 *q++ = '\0';
4797 p++;
4798 } else
4799 *q++ = *p++;
4801 nfrontp += q - netobuf;
4805 * Show banner that getty never gave. By default, this is `uname -sr`.
4807 * The banner includes some null's (for TELNET CR disambiguation),
4808 * so we have to be somewhat complicated.
4810 static void
4811 defbanner(void)
4813 struct utsname u;
4816 * Dont show this if the '-h' option was present
4818 if (!show_hostinfo)
4819 return;
4821 if (uname(&u) == -1)
4822 return;
4824 write_data_len((const char *) BANNER1, sizeof (BANNER1) - 1);
4825 write_data_len(u.sysname, strlen(u.sysname));
4826 write_data_len(" ", 1);
4827 write_data_len(u.release, strlen(u.release));
4828 write_data_len((const char *)BANNER2, sizeof (BANNER2) - 1);
4832 * Verify that the named module is at the top of the stream
4833 * and then pop it off.
4835 static int
4836 removemod(int f, char *modname)
4838 char topmodname[BUFSIZ];
4840 if (ioctl(f, I_LOOK, topmodname) < 0)
4841 return (-1);
4842 if (strcmp(modname, topmodname) != 0) {
4843 errno = ENXIO;
4844 return (-1);
4846 if (ioctl(f, I_POP, 0) < 0)
4847 return (-1);
4848 return (0);
4851 static void
4852 write_data(const char *format, ...)
4854 va_list args;
4855 int len;
4856 char argp[BUFSIZ];
4858 va_start(args, format);
4860 if ((len = vsnprintf(argp, sizeof (argp), format, args)) == -1)
4861 return;
4863 write_data_len(argp, len);
4864 va_end(args);
4867 static void
4868 write_data_len(const char *buf, int len)
4870 int remaining, copied;
4872 remaining = BUFSIZ - (nfrontp - netobuf);
4873 while (len > 0) {
4875 * If there's not enough space in netobuf then
4876 * try to make some.
4878 if ((len > BUFSIZ ? BUFSIZ : len) > remaining) {
4879 netflush();
4880 remaining = BUFSIZ - (nfrontp - netobuf);
4882 /* Copy as much as we can */
4883 copied = remaining > len ? len : remaining;
4884 (void) memmove(nfrontp, buf, copied);
4885 nfrontp += copied;
4886 len -= copied;
4887 remaining -= copied;
4888 buf += copied;