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]
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
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/socket.h>
51 #include <sys/filio.h>
53 #include <sys/stropts.h>
54 #include <sys/stream.h>
55 #include <sys/tihdr.h>
56 #include <sys/utsname.h>
59 #include <netinet/in.h>
62 #define AUTHTYPE_NAMES
67 #include <arpa/telnet.h>
68 #include <arpa/inet.h>
77 #include <sac.h> /* for SC_WILDC */
79 #include <sys/ttold.h>
82 #include <security/pam_appl.h>
83 #include <sys/tihdr.h>
84 #include <sys/logindmux.h>
85 #include <sys/telioctl.h>
94 #include <krb5_repository.h>
96 #include <rpc/des_crypt.h>
97 #include <sys/cryptmod.h>
100 #define TELNETD_OPTS "Ss:a:dEXUhR:M:"
102 #define DEBUG_OPTS "p:e"
104 #define DEBUG_OPTS ""
107 #define OPT_NO 0 /* won't do this option */
108 #define OPT_YES 1 /* will do this option */
109 #define OPT_YES_BUT_ALWAYS_LOOK 2
110 #define OPT_NO_BUT_ALWAYS_LOOK 3
112 #define MAXOPTLEN 256
113 #define MAXUSERNAMELEN 256
115 static char remopts
[MAXOPTLEN
];
116 static char myopts
[MAXOPTLEN
];
117 static uchar_t doopt
[] = { (uchar_t
)IAC
, (uchar_t
)DO
, '%', 'c', 0 };
118 static uchar_t dont
[] = { (uchar_t
)IAC
, (uchar_t
)DONT
, '%', 'c', 0 };
119 static uchar_t will
[] = { (uchar_t
)IAC
, (uchar_t
)WILL
, '%', 'c', 0 };
120 static uchar_t wont
[] = { (uchar_t
)IAC
, (uchar_t
)WONT
, '%', 'c', 0 };
122 * I/O data buffers, pointers, and counters.
124 static char ptyobuf
[BUFSIZ
], *pfrontp
= ptyobuf
, *pbackp
= ptyobuf
;
126 static char *netibuf
, *netip
;
127 static int netibufsize
;
129 #define NIACCUM(c) { *netip++ = c; \
133 static char netobuf
[BUFSIZ
], *nfrontp
= netobuf
, *nbackp
= netobuf
;
134 static char *neturg
= 0; /* one past last bye of urgent data */
135 /* the remote system seems to NOT be an old 4.2 */
136 static int not42
= 1;
137 static char defaultfile
[] = "/etc/default/telnetd";
138 static char bannervar
[] = "BANNER=";
140 static char BANNER1
[] = "\r\n\r\n";
141 static char BANNER2
[] = "\r\n\r\0\r\n\r\0";
144 * buffer for sub-options - enlarged to 4096 to handle credentials
147 static char subbuffer
[4096], *subpointer
= subbuffer
, *subend
= subbuffer
;
148 #define SB_CLEAR() subpointer = subbuffer;
149 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
150 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof (subbuffer))) { \
151 *subpointer++ = (c); \
153 #define SB_GET() ((*subpointer++)&0xff)
154 #define SB_EOF() (subpointer >= subend)
155 #define SB_LEN() (subend - subpointer)
157 #define MAXERRSTRLEN 1024
158 #define MAXPRINCLEN 256
160 extern uint_t
kwarn_add_warning(char *, int);
161 extern uint_t
kwarn_del_warning(char *);
163 static boolean_t auth_debug
= 0;
164 static boolean_t negotiate_auth_krb5
= 1;
165 static boolean_t auth_negotiated
= 0;
166 static int auth_status
= 0;
167 static int auth_level
= 0;
168 static char *AuthenticatingUser
= NULL
;
169 static char *krb5_name
= NULL
;
171 static krb5_address rsaddr
= { 0, 0, 0, NULL
};
172 static krb5_address rsport
= { 0, 0, 0, NULL
};
174 static krb5_context telnet_context
= 0;
175 static krb5_auth_context auth_context
= 0;
177 /* telnetd gets session key from here */
178 static krb5_ticket
*ticket
= NULL
;
179 static krb5_keyblock
*session_key
= NULL
;
180 static char *telnet_srvtab
= NULL
;
188 static AuthInfo auth_list
[] = {
189 {AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
| AUTH_HOW_MUTUAL
|
190 AUTH_ENCRYPT_ON
, "KRB5 MUTUAL CRYPTO"},
191 {AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
| AUTH_HOW_MUTUAL
,
193 {AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
| AUTH_HOW_ONE_WAY
,
198 static AuthInfo NoAuth
= {0, 0, NULL
};
200 static AuthInfo
*authenticated
= NULL
;
202 #define PREAMBLE_SIZE 5 /* for auth_reply_str allocation */
203 #define POSTAMBLE_SIZE 5
204 #define STR_DATA_LEN(len) ((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE)
206 static void auth_name(uchar_t
*, int);
207 static void auth_is(uchar_t
*, int);
209 #define NO_ENCRYPTION 0x00
210 #define SEND_ENCRYPTED 0x01
211 #define RECV_ENCRYPTED 0x02
212 #define ENCRYPT_BOTH_WAYS (SEND_ENCRYPTED | RECV_ENCRYPTED)
214 static telnet_enc_data_t encr_data
;
215 static boolean_t negotiate_encrypt
= B_TRUE
;
216 static boolean_t sent_encrypt_support
= B_FALSE
;
217 static boolean_t sent_will_encrypt
= B_FALSE
;
218 static boolean_t sent_do_encrypt
= B_FALSE
;
219 static boolean_t enc_debug
= 0;
221 static void encrypt_session_key(Session_Key
*key
, cipher_info_t
*cinfo
);
222 static int encrypt_send_encrypt_is();
224 extern void mit_des_fixup_key_parity(Block
);
225 extern int krb5_setenv(const char *, const char *, int);
226 /* need to know what FD to use to talk to the crypto module */
227 static int cryptmod_fd
= -1;
229 #define LOGIN_PROGRAM "/bin/login"
234 #define TS_DATA 0 /* base state */
235 #define TS_IAC 1 /* look for double IAC's */
236 #define TS_CR 2 /* CR-LF ->'s CR */
237 #define TS_SB 3 /* throw away begin's... */
238 #define TS_SE 4 /* ...end's (suboption negotiation) */
239 #define TS_WILL 5 /* will option negotiation */
240 #define TS_WONT 6 /* wont " */
241 #define TS_DO 7 /* do " */
242 #define TS_DONT 8 /* dont " */
245 static int master
; /* master side of pty */
246 static int pty
; /* side of pty that gets ioctls */
249 extern char **environ
;
251 static int SYNCHing
= 0; /* we are in TELNET SYNCH mode */
252 static int state
= TS_DATA
;
254 static int env_ovar
= -1; /* XXX.sparker */
255 static int env_ovalue
= -1; /* XXX.sparker */
256 static char pam_svc_name
[64];
257 static boolean_t telmod_init_done
= B_FALSE
;
259 static void doit(int, struct sockaddr_storage
*);
260 static void willoption(int);
261 static void wontoption(int);
262 static void dooption(int);
263 static void dontoption(int);
264 static void fatal(int, char *);
265 static void fatalperror(int, char *, int);
266 static void mode(int, int);
267 static void interrupt(void);
268 static void drainstream(int);
269 static int readstream(int, char *, int);
270 static int send_oob(int fd
, char *ptr
, int count
);
271 static int local_setenv(const char *name
, const char *value
, int rewrite
);
272 static void local_unsetenv(const char *name
);
273 static void suboption(void);
274 static int removemod(int f
, char *modname
);
275 static void willoption(int option
);
276 static void wontoption(int option
);
277 static void dooption(int option
);
278 static void dontoption(int option
);
279 static void write_data(const char *, ...);
280 static void write_data_len(const char *, int);
281 static void rmut(void);
282 static void cleanup(int);
283 static void telnet(int, int);
284 static void telrcv(void);
285 static void sendbrk(void);
286 static void ptyflush(void);
287 static void netclear(void);
288 static void netflush(void);
289 static void showbanner(void);
290 static void map_banner(char *);
291 static void defbanner(void);
292 static void ttloop(void);
295 * The env_list linked list is used to store the environment variables
296 * until the final exec of login. A malevolent client might try to
297 * send an environment variable intended to affect the telnet daemon's
298 * execution. Right now the BANNER expansion is the only instance.
299 * Note that it is okay to pass the environment variables to login
300 * because login protects itself against environment variables mischief.
304 struct envlist
*next
;
310 static struct envlist
*envlist_head
= NULL
;
313 * The following are some clocks used to decide how to interpret
314 * the relationship between various variables.
319 system
, /* what the current time is */
320 echotoggle
, /* last time user entered echo character */
321 modenegotiated
, /* last time operating mode negotiated */
322 didnetreceive
, /* last time we read data from network */
323 ttypeopt
, /* ttype will/won't received */
324 ttypesubopt
, /* ttype subopt is received */
325 getterminal
, /* time started to get terminal information */
326 xdisplocopt
, /* xdisploc will/wont received */
327 xdisplocsubopt
, /* xdisploc suboption received */
328 nawsopt
, /* window size will/wont received */
329 nawssubopt
, /* window size received */
330 environopt
, /* environment option will/wont received */
331 oenvironopt
, /* "old" environ option will/wont received */
332 environsubopt
, /* environment option suboption received */
333 oenvironsubopt
, /* "old environ option suboption received */
334 gotDM
; /* when did we last see a data mark */
337 int authopt
; /* Authentication option negotiated */
345 static int init_neg_done
= 0;
346 static boolean_t resolve_hostname
= 0;
347 static boolean_t show_hostinfo
= 1;
349 #define settimer(x) (clocks.x = ++clocks.system)
350 #define sequenceIs(x, y) (clocks.x < clocks.y)
352 static void send_will(int);
353 static void send_wont(int);
354 static void send_do(int);
355 static char *__findenv(const char *name
, int *offset
);
359 auth_finished(AuthInfo
*ap
, int result
)
361 if ((authenticated
= ap
) == NULL
) {
362 authenticated
= &NoAuth
;
363 if (myopts
[TELOPT_ENCRYPT
] == OPT_YES
)
364 send_wont(TELOPT_ENCRYPT
);
365 myopts
[TELOPT_ENCRYPT
] = remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
366 encr_data
.encrypt
.autoflag
= 0;
367 } else if (result
!= AUTH_REJECT
&&
368 myopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
369 remopts
[TELOPT_ENCRYPT
] == OPT_YES
) {
372 * Authentication successful, so we have a session key, and
373 * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT.
375 * Can't have sent ENCRYPT SUPPORT yet! And if we're sending it
376 * now it's really only because we did the DO ENCRYPT/WILL
377 * ENCRYPT dance before authentication, which is ok, but not too
378 * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT
379 * dance if authentication fails, though clients typically just
382 write_data("%c%c%c%c%c%c%c",
385 (uchar_t
)TELOPT_ENCRYPT
,
386 (uchar_t
)ENCRYPT_SUPPORT
,
387 (uchar_t
)TELOPT_ENCTYPE_DES_CFB64
,
393 sent_encrypt_support
= B_TRUE
;
396 (void) fprintf(stderr
,
397 "SENT ENCRYPT SUPPORT\n");
399 (void) encrypt_send_encrypt_is();
402 auth_status
= result
;
408 reply_to_client(AuthInfo
*ap
, int type
, void *data
, int len
)
410 uchar_t reply
[BUFSIZ
];
412 uchar_t
*cd
= (uchar_t
*)data
;
414 if (len
== -1 && data
!= NULL
)
415 len
= strlen((char *)data
);
416 else if (len
> (sizeof (reply
) - 9)) {
418 "krb5 auth reply length too large (%d)", len
);
420 (void) fprintf(stderr
,
421 "krb5 auth reply length too large (%d)\n",
424 } else if (data
== NULL
)
429 *p
++ = TELOPT_AUTHENTICATION
;
430 *p
++ = AUTHTYPE_KERBEROS_V5
;
432 *p
++ = ap
->AuthHow
; /* MUTUAL, ONE-WAY, etc */
433 *p
++ = type
; /* RESPONSE or ACCEPT */
435 if ((*p
++ = *cd
++) == IAC
)
441 /* queue the data to be sent */
442 write_data_len((const char *)reply
, p
-reply
);
444 #if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\
445 defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES)
447 (void) fprintf(stderr
, "SENT TELOPT_AUTHENTICATION REPLY "
449 AUTHTYPE_NAME(ap
->AuthName
),
450 AUTHWHO_NAME(ap
->AuthHow
& AUTH_WHO_MASK
),
451 AUTHHOW_NAME(ap
->AuthHow
& AUTH_HOW_MASK
),
454 #endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */
459 /* Decode, decrypt and store the forwarded creds in the local ccache. */
460 static krb5_error_code
461 rd_and_store_forwarded_creds(krb5_context context
,
462 krb5_auth_context auth_context
,
463 krb5_data
*inbuf
, krb5_ticket
*ticket
,
467 krb5_error_code retval
;
468 char ccname
[MAXPATHLEN
];
469 krb5_ccache ccache
= NULL
;
470 char *client_name
= NULL
;
472 if (retval
= krb5_rd_cred(context
, auth_context
, inbuf
, &creds
, NULL
))
475 (void) sprintf(ccname
, "FILE:/tmp/krb5cc_p%ld", getpid());
476 (void) krb5_setenv("KRB5CCNAME", ccname
, 1);
478 if ((retval
= krb5_cc_default(context
, &ccache
)))
481 if ((retval
= krb5_cc_initialize(context
, ccache
,
482 ticket
->enc_part2
->client
)) != 0)
485 if ((retval
= krb5_cc_store_cred(context
, ccache
, *creds
)) != 0)
488 if ((retval
= krb5_cc_close(context
, ccache
)) != 0)
491 /* Register with ktkt_warnd(1M) */
492 if ((retval
= krb5_unparse_name(context
, (*creds
)->client
,
495 (void) kwarn_del_warning(client_name
);
496 if (kwarn_add_warning(client_name
, (*creds
)->times
.endtime
) != 0) {
497 syslog(LOG_AUTH
|LOG_NOTICE
,
498 "rd_and_store_forwarded_creds: kwarn_add_warning"
499 " failed: ktkt_warnd(1M) down? ");
501 (void) fprintf(stderr
,
502 "kwarn_add_warning failed:"
503 " ktkt_warnd(1M) down?\n");
508 if (username
!= NULL
) {
510 * This verifies that the user is valid on the local system,
511 * maps the username from KerberosV5 to unix,
512 * and moves the KRB5CCNAME file to the correct place
513 * /tmp/krb5cc_[uid] with correct ownership (0600 uid gid).
515 * NOTE: the user must be in the gsscred table in order to map
518 (void) krb5_kuserok(context
, ticket
->enc_part2
->client
,
522 (void) fprintf(stderr
,
523 "Successfully stored forwarded creds\n");
526 krb5_free_creds(context
, *creds
);
531 kerberos5_is(AuthInfo
*ap
, uchar_t
*data
, int cnt
)
533 krb5_error_code err
= 0;
534 krb5_principal server
;
535 krb5_keyblock
*newkey
= NULL
;
536 krb5_keytab keytabid
= 0;
539 krb5_authenticator
*authenticator
;
540 char errbuf
[MAXERRSTRLEN
];
550 auth
.data
= (char *)data
;
553 if (auth_context
== NULL
) {
554 err
= krb5_auth_con_init(telnet_context
, &auth_context
);
557 "Error getting krb5 auth "
558 "context: %s", error_message(err
));
563 err
= krb5_auth_con_getrcache(telnet_context
,
566 if (!err
&& !rcache
) {
567 err
= krb5_sname_to_principal(telnet_context
,
572 err
= krb5_get_server_rcache(
574 krb5_princ_component(
579 krb5_free_principal(telnet_context
,
585 "Error allocating krb5 replay cache: %s",
588 err
= krb5_auth_con_setrcache(telnet_context
,
593 "Error creating krb5 "
598 if (!err
&& telnet_srvtab
!= NULL
)
599 err
= krb5_kt_resolve(telnet_context
,
600 telnet_srvtab
, &keytabid
);
602 err
= krb5_rd_req(telnet_context
, &auth_context
, &auth
,
603 NULL
, keytabid
, NULL
, &ticket
);
605 (void) snprintf(errbuf
, sizeof (errbuf
),
606 "Error reading krb5 auth information:"
607 " %s", error_message(err
));
612 * Verify that the correct principal was used
614 if (krb5_princ_component(telnet_context
,
615 ticket
->server
, 0)->length
< MAXPRINCLEN
) {
616 char princ
[MAXPRINCLEN
];
617 (void) strncpy(princ
,
618 krb5_princ_component(telnet_context
,
619 ticket
->server
, 0)->data
,
620 krb5_princ_component(telnet_context
,
621 ticket
->server
, 0)->length
);
622 princ
[krb5_princ_component(telnet_context
,
623 ticket
->server
, 0)->length
] = '\0';
624 if (strcmp("host", princ
)) {
625 if (strlen(princ
) < sizeof (errbuf
) - 39) {
626 (void) snprintf(errbuf
, sizeof (errbuf
),
632 (void) strncpy(errbuf
,
634 "name: principal != "
641 (void) strlcpy(errbuf
, "service name too long",
646 err
= krb5_auth_con_getauthenticator(telnet_context
,
650 (void) snprintf(errbuf
, sizeof (errbuf
),
651 "Failed to get authenticator: %s",
655 if ((ap
->AuthHow
& AUTH_ENCRYPT_MASK
) == AUTH_ENCRYPT_ON
&&
656 !authenticator
->checksum
) {
657 (void) strlcpy(errbuf
,
658 "authenticator is missing checksum",
662 if (authenticator
->checksum
) {
664 krb5_checksum
*cksum
= authenticator
->checksum
;
669 type_check
[0] = ap
->AuthName
;
670 type_check
[1] = ap
->AuthHow
;
672 err
= krb5_auth_con_getkey(telnet_context
,
675 (void) snprintf(errbuf
, sizeof (errbuf
),
676 "Failed to get key from "
682 input
.data
= type_check
;
684 err
= krb5_c_verify_checksum(telnet_context
,
690 err
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
693 (void) snprintf(errbuf
, sizeof (errbuf
),
695 "verification failed: "
700 krb5_free_keyblock(telnet_context
, key
);
703 krb5_free_authenticator(telnet_context
, authenticator
);
704 if ((ap
->AuthHow
& AUTH_HOW_MASK
) == AUTH_HOW_MUTUAL
) {
705 /* do ap_rep stuff here */
706 if ((err
= krb5_mk_rep(telnet_context
, auth_context
,
708 (void) snprintf(errbuf
, sizeof (errbuf
),
710 "Kerberos auth reply: "
715 reply_to_client(ap
, KRB_RESPONSE
, outbuf
.data
,
718 if (krb5_unparse_name(telnet_context
,
719 ticket
->enc_part2
->client
,
722 reply_to_client(ap
, KRB_ACCEPT
, name
, name
? -1 : 0);
725 "\tKerberos5 identifies user as ``%s''\r\n",
729 krb5_name
= (char *)strdup(name
);
731 auth_finished(ap
, AUTH_USER
);
735 (void) krb5_auth_con_getremotesubkey(telnet_context
,
736 auth_context
, &newkey
);
737 if (session_key
!= NULL
) {
738 krb5_free_keyblock(telnet_context
, session_key
);
741 if (newkey
!= NULL
) {
742 (void) krb5_copy_keyblock(telnet_context
,
743 newkey
, &session_key
);
744 krb5_free_keyblock(telnet_context
, newkey
);
746 (void) krb5_copy_keyblock(telnet_context
,
747 ticket
->enc_part2
->session
, &session_key
);
751 * Initialize encryption stuff. Currently, we are only
752 * supporting 8 byte keys and blocks. Check for this later.
755 skey
.length
= DES_BLOCKSIZE
;
756 skey
.data
= session_key
->contents
;
757 encrypt_session_key(&skey
, &encr_data
.encrypt
);
758 encrypt_session_key(&skey
, &encr_data
.decrypt
);
762 inbuf
.data
= (char *)data
;
764 (void) fprintf(stderr
,
765 "RCVD KRB_FORWARD data (%d bytes)\n", cnt
);
767 if (auth_context
!= NULL
) {
770 err
= krb5_auth_con_getrcache(telnet_context
,
771 auth_context
, &rcache
);
772 if (!err
&& !rcache
) {
773 err
= krb5_sname_to_principal(telnet_context
,
774 0, 0, KRB5_NT_SRV_HST
, &server
);
776 err
= krb5_get_server_rcache(
778 krb5_princ_component(
782 krb5_free_principal(telnet_context
,
788 "Error allocating krb5 replay cache: %s",
791 err
= krb5_auth_con_setrcache(telnet_context
,
792 auth_context
, rcache
);
795 "Error creating krb5 replay cache:"
801 * Use the 'rsaddr' and 'rsport' (remote service addr/port)
802 * from the original connection. This data is used to
803 * verify the forwarded credentials.
805 if (!(err
= krb5_auth_con_setaddrs(telnet_context
, auth_context
,
807 err
= krb5_auth_con_setports(telnet_context
,
808 auth_context
, NULL
, &rsport
);
812 * If all is well, store the forwarded creds in
813 * the users local credential cache.
815 err
= rd_and_store_forwarded_creds(telnet_context
,
816 auth_context
, &inbuf
,
820 (void) snprintf(errbuf
, sizeof (errbuf
),
821 "Read forwarded creds failed: %s",
823 syslog(LOG_ERR
, "%s", errbuf
);
825 reply_to_client(ap
, KRB_FORWARD_REJECT
, errbuf
, -1);
827 (void) fprintf(stderr
,
829 "forwarded credentials\r\n");
831 reply_to_client(ap
, KRB_FORWARD_ACCEPT
, (void *) 0, 0);
833 if (rsaddr
.contents
!= NULL
)
834 free(rsaddr
.contents
);
836 if (rsport
.contents
!= NULL
)
837 free(rsport
.contents
);
840 (void) fprintf(stderr
, "\tForwarded "
841 "credentials obtained\r\n");
845 (void) fprintf(stderr
,
846 "\tUnknown Kerberos option %d\r\n",
848 reply_to_client(ap
, KRB_REJECT
, (void *) 0, 0);
854 reply_to_client(ap
, KRB_REJECT
, errbuf
, -1);
857 (void) fprintf(stderr
, "\tKerberos V5 error: %s\r\n", errbuf
);
859 syslog(LOG_ERR
, "%s", errbuf
);
861 if (auth_context
!= NULL
) {
862 (void) krb5_auth_con_free(telnet_context
, auth_context
);
872 if (telnet_context
== NULL
) {
873 code
= krb5_init_context(&telnet_context
);
874 if (code
!= 0 && auth_debug
)
876 "Cannot initialize Kerberos V5: %s",
877 error_message(code
));
884 auth_name(uchar_t
*data
, int cnt
)
886 char namebuf
[MAXPRINCLEN
];
890 (void) fprintf(stderr
,
891 "\t(auth_name) Empty NAME in auth "
895 if (cnt
> sizeof (namebuf
)-1) {
897 (void) fprintf(stderr
,
898 "\t(auth_name) NAME exceeds %d bytes\n",
902 (void) memcpy((void *)namebuf
, (void *)data
, cnt
);
905 (void) fprintf(stderr
, "\t(auth_name) name [%s]\n", namebuf
);
906 AuthenticatingUser
= (char *)strdup(namebuf
);
910 auth_is(uchar_t
*data
, int cnt
)
912 AuthInfo
*aptr
= auth_list
;
918 * We failed to negoiate secure authentication
920 if (data
[0] == AUTHTYPE_NULL
) {
921 auth_finished(0, AUTH_REJECT
);
925 while (aptr
->AuthName
!= NULL
&&
926 (aptr
->AuthName
!= data
[0] || aptr
->AuthHow
!= data
[1]))
931 (void) fprintf(stderr
, "\t(auth_is) auth type is %s "
932 "(%d bytes)\n", aptr
->AuthString
, cnt
);
934 if (aptr
->AuthName
== AUTHTYPE_KERBEROS_V5
)
935 kerberos5_is(aptr
, data
+2, cnt
-2);
940 krb5_user_status(char *name
, int namelen
, int level
)
942 int retval
= AUTH_USER
;
945 (void) fprintf(stderr
, "\t(krb5_user_status) level = %d "
946 "auth_level = %d user = %s\n",
948 (AuthenticatingUser
!= NULL
? AuthenticatingUser
: ""));
950 if (level
< AUTH_USER
)
953 if (AuthenticatingUser
!= NULL
&&
954 (retval
= krb5_kuserok(telnet_context
, ticket
->enc_part2
->client
,
955 AuthenticatingUser
))) {
956 (void) strncpy(name
, AuthenticatingUser
, namelen
);
961 "Krb5 principal lacks permission to "
962 "access local account for %s",
969 * Wrapper around /dev/urandom
972 getrandom(char *buf
, int buflen
)
974 static int devrandom
= -1;
976 if (devrandom
== -1 &&
977 (devrandom
= open("/dev/urandom", O_RDONLY
)) == -1) {
978 fatalperror(net
, "Unable to open /dev/urandom: ",
983 if (read(devrandom
, buf
, buflen
) == -1) {
984 fatalperror(net
, "Unable to read from /dev/urandom: ",
995 * Initialize the encryption data structures
1000 (void) memset(&encr_data
.encrypt
, 0, sizeof (cipher_info_t
));
1001 (void) memset(&encr_data
.decrypt
, 0, sizeof (cipher_info_t
));
1003 encr_data
.encrypt
.state
= ENCR_STATE_NOT_READY
;
1004 encr_data
.decrypt
.state
= ENCR_STATE_NOT_READY
;
1008 * encrypt_send_request_start
1010 * Request that the remote side automatically start sending
1014 encrypt_send_request_start()
1016 uchar_t buf
[6+TELNET_MAXKEYIDLEN
], *p
;
1022 *p
++ = TELOPT_ENCRYPT
;
1023 *p
++ = ENCRYPT_REQSTART
;
1025 * We are telling the remote side which
1026 * decrypt key we will use so that it may
1027 * encrypt in the same key.
1029 (void) memcpy(p
, encr_data
.decrypt
.keyid
, encr_data
.decrypt
.keyidlen
);
1030 p
+= encr_data
.decrypt
.keyidlen
;
1035 write_data_len((const char *)buf
, p
-buf
);
1038 (void) fprintf(stderr
,
1039 "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
1045 * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
1046 * message, the client is telling us that it will be sending
1047 * encrypted data using the indicated cipher.
1048 * We must initialize the read (decrypt) side of our connection
1051 encrypt_is(uchar_t
*data
, int cnt
)
1054 register int iv_status
= CFB64_IV_OK
;
1055 register int lstate
= 0;
1060 (uchar_t
)TELOPT_ENCRYPT
,
1061 (uchar_t
)ENCRYPT_REPLY
,
1062 (uchar_t
)0, /* placeholder: sbbuf[4] */
1063 (uchar_t
)CFB64_IV_OK
, /* placeholder: sbbuf[5] */
1071 type
= sbbuf
[4] = *data
++;
1075 * 1. Create the proper stream Initialization vector
1076 * - copy the correct 'seed' to IV and output blocks
1077 * - set the correct key schedule
1078 * 2. Generate reply for the other side:
1079 * IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
1080 * [ data ... ] IAC SE
1081 * 3. Tell crypto module: method, direction, IV
1084 case TELOPT_ENCTYPE_DES_CFB64
:
1085 encr_data
.decrypt
.type
= type
;
1087 lstate
= encr_data
.decrypt
.state
;
1089 (void) fprintf(stderr
,
1090 "\t(encrypt_is) initial state = %d\n",
1093 * Before we extract the IV bytes, make sure we got
1096 if (cnt
< sizeof (Block
)) {
1097 iv_status
= CFB64_IV_BAD
;
1099 (void) fprintf(stderr
,
1100 "\t(encrypt_is) Not enough "
1102 lstate
= ENCR_STATE_NOT_READY
;
1104 data
++; /* skip over the CFB64_IV byte */
1105 (void) memcpy(encr_data
.decrypt
.ivec
, data
,
1107 lstate
= ENCR_STATE_IN_PROGRESS
;
1110 case TELOPT_ENCTYPE_NULL
:
1111 encr_data
.decrypt
.type
= type
;
1112 lstate
&= ~ENCR_STATE_NO_RECV_IV
;
1113 lstate
&= ~ENCR_STATE_NO_SEND_IV
;
1115 (void) fprintf(stderr
,
1116 "\t(encrypt_is) We accept NULL encr\n");
1119 iv_status
= CFB64_IV_BAD
;
1120 encr_data
.decrypt
.type
= NULL
;
1122 (void) fprintf(stderr
,
1123 "\t(encrypt_is) Can't find type (%d) "
1124 "for initial negotiation\r\n",
1126 lstate
= ENCR_STATE_NOT_READY
;
1130 sbbuf
[5] = (uchar_t
)iv_status
; /* either CFB64_IV_OK or BAD */
1132 if (iv_status
== CFB64_IV_OK
) {
1134 * send IV to crypto module and indicate it is for
1137 lstate
&= ~ENCR_STATE_NO_RECV_IV
; /* we received an OK IV */
1138 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we dont send an IV */
1140 /* tell crypto module to disable crypto on "read" stream */
1141 lstate
= ENCR_STATE_NOT_READY
;
1144 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
1146 #ifdef ENCRYPT_NAMES
1148 (void) fprintf(stderr
,
1149 "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
1151 (iv_status
== CFB64_IV_OK
? "CFB64_IV_OK" :
1153 #endif /* ENCRYPT_NAMES */
1154 /* Update the state of the decryption negotiation */
1155 encr_data
.decrypt
.state
= lstate
;
1157 if (lstate
== ENCR_STATE_NOT_READY
)
1158 encr_data
.decrypt
.autoflag
= 0;
1160 if (lstate
== ENCR_STATE_OK
&& encr_data
.decrypt
.autoflag
)
1161 encrypt_send_request_start();
1164 (void) fprintf(stderr
,
1165 "\t(encrypt_is) final DECRYPT state = %d\n",
1166 encr_data
.decrypt
.state
);
1170 * encrypt_send_encrypt_is
1172 * Tell the client what encryption we will use
1173 * and what our IV will be.
1176 encrypt_send_encrypt_is()
1178 register int lstate
;
1179 krb5_error_code kret
;
1180 uchar_t sbbuf
[MAXOPTLEN
], *p
;
1183 lstate
= encr_data
.encrypt
.state
;
1185 if (encr_data
.encrypt
.type
== ENCTYPE_NULL
) {
1187 * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
1194 * - Create a random DES key
1197 * encrypt the IV using itself as the key.
1200 * IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
1204 if (lstate
== ENCR_STATE_NOT_READY
)
1205 lstate
= ENCR_STATE_IN_PROGRESS
;
1206 else if ((lstate
& ENCR_STATE_NO_SEND_IV
) == 0) {
1208 (void) fprintf(stderr
,
1209 "\t(encrypt_send_is) IV already sent,"
1210 " state = %d\n", lstate
);
1214 if (!VALIDKEY(encr_data
.encrypt
.krbdes_key
)) {
1216 * Invalid key, set flag so we try again later
1217 * when we get a good one
1219 encr_data
.encrypt
.need_start
= 1;
1221 (void) fprintf(stderr
,
1222 "\t(encrypt_send_is) No Key, cannot "
1223 "start encryption yet\n");
1227 (void) fprintf(stderr
,
1228 "\t(encrypt_send_is) Creating new feed\n");
1231 * Create a random feed and send it over.
1233 * Use the /dev/[u]random interface to generate
1234 * our encryption IV.
1236 kret
= getrandom((char *)encr_data
.encrypt
.ivec
, sizeof (Block
));
1240 (void) fprintf(stderr
,
1241 "\t(encrypt_send_is) error from "
1242 "getrandom: %d\n", kret
);
1243 syslog(LOG_ERR
, "Failed to create encryption key (err %d)\n");
1244 encr_data
.encrypt
.type
= ENCTYPE_NULL
;
1246 mit_des_fixup_key_parity(encr_data
.encrypt
.ivec
);
1252 *p
++ = TELOPT_ENCRYPT
;
1254 *p
++ = encr_data
.encrypt
.type
;
1258 * Copy the IV bytes individually so that when a
1259 * 255 (telnet IAC) is used, it can be "escaped" by
1260 * adding it twice (telnet RFC 854).
1262 for (i
= 0; i
< sizeof (Block
); i
++)
1263 if ((*p
++ = encr_data
.encrypt
.ivec
[i
]) == IAC
)
1268 write_data_len((const char *)sbbuf
, (size_t)(p
-sbbuf
));
1272 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we sent our IV */
1273 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* dont need decrypt IV */
1275 encr_data
.encrypt
.state
= lstate
;
1279 (void) fprintf(stderr
,
1280 "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
1281 encr_data
.encrypt
.type
);
1282 for (i
= 0; i
< (p
-sbbuf
); i
++)
1283 (void) fprintf(stderr
, "%d ", (int)sbbuf
[i
]);
1284 (void) fprintf(stderr
, "\n");
1293 * Utility routine to send a CRIOCSTOP ioctl to the
1294 * crypto module (cryptmod).
1297 stop_stream(int fd
, int dir
)
1299 struct strioctl crioc
;
1300 uint32_t stopdir
= dir
;
1302 crioc
.ic_cmd
= CRYPTIOCSTOP
;
1303 crioc
.ic_timout
= -1;
1304 crioc
.ic_len
= sizeof (stopdir
);
1305 crioc
.ic_dp
= (char *)&stopdir
;
1307 if (ioctl(fd
, I_STR
, &crioc
)) {
1308 syslog(LOG_ERR
, "Error sending CRYPTIOCSTOP ioctl: %m");
1315 * Utility routine to send a CRYPTIOCSTART ioctl to the
1316 * crypto module (cryptmod). This routine may contain optional
1317 * payload data that the cryptmod will interpret as bytes that
1318 * need to be decrypted and sent back up to the application
1319 * via the data stream.
1322 start_stream(int fd
, int dir
, int datalen
, char *data
)
1324 struct strioctl crioc
;
1326 crioc
.ic_cmd
= (dir
== CRYPT_ENCRYPT
? CRYPTIOCSTARTENC
:
1328 crioc
.ic_timout
= -1;
1329 crioc
.ic_len
= datalen
;
1332 if (ioctl(fd
, I_STR
, &crioc
)) {
1333 syslog(LOG_ERR
, "Error sending CRYPTIOCSTART ioctl: %m");
1338 * encrypt_start_output
1340 * Tell the other side to start encrypting its data
1343 encrypt_start_output()
1347 uchar_t sbbuf
[MAXOPTLEN
];
1348 struct strioctl crioc
;
1349 struct cr_info_t cki
;
1352 * Initialize crypto and send the ENCRYPT_IS msg
1354 lstate
= encrypt_send_encrypt_is();
1356 if (lstate
!= ENCR_STATE_OK
) {
1358 (void) fprintf(stderr
,
1359 "\t(encrypt_start_output) ENCRYPT state "
1368 *p
++ = TELOPT_ENCRYPT
;
1369 *p
++ = ENCRYPT_START
;
1371 (void) memcpy(p
, encr_data
.encrypt
.keyid
, encr_data
.encrypt
.keyidlen
);
1372 p
+= encr_data
.encrypt
.keyidlen
;
1377 /* Flush this data out before we start encrypting */
1378 write_data_len((const char *)sbbuf
, (int)(p
-sbbuf
));
1382 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
1383 "(lstate = %d) data waiting = %d\n",
1384 (int)encr_data
.encrypt
.keyid
[0],
1385 lstate
, nfrontp
-nbackp
);
1387 encr_data
.encrypt
.state
= lstate
;
1390 * tell crypto module what key to use for encrypting
1391 * Note that the ENCRYPT has not yet been enabled, but we
1392 * need to first set the crypto key to use.
1394 cki
.direction_mask
= CRYPT_ENCRYPT
;
1396 if (encr_data
.encrypt
.type
== TELOPT_ENCTYPE_DES_CFB64
) {
1397 cki
.crypto_method
= CRYPT_METHOD_DES_CFB
;
1400 (void) fprintf(stderr
,
1401 "\t(encrypt_start_output) - unknown "
1402 "crypto_method %d\n",
1403 encr_data
.encrypt
.type
);
1404 syslog(LOG_ERR
, "unrecognized crypto encrypt method: %d",
1405 encr_data
.encrypt
.type
);
1411 * If we previously configured this crypto method, we dont want to
1412 * overwrite the key or ivec information already given to the crypto
1413 * module as it will cause the cipher data between the client and server
1414 * to become out of synch and impossible to decipher.
1416 if (encr_data
.encrypt
.setup
== cki
.crypto_method
) {
1420 cki
.keylen
= DES_BLOCKSIZE
;
1421 (void) memcpy(cki
.key
, (void *)encr_data
.encrypt
.krbdes_key
,
1424 cki
.iveclen
= DES_BLOCKSIZE
;
1425 (void) memcpy(cki
.ivec
, (void *)encr_data
.encrypt
.ivec
,
1428 cki
.ivec_usage
= IVEC_ONETIME
;
1431 cki
.option_mask
= 0;
1433 /* Stop encrypt side prior to setup so we dont lose data */
1434 stop_stream(cryptmod_fd
, CRYPT_ENCRYPT
);
1436 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1437 crioc
.ic_timout
= -1;
1438 crioc
.ic_len
= sizeof (struct cr_info_t
);
1439 crioc
.ic_dp
= (char *)&cki
;
1441 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1442 perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
1444 /* Setup completed OK */
1445 encr_data
.encrypt
.setup
= cki
.crypto_method
;
1449 * We do not check for "stuck" data when setting up the
1450 * outbound "encrypt" channel. Any data queued prior to
1451 * this IOCTL will get processed correctly without our help.
1453 start_stream(cryptmod_fd
, CRYPT_ENCRYPT
, 0, NULL
);
1456 * tell crypto module to start encrypting
1459 (void) fprintf(stderr
,
1460 "\t(encrypt_start_output) Encrypting output\n");
1464 * encrypt_request_start
1466 * The client requests that we start encryption immediately after
1467 * successful negotiation
1470 encrypt_request_start(void)
1472 if (encr_data
.encrypt
.type
== ENCTYPE_NULL
) {
1473 encr_data
.encrypt
.autoflag
= 1;
1475 (void) fprintf(stderr
, "\t(encrypt_request_start) "
1476 "autoencrypt = ON\n");
1478 encrypt_start_output();
1485 * ENCRYPT END received, stop decrypting the read stream
1488 encrypt_end(int direction
)
1490 struct cr_info_t cki
;
1491 struct strioctl crioc
;
1494 stopdir
= (direction
== TELNET_DIR_DECRYPT
? CRYPT_DECRYPT
:
1497 stop_stream(cryptmod_fd
, stopdir
);
1500 * Call this function when we wish to disable crypto in
1501 * either direction (ENCRYPT or DECRYPT)
1503 cki
.direction_mask
= (direction
== TELNET_DIR_DECRYPT
? CRYPT_DECRYPT
:
1505 cki
.crypto_method
= CRYPT_METHOD_NONE
;
1506 cki
.option_mask
= 0;
1510 cki
.ivec_usage
= IVEC_ONETIME
;
1512 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1513 crioc
.ic_timout
= -1;
1514 crioc
.ic_len
= sizeof (cki
);
1515 crioc
.ic_dp
= (char *)&cki
;
1517 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1518 perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
1521 start_stream(cryptmod_fd
, stopdir
, 0, NULL
);
1525 * encrypt_request_end
1527 * When we receive a REQEND from the client, it means
1528 * that we are supposed to stop encrypting
1531 encrypt_request_end()
1534 * Tell the other side we are done encrypting
1537 write_data("%c%c%c%c%c%c",
1540 (uchar_t
)TELOPT_ENCRYPT
,
1541 (uchar_t
)ENCRYPT_END
,
1546 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
1549 * Turn off encryption of the write stream
1551 encrypt_end(TELNET_DIR_ENCRYPT
);
1555 * encrypt_send_request_end
1557 * We stop encrypting the write stream and tell the other side about it.
1560 encrypt_send_request_end()
1562 write_data("%c%c%c%c%c%c",
1565 (uchar_t
)TELOPT_ENCRYPT
,
1566 (uchar_t
)ENCRYPT_REQEND
,
1571 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
1577 * The client is going to start sending encrypted data
1578 * using the previously negotiated cipher (see what we set
1579 * when we did the REPLY in encrypt_is).
1584 struct cr_info_t cki
;
1585 struct strioctl crioc
;
1587 char *dataptr
= NULL
;
1589 if (encr_data
.decrypt
.type
== ENCTYPE_NULL
) {
1591 (void) fprintf(stderr
,
1592 "\t(encrypt_start) No DECRYPT method "
1594 encrypt_send_request_end();
1598 cki
.direction_mask
= CRYPT_DECRYPT
;
1600 if (encr_data
.decrypt
.type
== TELOPT_ENCTYPE_DES_CFB64
) {
1601 cki
.crypto_method
= CRYPT_METHOD_DES_CFB
;
1604 (void) fprintf(stderr
,
1605 "\t(encrypt_start) - unknown "
1606 "crypto_method %d\n", encr_data
.decrypt
.type
);
1608 syslog(LOG_ERR
, "unrecognized crypto decrypt method: %d",
1609 encr_data
.decrypt
.type
);
1615 * Don't overwrite previously configured key and ivec info
1617 if (encr_data
.decrypt
.setup
!= cki
.crypto_method
) {
1618 (void) memcpy(cki
.key
, (void *)encr_data
.decrypt
.krbdes_key
,
1620 (void) memcpy(cki
.ivec
, (void *)encr_data
.decrypt
.ivec
,
1623 cki
.keylen
= DES_BLOCKSIZE
;
1624 cki
.iveclen
= DES_BLOCKSIZE
;
1625 cki
.ivec_usage
= IVEC_ONETIME
;
1630 cki
.option_mask
= 0;
1632 stop_stream(cryptmod_fd
, CRYPT_DECRYPT
);
1634 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1635 crioc
.ic_timout
= -1;
1636 crioc
.ic_len
= sizeof (struct cr_info_t
);
1637 crioc
.ic_dp
= (char *)&cki
;
1639 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1640 syslog(LOG_ERR
, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
1643 encr_data
.decrypt
.setup
= cki
.crypto_method
;
1646 (void) fprintf(stderr
,
1647 "\t(encrypt_start) called CRYPTIOCSETUP for "
1651 * Read any data stuck between the cryptmod and the application
1652 * so we can pass it back down to be properly decrypted after
1653 * this operation finishes.
1655 if (ioctl(cryptmod_fd
, I_NREAD
, &bytes
) < 0) {
1656 syslog(LOG_ERR
, "I_NREAD returned error %m");
1661 * Any data which was read AFTER the ENCRYPT START message
1662 * must be sent back down to be decrypted properly.
1664 * 'ncc' is the number of bytes that have been read but
1665 * not yet processed by the telnet state machine.
1667 * 'bytes' is the number of bytes waiting to be read from
1670 * If either one is a positive value, then those bytes
1671 * must be pulled up and sent back down to be decrypted.
1676 (void) fprintf(stderr
,
1677 "\t(encrypt_start) after drainstream, "
1678 "ncc=%d bytes = %d\n", ncc
, bytes
);
1683 start_stream(cryptmod_fd
, CRYPT_DECRYPT
, bytes
, dataptr
);
1686 * The bytes putback into the stream are no longer
1687 * available to be read by the server, so adjust the
1688 * counter accordingly.
1692 (void) memset(netip
, 0, netibufsize
);
1694 #ifdef ENCRYPT_NAMES
1696 (void) fprintf(stderr
,
1697 "\t(encrypt_start) Start DECRYPT using %s\n",
1698 ENCTYPE_NAME(encr_data
.decrypt
.type
));
1700 #endif /* ENCRYPT_NAMES */
1706 * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
1707 * message from a client.
1709 * Choose an agreeable method (DES_CFB64) and
1710 * respond with TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
1715 encrypt_support(char *data
, int cnt
)
1717 int lstate
= ENCR_STATE_NOT_READY
;
1718 int type
, use_type
= 0;
1720 while (cnt
-- > 0 && use_type
== 0) {
1722 #ifdef ENCRYPT_NAMES
1724 (void) fprintf(stderr
,
1725 "RCVD ENCRYPT SUPPORT %s\n",
1726 ENCTYPE_NAME(type
));
1727 #endif /* ENCRYPT_NAMES */
1731 if (type
== TELOPT_ENCTYPE_DES_CFB64
) {
1735 encr_data
.encrypt
.type
= use_type
;
1737 if (use_type
!= TELOPT_ENCTYPE_NULL
&&
1738 authenticated
!= NULL
&& authenticated
!= &NoAuth
&&
1739 auth_status
!= AUTH_REJECT
) {
1741 /* Authenticated -> have session key -> send ENCRYPT IS */
1742 lstate
= encrypt_send_encrypt_is();
1743 if (lstate
== ENCR_STATE_OK
)
1744 encrypt_start_output();
1745 } else if (use_type
== TELOPT_ENCTYPE_NULL
) {
1747 (void) fprintf(stderr
,
1748 "\t(encrypt_support) Cannot agree "
1749 "on crypto algorithm, output encryption "
1753 * Cannot agree on crypto algorithm
1755 * send "IAC SB ENCRYPT IS NULL IAC SE"
1756 * optionally, also send IAC WONT ENCRYPT
1758 write_data("%c%c%c%c%c%c%c",
1761 (uchar_t
)TELOPT_ENCRYPT
,
1762 (uchar_t
)ENCRYPT_IS
,
1763 (uchar_t
)TELOPT_ENCTYPE_NULL
,
1766 send_wont(TELOPT_ENCRYPT
);
1769 (void) fprintf(stderr
,
1770 "SENT TELOPT_ENCRYPT ENCRYPT_IS "
1773 remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
1775 settimer(encr_support
);
1779 * encrypt_send_keyid
1781 * Sent the key id we will use to the client
1784 encrypt_send_keyid(int dir
, uchar_t
*keyid
, int keylen
, boolean_t saveit
)
1786 uchar_t sbbuf
[128], *p
;
1792 *p
++ = TELOPT_ENCRYPT
;
1793 *p
++ = (dir
== TELNET_DIR_ENCRYPT
? ENCRYPT_ENC_KEYID
:
1797 (void) fprintf(stderr
,
1798 "\t(send_keyid) store %d byte %s keyid\n",
1800 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1803 if (dir
== TELNET_DIR_ENCRYPT
) {
1804 (void) memcpy(encr_data
.encrypt
.keyid
, keyid
, keylen
);
1805 encr_data
.encrypt
.keyidlen
= keylen
;
1807 (void) memcpy(encr_data
.decrypt
.keyid
, keyid
, keylen
);
1808 encr_data
.decrypt
.keyidlen
= keylen
;
1811 (void) memcpy(p
, keyid
, keylen
);
1816 write_data_len((const char *)sbbuf
, (size_t)(p
-sbbuf
));
1820 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT %s %d\n",
1821 (dir
== TELNET_DIR_ENCRYPT
? "ENC_KEYID" :
1822 "DEC_KEYID"), keyid
[0]);
1828 * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
1829 * message, process it accordingly.
1830 * If the vector is acceptable, tell client we are encrypting and
1831 * enable encryption on our write stream.
1833 * Negotiate the KEYID next..
1837 encrypt_reply(char *data
, int len
)
1839 uchar_t type
= (uchar_t
)(*data
++);
1840 uchar_t result
= (uchar_t
)(*data
);
1843 #ifdef ENCRYPT_NAMES
1845 (void) fprintf(stderr
,
1846 "\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
1848 (result
== CFB64_IV_OK
? "CFB64_IV_OK" :
1849 "CFB64_IV_BAD"), len
);
1850 #endif /* ENCRYPT_NAMES */
1852 lstate
= encr_data
.encrypt
.state
;
1854 (void) fprintf(stderr
,
1855 "\t(encrypt_reply) initial ENCRYPT state = %d\n",
1859 if (lstate
== ENCR_STATE_NOT_READY
)
1860 lstate
= ENCR_STATE_IN_PROGRESS
;
1861 lstate
&= ~ENCR_STATE_NO_RECV_IV
; /* we got the IV */
1862 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we dont need to send IV */
1865 * The correct response here is to send the encryption key id
1868 * Send keyid 0 to indicate that we will just use default
1871 encrypt_send_keyid(TELNET_DIR_ENCRYPT
, (uchar_t
*)"\0", 1, 1);
1878 (void) memset(encr_data
.encrypt
.ivec
, 0, sizeof (Block
));
1879 lstate
= ENCR_STATE_NOT_READY
;
1883 (void) fprintf(stderr
,
1884 "\t(encrypt_reply) Got unknown IV value in "
1886 lstate
= ENCR_STATE_NOT_READY
;
1890 encr_data
.encrypt
.state
= lstate
;
1891 if (lstate
== ENCR_STATE_NOT_READY
) {
1892 encr_data
.encrypt
.autoflag
= 0;
1893 encr_data
.encrypt
.type
= ENCTYPE_NULL
;
1895 (void) fprintf(stderr
,
1896 "\t(encrypt_reply) encrypt.autoflag = "
1899 encr_data
.encrypt
.type
= type
;
1900 if ((lstate
== ENCR_STATE_OK
) && encr_data
.encrypt
.autoflag
)
1901 encrypt_start_output();
1905 (void) fprintf(stderr
,
1906 "\t(encrypt_reply) ENCRYPT final state = %d\n",
1911 encrypt_set_keyid_state(uchar_t
*keyid
, int *keyidlen
, int dir
)
1915 lstate
= (dir
== TELNET_DIR_ENCRYPT
? encr_data
.encrypt
.state
:
1916 encr_data
.decrypt
.state
);
1919 (void) fprintf(stderr
,
1920 "\t(set_keyid_state) %s initial state = %d\n",
1921 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1922 "DECRYPT"), lstate
);
1925 * Currently, we only support using the default keyid,
1926 * so it should be an error if the len > 1 or the keyid != 0.
1928 if (*keyidlen
!= 1 || (*keyid
!= '\0')) {
1930 (void) fprintf(stderr
,
1931 "\t(set_keyid_state) unexpected keyid: "
1932 "len=%d value=%d\n", *keyidlen
, *keyid
);
1934 syslog(LOG_ERR
, "rcvd unexpected keyid %d - only keyid of 0 "
1935 "is supported", *keyid
);
1938 * We move to the "IN_PROGRESS" state.
1940 if (lstate
== ENCR_STATE_NOT_READY
)
1941 lstate
= ENCR_STATE_IN_PROGRESS
;
1943 * Clear the NO_KEYID bit because we now have a valid keyid
1945 lstate
&= ~ENCR_STATE_NO_KEYID
;
1949 (void) fprintf(stderr
,
1950 "\t(set_keyid_state) %s final state = %d\n",
1951 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1952 "DECRYPT"), lstate
);
1954 if (dir
== TELNET_DIR_ENCRYPT
)
1955 encr_data
.encrypt
.state
= lstate
;
1957 encr_data
.decrypt
.state
= lstate
;
1963 * Set the keyid value in the key_info structure.
1964 * if necessary send a response to the sender
1967 encrypt_keyid(uchar_t
*newkeyid
, int *keyidlen
, uchar_t
*keyid
,
1970 if (len
> TELNET_MAXNUMKEYS
) {
1972 (void) fprintf(stderr
,
1973 "\t(keyid) keylen too big (%d)\n", len
);
1978 (void) fprintf(stderr
, "\t(keyid) set KEYID for %s len = %d\n",
1979 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1984 if (*keyidlen
== 0) {
1986 (void) fprintf(stderr
,
1987 "\t(keyid) Got 0 length keyid - "
1992 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
1994 } else if (len
!= *keyidlen
|| memcmp(keyid
, newkeyid
, len
)) {
1996 (void) fprintf(stderr
,
1997 "\t(keyid) Setting new key (%d bytes)\n",
2001 (void) memcpy(newkeyid
, keyid
, len
);
2003 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
2005 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
2008 (void) fprintf(stderr
,
2009 "\t(keyid) %s Key already in place,"
2010 "state = %d autoflag=%d\n",
2011 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" : "DECRYPT"),
2012 (dir
== TELNET_DIR_ENCRYPT
? encr_data
.encrypt
.state
:
2013 encr_data
.decrypt
.state
),
2014 (dir
== TELNET_DIR_ENCRYPT
?
2015 encr_data
.encrypt
.autoflag
:
2016 encr_data
.decrypt
.autoflag
));
2018 /* key already in place */
2019 if ((encr_data
.encrypt
.state
== ENCR_STATE_OK
) &&
2020 dir
== TELNET_DIR_ENCRYPT
&& encr_data
.encrypt
.autoflag
) {
2021 encrypt_start_output();
2027 (void) fprintf(stderr
, "\t(keyid) %s final state = %d\n",
2028 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
2030 (dir
== TELNET_DIR_ENCRYPT
?
2031 encr_data
.encrypt
.state
:
2032 encr_data
.decrypt
.state
));
2034 encrypt_send_keyid(dir
, newkeyid
, *keyidlen
, 0);
2040 * We received the ENC_KEYID message from a client indicating that
2041 * the client wishes to verify that the indicated keyid maps to a
2045 encrypt_enc_keyid(char *data
, int cnt
)
2048 * Verify the decrypt keyid is valid
2050 encrypt_keyid(encr_data
.decrypt
.keyid
, &encr_data
.decrypt
.keyidlen
,
2051 (uchar_t
*)data
, cnt
, TELNET_DIR_DECRYPT
);
2057 * We received the DEC_KEYID message from a client indicating that
2058 * the client wants to verify that the indicated keyid maps to a valid key.
2061 encrypt_dec_keyid(char *data
, int cnt
)
2063 encrypt_keyid(encr_data
.encrypt
.keyid
, &encr_data
.encrypt
.keyidlen
,
2064 (uchar_t
*)data
, cnt
, TELNET_DIR_ENCRYPT
);
2068 * encrypt_session_key
2070 * Store the session key in the encryption data record
2073 encrypt_session_key(Session_Key
*key
, cipher_info_t
*cinfo
)
2075 if (key
== NULL
|| key
->type
!= SK_DES
) {
2077 (void) fprintf(stderr
,
2078 "\t(session_key) Cannot set krb5 "
2079 "session key (unknown type = %d)\n",
2080 key
? key
->type
: -1);
2083 (void) fprintf(stderr
,
2084 "\t(session_key) Settting session key "
2087 /* store the key in the cipher info data struct */
2088 (void) memcpy(cinfo
->krbdes_key
, (void *)key
->data
, sizeof (Block
));
2091 * Now look to see if we still need to send the key and start
2094 * If so, go ahead an call it now that we have the key.
2096 if (cinfo
->need_start
) {
2097 if (encrypt_send_encrypt_is() == ENCR_STATE_OK
) {
2098 cinfo
->need_start
= 0;
2106 * Used to add an environment variable and value to the
2107 * linked list structure.
2110 new_env(const char *name
, const char *value
)
2112 struct envlist
*env
;
2114 env
= malloc(sizeof (struct envlist
));
2117 if ((env
->name
= strdup(name
)) == NULL
) {
2121 if ((env
->value
= strdup(value
)) == NULL
) {
2127 env
->next
= envlist_head
;
2135 * Used to delete an environment variable from the linked list
2136 * structure. We just set a flag because we will delete the list
2137 * anyway before we exec login.
2140 del_env(const char *name
)
2142 struct envlist
*env
;
2144 for (env
= envlist_head
; env
; env
= env
->next
) {
2145 if (strcmp(env
->name
, name
) == 0) {
2158 if (fstat(fd
, &stats
) == -1)
2160 return (S_ISSOCK(stats
.st_mode
));
2164 * audit_telnet_settid stores the terminal id while it is still
2165 * available. Subsequent calls to adt_load_hostname() return
2166 * the id which is stored here.
2169 audit_telnet_settid(int sock
) {
2170 adt_session_data_t
*ah
;
2171 adt_termid_t
*termid
;
2174 if ((rc
= adt_start_session(&ah
, NULL
, 0)) == 0) {
2175 if ((rc
= adt_load_termid(sock
, &termid
)) == 0) {
2176 if ((rc
= adt_set_user(ah
, ADT_NO_AUDIT
,
2177 ADT_NO_AUDIT
, 0, ADT_NO_AUDIT
,
2178 termid
, ADT_SETTID
)) == 0)
2179 (void) adt_set_proc(ah
);
2182 (void) adt_end_session(ah
);
2189 main(int argc
, char *argv
[])
2191 struct sockaddr_storage from
;
2196 ushort_t porttouse
= 0;
2197 boolean_t standalone
= 0;
2198 #endif /* defined(DEBUG) */
2199 extern char *optarg
;
2203 while ((c
= getopt(argc
, argv
, TELNETD_OPTS DEBUG_OPTS
)) != -1) {
2208 * note: alternative port number only used in
2211 porttouse
= atoi(optarg
);
2219 if (strcasecmp(optarg
, "none") == 0) {
2221 } else if (strcasecmp(optarg
, "user") == 0) {
2222 auth_level
= AUTH_USER
;
2223 } else if (strcasecmp(optarg
, "valid") == 0) {
2224 auth_level
= AUTH_VALID
;
2225 } else if (strcasecmp(optarg
, "off") == 0) {
2227 negotiate_auth_krb5
= 0;
2228 } else if (strcasecmp(optarg
, "debug") == 0) {
2232 "unknown authentication level specified "
2233 "with \'-a\' option (%s)", optarg
);
2234 auth_level
= AUTH_USER
;
2238 /* disable authentication negotiation */
2239 negotiate_auth_krb5
= 0;
2243 if (optarg
!= NULL
) {
2244 int ret
= krb5_init();
2247 "Unable to use Kerberos V5 as "
2248 "requested, exiting");
2251 (void) krb5_set_default_realm(telnet_context
,
2254 "using %s as default KRB5 realm", optarg
);
2258 telnet_srvtab
= (char *)strdup(optarg
);
2260 case 'E': /* disable automatic encryption */
2261 negotiate_encrypt
= B_FALSE
;
2264 resolve_hostname
= 1;
2267 if (optarg
== NULL
|| (tos
= atoi(optarg
)) < 0 ||
2269 syslog(LOG_ERR
, "telnetd: illegal tos value: "
2280 syslog(LOG_ERR
, "telnetd: illegal cmd line option %c",
2286 netibufsize
= BUFSIZ
;
2287 if (!(netibuf
= (char *)malloc(netibufsize
)))
2288 syslog(LOG_ERR
, "netibuf malloc failed\n");
2289 (void) memset(netibuf
, 0, netibufsize
);
2296 static struct sockaddr_in6 sin6
= { AF_INET6
};
2300 sin6
.sin6_port
= htons(porttouse
);
2302 sp
= getservbyname("telnet", "tcp");
2304 (void) fprintf(stderr
,
2305 "telnetd: tcp/telnet: "
2306 "unknown service\n");
2309 sin6
.sin6_port
= sp
->s_port
;
2312 s
= socket(AF_INET6
, SOCK_STREAM
, IPPROTO_TCP
);
2314 perror("telnetd: socket");
2317 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, (char *)&option
,
2318 sizeof (option
)) == -1)
2319 perror("setsockopt SO_REUSEADDR");
2320 if (bind(s
, (struct sockaddr
*)&sin6
, sizeof (sin6
)) < 0) {
2324 if (listen(s
, 32) < 0) {
2329 /* automatically reap all child processes */
2330 (void) signal(SIGCHLD
, SIG_IGN
);
2335 foo
= sizeof (sin6
);
2336 ns
= accept(s
, (struct sockaddr
*)&sin6
, &foo
);
2349 (void) signal(SIGCHLD
, SIG_DFL
);
2355 #endif /* defined(DEBUG) */
2357 openlog("telnetd", LOG_PID
| LOG_ODELAY
, LOG_DAEMON
);
2359 issocket
= issock(0);
2361 fatal(0, "stdin is not a socket file descriptor");
2363 fromlen
= (socklen_t
)sizeof (from
);
2364 (void) memset((char *)&from
, 0, sizeof (from
));
2365 if (getpeername(0, (struct sockaddr
*)&from
, &fromlen
)
2367 (void) fprintf(stderr
, "%s: ", argv
[0]);
2368 perror("getpeername");
2369 _exit(EXIT_FAILURE
);
2372 if (audit_telnet_settid(0)) { /* set terminal ID */
2373 (void) fprintf(stderr
, "%s: ", argv
[0]);
2378 if (setsockopt(0, SOL_SOCKET
, SO_KEEPALIVE
, (const char *)&on
,
2380 syslog(LOG_WARNING
, "setsockopt (SO_KEEPALIVE): %m");
2387 setsockopt(0, IPPROTO_IP
, IP_TOS
,
2388 (char *)&tos
, sizeof (tos
)) < 0 &&
2389 errno
!= ENOPROTOOPT
) {
2390 syslog(LOG_ERR
, "setsockopt (IP_TOS %d): %m", tos
);
2393 if (setsockopt(net
, SOL_SOCKET
, SO_OOBINLINE
, (char *)&on
,
2395 syslog(LOG_WARNING
, "setsockopt (SO_OOBINLINE): %m");
2398 /* set the default PAM service name */
2399 (void) strcpy(pam_svc_name
, "telnet");
2402 return (EXIT_SUCCESS
);
2405 static char *terminaltype
= 0;
2410 * A small subroutine to flush the network output buffer, get some data
2411 * from the network, and pass it through the telnet state machine. We
2412 * also flush the pty input buffer (by dropping its data) if it becomes
2418 if (nfrontp
-nbackp
) {
2422 ncc
= read(net
, netibuf
, netibufsize
);
2426 syslog(LOG_INFO
, "ttloop: read: %m");
2428 } else if (ncc
== 0) {
2429 syslog(LOG_INFO
, "ttloop: peer closed connection\n");
2434 telrcv(); /* state machine */
2436 pfrontp
= pbackp
= ptyobuf
;
2444 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)DO
, (uchar_t
)option
);
2448 send_will(int option
)
2450 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)WILL
, (uchar_t
)option
);
2454 send_wont(int option
)
2456 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)WONT
, (uchar_t
)option
);
2463 * Negotiate automatic authentication, is possible.
2466 getauthtype(char *username
, int *len
)
2468 int init_status
= -1;
2470 init_status
= krb5_init();
2472 if (auth_level
== -1 || init_status
!= 0) {
2473 remopts
[TELOPT_AUTHENTICATION
] = OPT_NO
;
2474 myopts
[TELOPT_AUTHENTICATION
] = OPT_NO
;
2475 negotiate_auth_krb5
= B_FALSE
;
2476 negotiate_encrypt
= B_FALSE
;
2477 return (AUTH_REJECT
);
2480 if (init_status
== 0 && auth_level
!= -1) {
2481 if (negotiate_auth_krb5
) {
2483 * Negotiate Authentication FIRST
2485 send_do(TELOPT_AUTHENTICATION
);
2486 remopts
[TELOPT_AUTHENTICATION
] =
2487 OPT_YES_BUT_ALWAYS_LOOK
;
2489 while (sequenceIs(authopt
, getauth
))
2492 if (remopts
[TELOPT_AUTHENTICATION
] == OPT_YES
) {
2494 * Request KRB5 Mutual authentication and if that fails,
2495 * KRB5 1-way client authentication
2497 uchar_t sbbuf
[MAXOPTLEN
], *p
;
2499 *p
++ = (uchar_t
)IAC
;
2501 *p
++ = (uchar_t
)TELOPT_AUTHENTICATION
;
2502 *p
++ = (uchar_t
)TELQUAL_SEND
;
2503 if (negotiate_auth_krb5
) {
2504 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2505 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2508 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2509 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2511 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2512 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2515 *p
++ = (uchar_t
)AUTHTYPE_NULL
;
2517 *p
++ = (uchar_t
)IAC
;
2520 write_data_len((const char *)sbbuf
,
2521 (size_t)(p
- sbbuf
));
2524 (void) fprintf(stderr
,
2525 "SENT TELOPT_AUTHENTICATION "
2528 /* auth_wait returns the authentication level */
2529 /* status = auth_wait(username, len); */
2530 while (sequenceIs(authdone
, getauth
))
2533 * Now check to see if the user is valid or not
2535 if (authenticated
== NULL
|| authenticated
== &NoAuth
)
2536 auth_status
= AUTH_REJECT
;
2539 * We cant be VALID until the user status is
2542 if (auth_status
== AUTH_VALID
)
2543 auth_status
= AUTH_USER
;
2545 if (authenticated
->AuthName
==
2546 AUTHTYPE_KERBEROS_V5
)
2547 auth_status
= krb5_user_status(
2548 username
, *len
, auth_status
);
2552 return (auth_status
);
2558 if (krb5_privacy_allowed() && negotiate_encrypt
) {
2559 if (myopts
[TELOPT_ENCRYPT
] != OPT_YES
) {
2560 if (!sent_will_encrypt
) {
2561 send_will(TELOPT_ENCRYPT
);
2562 sent_will_encrypt
= B_TRUE
;
2565 (void) fprintf(stderr
, "SENT WILL ENCRYPT\n");
2567 if (remopts
[TELOPT_ENCRYPT
] != OPT_YES
) {
2568 if (!sent_do_encrypt
) {
2569 send_do(TELOPT_ENCRYPT
);
2570 sent_do_encrypt
= B_TRUE
;
2571 remopts
[TELOPT_ENCRYPT
] =
2572 OPT_YES_BUT_ALWAYS_LOOK
;
2575 (void) fprintf(stderr
, "SENT DO ENCRYPT\n");
2577 myopts
[TELOPT_ENCRYPT
] = OPT_YES
;
2579 while (sequenceIs(encropt
, getencr
))
2582 if (auth_status
!= AUTH_REJECT
&&
2583 remopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
2584 myopts
[TELOPT_ENCRYPT
] == OPT_YES
) {
2586 if (sent_encrypt_support
== B_FALSE
) {
2587 write_data("%c%c%c%c%c%c%c",
2590 (uchar_t
)TELOPT_ENCRYPT
,
2591 (uchar_t
)ENCRYPT_SUPPORT
,
2592 (uchar_t
)TELOPT_ENCTYPE_DES_CFB64
,
2599 * Now wait for a response to these messages before
2601 * Look for TELOPT_ENCRYPT suboptions
2603 while (sequenceIs(encr_support
, getencr
))
2607 /* Dont need responses to these, so dont wait for them */
2609 remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
2610 myopts
[TELOPT_ENCRYPT
] = OPT_NO
;
2618 * Ask the other end to send along its terminal type.
2619 * Output is the variable terminaltype filled in.
2622 getterminaltype(void)
2625 * The remote side may have already sent this info, so
2626 * dont ask for these options if the other side already
2627 * sent the information.
2629 if (sequenceIs(ttypeopt
, getterminal
)) {
2630 send_do(TELOPT_TTYPE
);
2631 remopts
[TELOPT_TTYPE
] = OPT_YES_BUT_ALWAYS_LOOK
;
2634 if (sequenceIs(nawsopt
, getterminal
)) {
2635 send_do(TELOPT_NAWS
);
2636 remopts
[TELOPT_NAWS
] = OPT_YES_BUT_ALWAYS_LOOK
;
2639 if (sequenceIs(xdisplocopt
, getterminal
)) {
2640 send_do(TELOPT_XDISPLOC
);
2641 remopts
[TELOPT_XDISPLOC
] = OPT_YES_BUT_ALWAYS_LOOK
;
2644 if (sequenceIs(environopt
, getterminal
)) {
2645 send_do(TELOPT_NEW_ENVIRON
);
2646 remopts
[TELOPT_NEW_ENVIRON
] = OPT_YES_BUT_ALWAYS_LOOK
;
2649 if (sequenceIs(oenvironopt
, getterminal
)) {
2650 send_do(TELOPT_OLD_ENVIRON
);
2651 remopts
[TELOPT_OLD_ENVIRON
] = OPT_YES_BUT_ALWAYS_LOOK
;
2654 /* make sure encryption is started here */
2655 while (auth_status
!= AUTH_REJECT
&&
2656 authenticated
!= &NoAuth
&& authenticated
!= NULL
&&
2657 remopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
2658 encr_data
.encrypt
.autoflag
&&
2659 encr_data
.encrypt
.state
!= ENCR_STATE_OK
) {
2661 (void) fprintf(stderr
, "getterminaltype() forcing encrypt\n");
2666 (void) fprintf(stderr
, "getterminaltype() encryption %sstarted\n",
2667 encr_data
.encrypt
.state
== ENCR_STATE_OK
? "" : "not ");
2670 while (sequenceIs(ttypeopt
, getterminal
) ||
2671 sequenceIs(nawsopt
, getterminal
) ||
2672 sequenceIs(xdisplocopt
, getterminal
) ||
2673 sequenceIs(environopt
, getterminal
) ||
2674 sequenceIs(oenvironopt
, getterminal
)) {
2679 if (remopts
[TELOPT_TTYPE
] == OPT_YES
) {
2680 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2681 (uchar_t
)TELOPT_TTYPE
, (uchar_t
)TELQUAL_SEND
,
2682 (uchar_t
)IAC
, (uchar_t
)SE
};
2684 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2686 if (remopts
[TELOPT_XDISPLOC
] == OPT_YES
) {
2687 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2688 (uchar_t
)TELOPT_XDISPLOC
, (uchar_t
)TELQUAL_SEND
,
2689 (uchar_t
)IAC
, (uchar_t
)SE
};
2691 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2693 if (remopts
[TELOPT_NEW_ENVIRON
] == OPT_YES
) {
2694 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2695 (uchar_t
)TELOPT_NEW_ENVIRON
, (uchar_t
)TELQUAL_SEND
,
2696 (uchar_t
)IAC
, (uchar_t
)SE
};
2698 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2700 if (remopts
[TELOPT_OLD_ENVIRON
] == OPT_YES
) {
2701 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2702 (uchar_t
)TELOPT_OLD_ENVIRON
, (uchar_t
)TELQUAL_SEND
,
2703 (uchar_t
)IAC
, (uchar_t
)SE
};
2705 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2708 if (remopts
[TELOPT_TTYPE
] == OPT_YES
) {
2709 while (sequenceIs(ttypesubopt
, getterminal
)) {
2713 if (remopts
[TELOPT_XDISPLOC
] == OPT_YES
) {
2714 while (sequenceIs(xdisplocsubopt
, getterminal
)) {
2718 if (remopts
[TELOPT_NEW_ENVIRON
] == OPT_YES
) {
2719 while (sequenceIs(environsubopt
, getterminal
)) {
2723 if (remopts
[TELOPT_OLD_ENVIRON
] == OPT_YES
) {
2724 while (sequenceIs(oenvironsubopt
, getterminal
)) {
2734 * Get a pty, scan input lines.
2737 doit(int f
, struct sockaddr_storage
*who
)
2740 char host_name
[MAXHOSTNAMELEN
];
2743 int ptmfd
; /* fd of logindmux connected to pty */
2744 int netfd
; /* fd of logindmux connected to netf */
2746 struct protocol_arg telnetp
;
2747 struct strioctl telnetmod
;
2748 struct envlist
*env
, *next
;
2750 char abuf
[INET6_ADDRSTRLEN
];
2751 struct sockaddr_in
*sin
;
2752 struct sockaddr_in6
*sin6
;
2754 char username
[MAXUSERNAMELEN
];
2759 if ((p
= open("/dev/ptmx", O_RDWR
| O_NOCTTY
)) == -1) {
2760 fatalperror(f
, "open /dev/ptmx", errno
);
2762 if (grantpt(p
) == -1)
2763 fatal(f
, "could not grant slave pty");
2764 if (unlockpt(p
) == -1)
2765 fatal(f
, "could not unlock slave pty");
2766 if ((slavename
= ptsname(p
)) == NULL
)
2767 fatal(f
, "could not enable slave pty");
2769 if ((t
= open(slavename
, O_RDWR
| O_NOCTTY
)) == -1)
2770 fatal(f
, "could not open slave pty");
2771 if (ioctl(t
, I_PUSH
, "ptem") == -1)
2772 fatalperror(f
, "ioctl I_PUSH ptem", errno
);
2773 if (ioctl(t
, I_PUSH
, "ldterm") == -1)
2774 fatalperror(f
, "ioctl I_PUSH ldterm", errno
);
2775 if (ioctl(t
, I_PUSH
, "ttcompat") == -1)
2776 fatalperror(f
, "ioctl I_PUSH ttcompat", errno
);
2782 if (ioctl(t
, TIOCGETP
, &b
) == -1)
2783 syslog(LOG_INFO
, "ioctl TIOCGETP pty t: %m\n");
2784 b
.sg_flags
= O_CRMOD
|O_XTABS
|O_ANYP
;
2785 /* XXX - ispeed and ospeed must be non-zero */
2786 b
.sg_ispeed
= B38400
;
2787 b
.sg_ospeed
= B38400
;
2788 if (ioctl(t
, TIOCSETN
, &b
) == -1)
2789 syslog(LOG_INFO
, "ioctl TIOCSETN pty t: %m\n");
2790 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
2791 syslog(LOG_INFO
, "ioctl TIOCGETP pty pty: %m\n");
2792 b
.sg_flags
&= ~O_ECHO
;
2793 if (ioctl(pty
, TIOCSETN
, &b
) == -1)
2794 syslog(LOG_INFO
, "ioctl TIOCSETN pty pty: %m\n");
2796 if (who
->ss_family
== AF_INET
) {
2797 char *addrbuf
= NULL
;
2798 char *portbuf
= NULL
;
2800 sin
= (struct sockaddr_in
*)who
;
2801 wholen
= sizeof (struct sockaddr_in
);
2803 addrbuf
= (char *)malloc(wholen
);
2804 if (addrbuf
== NULL
)
2805 fatal(f
, "Cannot alloc memory for address info\n");
2806 portbuf
= (char *)malloc(sizeof (sin
->sin_port
));
2807 if (portbuf
== NULL
) {
2809 fatal(f
, "Cannot alloc memory for port info\n");
2812 (void) memcpy(addrbuf
, (const void *)&sin
->sin_addr
, wholen
);
2813 (void) memcpy(portbuf
, (const void *)&sin
->sin_port
,
2814 sizeof (sin
->sin_port
));
2816 if (rsaddr
.contents
!= NULL
)
2817 free(rsaddr
.contents
);
2819 rsaddr
.contents
= (krb5_octet
*)addrbuf
;
2820 rsaddr
.length
= wholen
;
2821 rsaddr
.addrtype
= ADDRTYPE_INET
;
2823 if (rsport
.contents
!= NULL
)
2824 free(rsport
.contents
);
2826 rsport
.contents
= (krb5_octet
*)portbuf
;
2827 rsport
.length
= sizeof (sin
->sin_port
);
2828 rsport
.addrtype
= ADDRTYPE_IPPORT
;
2829 } else if (who
->ss_family
== AF_INET6
) {
2830 struct in_addr ipv4_addr
;
2831 char *addrbuf
= NULL
;
2832 char *portbuf
= NULL
;
2834 sin6
= (struct sockaddr_in6
*)who
;
2835 wholen
= sizeof (struct sockaddr_in6
);
2837 IN6_V4MAPPED_TO_INADDR(&sin6
->sin6_addr
,
2840 addrbuf
= (char *)malloc(wholen
);
2841 if (addrbuf
== NULL
)
2842 fatal(f
, "Cannot alloc memory for address info\n");
2844 portbuf
= (char *)malloc(sizeof (sin6
->sin6_port
));
2845 if (portbuf
== NULL
) {
2847 fatal(f
, "Cannot alloc memory for port info\n");
2850 (void) memcpy((void *) addrbuf
,
2851 (const void *)&ipv4_addr
,
2854 * If we already used rsaddr.contents, free the previous
2857 if (rsaddr
.contents
!= NULL
)
2858 free(rsaddr
.contents
);
2860 rsaddr
.contents
= (krb5_octet
*)addrbuf
;
2861 rsaddr
.length
= sizeof (ipv4_addr
);
2862 rsaddr
.addrtype
= ADDRTYPE_INET
;
2864 (void) memcpy((void *) portbuf
, (const void *)&sin6
->sin6_port
,
2865 sizeof (sin6
->sin6_port
));
2867 if (rsport
.contents
!= NULL
)
2868 free(rsport
.contents
);
2870 rsport
.contents
= (krb5_octet
*)portbuf
;
2871 rsport
.length
= sizeof (sin6
->sin6_port
);
2872 rsport
.addrtype
= ADDRTYPE_IPPORT
;
2874 syslog(LOG_ERR
, "unknown address family %d\n",
2876 fatal(f
, "getpeername: unknown address family\n");
2879 if (getnameinfo((const struct sockaddr
*) who
, wholen
, host_name
,
2880 sizeof (host_name
), NULL
, 0, 0) == 0) {
2884 * If the '-U' option was given on the cmd line, we must
2885 * be able to lookup the hostname
2887 if (resolve_hostname
) {
2888 fatal(f
, "Couldn't resolve your address into a "
2889 "host name.\r\nPlease contact your net "
2893 if (who
->ss_family
== AF_INET6
) {
2894 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
2895 struct in_addr ipv4_addr
;
2897 IN6_V4MAPPED_TO_INADDR(&sin6
->sin6_addr
,
2899 host
= (char *)inet_ntop(AF_INET
,
2900 &ipv4_addr
, abuf
, sizeof (abuf
));
2902 host
= (char *)inet_ntop(AF_INET6
,
2903 &sin6
->sin6_addr
, abuf
,
2906 } else if (who
->ss_family
== AF_INET
) {
2907 host
= (char *)inet_ntop(AF_INET
,
2908 &sin
->sin_addr
, abuf
, sizeof (abuf
));
2912 * Note that sockmod has to be removed since readstream assumes
2913 * a "raw" TPI endpoint (e.g. it uses getmsg).
2915 if (removemod(f
, "sockmod") < 0)
2916 fatalperror(f
, "couldn't remove sockmod", errno
);
2921 * Push the crypto module on the stream before 'telmod' so it
2922 * can encrypt/decrypt without interfering with telmod functionality
2923 * We must push it now because many of the crypto options negotiated
2924 * initially must be saved in the crypto module (via IOCTL calls).
2926 if (ioctl(f
, I_PUSH
, "cryptmod") < 0)
2927 fatalperror(f
, "ioctl I_PUSH cryptmod", errno
);
2931 * gotta set the encryption clock now because it is often negotiated
2932 * immediately by the client, and if we wait till after we negotiate
2933 * auth, it will be out of whack with when the WILL/WONT ENCRYPT
2934 * option is received.
2939 * get terminal type.
2942 len
= sizeof (username
);
2944 settimer(getterminal
);
2947 * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
2949 auth_status
= getauthtype(username
, &len
);
2951 * Exchange TELOPT_ENCRYPT options per RFC 2946
2956 if (ioctl(f
, I_PUSH
, "telmod") < 0)
2957 fatalperror(f
, "ioctl I_PUSH telmod", errno
);
2960 * Make sure telmod will pass unrecognized IOCTLs to cryptmod
2964 telnetmod
.ic_cmd
= CRYPTPASSTHRU
;
2965 telnetmod
.ic_timout
= -1;
2966 telnetmod
.ic_len
= sizeof (uchar_t
);
2967 telnetmod
.ic_dp
= (char *)&passthru
;
2969 if (ioctl(f
, I_STR
, &telnetmod
) < 0)
2970 fatal(f
, "ioctl CRPASSTHRU failed\n");
2976 * readstream will do a getmsg till it receives M_PROTO type
2977 * T_DATA_REQ from telnetmodopen(). This signals that all data
2978 * in-flight before telmod was pushed has been received at the
2981 while ((nsize
= readstream(f
, netibuf
, ncc
+ netip
- netibuf
)) > 0) {
2986 fatalperror(f
, "readstream failed\n", errno
);
2990 * open logindmux drivers and link them with network and ptm
2993 if ((ptmfd
= open("/dev/logindmux", O_RDWR
)) == -1) {
2994 fatalperror(f
, "open /dev/logindmux", errno
);
2996 if ((netfd
= open("/dev/logindmux", O_RDWR
)) == -1) {
2997 fatalperror(f
, "open /dev/logindmux", errno
);
3000 if (ioctl(ptmfd
, I_LINK
, p
) < 0)
3001 fatal(f
, "ioctl I_LINK of /dev/ptmx failed\n");
3002 if (ioctl(netfd
, I_LINK
, f
) < 0)
3003 fatal(f
, "ioctl I_LINK of tcp connection failed\n");
3006 * Figure out the device number of ptm's mux fd, and pass that
3009 if (fstat(ptmfd
, &buf
) < 0) {
3010 fatalperror(f
, "fstat ptmfd failed", errno
);
3012 telnetp
.dev
= buf
.st_rdev
;
3015 telnetmod
.ic_cmd
= LOGDMX_IOC_QEXCHANGE
;
3016 telnetmod
.ic_timout
= -1;
3017 telnetmod
.ic_len
= sizeof (struct protocol_arg
);
3018 telnetmod
.ic_dp
= (char *)&telnetp
;
3020 if (ioctl(netfd
, I_STR
, &telnetmod
) < 0)
3021 fatal(netfd
, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
3024 * Figure out the device number of the net's mux fd, and pass that
3027 if (fstat(netfd
, &buf
) < 0) {
3028 fatalperror(f
, "fstat netfd failed", errno
);
3030 telnetp
.dev
= buf
.st_rdev
;
3033 telnetmod
.ic_cmd
= LOGDMX_IOC_QEXCHANGE
;
3034 telnetmod
.ic_timout
= -1;
3035 telnetmod
.ic_len
= sizeof (struct protocol_arg
);
3036 telnetmod
.ic_dp
= (char *)&telnetp
;
3038 if (ioctl(ptmfd
, I_STR
, &telnetmod
) < 0)
3039 fatal(netfd
, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
3043 cryptmod_fd
= netfd
;
3046 * Show banner that getty never gave, but
3047 * only if the user did not automatically authenticate.
3049 if (getenv("USER") == '\0' && auth_status
< AUTH_USER
)
3053 * If the user automatically authenticated with Kerberos
3054 * we must set the service name that PAM will use. We
3055 * need to do it BEFORE the child fork so that 'cleanup'
3056 * in the parent can call the PAM cleanup stuff with the
3057 * same PAM service that /bin/login will use to authenticate
3060 if (auth_level
>= 0 && auth_status
>= AUTH_USER
&&
3061 (AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
)) {
3062 (void) strcpy(pam_svc_name
, "ktelnet");
3065 * Request to do suppress go ahead.
3067 * Send this before sending the TELOPT_ECHO stuff below because
3068 * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
3069 * that has them turn off local echo mode if SGA is not received first.
3070 * This also has the odd side-effect of causing the client to enable
3071 * encryption and then immediately disable it during the ECHO option
3072 * negotiations. Its just better to to SGA first now that we support
3075 if (!myopts
[TELOPT_SGA
]) {
3076 dooption(TELOPT_SGA
);
3080 * Pretend we got a DO ECHO from the client if we have not
3081 * yet negotiated the ECHO.
3083 if (!myopts
[TELOPT_ECHO
]) {
3084 dooption(TELOPT_ECHO
);
3088 * Is the client side a 4.2 (NOT 4.3) system? We need to know this
3089 * because 4.2 clients are unable to deal with TCP urgent data.
3091 * To find out, we send out a "DO ECHO". If the remote system
3092 * answers "WILL ECHO" it is probably a 4.2 client, and we note
3093 * that fact ("WILL ECHO" ==> that the client will echo what
3094 * WE, the server, sends it; it does NOT mean that the client will
3095 * echo the terminal input).
3097 send_do(TELOPT_ECHO
);
3098 remopts
[TELOPT_ECHO
] = OPT_YES_BUT_ALWAYS_LOOK
;
3100 if ((pid
= fork()) < 0)
3101 fatalperror(netfd
, "fork", errno
);
3103 telnet(net
, master
);
3105 * The child process needs to be the session leader
3106 * and have the pty as its controlling tty. Thus we need
3107 * to re-open the slave side of the pty no without
3108 * the O_NOCTTY flag that we have been careful to
3109 * use up to this point.
3113 tt
= open(line
, O_RDWR
);
3115 fatalperror(netfd
, line
, errno
);
3116 (void) close(netfd
);
3117 (void) close(ptmfd
);
3131 (void) local_setenv("TERM", terminaltype
+5, 1);
3133 * -h : pass on name of host.
3134 * WARNING: -h is accepted by login if and only if
3136 * -p : don't clobber the environment (so terminal type stays set).
3139 /* System V login expects a utmp entry to already be there */
3141 (void) memset((char *)&ut
, 0, sizeof (ut
));
3142 (void) strncpy(ut
.ut_user
, ".telnet", sizeof (ut
.ut_user
));
3143 (void) strncpy(ut
.ut_line
, line
, sizeof (ut
.ut_line
));
3144 ut
.ut_pid
= getpid();
3146 ut
.ut_id
[1] = (char)SC_WILDC
;
3147 ut
.ut_id
[2] = (char)SC_WILDC
;
3148 ut
.ut_id
[3] = (char)SC_WILDC
;
3149 ut
.ut_type
= LOGIN_PROCESS
;
3150 ut
.ut_exit
.e_termination
= 0;
3151 ut
.ut_exit
.e_exit
= 0;
3152 (void) time(&ut
.ut_tv
.tv_sec
);
3153 if (makeutx(&ut
) == NULL
)
3154 syslog(LOG_INFO
, "in.telnetd:\tmakeutx failed");
3158 * Load in the cached environment variables and either
3159 * set/unset them in the environment.
3161 for (next
= envlist_head
; next
; ) {
3164 (void) local_unsetenv(env
->name
);
3166 (void) local_setenv(env
->name
, env
->value
, 1);
3173 if (!username
|| !username
[0])
3174 auth_status
= AUTH_REJECT
; /* we dont know who this is */
3176 /* If the current auth status is less than the required level, exit */
3177 if (auth_status
< auth_level
) {
3178 fatal(net
, "Authentication failed\n");
3183 * If AUTH_VALID (proper authentication REQUIRED and we have
3184 * a krb5_name), exec '/bin/login', make sure it uses the
3185 * correct PAM service name (pam_svc_name). If possible,
3186 * make sure the krb5 authenticated user's name (krb5_name)
3187 * is in the PAM REPOSITORY for krb5.
3189 if (auth_level
>= 0 &&
3190 (auth_status
== AUTH_VALID
|| auth_status
== AUTH_USER
) &&
3191 ((krb5_name
!= NULL
) && strlen(krb5_name
)) &&
3192 ((AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
))) {
3193 (void) execl(LOGIN_PROGRAM
, "login",
3199 "-R", KRB5_REPOSITORY_NAME
,
3200 AuthenticatingUser
, 0);
3201 } else if (auth_level
>= 0 &&
3202 auth_status
>= AUTH_USER
&&
3203 (((AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
)) ||
3206 * If we only know the name but not the principal,
3207 * login will have to authenticate further.
3209 (void) execl(LOGIN_PROGRAM
, "login",
3213 "-s", pam_svc_name
, "--",
3214 (AuthenticatingUser
!= NULL
? AuthenticatingUser
:
3215 getenv("USER")), 0);
3217 } else /* default, no auth. info available, login does it all */ {
3218 (void) execl(LOGIN_PROGRAM
, "login",
3219 "-p", "-h", host
, "-d", slavename
, "--",
3223 fatalperror(netfd
, LOGIN_PROGRAM
, errno
);
3228 fatal(int f
, char *msg
)
3232 (void) snprintf(buf
, sizeof (buf
), "telnetd: %s.\r\n", msg
);
3233 (void) write(f
, buf
, strlen(buf
));
3239 fatalperror(int f
, char *msg
, int errnum
)
3243 (void) snprintf(buf
, sizeof (buf
),
3244 "%s: %s\r\n", msg
, strerror(errnum
));
3250 * Main loop. Select from pty and network, and
3251 * hand data to telnet receiver finite state machine
3252 * when it receives telnet protocol. Regular data
3253 * flow between pty and network takes place through
3254 * inkernel telnet streams module (telmod).
3257 telnet(int net
, int master
)
3261 struct strioctl telnetmod
;
3264 char binary_out
= 0;
3266 if (ioctl(net
, FIONBIO
, &on
) == -1)
3267 syslog(LOG_INFO
, "ioctl FIONBIO net: %m\n");
3268 if (ioctl(master
, FIONBIO
, &on
) == -1)
3269 syslog(LOG_INFO
, "ioctl FIONBIO pty p: %m\n");
3270 (void) signal(SIGTSTP
, SIG_IGN
);
3271 (void) signal(SIGCHLD
, (void (*)())cleanup
);
3275 * Call telrcv() once to pick up anything received during
3276 * terminal type negotiation.
3284 fd_set ibits
, obits
, xbits
;
3295 * If we couldn't flush all our output to the network,
3296 * keep checking for when we can.
3298 if (nfrontp
- nbackp
)
3299 FD_SET(net
, &obits
);
3301 * Never look for input if there's still
3302 * stuff in the corresponding output buffer
3304 if (pfrontp
- pbackp
) {
3305 FD_SET(master
, &obits
);
3307 FD_SET(net
, &ibits
);
3310 FD_SET(net
, &xbits
);
3313 #define max(x, y) (((x) < (y)) ? (y) : (x))
3316 * make an ioctl to telnet module (net side) to send
3317 * binary mode of telnet daemon. binary_in and
3318 * binary_out are 0 if not in binary mode.
3320 if (binary_in
!= myopts
[TELOPT_BINARY
] ||
3321 binary_out
!= remopts
[TELOPT_BINARY
]) {
3324 if (myopts
[TELOPT_BINARY
] != OPT_NO
)
3325 mode
|= TEL_BINARY_IN
;
3327 if (remopts
[TELOPT_BINARY
] != OPT_NO
)
3328 mode
|= TEL_BINARY_OUT
;
3330 telnetmod
.ic_cmd
= TEL_IOC_MODE
;
3331 telnetmod
.ic_timout
= -1;
3332 telnetmod
.ic_len
= 1;
3333 telnetmod
.ic_dp
= &mode
;
3335 syslog(LOG_DEBUG
, "TEL_IOC_MODE binary has changed\n");
3337 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3338 fatal(net
, "ioctl TEL_IOC_MODE failed\n");
3339 binary_in
= myopts
[TELOPT_BINARY
];
3340 binary_out
= remopts
[TELOPT_BINARY
];
3342 if (state
== TS_DATA
) {
3343 if ((nfrontp
== nbackp
) &&
3344 (pfrontp
== pbackp
)) {
3345 if (ioctl(net
, I_NREAD
, &nsize
) < 0)
3347 "ioctl I_NREAD failed\n", errno
);
3352 * make an ioctl to reinsert remaining data at
3353 * streamhead. After this, ioctl reenables the
3354 * telnet lower put queue. This queue was
3355 * noenabled by telnet module after sending
3356 * protocol/urgent data to telnetd.
3359 telnetmod
.ic_cmd
= TEL_IOC_ENABLE
;
3360 telnetmod
.ic_timout
= -1;
3362 telnetmod
.ic_len
= ncc
+ nsize
;
3363 telnetmod
.ic_dp
= netip
;
3365 telnetmod
.ic_len
= 0;
3366 telnetmod
.ic_dp
= NULL
;
3368 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3369 fatal(net
, "ioctl TEL_IOC_ENABLE \
3372 telmod_init_done
= B_TRUE
;
3375 (void) memset(netibuf
, 0, netibufsize
);
3381 * state not changed to TS_DATA and hence, more to read
3382 * send ioctl to get one more message block.
3384 telnetmod
.ic_cmd
= TEL_IOC_GETBLK
;
3385 telnetmod
.ic_timout
= -1;
3386 telnetmod
.ic_len
= 0;
3387 telnetmod
.ic_dp
= NULL
;
3389 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3390 fatal(net
, "ioctl TEL_IOC_GETBLK failed\n");
3393 if ((c
= select(max(net
, master
) + 1, &ibits
, &obits
, &xbits
,
3394 (struct timeval
*)0)) < 1) {
3396 if (errno
== EINTR
) {
3407 if (FD_ISSET(net
, &xbits
)) {
3412 * Something to read from the network...
3414 if (FD_ISSET(net
, &ibits
)) {
3415 ncc
= read(net
, netibuf
, netibufsize
);
3416 if (ncc
< 0 && errno
== EWOULDBLOCK
)
3426 if (FD_ISSET(net
, &obits
) && (nfrontp
- nbackp
) > 0)
3430 if (FD_ISSET(master
, &obits
) && (pfrontp
- pbackp
) > 0)
3442 if ((&ptyobuf
[BUFSIZ
] - pfrontp
) < 2)
3446 * Once we hit data, we want to transition back to
3447 * in-kernel processing. However, this code is shared
3448 * by getterminaltype()/ttloop() which run before the
3449 * in-kernel plumbing is available. So if we are still
3450 * processing the initial option negotiation, even TS_DATA
3451 * must be processed here.
3453 if (c
!= IAC
&& state
== TS_DATA
&& init_neg_done
) {
3462 /* Strip off \n or \0 after a \r */
3463 if ((c
== 0) || (c
== '\n')) {
3476 * We map \r\n ==> \r, since
3477 * We now map \r\n ==> \r for pragmatic reasons.
3478 * Many client implementations send \r\n when
3479 * the user hits the CarriageReturn key.
3481 * We USED to map \r\n ==> \n, since \r\n says
3482 * that we want to be in column 1 of the next
3485 if (c
== '\r' && (myopts
[TELOPT_BINARY
] == OPT_NO
)) {
3495 * Send the process on the pty side an
3496 * interrupt. Do this with a NULL or
3497 * interrupt char; depending on the tty mode.
3511 write_data_len("\r\n[Yes]\r\n", 9);
3518 struct ltchars tmpltc
;
3520 ptyflush(); /* half-hearted */
3521 if (ioctl(pty
, TIOCGLTC
, &tmpltc
) == -1)
3523 "ioctl TIOCGLTC: %m\n");
3524 if (tmpltc
.t_flushc
!= '\377') {
3525 *pfrontp
++ = tmpltc
.t_flushc
;
3527 netclear(); /* clear buffer back */
3528 write_data("%c%c", (uchar_t
)IAC
,
3531 neturg
= nfrontp
-1; /* off by one XXX */
3533 netflush(); /* XXX.sparker */
3538 * Erase Character and
3546 ptyflush(); /* half-hearted */
3547 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
3549 "ioctl TIOCGETP: %m\n");
3551 b
.sg_erase
: b
.sg_kill
;
3559 * Check for urgent data...
3565 * Begin option subnegotiation...
3604 SB_ACCUM((uchar_t
)IAC
);
3611 suboption(); /* handle sub-option */
3617 if (remopts
[c
] != OPT_YES
)
3623 if (remopts
[c
] != OPT_NO
)
3629 if (myopts
[c
] != OPT_YES
)
3635 if (myopts
[c
] != OPT_NO
) {
3642 syslog(LOG_ERR
, "telnetd: panic state=%d\n", state
);
3643 (void) printf("telnetd: panic state=%d\n", state
);
3650 willoption(int option
)
3653 boolean_t send_reply
= B_TRUE
;
3662 not42
= 0; /* looks like a 4.2 system */
3664 * Now, in a 4.2 system, to break them out of ECHOing
3665 * (to the terminal) mode, we need to send a "WILL ECHO".
3666 * Kludge upon kludge!
3668 if (myopts
[TELOPT_ECHO
] == OPT_YES
) {
3669 dooption(TELOPT_ECHO
);
3681 case TELOPT_XDISPLOC
:
3682 settimer(xdisplocopt
);
3685 case TELOPT_NEW_ENVIRON
:
3686 settimer(environopt
);
3689 case TELOPT_AUTHENTICATION
:
3691 if (remopts
[option
] == OPT_NO
||
3692 negotiate_auth_krb5
== 0)
3698 case TELOPT_OLD_ENVIRON
:
3699 settimer(oenvironopt
);
3702 if (remopts
[option
] == OPT_YES_BUT_ALWAYS_LOOK
) {
3703 remopts
[option
] = OPT_YES
;
3715 case TELOPT_ENCRYPT
:
3716 settimer(encropt
); /* got response to do/dont */
3718 (void) fprintf(stderr
,
3719 "RCVD IAC WILL TELOPT_ENCRYPT\n");
3720 if (krb5_privacy_allowed()) {
3722 if (sent_do_encrypt
)
3723 send_reply
= B_FALSE
;
3725 sent_do_encrypt
= B_TRUE
;
3736 remopts
[option
] = OPT_YES
;
3738 remopts
[option
] = OPT_NO
;
3741 write_data((const char *)fmt
, option
);
3747 wontoption(int option
)
3754 not42
= 1; /* doesn't seem to be a 4.2 system */
3769 case TELOPT_XDISPLOC
:
3770 settimer(xdisplocopt
);
3773 case TELOPT_NEW_ENVIRON
:
3774 settimer(environopt
);
3777 case TELOPT_OLD_ENVIRON
:
3778 settimer(oenvironopt
);
3781 case TELOPT_AUTHENTICATION
:
3783 auth_finished(0, AUTH_REJECT
);
3785 (void) fprintf(stderr
,
3786 "RCVD WONT TELOPT_AUTHENTICATE\n");
3788 remopts
[option
] = OPT_NO
;
3792 case TELOPT_ENCRYPT
:
3794 (void) fprintf(stderr
,
3795 "RCVD IAC WONT TELOPT_ENCRYPT\n");
3796 settimer(encropt
); /* got response to will/wont */
3798 * Remote side cannot send encryption. No reply necessary
3799 * Treat this as if "IAC SB ENCRYPT END IAC SE" were
3800 * received (RFC 2946) and disable crypto.
3802 encrypt_end(TELNET_DIR_DECRYPT
);
3808 remopts
[option
] = OPT_NO
;
3810 write_data((const char *)fmt
, option
);
3815 * We received an "IAC DO ..." message from the client, change our state
3819 dooption(int option
)
3822 boolean_t send_reply
= B_TRUE
;
3831 mode(O_ECHO
|O_CRMOD
, 0);
3846 * Options don't get much easier. Acknowledge the option,
3847 * and then clean up and exit.
3849 write_data((const char *)will
, option
);
3854 case TELOPT_ENCRYPT
:
3856 (void) fprintf(stderr
, "RCVD DO TELOPT_ENCRYPT\n");
3859 * We received a "DO". This indicates that the other side
3860 * wants us to encrypt our data (pending negotiatoin).
3861 * reply with "IAC WILL ENCRYPT" if we are able to send
3864 if (krb5_privacy_allowed() && negotiate_encrypt
) {
3866 if (sent_will_encrypt
)
3867 send_reply
= B_FALSE
;
3869 sent_will_encrypt
= B_TRUE
;
3870 /* return if we already sent "WILL ENCRYPT" */
3871 if (myopts
[option
] == OPT_YES
)
3878 case TELOPT_AUTHENTICATION
:
3880 (void) fprintf(stderr
,
3881 "RCVD DO TELOPT_AUTHENTICATION\n");
3884 * RFC 2941 - only the server can send
3885 * "DO TELOPT_AUTHENTICATION".
3886 * if a server receives this, it must respond with WONT...
3896 myopts
[option
] = OPT_YES
;
3898 myopts
[option
] = OPT_NO
;
3901 write_data((const char *)fmt
, option
);
3907 * We received an "IAC DONT ..." message from client.
3908 * Client does not agree with the option so act accordingly.
3911 dontoption(int option
)
3917 * we should stop echoing, since the client side will be doing
3918 * it, but keep mapping CR since CR-LF will be mapped to it.
3923 case TELOPT_ENCRYPT
:
3925 (void) fprintf(stderr
, "RCVD IAC DONT ENCRYPT\n");
3928 * Remote side cannot receive any encrypted data,
3929 * so dont send any. No reply necessary.
3938 myopts
[option
] = OPT_NO
;
3941 write_data((const char *)wont
, option
);
3948 * Look at the sub-option buffer, and try to be helpful to the other
3957 switch (subchar
= SB_GET()) {
3958 case TELOPT_TTYPE
: { /* Yaaaay! */
3959 static char terminalname
[5+41] = "TERM=";
3961 settimer(ttypesubopt
);
3963 if (SB_GET() != TELQUAL_IS
) {
3964 return; /* ??? XXX but, this is the most robust */
3967 terminaltype
= terminalname
+strlen(terminalname
);
3969 while (terminaltype
< (terminalname
+ sizeof (terminalname
) -
3977 *terminaltype
++ = c
; /* accumulate name */
3980 terminaltype
= terminalname
;
3990 ws
.ws_col
= SB_GET() << 8;
3994 ws
.ws_col
|= SB_GET();
3998 ws
.ws_row
= SB_GET() << 8;
4002 ws
.ws_row
|= SB_GET();
4003 ws
.ws_xpixel
= 0; ws
.ws_ypixel
= 0;
4004 (void) ioctl(pty
, TIOCSWINSZ
, &ws
);
4009 case TELOPT_XDISPLOC
: {
4010 if (SB_EOF() || SB_GET() != TELQUAL_IS
) {
4013 settimer(xdisplocsubopt
);
4014 subpointer
[SB_LEN()] = '\0';
4015 if ((new_env("DISPLAY", subpointer
)) == 1)
4020 case TELOPT_NEW_ENVIRON
:
4021 case TELOPT_OLD_ENVIRON
: {
4023 char *cp
, *varp
, *valp
;
4028 if (c
== TELQUAL_IS
) {
4029 if (subchar
== TELOPT_OLD_ENVIRON
)
4030 settimer(oenvironsubopt
);
4032 settimer(environsubopt
);
4033 } else if (c
!= TELQUAL_INFO
) {
4037 if (subchar
== TELOPT_NEW_ENVIRON
) {
4040 if ((c
== NEW_ENV_VAR
) || (c
== ENV_USERVAR
))
4047 if ((c
== env_ovar
) || (c
== ENV_USERVAR
))
4055 cp
= varp
= (char *)subpointer
;
4060 if (subchar
== TELOPT_OLD_ENVIRON
) {
4063 else if (c
== env_ovalue
)
4070 cp
= valp
= (char *)subpointer
;
4077 if ((new_env(varp
, valp
)) == 1) {
4081 (void) del_env(varp
);
4083 cp
= varp
= (char *)subpointer
;
4099 if ((new_env(varp
, valp
)) == 1) {
4103 (void) del_env(varp
);
4106 } /* end of case TELOPT_NEW_ENVIRON */
4108 case TELOPT_AUTHENTICATION
:
4115 * These are sent server only and cannot be sent by the
4121 (void) fprintf(stderr
,
4122 "RCVD AUTHENTICATION IS "
4125 if (!auth_negotiated
)
4126 auth_is((uchar_t
*)subpointer
, SB_LEN());
4130 (void) fprintf(stderr
,
4131 "RCVD AUTHENTICATION NAME "
4134 if (!auth_negotiated
)
4135 auth_name((uchar_t
*)subpointer
, SB_LEN());
4140 case TELOPT_ENCRYPT
: {
4145 #ifdef ENCRYPT_NAMES
4147 (void) fprintf(stderr
, "RCVD ENCRYPT %s\n",
4149 #endif /* ENCRYPT_NAMES */
4151 case ENCRYPT_SUPPORT
:
4152 encrypt_support(subpointer
, SB_LEN());
4155 encrypt_is((uchar_t
*)subpointer
, SB_LEN());
4158 (void) encrypt_reply(subpointer
, SB_LEN());
4164 encrypt_end(TELNET_DIR_DECRYPT
);
4166 case ENCRYPT_REQSTART
:
4167 encrypt_request_start();
4169 case ENCRYPT_REQEND
:
4171 * We can always send an REQEND so that we cannot
4172 * get stuck encrypting. We should only get this
4173 * if we have been able to get in the correct mode
4176 encrypt_request_end();
4178 case ENCRYPT_ENC_KEYID
:
4179 encrypt_enc_keyid(subpointer
, SB_LEN());
4181 case ENCRYPT_DEC_KEYID
:
4182 encrypt_dec_keyid(subpointer
, SB_LEN());
4196 mode(int on
, int off
)
4198 struct termios tios
;
4201 if (tcgetattr(pty
, &tios
) < 0)
4202 syslog(LOG_INFO
, "tcgetattr: %m\n");
4205 tios
.c_cflag
|= CS8
;
4206 tios
.c_iflag
&= ~IUCLC
;
4207 tios
.c_lflag
&= ~(XCASE
|IEXTEN
);
4210 if ((tios
.c_cflag
& PARENB
) != 0)
4211 tios
.c_cflag
&= ~CS8
;
4212 tios
.c_lflag
|= IEXTEN
;
4216 tios
.c_lflag
|= ECHO
;
4218 tios
.c_lflag
&= ~ECHO
;
4221 tios
.c_iflag
|= ICRNL
;
4222 tios
.c_oflag
|= ONLCR
;
4225 * Because "O_CRMOD" will never be set in "off" we don't have to
4226 * handle this case here.
4229 if (tcsetattr(pty
, TCSANOW
, &tios
) < 0)
4230 syslog(LOG_INFO
, "tcsetattr: %m\n");
4234 * Send interrupt to process on other side of pty.
4235 * If it is in raw mode, just write NULL;
4236 * otherwise, write intr char.
4242 struct tchars tchars
;
4244 ptyflush(); /* half-hearted */
4245 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
4246 syslog(LOG_INFO
, "ioctl TIOCGETP: %m\n");
4247 if (b
.sg_flags
& O_RAW
) {
4251 *pfrontp
++ = ioctl(pty
, TIOCGETC
, &tchars
) < 0 ?
4252 '\177' : tchars
.t_intrc
;
4256 * Send quit to process on other side of pty.
4257 * If it is in raw mode, just write NULL;
4258 * otherwise, write quit char.
4264 struct tchars tchars
;
4266 ptyflush(); /* half-hearted */
4267 (void) ioctl(pty
, TIOCGETP
, &b
);
4268 if (b
.sg_flags
& O_RAW
) {
4272 *pfrontp
++ = ioctl(pty
, TIOCGETC
, &tchars
) < 0 ?
4273 '\034' : tchars
.t_quitc
;
4281 if ((n
= pfrontp
- pbackp
) > 0)
4282 n
= write(master
, pbackp
, n
);
4286 if (pbackp
== pfrontp
)
4287 pbackp
= pfrontp
= ptyobuf
;
4293 * Return the address of the next "item" in the TELNET data
4294 * stream. This will be the address of the next character if
4295 * the current address is a user data character, or it will
4296 * be the address of the character following the TELNET command
4297 * if the current address is a TELNET IAC ("I Am a Command")
4302 nextitem(char *current
)
4304 if ((*current
&0xff) != IAC
) {
4307 switch (*(current
+1)&0xff) {
4313 case SB
: /* loop forever looking for the SE */
4315 char *look
= current
+2;
4318 if ((*look
++&0xff) == IAC
) {
4319 if ((*look
++&0xff) == SE
) {
4334 * We are about to do a TELNET SYNCH operation. Clear
4335 * the path to the network.
4337 * Things are a bit tricky since we may have sent the first
4338 * byte or so of a previous TELNET command into the network.
4339 * So, we have to scan the network buffer from the beginning
4340 * until we are up to where we want to be.
4342 * A side effect of what we do, just to keep things
4343 * simple, is to clear the urgent data pointer. The principal
4344 * caller should be setting the urgent data pointer AFTER calling
4350 char *thisitem
, *next
;
4352 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
4353 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
4357 while ((next
= nextitem(thisitem
)) <= nbackp
) {
4361 /* Now, thisitem is first before/at boundary. */
4363 good
= netobuf
; /* where the good bytes go */
4365 while (nfrontp
> thisitem
) {
4366 if (wewant(thisitem
)) {
4371 next
= nextitem(next
);
4372 } while (wewant(next
) && (nfrontp
> next
));
4373 length
= next
-thisitem
;
4374 (void) memmove(good
, thisitem
, length
);
4378 thisitem
= nextitem(thisitem
);
4383 nfrontp
= good
; /* next byte to be sent */
4390 * Send as much data as possible to the network,
4391 * handling requests for urgent data.
4398 if ((n
= nfrontp
- nbackp
) > 0) {
4400 * if no urgent data, or if the other side appears to be an
4401 * old 4.2 client (and thus unable to survive TCP urgent data),
4402 * write the entire buffer in non-OOB mode.
4404 if ((neturg
== 0) || (not42
== 0)) {
4405 n
= write(net
, nbackp
, n
); /* normal write */
4407 n
= neturg
- nbackp
;
4409 * In 4.2 (and 4.3) systems, there is some question
4410 * about what byte in a sendOOB operation is the "OOB"
4411 * data. To make ourselves compatible, we only send ONE
4412 * byte out of band, the one WE THINK should be OOB
4413 * (though we really have more the TCP philosophy of
4414 * urgent data rather than the Unix philosophy of OOB
4418 /* send URGENT all by itself */
4419 n
= write(net
, nbackp
, n
-1);
4422 n
= send_oob(net
, nbackp
, n
);
4427 if (errno
== EWOULDBLOCK
)
4429 /* should blow this guy away... */
4435 if (nbackp
>= neturg
) {
4438 if (nbackp
== nfrontp
) {
4439 nbackp
= nfrontp
= netobuf
;
4448 * If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
4449 * handle closing differently. We close "net" first and then
4450 * "master" in that order. We do close(net) first because
4451 * we have no other way to disconnect forwarding between the network
4452 * and master. So by issuing the close()'s we ensure that no further
4453 * data rises from TCP. A more complex fix would be adding proper
4454 * support for throwing a "stop" switch for forwarding data between
4455 * logindmux peers. It's possible to block in the close of the tty
4456 * while the network still receives data and the telmod module is
4457 * TEL_STOPPED. A denial-of-service attack generates this case,
4461 if (!telmod_init_done
) {
4463 (void) close(master
);
4475 char user
[sizeof (up
->ut_user
) + 1];
4476 char ttyn
[sizeof (up
->ut_line
) + 1];
4477 char rhost
[sizeof (up
->ut_host
) + 1];
4479 /* while cleaning up don't allow disruption */
4480 (void) signal(SIGCHLD
, SIG_IGN
);
4483 while (up
= getutxent()) {
4484 if (up
->ut_pid
== pid
) {
4485 if (up
->ut_type
== DEAD_PROCESS
) {
4487 * Cleaned up elsewhere.
4493 * call pam_close_session if login changed
4494 * the utmpx user entry from type LOGIN_PROCESS
4495 * to type USER_PROCESS, which happens
4496 * after pam_open_session is called.
4498 if (up
->ut_type
== USER_PROCESS
) {
4499 (void) strlcpy(user
, up
->ut_user
,
4501 (void) strlcpy(ttyn
, up
->ut_line
,
4503 (void) strlcpy(rhost
, up
->ut_host
,
4505 if ((pam_start("telnet", user
, NULL
, &pamh
)) ==
4507 (void) pam_set_item(pamh
, PAM_TTY
,
4509 (void) pam_set_item(pamh
, PAM_RHOST
,
4511 (void) pam_close_session(pamh
, 0);
4512 (void) pam_end(pamh
, PAM_SUCCESS
);
4516 up
->ut_type
= DEAD_PROCESS
;
4517 up
->ut_exit
.e_termination
= WTERMSIG(0);
4518 up
->ut_exit
.e_exit
= WEXITSTATUS(0);
4519 (void) time(&up
->ut_tv
.tv_sec
);
4521 if (modutx(up
) == NULL
) {
4523 * Since modutx failed we'll
4524 * write out the new entry
4527 (void) pututxline(up
);
4528 updwtmpx("wtmpx", up
);
4536 (void) signal(SIGCHLD
, (void (*)())cleanup
);
4540 readstream(int fd
, char *buf
, int offset
)
4542 struct strbuf ctlbuf
, datbuf
;
4543 union T_primitives tpi
;
4546 int bytes_avail
, count
;
4548 (void) memset((char *)&ctlbuf
, 0, sizeof (ctlbuf
));
4549 (void) memset((char *)&datbuf
, 0, sizeof (datbuf
));
4551 ctlbuf
.buf
= (char *)&tpi
;
4552 ctlbuf
.maxlen
= sizeof (tpi
);
4554 if (ioctl(fd
, I_NREAD
, &bytes_avail
) < 0) {
4555 syslog(LOG_ERR
, "I_NREAD returned error %m");
4558 if (bytes_avail
> netibufsize
- offset
) {
4559 count
= netip
- netibuf
;
4560 netibuf
= (char *)realloc(netibuf
,
4561 (unsigned)netibufsize
+ bytes_avail
);
4562 if (netibuf
== NULL
) {
4563 fatal(net
, "netibuf realloc failed\n");
4565 netibufsize
+= bytes_avail
;
4566 netip
= netibuf
+ count
;
4569 datbuf
.buf
= buf
+ offset
;
4570 datbuf
.maxlen
= netibufsize
;
4571 ret
= getmsg(fd
, &ctlbuf
, &datbuf
, &flags
);
4573 syslog(LOG_ERR
, "getmsg returned -1, errno %d\n",
4577 if (ctlbuf
.len
<= 0) {
4578 return (datbuf
.len
);
4581 if (tpi
.type
== T_DATA_REQ
) {
4585 if ((tpi
.type
== T_ORDREL_IND
) || (tpi
.type
== T_DISCON_IND
))
4587 fatal(fd
, "no data or protocol element recognized");
4592 drainstream(int size
)
4597 tsize
= netip
- netibuf
;
4599 if ((tsize
+ ncc
+ size
) > netibufsize
) {
4600 if (!(netibuf
= (char *)realloc(netibuf
,
4601 (unsigned)tsize
+ ncc
+ size
)))
4602 fatalperror(net
, "netibuf realloc failed\n", errno
);
4603 netibufsize
= tsize
+ ncc
+ size
;
4605 netip
= netibuf
+ tsize
;
4608 if ((nbytes
= read(net
, (char *)netip
+ ncc
, size
)) != size
)
4609 syslog(LOG_ERR
, "read %d bytes\n", nbytes
);
4613 * TPI style replacement for socket send() primitive, so we don't require
4614 * sockmod to be on the stream.
4617 send_oob(int fd
, char *ptr
, int count
)
4619 struct T_exdata_req exd_req
;
4620 struct strbuf hdr
, dat
;
4623 exd_req
.PRIM_type
= T_EXDATA_REQ
;
4624 exd_req
.MORE_flag
= 0;
4626 hdr
.buf
= (char *)&exd_req
;
4627 hdr
.len
= sizeof (exd_req
);
4632 ret
= putmsg(fd
, &hdr
, &dat
, 0);
4642 * Set the value of the environmental variable "name" to be
4643 * "value". If rewrite is set, replace any current value.
4646 local_setenv(const char *name
, const char *value
, int rewrite
)
4648 static int alloced
; /* if allocated space before */
4650 int l_value
, offset
;
4653 * Do not allow environment variables which begin with LD_ to be
4654 * inserted into the environment. While normally the dynamic linker
4655 * protects the login program, that is based on the assumption hostile
4656 * invocation of login are from non-root users. However, since telnetd
4657 * runs as root, this cannot be utilized. So instead we simply
4658 * prevent LD_* from being inserted into the environment.
4659 * This also applies to other environment variables that
4660 * are to be ignored in setugid apps.
4661 * Note that at this point name can contain '='!
4662 * Also, do not allow TTYPROMPT to be passed along here.
4664 if (strncmp(name
, "LD_", 3) == 0 ||
4665 strncmp(name
, "NLSPATH", 7) == 0 ||
4666 (strncmp(name
, "TTYPROMPT", 9) == 0 &&
4667 (name
[9] == '\0' || name
[9] == '='))) {
4670 if (*value
== '=') /* no `=' in value */
4672 l_value
= strlen(value
);
4673 if ((c
= __findenv(name
, &offset
))) { /* find if already exists */
4676 if ((int)strlen(c
) >= l_value
) { /* old larger; copy over */
4677 while (*c
++ = *value
++)
4681 } else { /* create new slot */
4685 for (p
= environ
, cnt
= 0; *p
; ++p
, ++cnt
)
4687 if (alloced
) { /* just increase size */
4688 environ
= (char **)realloc((char *)environ
,
4689 (size_t)(sizeof (char *) * (cnt
+ 2)));
4692 } else { /* get new space */
4693 alloced
= 1; /* copy old entries into it */
4694 p
= (char **)malloc((size_t)(sizeof (char *)*
4698 (void) memcpy(p
, environ
, cnt
* sizeof (char *));
4701 environ
[cnt
+ 1] = NULL
;
4704 for (c
= (char *)name
; *c
&& *c
!= '='; ++c
) /* no `=' in name */
4706 if (!(environ
[offset
] = /* name + `=' + value */
4707 malloc((size_t)((int)(c
- name
) + l_value
+ 2))))
4709 for (c
= environ
[offset
]; ((*c
= *name
++) != 0) && (*c
!= '='); ++c
)
4711 for (*c
++ = '='; *c
++ = *value
++; )
4717 * local_unsetenv(name) --
4718 * Delete environmental variable "name".
4721 local_unsetenv(const char *name
)
4726 while (__findenv(name
, &offset
)) /* if set multiple times */
4727 for (p
= &environ
[offset
]; ; ++p
)
4728 if ((*p
= *(p
+ 1)) == 0)
4734 * Returns pointer to value associated with name, if any, else NULL.
4735 * Sets offset to be the offset of the name/value combination in the
4736 * environmental array, for use by local_setenv() and local_unsetenv().
4737 * Explicitly removes '=' in argument name.
4740 __findenv(const char *name
, int *offset
)
4742 extern char **environ
;
4747 if (name
== NULL
|| environ
== NULL
)
4749 for (np
= name
; *np
&& *np
!= '='; ++np
)
4752 for (p
= environ
; (c
= *p
) != NULL
; ++p
)
4753 if (strncmp(c
, name
, len
) == 0 && c
[len
] == '=') {
4754 *offset
= p
- environ
;
4755 return (c
+ len
+ 1);
4764 char evalbuf
[BUFSIZ
];
4766 if (defopen(defaultfile
) == 0) {
4770 flags
= defcntl(DC_GETFLAGS
, 0);
4771 TURNOFF(flags
, DC_CASE
);
4772 (void) defcntl(DC_SETFLAGS
, flags
);
4773 if (cp
= defread(bannervar
)) {
4776 if (strlen(cp
) + strlen("eval echo '") + strlen("'\n")
4777 + 1 < sizeof (evalbuf
)) {
4778 (void) strlcpy(evalbuf
, "eval echo '",
4780 (void) strlcat(evalbuf
, cp
, sizeof (evalbuf
));
4781 (void) strlcat(evalbuf
, "'\n",
4784 if (fp
= popen(evalbuf
, "r")) {
4789 * Pipe I/O atomicity guarantees we
4790 * need only one read.
4792 if ((size
= fread(buf
, 1,
4797 p
= strrchr(buf
, '\n');
4806 /* close default file */
4807 (void) defopen(NULL
);
4812 (void) defopen(NULL
); /* close default file */
4825 * Map the banner: "\n" -> "\r\n" and "\r" -> "\r\0"
4827 for (q
= nfrontp
; p
&& *p
&& q
< nfrontp
+ sizeof (netobuf
) - 1; )
4832 } else if (*p
== '\r') {
4839 nfrontp
+= q
- netobuf
;
4843 * Show banner that getty never gave. By default, this is `uname -sr`.
4845 * The banner includes some null's (for TELNET CR disambiguation),
4846 * so we have to be somewhat complicated.
4854 * Dont show this if the '-h' option was present
4859 if (uname(&u
) == -1)
4862 write_data_len((const char *) BANNER1
, sizeof (BANNER1
) - 1);
4863 write_data_len(u
.sysname
, strlen(u
.sysname
));
4864 write_data_len(" ", 1);
4865 write_data_len(u
.release
, strlen(u
.release
));
4866 write_data_len((const char *)BANNER2
, sizeof (BANNER2
) - 1);
4870 * Verify that the named module is at the top of the stream
4871 * and then pop it off.
4874 removemod(int f
, char *modname
)
4876 char topmodname
[BUFSIZ
];
4878 if (ioctl(f
, I_LOOK
, topmodname
) < 0)
4880 if (strcmp(modname
, topmodname
) != 0) {
4884 if (ioctl(f
, I_POP
, 0) < 0)
4890 write_data(const char *format
, ...)
4896 va_start(args
, format
);
4898 if ((len
= vsnprintf(argp
, sizeof (argp
), format
, args
)) == -1)
4901 write_data_len(argp
, len
);
4906 write_data_len(const char *buf
, int len
)
4908 int remaining
, copied
;
4910 remaining
= BUFSIZ
- (nfrontp
- netobuf
);
4913 * If there's not enough space in netobuf then
4916 if ((len
> BUFSIZ
? BUFSIZ
: len
) > remaining
) {
4918 remaining
= BUFSIZ
- (nfrontp
- netobuf
);
4920 /* Copy as much as we can */
4921 copied
= remaining
> len
? len
: remaining
;
4922 (void) memmove(nfrontp
, buf
, copied
);
4925 remaining
-= copied
;