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
);
734 (void) krb5_auth_con_getremotesubkey(telnet_context
,
735 auth_context
, &newkey
);
736 if (session_key
!= NULL
) {
737 krb5_free_keyblock(telnet_context
, session_key
);
740 if (newkey
!= NULL
) {
741 (void) krb5_copy_keyblock(telnet_context
,
742 newkey
, &session_key
);
743 krb5_free_keyblock(telnet_context
, newkey
);
745 (void) krb5_copy_keyblock(telnet_context
,
746 ticket
->enc_part2
->session
, &session_key
);
750 * Initialize encryption stuff. Currently, we are only
751 * supporting 8 byte keys and blocks. Check for this later.
754 skey
.length
= DES_BLOCKSIZE
;
755 skey
.data
= session_key
->contents
;
756 encrypt_session_key(&skey
, &encr_data
.encrypt
);
757 encrypt_session_key(&skey
, &encr_data
.decrypt
);
761 inbuf
.data
= (char *)data
;
763 (void) fprintf(stderr
,
764 "RCVD KRB_FORWARD data (%d bytes)\n", cnt
);
766 if (auth_context
!= NULL
) {
769 err
= krb5_auth_con_getrcache(telnet_context
,
770 auth_context
, &rcache
);
771 if (!err
&& !rcache
) {
772 err
= krb5_sname_to_principal(telnet_context
,
773 0, 0, KRB5_NT_SRV_HST
, &server
);
775 err
= krb5_get_server_rcache(
777 krb5_princ_component(
781 krb5_free_principal(telnet_context
,
787 "Error allocating krb5 replay cache: %s",
790 err
= krb5_auth_con_setrcache(telnet_context
,
791 auth_context
, rcache
);
794 "Error creating krb5 replay cache:"
800 * Use the 'rsaddr' and 'rsport' (remote service addr/port)
801 * from the original connection. This data is used to
802 * verify the forwarded credentials.
804 if (!(err
= krb5_auth_con_setaddrs(telnet_context
, auth_context
,
806 err
= krb5_auth_con_setports(telnet_context
,
807 auth_context
, NULL
, &rsport
);
811 * If all is well, store the forwarded creds in
812 * the users local credential cache.
814 err
= rd_and_store_forwarded_creds(telnet_context
,
815 auth_context
, &inbuf
,
819 (void) snprintf(errbuf
, sizeof (errbuf
),
820 "Read forwarded creds failed: %s",
822 syslog(LOG_ERR
, "%s", errbuf
);
824 reply_to_client(ap
, KRB_FORWARD_REJECT
, errbuf
, -1);
826 (void) fprintf(stderr
,
828 "forwarded credentials\r\n");
830 reply_to_client(ap
, KRB_FORWARD_ACCEPT
, NULL
, 0);
832 free(rsaddr
.contents
);
834 free(rsport
.contents
);
837 (void) fprintf(stderr
, "\tForwarded "
838 "credentials obtained\r\n");
842 (void) fprintf(stderr
,
843 "\tUnknown Kerberos option %d\r\n",
845 reply_to_client(ap
, KRB_REJECT
, NULL
, 0);
851 reply_to_client(ap
, KRB_REJECT
, errbuf
, -1);
854 (void) fprintf(stderr
, "\tKerberos V5 error: %s\r\n", errbuf
);
856 syslog(LOG_ERR
, "%s", errbuf
);
858 if (auth_context
!= NULL
) {
859 (void) krb5_auth_con_free(telnet_context
, auth_context
);
869 if (telnet_context
== NULL
) {
870 code
= krb5_init_context(&telnet_context
);
871 if (code
!= 0 && auth_debug
)
873 "Cannot initialize Kerberos V5: %s",
874 error_message(code
));
881 auth_name(uchar_t
*data
, int cnt
)
883 char namebuf
[MAXPRINCLEN
];
887 (void) fprintf(stderr
,
888 "\t(auth_name) Empty NAME in auth "
892 if (cnt
> sizeof (namebuf
)-1) {
894 (void) fprintf(stderr
,
895 "\t(auth_name) NAME exceeds %d bytes\n",
899 (void) memcpy((void *)namebuf
, (void *)data
, cnt
);
902 (void) fprintf(stderr
, "\t(auth_name) name [%s]\n", namebuf
);
903 AuthenticatingUser
= (char *)strdup(namebuf
);
907 auth_is(uchar_t
*data
, int cnt
)
909 AuthInfo
*aptr
= auth_list
;
915 * We failed to negoiate secure authentication
917 if (data
[0] == AUTHTYPE_NULL
) {
918 auth_finished(0, AUTH_REJECT
);
922 while (aptr
->AuthName
!= 0 &&
923 (aptr
->AuthName
!= data
[0] || aptr
->AuthHow
!= data
[1]))
928 (void) fprintf(stderr
, "\t(auth_is) auth type is %s "
929 "(%d bytes)\n", aptr
->AuthString
, cnt
);
931 if (aptr
->AuthName
== AUTHTYPE_KERBEROS_V5
)
932 kerberos5_is(aptr
, data
+2, cnt
-2);
937 krb5_user_status(char *name
, int namelen
, int level
)
939 int retval
= AUTH_USER
;
942 (void) fprintf(stderr
, "\t(krb5_user_status) level = %d "
943 "auth_level = %d user = %s\n",
945 (AuthenticatingUser
!= NULL
? AuthenticatingUser
: ""));
947 if (level
< AUTH_USER
)
950 if (AuthenticatingUser
!= NULL
&&
951 (retval
= krb5_kuserok(telnet_context
, ticket
->enc_part2
->client
,
952 AuthenticatingUser
))) {
953 (void) strncpy(name
, AuthenticatingUser
, namelen
);
958 "Krb5 principal lacks permission to "
959 "access local account for %s",
966 * Wrapper around /dev/urandom
969 getrandom(char *buf
, int buflen
)
971 static int devrandom
= -1;
973 if (devrandom
== -1 &&
974 (devrandom
= open("/dev/urandom", O_RDONLY
)) == -1) {
975 fatalperror(net
, "Unable to open /dev/urandom: ",
980 if (read(devrandom
, buf
, buflen
) == -1) {
981 fatalperror(net
, "Unable to read from /dev/urandom: ",
992 * Initialize the encryption data structures
997 (void) memset(&encr_data
.encrypt
, 0, sizeof (cipher_info_t
));
998 (void) memset(&encr_data
.decrypt
, 0, sizeof (cipher_info_t
));
1000 encr_data
.encrypt
.state
= ENCR_STATE_NOT_READY
;
1001 encr_data
.decrypt
.state
= ENCR_STATE_NOT_READY
;
1005 * encrypt_send_request_start
1007 * Request that the remote side automatically start sending
1011 encrypt_send_request_start()
1013 uchar_t buf
[6+TELNET_MAXKEYIDLEN
], *p
;
1019 *p
++ = TELOPT_ENCRYPT
;
1020 *p
++ = ENCRYPT_REQSTART
;
1022 * We are telling the remote side which
1023 * decrypt key we will use so that it may
1024 * encrypt in the same key.
1026 (void) memcpy(p
, encr_data
.decrypt
.keyid
, encr_data
.decrypt
.keyidlen
);
1027 p
+= encr_data
.decrypt
.keyidlen
;
1032 write_data_len((const char *)buf
, p
-buf
);
1035 (void) fprintf(stderr
,
1036 "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
1042 * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
1043 * message, the client is telling us that it will be sending
1044 * encrypted data using the indicated cipher.
1045 * We must initialize the read (decrypt) side of our connection
1048 encrypt_is(uchar_t
*data
, int cnt
)
1051 register int iv_status
= CFB64_IV_OK
;
1052 register int lstate
= 0;
1057 (uchar_t
)TELOPT_ENCRYPT
,
1058 (uchar_t
)ENCRYPT_REPLY
,
1059 (uchar_t
)0, /* placeholder: sbbuf[4] */
1060 (uchar_t
)CFB64_IV_OK
, /* placeholder: sbbuf[5] */
1068 type
= sbbuf
[4] = *data
++;
1072 * 1. Create the proper stream Initialization vector
1073 * - copy the correct 'seed' to IV and output blocks
1074 * - set the correct key schedule
1075 * 2. Generate reply for the other side:
1076 * IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
1077 * [ data ... ] IAC SE
1078 * 3. Tell crypto module: method, direction, IV
1081 case TELOPT_ENCTYPE_DES_CFB64
:
1082 encr_data
.decrypt
.type
= type
;
1084 lstate
= encr_data
.decrypt
.state
;
1086 (void) fprintf(stderr
,
1087 "\t(encrypt_is) initial state = %d\n",
1090 * Before we extract the IV bytes, make sure we got
1093 if (cnt
< sizeof (Block
)) {
1094 iv_status
= CFB64_IV_BAD
;
1096 (void) fprintf(stderr
,
1097 "\t(encrypt_is) Not enough "
1099 lstate
= ENCR_STATE_NOT_READY
;
1101 data
++; /* skip over the CFB64_IV byte */
1102 (void) memcpy(encr_data
.decrypt
.ivec
, data
,
1104 lstate
= ENCR_STATE_IN_PROGRESS
;
1107 case TELOPT_ENCTYPE_NULL
:
1108 encr_data
.decrypt
.type
= type
;
1109 lstate
&= ~ENCR_STATE_NO_RECV_IV
;
1110 lstate
&= ~ENCR_STATE_NO_SEND_IV
;
1112 (void) fprintf(stderr
,
1113 "\t(encrypt_is) We accept NULL encr\n");
1116 iv_status
= CFB64_IV_BAD
;
1117 encr_data
.decrypt
.type
= 0;
1119 (void) fprintf(stderr
,
1120 "\t(encrypt_is) Can't find type (%d) "
1121 "for initial negotiation\r\n",
1123 lstate
= ENCR_STATE_NOT_READY
;
1127 sbbuf
[5] = (uchar_t
)iv_status
; /* either CFB64_IV_OK or BAD */
1129 if (iv_status
== CFB64_IV_OK
) {
1131 * send IV to crypto module and indicate it is for
1134 lstate
&= ~ENCR_STATE_NO_RECV_IV
; /* we received an OK IV */
1135 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we dont send an IV */
1137 /* tell crypto module to disable crypto on "read" stream */
1138 lstate
= ENCR_STATE_NOT_READY
;
1141 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
1143 #ifdef ENCRYPT_NAMES
1145 (void) fprintf(stderr
,
1146 "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
1148 (iv_status
== CFB64_IV_OK
? "CFB64_IV_OK" :
1150 #endif /* ENCRYPT_NAMES */
1151 /* Update the state of the decryption negotiation */
1152 encr_data
.decrypt
.state
= lstate
;
1154 if (lstate
== ENCR_STATE_NOT_READY
)
1155 encr_data
.decrypt
.autoflag
= 0;
1157 if (lstate
== ENCR_STATE_OK
&& encr_data
.decrypt
.autoflag
)
1158 encrypt_send_request_start();
1161 (void) fprintf(stderr
,
1162 "\t(encrypt_is) final DECRYPT state = %d\n",
1163 encr_data
.decrypt
.state
);
1167 * encrypt_send_encrypt_is
1169 * Tell the client what encryption we will use
1170 * and what our IV will be.
1173 encrypt_send_encrypt_is()
1175 register int lstate
;
1176 krb5_error_code kret
;
1177 uchar_t sbbuf
[MAXOPTLEN
], *p
;
1180 lstate
= encr_data
.encrypt
.state
;
1182 if (encr_data
.encrypt
.type
== ENCTYPE_NULL
) {
1184 * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
1191 * - Create a random DES key
1194 * encrypt the IV using itself as the key.
1197 * IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
1201 if (lstate
== ENCR_STATE_NOT_READY
)
1202 lstate
= ENCR_STATE_IN_PROGRESS
;
1203 else if ((lstate
& ENCR_STATE_NO_SEND_IV
) == 0) {
1205 (void) fprintf(stderr
,
1206 "\t(encrypt_send_is) IV already sent,"
1207 " state = %d\n", lstate
);
1211 if (!VALIDKEY(encr_data
.encrypt
.krbdes_key
)) {
1213 * Invalid key, set flag so we try again later
1214 * when we get a good one
1216 encr_data
.encrypt
.need_start
= 1;
1218 (void) fprintf(stderr
,
1219 "\t(encrypt_send_is) No Key, cannot "
1220 "start encryption yet\n");
1224 (void) fprintf(stderr
,
1225 "\t(encrypt_send_is) Creating new feed\n");
1228 * Create a random feed and send it over.
1230 * Use the /dev/[u]random interface to generate
1231 * our encryption IV.
1233 kret
= getrandom((char *)encr_data
.encrypt
.ivec
, sizeof (Block
));
1237 (void) fprintf(stderr
,
1238 "\t(encrypt_send_is) error from "
1239 "getrandom: %d\n", kret
);
1240 syslog(LOG_ERR
, "Failed to create encryption key (err %d)\n");
1241 encr_data
.encrypt
.type
= ENCTYPE_NULL
;
1243 mit_des_fixup_key_parity(encr_data
.encrypt
.ivec
);
1249 *p
++ = TELOPT_ENCRYPT
;
1251 *p
++ = encr_data
.encrypt
.type
;
1255 * Copy the IV bytes individually so that when a
1256 * 255 (telnet IAC) is used, it can be "escaped" by
1257 * adding it twice (telnet RFC 854).
1259 for (i
= 0; i
< sizeof (Block
); i
++)
1260 if ((*p
++ = encr_data
.encrypt
.ivec
[i
]) == IAC
)
1265 write_data_len((const char *)sbbuf
, (size_t)(p
-sbbuf
));
1269 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we sent our IV */
1270 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* dont need decrypt IV */
1272 encr_data
.encrypt
.state
= lstate
;
1276 (void) fprintf(stderr
,
1277 "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
1278 encr_data
.encrypt
.type
);
1279 for (i
= 0; i
< (p
-sbbuf
); i
++)
1280 (void) fprintf(stderr
, "%d ", (int)sbbuf
[i
]);
1281 (void) fprintf(stderr
, "\n");
1290 * Utility routine to send a CRIOCSTOP ioctl to the
1291 * crypto module (cryptmod).
1294 stop_stream(int fd
, int dir
)
1296 struct strioctl crioc
;
1297 uint32_t stopdir
= dir
;
1299 crioc
.ic_cmd
= CRYPTIOCSTOP
;
1300 crioc
.ic_timout
= -1;
1301 crioc
.ic_len
= sizeof (stopdir
);
1302 crioc
.ic_dp
= (char *)&stopdir
;
1304 if (ioctl(fd
, I_STR
, &crioc
)) {
1305 syslog(LOG_ERR
, "Error sending CRYPTIOCSTOP ioctl: %m");
1312 * Utility routine to send a CRYPTIOCSTART ioctl to the
1313 * crypto module (cryptmod). This routine may contain optional
1314 * payload data that the cryptmod will interpret as bytes that
1315 * need to be decrypted and sent back up to the application
1316 * via the data stream.
1319 start_stream(int fd
, int dir
, int datalen
, char *data
)
1321 struct strioctl crioc
;
1323 crioc
.ic_cmd
= (dir
== CRYPT_ENCRYPT
? CRYPTIOCSTARTENC
:
1325 crioc
.ic_timout
= -1;
1326 crioc
.ic_len
= datalen
;
1329 if (ioctl(fd
, I_STR
, &crioc
)) {
1330 syslog(LOG_ERR
, "Error sending CRYPTIOCSTART ioctl: %m");
1335 * encrypt_start_output
1337 * Tell the other side to start encrypting its data
1340 encrypt_start_output()
1344 uchar_t sbbuf
[MAXOPTLEN
];
1345 struct strioctl crioc
;
1346 struct cr_info_t cki
;
1349 * Initialize crypto and send the ENCRYPT_IS msg
1351 lstate
= encrypt_send_encrypt_is();
1353 if (lstate
!= ENCR_STATE_OK
) {
1355 (void) fprintf(stderr
,
1356 "\t(encrypt_start_output) ENCRYPT state "
1365 *p
++ = TELOPT_ENCRYPT
;
1366 *p
++ = ENCRYPT_START
;
1368 (void) memcpy(p
, encr_data
.encrypt
.keyid
, encr_data
.encrypt
.keyidlen
);
1369 p
+= encr_data
.encrypt
.keyidlen
;
1374 /* Flush this data out before we start encrypting */
1375 write_data_len((const char *)sbbuf
, (int)(p
-sbbuf
));
1379 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
1380 "(lstate = %d) data waiting = %d\n",
1381 (int)encr_data
.encrypt
.keyid
[0],
1382 lstate
, nfrontp
-nbackp
);
1384 encr_data
.encrypt
.state
= lstate
;
1387 * tell crypto module what key to use for encrypting
1388 * Note that the ENCRYPT has not yet been enabled, but we
1389 * need to first set the crypto key to use.
1391 cki
.direction_mask
= CRYPT_ENCRYPT
;
1393 if (encr_data
.encrypt
.type
== TELOPT_ENCTYPE_DES_CFB64
) {
1394 cki
.crypto_method
= CRYPT_METHOD_DES_CFB
;
1397 (void) fprintf(stderr
,
1398 "\t(encrypt_start_output) - unknown "
1399 "crypto_method %d\n",
1400 encr_data
.encrypt
.type
);
1401 syslog(LOG_ERR
, "unrecognized crypto encrypt method: %d",
1402 encr_data
.encrypt
.type
);
1408 * If we previously configured this crypto method, we dont want to
1409 * overwrite the key or ivec information already given to the crypto
1410 * module as it will cause the cipher data between the client and server
1411 * to become out of synch and impossible to decipher.
1413 if (encr_data
.encrypt
.setup
== cki
.crypto_method
) {
1417 cki
.keylen
= DES_BLOCKSIZE
;
1418 (void) memcpy(cki
.key
, (void *)encr_data
.encrypt
.krbdes_key
,
1421 cki
.iveclen
= DES_BLOCKSIZE
;
1422 (void) memcpy(cki
.ivec
, (void *)encr_data
.encrypt
.ivec
,
1425 cki
.ivec_usage
= IVEC_ONETIME
;
1428 cki
.option_mask
= 0;
1430 /* Stop encrypt side prior to setup so we dont lose data */
1431 stop_stream(cryptmod_fd
, CRYPT_ENCRYPT
);
1433 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1434 crioc
.ic_timout
= -1;
1435 crioc
.ic_len
= sizeof (struct cr_info_t
);
1436 crioc
.ic_dp
= (char *)&cki
;
1438 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1439 perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
1441 /* Setup completed OK */
1442 encr_data
.encrypt
.setup
= cki
.crypto_method
;
1446 * We do not check for "stuck" data when setting up the
1447 * outbound "encrypt" channel. Any data queued prior to
1448 * this IOCTL will get processed correctly without our help.
1450 start_stream(cryptmod_fd
, CRYPT_ENCRYPT
, 0, NULL
);
1453 * tell crypto module to start encrypting
1456 (void) fprintf(stderr
,
1457 "\t(encrypt_start_output) Encrypting output\n");
1461 * encrypt_request_start
1463 * The client requests that we start encryption immediately after
1464 * successful negotiation
1467 encrypt_request_start(void)
1469 if (encr_data
.encrypt
.type
== ENCTYPE_NULL
) {
1470 encr_data
.encrypt
.autoflag
= 1;
1472 (void) fprintf(stderr
, "\t(encrypt_request_start) "
1473 "autoencrypt = ON\n");
1475 encrypt_start_output();
1482 * ENCRYPT END received, stop decrypting the read stream
1485 encrypt_end(int direction
)
1487 struct cr_info_t cki
;
1488 struct strioctl crioc
;
1491 stopdir
= (direction
== TELNET_DIR_DECRYPT
? CRYPT_DECRYPT
:
1494 stop_stream(cryptmod_fd
, stopdir
);
1497 * Call this function when we wish to disable crypto in
1498 * either direction (ENCRYPT or DECRYPT)
1500 cki
.direction_mask
= (direction
== TELNET_DIR_DECRYPT
? CRYPT_DECRYPT
:
1502 cki
.crypto_method
= CRYPT_METHOD_NONE
;
1503 cki
.option_mask
= 0;
1507 cki
.ivec_usage
= IVEC_ONETIME
;
1509 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1510 crioc
.ic_timout
= -1;
1511 crioc
.ic_len
= sizeof (cki
);
1512 crioc
.ic_dp
= (char *)&cki
;
1514 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1515 perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
1518 start_stream(cryptmod_fd
, stopdir
, 0, NULL
);
1522 * encrypt_request_end
1524 * When we receive a REQEND from the client, it means
1525 * that we are supposed to stop encrypting
1528 encrypt_request_end()
1531 * Tell the other side we are done encrypting
1534 write_data("%c%c%c%c%c%c",
1537 (uchar_t
)TELOPT_ENCRYPT
,
1538 (uchar_t
)ENCRYPT_END
,
1543 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
1546 * Turn off encryption of the write stream
1548 encrypt_end(TELNET_DIR_ENCRYPT
);
1552 * encrypt_send_request_end
1554 * We stop encrypting the write stream and tell the other side about it.
1557 encrypt_send_request_end()
1559 write_data("%c%c%c%c%c%c",
1562 (uchar_t
)TELOPT_ENCRYPT
,
1563 (uchar_t
)ENCRYPT_REQEND
,
1568 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
1574 * The client is going to start sending encrypted data
1575 * using the previously negotiated cipher (see what we set
1576 * when we did the REPLY in encrypt_is).
1581 struct cr_info_t cki
;
1582 struct strioctl crioc
;
1584 char *dataptr
= NULL
;
1586 if (encr_data
.decrypt
.type
== ENCTYPE_NULL
) {
1588 (void) fprintf(stderr
,
1589 "\t(encrypt_start) No DECRYPT method "
1591 encrypt_send_request_end();
1595 cki
.direction_mask
= CRYPT_DECRYPT
;
1597 if (encr_data
.decrypt
.type
== TELOPT_ENCTYPE_DES_CFB64
) {
1598 cki
.crypto_method
= CRYPT_METHOD_DES_CFB
;
1601 (void) fprintf(stderr
,
1602 "\t(encrypt_start) - unknown "
1603 "crypto_method %d\n", encr_data
.decrypt
.type
);
1605 syslog(LOG_ERR
, "unrecognized crypto decrypt method: %d",
1606 encr_data
.decrypt
.type
);
1612 * Don't overwrite previously configured key and ivec info
1614 if (encr_data
.decrypt
.setup
!= cki
.crypto_method
) {
1615 (void) memcpy(cki
.key
, (void *)encr_data
.decrypt
.krbdes_key
,
1617 (void) memcpy(cki
.ivec
, (void *)encr_data
.decrypt
.ivec
,
1620 cki
.keylen
= DES_BLOCKSIZE
;
1621 cki
.iveclen
= DES_BLOCKSIZE
;
1622 cki
.ivec_usage
= IVEC_ONETIME
;
1627 cki
.option_mask
= 0;
1629 stop_stream(cryptmod_fd
, CRYPT_DECRYPT
);
1631 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1632 crioc
.ic_timout
= -1;
1633 crioc
.ic_len
= sizeof (struct cr_info_t
);
1634 crioc
.ic_dp
= (char *)&cki
;
1636 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1637 syslog(LOG_ERR
, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
1640 encr_data
.decrypt
.setup
= cki
.crypto_method
;
1643 (void) fprintf(stderr
,
1644 "\t(encrypt_start) called CRYPTIOCSETUP for "
1648 * Read any data stuck between the cryptmod and the application
1649 * so we can pass it back down to be properly decrypted after
1650 * this operation finishes.
1652 if (ioctl(cryptmod_fd
, I_NREAD
, &bytes
) < 0) {
1653 syslog(LOG_ERR
, "I_NREAD returned error %m");
1658 * Any data which was read AFTER the ENCRYPT START message
1659 * must be sent back down to be decrypted properly.
1661 * 'ncc' is the number of bytes that have been read but
1662 * not yet processed by the telnet state machine.
1664 * 'bytes' is the number of bytes waiting to be read from
1667 * If either one is a positive value, then those bytes
1668 * must be pulled up and sent back down to be decrypted.
1673 (void) fprintf(stderr
,
1674 "\t(encrypt_start) after drainstream, "
1675 "ncc=%d bytes = %d\n", ncc
, bytes
);
1680 start_stream(cryptmod_fd
, CRYPT_DECRYPT
, bytes
, dataptr
);
1683 * The bytes putback into the stream are no longer
1684 * available to be read by the server, so adjust the
1685 * counter accordingly.
1689 (void) memset(netip
, 0, netibufsize
);
1691 #ifdef ENCRYPT_NAMES
1693 (void) fprintf(stderr
,
1694 "\t(encrypt_start) Start DECRYPT using %s\n",
1695 ENCTYPE_NAME(encr_data
.decrypt
.type
));
1697 #endif /* ENCRYPT_NAMES */
1703 * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
1704 * message from a client.
1706 * Choose an agreeable method (DES_CFB64) and
1707 * respond with TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
1712 encrypt_support(char *data
, int cnt
)
1714 int lstate
= ENCR_STATE_NOT_READY
;
1715 int type
, use_type
= 0;
1717 while (cnt
-- > 0 && use_type
== 0) {
1719 #ifdef ENCRYPT_NAMES
1721 (void) fprintf(stderr
,
1722 "RCVD ENCRYPT SUPPORT %s\n",
1723 ENCTYPE_NAME(type
));
1724 #endif /* ENCRYPT_NAMES */
1728 if (type
== TELOPT_ENCTYPE_DES_CFB64
) {
1732 encr_data
.encrypt
.type
= use_type
;
1734 if (use_type
!= TELOPT_ENCTYPE_NULL
&&
1735 authenticated
!= NULL
&& authenticated
!= &NoAuth
&&
1736 auth_status
!= AUTH_REJECT
) {
1738 /* Authenticated -> have session key -> send ENCRYPT IS */
1739 lstate
= encrypt_send_encrypt_is();
1740 if (lstate
== ENCR_STATE_OK
)
1741 encrypt_start_output();
1742 } else if (use_type
== TELOPT_ENCTYPE_NULL
) {
1744 (void) fprintf(stderr
,
1745 "\t(encrypt_support) Cannot agree "
1746 "on crypto algorithm, output encryption "
1750 * Cannot agree on crypto algorithm
1752 * send "IAC SB ENCRYPT IS NULL IAC SE"
1753 * optionally, also send IAC WONT ENCRYPT
1755 write_data("%c%c%c%c%c%c%c",
1758 (uchar_t
)TELOPT_ENCRYPT
,
1759 (uchar_t
)ENCRYPT_IS
,
1760 (uchar_t
)TELOPT_ENCTYPE_NULL
,
1763 send_wont(TELOPT_ENCRYPT
);
1766 (void) fprintf(stderr
,
1767 "SENT TELOPT_ENCRYPT ENCRYPT_IS "
1770 remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
1772 settimer(encr_support
);
1776 * encrypt_send_keyid
1778 * Sent the key id we will use to the client
1781 encrypt_send_keyid(int dir
, uchar_t
*keyid
, int keylen
, boolean_t saveit
)
1783 uchar_t sbbuf
[128], *p
;
1789 *p
++ = TELOPT_ENCRYPT
;
1790 *p
++ = (dir
== TELNET_DIR_ENCRYPT
? ENCRYPT_ENC_KEYID
:
1794 (void) fprintf(stderr
,
1795 "\t(send_keyid) store %d byte %s keyid\n",
1797 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1800 if (dir
== TELNET_DIR_ENCRYPT
) {
1801 (void) memcpy(encr_data
.encrypt
.keyid
, keyid
, keylen
);
1802 encr_data
.encrypt
.keyidlen
= keylen
;
1804 (void) memcpy(encr_data
.decrypt
.keyid
, keyid
, keylen
);
1805 encr_data
.decrypt
.keyidlen
= keylen
;
1808 (void) memcpy(p
, keyid
, keylen
);
1813 write_data_len((const char *)sbbuf
, (size_t)(p
-sbbuf
));
1817 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT %s %d\n",
1818 (dir
== TELNET_DIR_ENCRYPT
? "ENC_KEYID" :
1819 "DEC_KEYID"), keyid
[0]);
1825 * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
1826 * message, process it accordingly.
1827 * If the vector is acceptable, tell client we are encrypting and
1828 * enable encryption on our write stream.
1830 * Negotiate the KEYID next..
1834 encrypt_reply(char *data
, int len
)
1836 uchar_t type
= (uchar_t
)(*data
++);
1837 uchar_t result
= (uchar_t
)(*data
);
1840 #ifdef ENCRYPT_NAMES
1842 (void) fprintf(stderr
,
1843 "\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
1845 (result
== CFB64_IV_OK
? "CFB64_IV_OK" :
1846 "CFB64_IV_BAD"), len
);
1847 #endif /* ENCRYPT_NAMES */
1849 lstate
= encr_data
.encrypt
.state
;
1851 (void) fprintf(stderr
,
1852 "\t(encrypt_reply) initial ENCRYPT state = %d\n",
1856 if (lstate
== ENCR_STATE_NOT_READY
)
1857 lstate
= ENCR_STATE_IN_PROGRESS
;
1858 lstate
&= ~ENCR_STATE_NO_RECV_IV
; /* we got the IV */
1859 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we dont need to send IV */
1862 * The correct response here is to send the encryption key id
1865 * Send keyid 0 to indicate that we will just use default
1868 encrypt_send_keyid(TELNET_DIR_ENCRYPT
, (uchar_t
*)"\0", 1, 1);
1875 (void) memset(encr_data
.encrypt
.ivec
, 0, sizeof (Block
));
1876 lstate
= ENCR_STATE_NOT_READY
;
1880 (void) fprintf(stderr
,
1881 "\t(encrypt_reply) Got unknown IV value in "
1883 lstate
= ENCR_STATE_NOT_READY
;
1887 encr_data
.encrypt
.state
= lstate
;
1888 if (lstate
== ENCR_STATE_NOT_READY
) {
1889 encr_data
.encrypt
.autoflag
= 0;
1890 encr_data
.encrypt
.type
= ENCTYPE_NULL
;
1892 (void) fprintf(stderr
,
1893 "\t(encrypt_reply) encrypt.autoflag = "
1896 encr_data
.encrypt
.type
= type
;
1897 if ((lstate
== ENCR_STATE_OK
) && encr_data
.encrypt
.autoflag
)
1898 encrypt_start_output();
1902 (void) fprintf(stderr
,
1903 "\t(encrypt_reply) ENCRYPT final state = %d\n",
1908 encrypt_set_keyid_state(uchar_t
*keyid
, int *keyidlen
, int dir
)
1912 lstate
= (dir
== TELNET_DIR_ENCRYPT
? encr_data
.encrypt
.state
:
1913 encr_data
.decrypt
.state
);
1916 (void) fprintf(stderr
,
1917 "\t(set_keyid_state) %s initial state = %d\n",
1918 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1919 "DECRYPT"), lstate
);
1922 * Currently, we only support using the default keyid,
1923 * so it should be an error if the len > 1 or the keyid != 0.
1925 if (*keyidlen
!= 1 || (*keyid
!= '\0')) {
1927 (void) fprintf(stderr
,
1928 "\t(set_keyid_state) unexpected keyid: "
1929 "len=%d value=%d\n", *keyidlen
, *keyid
);
1931 syslog(LOG_ERR
, "rcvd unexpected keyid %d - only keyid of 0 "
1932 "is supported", *keyid
);
1935 * We move to the "IN_PROGRESS" state.
1937 if (lstate
== ENCR_STATE_NOT_READY
)
1938 lstate
= ENCR_STATE_IN_PROGRESS
;
1940 * Clear the NO_KEYID bit because we now have a valid keyid
1942 lstate
&= ~ENCR_STATE_NO_KEYID
;
1946 (void) fprintf(stderr
,
1947 "\t(set_keyid_state) %s final state = %d\n",
1948 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1949 "DECRYPT"), lstate
);
1951 if (dir
== TELNET_DIR_ENCRYPT
)
1952 encr_data
.encrypt
.state
= lstate
;
1954 encr_data
.decrypt
.state
= lstate
;
1960 * Set the keyid value in the key_info structure.
1961 * if necessary send a response to the sender
1964 encrypt_keyid(uchar_t
*newkeyid
, int *keyidlen
, uchar_t
*keyid
,
1967 if (len
> TELNET_MAXNUMKEYS
) {
1969 (void) fprintf(stderr
,
1970 "\t(keyid) keylen too big (%d)\n", len
);
1975 (void) fprintf(stderr
, "\t(keyid) set KEYID for %s len = %d\n",
1976 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1981 if (*keyidlen
== 0) {
1983 (void) fprintf(stderr
,
1984 "\t(keyid) Got 0 length keyid - "
1989 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
1991 } else if (len
!= *keyidlen
|| memcmp(keyid
, newkeyid
, len
)) {
1993 (void) fprintf(stderr
,
1994 "\t(keyid) Setting new key (%d bytes)\n",
1998 (void) memcpy(newkeyid
, keyid
, len
);
2000 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
2002 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
2005 (void) fprintf(stderr
,
2006 "\t(keyid) %s Key already in place,"
2007 "state = %d autoflag=%d\n",
2008 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" : "DECRYPT"),
2009 (dir
== TELNET_DIR_ENCRYPT
? encr_data
.encrypt
.state
:
2010 encr_data
.decrypt
.state
),
2011 (dir
== TELNET_DIR_ENCRYPT
?
2012 encr_data
.encrypt
.autoflag
:
2013 encr_data
.decrypt
.autoflag
));
2015 /* key already in place */
2016 if ((encr_data
.encrypt
.state
== ENCR_STATE_OK
) &&
2017 dir
== TELNET_DIR_ENCRYPT
&& encr_data
.encrypt
.autoflag
) {
2018 encrypt_start_output();
2024 (void) fprintf(stderr
, "\t(keyid) %s final state = %d\n",
2025 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
2027 (dir
== TELNET_DIR_ENCRYPT
?
2028 encr_data
.encrypt
.state
:
2029 encr_data
.decrypt
.state
));
2031 encrypt_send_keyid(dir
, newkeyid
, *keyidlen
, 0);
2037 * We received the ENC_KEYID message from a client indicating that
2038 * the client wishes to verify that the indicated keyid maps to a
2042 encrypt_enc_keyid(char *data
, int cnt
)
2045 * Verify the decrypt keyid is valid
2047 encrypt_keyid(encr_data
.decrypt
.keyid
, &encr_data
.decrypt
.keyidlen
,
2048 (uchar_t
*)data
, cnt
, TELNET_DIR_DECRYPT
);
2054 * We received the DEC_KEYID message from a client indicating that
2055 * the client wants to verify that the indicated keyid maps to a valid key.
2058 encrypt_dec_keyid(char *data
, int cnt
)
2060 encrypt_keyid(encr_data
.encrypt
.keyid
, &encr_data
.encrypt
.keyidlen
,
2061 (uchar_t
*)data
, cnt
, TELNET_DIR_ENCRYPT
);
2065 * encrypt_session_key
2067 * Store the session key in the encryption data record
2070 encrypt_session_key(Session_Key
*key
, cipher_info_t
*cinfo
)
2072 if (key
== NULL
|| key
->type
!= SK_DES
) {
2074 (void) fprintf(stderr
,
2075 "\t(session_key) Cannot set krb5 "
2076 "session key (unknown type = %d)\n",
2077 key
? key
->type
: -1);
2080 (void) fprintf(stderr
,
2081 "\t(session_key) Settting session key "
2084 /* store the key in the cipher info data struct */
2085 (void) memcpy(cinfo
->krbdes_key
, (void *)key
->data
, sizeof (Block
));
2088 * Now look to see if we still need to send the key and start
2091 * If so, go ahead an call it now that we have the key.
2093 if (cinfo
->need_start
) {
2094 if (encrypt_send_encrypt_is() == ENCR_STATE_OK
) {
2095 cinfo
->need_start
= 0;
2103 * Used to add an environment variable and value to the
2104 * linked list structure.
2107 new_env(const char *name
, const char *value
)
2109 struct envlist
*env
;
2111 env
= malloc(sizeof (struct envlist
));
2114 if ((env
->name
= strdup(name
)) == NULL
) {
2118 if ((env
->value
= strdup(value
)) == NULL
) {
2124 env
->next
= envlist_head
;
2132 * Used to delete an environment variable from the linked list
2133 * structure. We just set a flag because we will delete the list
2134 * anyway before we exec login.
2137 del_env(const char *name
)
2139 struct envlist
*env
;
2141 for (env
= envlist_head
; env
; env
= env
->next
) {
2142 if (strcmp(env
->name
, name
) == 0) {
2155 if (fstat(fd
, &stats
) == -1)
2157 return (S_ISSOCK(stats
.st_mode
));
2161 * audit_telnet_settid stores the terminal id while it is still
2162 * available. Subsequent calls to adt_load_hostname() return
2163 * the id which is stored here.
2166 audit_telnet_settid(int sock
) {
2167 adt_session_data_t
*ah
;
2168 adt_termid_t
*termid
;
2171 if ((rc
= adt_start_session(&ah
, NULL
, 0)) == 0) {
2172 if ((rc
= adt_load_termid(sock
, &termid
)) == 0) {
2173 if ((rc
= adt_set_user(ah
, ADT_NO_AUDIT
,
2174 ADT_NO_AUDIT
, 0, ADT_NO_AUDIT
,
2175 termid
, ADT_SETTID
)) == 0)
2176 (void) adt_set_proc(ah
);
2179 (void) adt_end_session(ah
);
2186 main(int argc
, char *argv
[])
2188 struct sockaddr_storage from
;
2193 ushort_t porttouse
= 0;
2194 boolean_t standalone
= 0;
2195 #endif /* defined(DEBUG) */
2196 extern char *optarg
;
2200 while ((c
= getopt(argc
, argv
, TELNETD_OPTS DEBUG_OPTS
)) != -1) {
2205 * note: alternative port number only used in
2208 porttouse
= atoi(optarg
);
2216 if (strcasecmp(optarg
, "none") == 0) {
2218 } else if (strcasecmp(optarg
, "user") == 0) {
2219 auth_level
= AUTH_USER
;
2220 } else if (strcasecmp(optarg
, "valid") == 0) {
2221 auth_level
= AUTH_VALID
;
2222 } else if (strcasecmp(optarg
, "off") == 0) {
2224 negotiate_auth_krb5
= 0;
2225 } else if (strcasecmp(optarg
, "debug") == 0) {
2229 "unknown authentication level specified "
2230 "with \'-a\' option (%s)", optarg
);
2231 auth_level
= AUTH_USER
;
2235 /* disable authentication negotiation */
2236 negotiate_auth_krb5
= 0;
2240 if (optarg
!= NULL
) {
2241 int ret
= krb5_init();
2244 "Unable to use Kerberos V5 as "
2245 "requested, exiting");
2248 (void) krb5_set_default_realm(telnet_context
,
2251 "using %s as default KRB5 realm", optarg
);
2255 telnet_srvtab
= (char *)strdup(optarg
);
2257 case 'E': /* disable automatic encryption */
2258 negotiate_encrypt
= B_FALSE
;
2261 resolve_hostname
= 1;
2264 if (optarg
== NULL
|| (tos
= atoi(optarg
)) < 0 ||
2266 syslog(LOG_ERR
, "telnetd: illegal tos value: "
2277 syslog(LOG_ERR
, "telnetd: illegal cmd line option %c",
2283 netibufsize
= BUFSIZ
;
2284 if (!(netibuf
= (char *)malloc(netibufsize
)))
2285 syslog(LOG_ERR
, "netibuf malloc failed\n");
2286 (void) memset(netibuf
, 0, netibufsize
);
2293 static struct sockaddr_in6 sin6
= { AF_INET6
};
2297 sin6
.sin6_port
= htons(porttouse
);
2299 sp
= getservbyname("telnet", "tcp");
2301 (void) fprintf(stderr
,
2302 "telnetd: tcp/telnet: "
2303 "unknown service\n");
2306 sin6
.sin6_port
= sp
->s_port
;
2309 s
= socket(AF_INET6
, SOCK_STREAM
, IPPROTO_TCP
);
2311 perror("telnetd: socket");
2314 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, (char *)&option
,
2315 sizeof (option
)) == -1)
2316 perror("setsockopt SO_REUSEADDR");
2317 if (bind(s
, (struct sockaddr
*)&sin6
, sizeof (sin6
)) < 0) {
2321 if (listen(s
, 32) < 0) {
2326 /* automatically reap all child processes */
2327 (void) signal(SIGCHLD
, SIG_IGN
);
2332 foo
= sizeof (sin6
);
2333 ns
= accept(s
, (struct sockaddr
*)&sin6
, &foo
);
2346 (void) signal(SIGCHLD
, SIG_DFL
);
2352 #endif /* defined(DEBUG) */
2354 openlog("telnetd", LOG_PID
| LOG_ODELAY
, LOG_DAEMON
);
2356 issocket
= issock(0);
2358 fatal(0, "stdin is not a socket file descriptor");
2360 fromlen
= (socklen_t
)sizeof (from
);
2361 (void) memset((char *)&from
, 0, sizeof (from
));
2362 if (getpeername(0, (struct sockaddr
*)&from
, &fromlen
)
2364 (void) fprintf(stderr
, "%s: ", argv
[0]);
2365 perror("getpeername");
2366 _exit(EXIT_FAILURE
);
2369 if (audit_telnet_settid(0)) { /* set terminal ID */
2370 (void) fprintf(stderr
, "%s: ", argv
[0]);
2375 if (setsockopt(0, SOL_SOCKET
, SO_KEEPALIVE
, (const char *)&on
,
2377 syslog(LOG_WARNING
, "setsockopt (SO_KEEPALIVE): %m");
2384 setsockopt(0, IPPROTO_IP
, IP_TOS
,
2385 (char *)&tos
, sizeof (tos
)) < 0 &&
2386 errno
!= ENOPROTOOPT
) {
2387 syslog(LOG_ERR
, "setsockopt (IP_TOS %d): %m", tos
);
2390 if (setsockopt(net
, SOL_SOCKET
, SO_OOBINLINE
, (char *)&on
,
2392 syslog(LOG_WARNING
, "setsockopt (SO_OOBINLINE): %m");
2395 /* set the default PAM service name */
2396 (void) strcpy(pam_svc_name
, "telnet");
2399 return (EXIT_SUCCESS
);
2402 static char *terminaltype
= 0;
2407 * A small subroutine to flush the network output buffer, get some data
2408 * from the network, and pass it through the telnet state machine. We
2409 * also flush the pty input buffer (by dropping its data) if it becomes
2415 if (nfrontp
-nbackp
) {
2419 ncc
= read(net
, netibuf
, netibufsize
);
2423 syslog(LOG_INFO
, "ttloop: read: %m");
2425 } else if (ncc
== 0) {
2426 syslog(LOG_INFO
, "ttloop: peer closed connection\n");
2431 telrcv(); /* state machine */
2433 pfrontp
= pbackp
= ptyobuf
;
2441 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)DO
, (uchar_t
)option
);
2445 send_will(int option
)
2447 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)WILL
, (uchar_t
)option
);
2451 send_wont(int option
)
2453 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)WONT
, (uchar_t
)option
);
2460 * Negotiate automatic authentication, is possible.
2463 getauthtype(char *username
, int *len
)
2465 int init_status
= -1;
2467 init_status
= krb5_init();
2469 if (auth_level
== -1 || init_status
!= 0) {
2470 remopts
[TELOPT_AUTHENTICATION
] = OPT_NO
;
2471 myopts
[TELOPT_AUTHENTICATION
] = OPT_NO
;
2472 negotiate_auth_krb5
= B_FALSE
;
2473 negotiate_encrypt
= B_FALSE
;
2474 return (AUTH_REJECT
);
2477 if (init_status
== 0 && auth_level
!= -1) {
2478 if (negotiate_auth_krb5
) {
2480 * Negotiate Authentication FIRST
2482 send_do(TELOPT_AUTHENTICATION
);
2483 remopts
[TELOPT_AUTHENTICATION
] =
2484 OPT_YES_BUT_ALWAYS_LOOK
;
2486 while (sequenceIs(authopt
, getauth
))
2489 if (remopts
[TELOPT_AUTHENTICATION
] == OPT_YES
) {
2491 * Request KRB5 Mutual authentication and if that fails,
2492 * KRB5 1-way client authentication
2494 uchar_t sbbuf
[MAXOPTLEN
], *p
;
2496 *p
++ = (uchar_t
)IAC
;
2498 *p
++ = (uchar_t
)TELOPT_AUTHENTICATION
;
2499 *p
++ = (uchar_t
)TELQUAL_SEND
;
2500 if (negotiate_auth_krb5
) {
2501 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2502 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2505 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2506 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2508 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2509 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2512 *p
++ = (uchar_t
)AUTHTYPE_NULL
;
2514 *p
++ = (uchar_t
)IAC
;
2517 write_data_len((const char *)sbbuf
,
2518 (size_t)(p
- sbbuf
));
2521 (void) fprintf(stderr
,
2522 "SENT TELOPT_AUTHENTICATION "
2525 /* auth_wait returns the authentication level */
2526 /* status = auth_wait(username, len); */
2527 while (sequenceIs(authdone
, getauth
))
2530 * Now check to see if the user is valid or not
2532 if (authenticated
== NULL
|| authenticated
== &NoAuth
)
2533 auth_status
= AUTH_REJECT
;
2536 * We cant be VALID until the user status is
2539 if (auth_status
== AUTH_VALID
)
2540 auth_status
= AUTH_USER
;
2542 if (authenticated
->AuthName
==
2543 AUTHTYPE_KERBEROS_V5
)
2544 auth_status
= krb5_user_status(
2545 username
, *len
, auth_status
);
2549 return (auth_status
);
2555 if (krb5_privacy_allowed() && negotiate_encrypt
) {
2556 if (myopts
[TELOPT_ENCRYPT
] != OPT_YES
) {
2557 if (!sent_will_encrypt
) {
2558 send_will(TELOPT_ENCRYPT
);
2559 sent_will_encrypt
= B_TRUE
;
2562 (void) fprintf(stderr
, "SENT WILL ENCRYPT\n");
2564 if (remopts
[TELOPT_ENCRYPT
] != OPT_YES
) {
2565 if (!sent_do_encrypt
) {
2566 send_do(TELOPT_ENCRYPT
);
2567 sent_do_encrypt
= B_TRUE
;
2568 remopts
[TELOPT_ENCRYPT
] =
2569 OPT_YES_BUT_ALWAYS_LOOK
;
2572 (void) fprintf(stderr
, "SENT DO ENCRYPT\n");
2574 myopts
[TELOPT_ENCRYPT
] = OPT_YES
;
2576 while (sequenceIs(encropt
, getencr
))
2579 if (auth_status
!= AUTH_REJECT
&&
2580 remopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
2581 myopts
[TELOPT_ENCRYPT
] == OPT_YES
) {
2583 if (sent_encrypt_support
== B_FALSE
) {
2584 write_data("%c%c%c%c%c%c%c",
2587 (uchar_t
)TELOPT_ENCRYPT
,
2588 (uchar_t
)ENCRYPT_SUPPORT
,
2589 (uchar_t
)TELOPT_ENCTYPE_DES_CFB64
,
2596 * Now wait for a response to these messages before
2598 * Look for TELOPT_ENCRYPT suboptions
2600 while (sequenceIs(encr_support
, getencr
))
2604 /* Dont need responses to these, so dont wait for them */
2606 remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
2607 myopts
[TELOPT_ENCRYPT
] = OPT_NO
;
2615 * Ask the other end to send along its terminal type.
2616 * Output is the variable terminaltype filled in.
2619 getterminaltype(void)
2622 * The remote side may have already sent this info, so
2623 * dont ask for these options if the other side already
2624 * sent the information.
2626 if (sequenceIs(ttypeopt
, getterminal
)) {
2627 send_do(TELOPT_TTYPE
);
2628 remopts
[TELOPT_TTYPE
] = OPT_YES_BUT_ALWAYS_LOOK
;
2631 if (sequenceIs(nawsopt
, getterminal
)) {
2632 send_do(TELOPT_NAWS
);
2633 remopts
[TELOPT_NAWS
] = OPT_YES_BUT_ALWAYS_LOOK
;
2636 if (sequenceIs(xdisplocopt
, getterminal
)) {
2637 send_do(TELOPT_XDISPLOC
);
2638 remopts
[TELOPT_XDISPLOC
] = OPT_YES_BUT_ALWAYS_LOOK
;
2641 if (sequenceIs(environopt
, getterminal
)) {
2642 send_do(TELOPT_NEW_ENVIRON
);
2643 remopts
[TELOPT_NEW_ENVIRON
] = OPT_YES_BUT_ALWAYS_LOOK
;
2646 if (sequenceIs(oenvironopt
, getterminal
)) {
2647 send_do(TELOPT_OLD_ENVIRON
);
2648 remopts
[TELOPT_OLD_ENVIRON
] = OPT_YES_BUT_ALWAYS_LOOK
;
2651 /* make sure encryption is started here */
2652 while (auth_status
!= AUTH_REJECT
&&
2653 authenticated
!= &NoAuth
&& authenticated
!= NULL
&&
2654 remopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
2655 encr_data
.encrypt
.autoflag
&&
2656 encr_data
.encrypt
.state
!= ENCR_STATE_OK
) {
2658 (void) fprintf(stderr
, "getterminaltype() forcing encrypt\n");
2663 (void) fprintf(stderr
, "getterminaltype() encryption %sstarted\n",
2664 encr_data
.encrypt
.state
== ENCR_STATE_OK
? "" : "not ");
2667 while (sequenceIs(ttypeopt
, getterminal
) ||
2668 sequenceIs(nawsopt
, getterminal
) ||
2669 sequenceIs(xdisplocopt
, getterminal
) ||
2670 sequenceIs(environopt
, getterminal
) ||
2671 sequenceIs(oenvironopt
, getterminal
)) {
2676 if (remopts
[TELOPT_TTYPE
] == OPT_YES
) {
2677 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2678 (uchar_t
)TELOPT_TTYPE
, (uchar_t
)TELQUAL_SEND
,
2679 (uchar_t
)IAC
, (uchar_t
)SE
};
2681 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2683 if (remopts
[TELOPT_XDISPLOC
] == OPT_YES
) {
2684 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2685 (uchar_t
)TELOPT_XDISPLOC
, (uchar_t
)TELQUAL_SEND
,
2686 (uchar_t
)IAC
, (uchar_t
)SE
};
2688 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2690 if (remopts
[TELOPT_NEW_ENVIRON
] == OPT_YES
) {
2691 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2692 (uchar_t
)TELOPT_NEW_ENVIRON
, (uchar_t
)TELQUAL_SEND
,
2693 (uchar_t
)IAC
, (uchar_t
)SE
};
2695 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2697 if (remopts
[TELOPT_OLD_ENVIRON
] == OPT_YES
) {
2698 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2699 (uchar_t
)TELOPT_OLD_ENVIRON
, (uchar_t
)TELQUAL_SEND
,
2700 (uchar_t
)IAC
, (uchar_t
)SE
};
2702 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2705 if (remopts
[TELOPT_TTYPE
] == OPT_YES
) {
2706 while (sequenceIs(ttypesubopt
, getterminal
)) {
2710 if (remopts
[TELOPT_XDISPLOC
] == OPT_YES
) {
2711 while (sequenceIs(xdisplocsubopt
, getterminal
)) {
2715 if (remopts
[TELOPT_NEW_ENVIRON
] == OPT_YES
) {
2716 while (sequenceIs(environsubopt
, getterminal
)) {
2720 if (remopts
[TELOPT_OLD_ENVIRON
] == OPT_YES
) {
2721 while (sequenceIs(oenvironsubopt
, getterminal
)) {
2731 * Get a pty, scan input lines.
2734 doit(int f
, struct sockaddr_storage
*who
)
2737 char host_name
[MAXHOSTNAMELEN
];
2740 int ptmfd
; /* fd of logindmux connected to pty */
2741 int netfd
; /* fd of logindmux connected to netf */
2743 struct protocol_arg telnetp
;
2744 struct strioctl telnetmod
;
2745 struct envlist
*env
, *next
;
2747 char abuf
[INET6_ADDRSTRLEN
];
2748 struct sockaddr_in
*sin
;
2749 struct sockaddr_in6
*sin6
;
2751 char username
[MAXUSERNAMELEN
];
2756 if ((p
= open("/dev/ptmx", O_RDWR
| O_NOCTTY
)) == -1) {
2757 fatalperror(f
, "open /dev/ptmx", errno
);
2759 if (grantpt(p
) == -1)
2760 fatal(f
, "could not grant slave pty");
2761 if (unlockpt(p
) == -1)
2762 fatal(f
, "could not unlock slave pty");
2763 if ((slavename
= ptsname(p
)) == NULL
)
2764 fatal(f
, "could not enable slave pty");
2766 if ((t
= open(slavename
, O_RDWR
| O_NOCTTY
)) == -1)
2767 fatal(f
, "could not open slave pty");
2768 if (ioctl(t
, I_PUSH
, "ptem") == -1)
2769 fatalperror(f
, "ioctl I_PUSH ptem", errno
);
2770 if (ioctl(t
, I_PUSH
, "ldterm") == -1)
2771 fatalperror(f
, "ioctl I_PUSH ldterm", errno
);
2772 if (ioctl(t
, I_PUSH
, "ttcompat") == -1)
2773 fatalperror(f
, "ioctl I_PUSH ttcompat", errno
);
2779 if (ioctl(t
, TIOCGETP
, &b
) == -1)
2780 syslog(LOG_INFO
, "ioctl TIOCGETP pty t: %m\n");
2781 b
.sg_flags
= O_CRMOD
|O_XTABS
|O_ANYP
;
2782 /* XXX - ispeed and ospeed must be non-zero */
2783 b
.sg_ispeed
= B38400
;
2784 b
.sg_ospeed
= B38400
;
2785 if (ioctl(t
, TIOCSETN
, &b
) == -1)
2786 syslog(LOG_INFO
, "ioctl TIOCSETN pty t: %m\n");
2787 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
2788 syslog(LOG_INFO
, "ioctl TIOCGETP pty pty: %m\n");
2789 b
.sg_flags
&= ~O_ECHO
;
2790 if (ioctl(pty
, TIOCSETN
, &b
) == -1)
2791 syslog(LOG_INFO
, "ioctl TIOCSETN pty pty: %m\n");
2793 if (who
->ss_family
== AF_INET
) {
2794 char *addrbuf
= NULL
;
2795 char *portbuf
= NULL
;
2797 sin
= (struct sockaddr_in
*)who
;
2798 wholen
= sizeof (struct sockaddr_in
);
2800 addrbuf
= (char *)malloc(wholen
);
2801 if (addrbuf
== NULL
)
2802 fatal(f
, "Cannot alloc memory for address info\n");
2803 portbuf
= (char *)malloc(sizeof (sin
->sin_port
));
2804 if (portbuf
== NULL
) {
2806 fatal(f
, "Cannot alloc memory for port info\n");
2809 (void) memcpy(addrbuf
, (const void *)&sin
->sin_addr
, wholen
);
2810 (void) memcpy(portbuf
, (const void *)&sin
->sin_port
,
2811 sizeof (sin
->sin_port
));
2813 free(rsaddr
.contents
);
2815 rsaddr
.contents
= (krb5_octet
*)addrbuf
;
2816 rsaddr
.length
= wholen
;
2817 rsaddr
.addrtype
= ADDRTYPE_INET
;
2819 free(rsport
.contents
);
2821 rsport
.contents
= (krb5_octet
*)portbuf
;
2822 rsport
.length
= sizeof (sin
->sin_port
);
2823 rsport
.addrtype
= ADDRTYPE_IPPORT
;
2824 } else if (who
->ss_family
== AF_INET6
) {
2825 struct in_addr ipv4_addr
;
2826 char *addrbuf
= NULL
;
2827 char *portbuf
= NULL
;
2829 sin6
= (struct sockaddr_in6
*)who
;
2830 wholen
= sizeof (struct sockaddr_in6
);
2832 IN6_V4MAPPED_TO_INADDR(&sin6
->sin6_addr
,
2835 addrbuf
= (char *)malloc(wholen
);
2836 if (addrbuf
== NULL
)
2837 fatal(f
, "Cannot alloc memory for address info\n");
2839 portbuf
= (char *)malloc(sizeof (sin6
->sin6_port
));
2840 if (portbuf
== NULL
) {
2842 fatal(f
, "Cannot alloc memory for port info\n");
2845 (void) memcpy((void *) addrbuf
,
2846 (const void *)&ipv4_addr
,
2849 * If we already used rsaddr.contents, free the previous
2852 free(rsaddr
.contents
);
2854 rsaddr
.contents
= (krb5_octet
*)addrbuf
;
2855 rsaddr
.length
= sizeof (ipv4_addr
);
2856 rsaddr
.addrtype
= ADDRTYPE_INET
;
2858 (void) memcpy((void *) portbuf
, (const void *)&sin6
->sin6_port
,
2859 sizeof (sin6
->sin6_port
));
2861 free(rsport
.contents
);
2863 rsport
.contents
= (krb5_octet
*)portbuf
;
2864 rsport
.length
= sizeof (sin6
->sin6_port
);
2865 rsport
.addrtype
= ADDRTYPE_IPPORT
;
2867 syslog(LOG_ERR
, "unknown address family %d\n",
2869 fatal(f
, "getpeername: unknown address family\n");
2872 if (getnameinfo((const struct sockaddr
*) who
, wholen
, host_name
,
2873 sizeof (host_name
), NULL
, 0, 0) == 0) {
2877 * If the '-U' option was given on the cmd line, we must
2878 * be able to lookup the hostname
2880 if (resolve_hostname
) {
2881 fatal(f
, "Couldn't resolve your address into a "
2882 "host name.\r\nPlease contact your net "
2886 if (who
->ss_family
== AF_INET6
) {
2887 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
2888 struct in_addr ipv4_addr
;
2890 IN6_V4MAPPED_TO_INADDR(&sin6
->sin6_addr
,
2892 host
= (char *)inet_ntop(AF_INET
,
2893 &ipv4_addr
, abuf
, sizeof (abuf
));
2895 host
= (char *)inet_ntop(AF_INET6
,
2896 &sin6
->sin6_addr
, abuf
,
2899 } else if (who
->ss_family
== AF_INET
) {
2900 host
= (char *)inet_ntop(AF_INET
,
2901 &sin
->sin_addr
, abuf
, sizeof (abuf
));
2905 * Note that sockmod has to be removed since readstream assumes
2906 * a "raw" TPI endpoint (e.g. it uses getmsg).
2908 if (removemod(f
, "sockmod") < 0)
2909 fatalperror(f
, "couldn't remove sockmod", errno
);
2914 * Push the crypto module on the stream before 'telmod' so it
2915 * can encrypt/decrypt without interfering with telmod functionality
2916 * We must push it now because many of the crypto options negotiated
2917 * initially must be saved in the crypto module (via IOCTL calls).
2919 if (ioctl(f
, I_PUSH
, "cryptmod") < 0)
2920 fatalperror(f
, "ioctl I_PUSH cryptmod", errno
);
2924 * gotta set the encryption clock now because it is often negotiated
2925 * immediately by the client, and if we wait till after we negotiate
2926 * auth, it will be out of whack with when the WILL/WONT ENCRYPT
2927 * option is received.
2932 * get terminal type.
2935 len
= sizeof (username
);
2937 settimer(getterminal
);
2940 * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
2942 auth_status
= getauthtype(username
, &len
);
2944 * Exchange TELOPT_ENCRYPT options per RFC 2946
2949 if (ioctl(f
, I_PUSH
, "telmod") < 0)
2950 fatalperror(f
, "ioctl I_PUSH telmod", errno
);
2953 * Make sure telmod will pass unrecognized IOCTLs to cryptmod
2957 telnetmod
.ic_cmd
= CRYPTPASSTHRU
;
2958 telnetmod
.ic_timout
= -1;
2959 telnetmod
.ic_len
= sizeof (uchar_t
);
2960 telnetmod
.ic_dp
= (char *)&passthru
;
2962 if (ioctl(f
, I_STR
, &telnetmod
) < 0)
2963 fatal(f
, "ioctl CRPASSTHRU failed\n");
2969 * readstream will do a getmsg till it receives M_PROTO type
2970 * T_DATA_REQ from telnetmodopen(). This signals that all data
2971 * in-flight before telmod was pushed has been received at the
2974 while ((nsize
= readstream(f
, netibuf
, ncc
+ netip
- netibuf
)) > 0) {
2979 fatalperror(f
, "readstream failed\n", errno
);
2983 * open logindmux drivers and link them with network and ptm
2986 if ((ptmfd
= open("/dev/logindmux", O_RDWR
)) == -1) {
2987 fatalperror(f
, "open /dev/logindmux", errno
);
2989 if ((netfd
= open("/dev/logindmux", O_RDWR
)) == -1) {
2990 fatalperror(f
, "open /dev/logindmux", errno
);
2993 if (ioctl(ptmfd
, I_LINK
, p
) < 0)
2994 fatal(f
, "ioctl I_LINK of /dev/ptmx failed\n");
2995 if (ioctl(netfd
, I_LINK
, f
) < 0)
2996 fatal(f
, "ioctl I_LINK of tcp connection failed\n");
2999 * Figure out the device number of ptm's mux fd, and pass that
3002 if (fstat(ptmfd
, &buf
) < 0) {
3003 fatalperror(f
, "fstat ptmfd failed", errno
);
3005 telnetp
.dev
= buf
.st_rdev
;
3008 telnetmod
.ic_cmd
= LOGDMX_IOC_QEXCHANGE
;
3009 telnetmod
.ic_timout
= -1;
3010 telnetmod
.ic_len
= sizeof (struct protocol_arg
);
3011 telnetmod
.ic_dp
= (char *)&telnetp
;
3013 if (ioctl(netfd
, I_STR
, &telnetmod
) < 0)
3014 fatal(netfd
, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
3017 * Figure out the device number of the net's mux fd, and pass that
3020 if (fstat(netfd
, &buf
) < 0) {
3021 fatalperror(f
, "fstat netfd failed", errno
);
3023 telnetp
.dev
= buf
.st_rdev
;
3026 telnetmod
.ic_cmd
= LOGDMX_IOC_QEXCHANGE
;
3027 telnetmod
.ic_timout
= -1;
3028 telnetmod
.ic_len
= sizeof (struct protocol_arg
);
3029 telnetmod
.ic_dp
= (char *)&telnetp
;
3031 if (ioctl(ptmfd
, I_STR
, &telnetmod
) < 0)
3032 fatal(netfd
, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
3036 cryptmod_fd
= netfd
;
3039 * Show banner that getty never gave, but
3040 * only if the user did not automatically authenticate.
3042 if (getenv("USER") == '\0' && auth_status
< AUTH_USER
)
3046 * If the user automatically authenticated with Kerberos
3047 * we must set the service name that PAM will use. We
3048 * need to do it BEFORE the child fork so that 'cleanup'
3049 * in the parent can call the PAM cleanup stuff with the
3050 * same PAM service that /bin/login will use to authenticate
3053 if (auth_level
>= 0 && auth_status
>= AUTH_USER
&&
3054 (AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
)) {
3055 (void) strcpy(pam_svc_name
, "ktelnet");
3058 * Request to do suppress go ahead.
3060 * Send this before sending the TELOPT_ECHO stuff below because
3061 * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
3062 * that has them turn off local echo mode if SGA is not received first.
3063 * This also has the odd side-effect of causing the client to enable
3064 * encryption and then immediately disable it during the ECHO option
3065 * negotiations. Its just better to to SGA first now that we support
3068 if (!myopts
[TELOPT_SGA
]) {
3069 dooption(TELOPT_SGA
);
3073 * Pretend we got a DO ECHO from the client if we have not
3074 * yet negotiated the ECHO.
3076 if (!myopts
[TELOPT_ECHO
]) {
3077 dooption(TELOPT_ECHO
);
3081 * Is the client side a 4.2 (NOT 4.3) system? We need to know this
3082 * because 4.2 clients are unable to deal with TCP urgent data.
3084 * To find out, we send out a "DO ECHO". If the remote system
3085 * answers "WILL ECHO" it is probably a 4.2 client, and we note
3086 * that fact ("WILL ECHO" ==> that the client will echo what
3087 * WE, the server, sends it; it does NOT mean that the client will
3088 * echo the terminal input).
3090 send_do(TELOPT_ECHO
);
3091 remopts
[TELOPT_ECHO
] = OPT_YES_BUT_ALWAYS_LOOK
;
3093 if ((pid
= fork()) < 0)
3094 fatalperror(netfd
, "fork", errno
);
3096 telnet(net
, master
);
3098 * The child process needs to be the session leader
3099 * and have the pty as its controlling tty. Thus we need
3100 * to re-open the slave side of the pty no without
3101 * the O_NOCTTY flag that we have been careful to
3102 * use up to this point.
3106 tt
= open(line
, O_RDWR
);
3108 fatalperror(netfd
, line
, errno
);
3109 (void) close(netfd
);
3110 (void) close(ptmfd
);
3124 (void) local_setenv("TERM", terminaltype
+5, 1);
3126 * -h : pass on name of host.
3127 * WARNING: -h is accepted by login if and only if
3129 * -p : don't clobber the environment (so terminal type stays set).
3132 /* System V login expects a utmp entry to already be there */
3134 (void) memset((char *)&ut
, 0, sizeof (ut
));
3135 (void) strncpy(ut
.ut_user
, ".telnet", sizeof (ut
.ut_user
));
3136 (void) strncpy(ut
.ut_line
, line
, sizeof (ut
.ut_line
));
3137 ut
.ut_pid
= getpid();
3139 ut
.ut_id
[1] = (char)SC_WILDC
;
3140 ut
.ut_id
[2] = (char)SC_WILDC
;
3141 ut
.ut_id
[3] = (char)SC_WILDC
;
3142 ut
.ut_type
= LOGIN_PROCESS
;
3143 ut
.ut_exit
.e_termination
= 0;
3144 ut
.ut_exit
.e_exit
= 0;
3145 (void) time(&ut
.ut_tv
.tv_sec
);
3146 if (makeutx(&ut
) == NULL
)
3147 syslog(LOG_INFO
, "in.telnetd:\tmakeutx failed");
3151 * Load in the cached environment variables and either
3152 * set/unset them in the environment.
3154 for (next
= envlist_head
; next
; ) {
3157 (void) local_unsetenv(env
->name
);
3159 (void) local_setenv(env
->name
, env
->value
, 1);
3166 if (!username
|| !username
[0])
3167 auth_status
= AUTH_REJECT
; /* we dont know who this is */
3169 /* If the current auth status is less than the required level, exit */
3170 if (auth_status
< auth_level
) {
3171 fatal(net
, "Authentication failed\n");
3176 * If AUTH_VALID (proper authentication REQUIRED and we have
3177 * a krb5_name), exec '/bin/login', make sure it uses the
3178 * correct PAM service name (pam_svc_name). If possible,
3179 * make sure the krb5 authenticated user's name (krb5_name)
3180 * is in the PAM REPOSITORY for krb5.
3182 if (auth_level
>= 0 &&
3183 (auth_status
== AUTH_VALID
|| auth_status
== AUTH_USER
) &&
3184 ((krb5_name
!= NULL
) && strlen(krb5_name
)) &&
3185 ((AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
))) {
3186 (void) execl(LOGIN_PROGRAM
, "login",
3192 "-R", KRB5_REPOSITORY_NAME
,
3193 AuthenticatingUser
, 0);
3194 } else if (auth_level
>= 0 &&
3195 auth_status
>= AUTH_USER
&&
3196 (((AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
)) ||
3199 * If we only know the name but not the principal,
3200 * login will have to authenticate further.
3202 (void) execl(LOGIN_PROGRAM
, "login",
3206 "-s", pam_svc_name
, "--",
3207 (AuthenticatingUser
!= NULL
? AuthenticatingUser
:
3208 getenv("USER")), 0);
3210 } else /* default, no auth. info available, login does it all */ {
3211 (void) execl(LOGIN_PROGRAM
, "login",
3212 "-p", "-h", host
, "-d", slavename
, "--",
3216 fatalperror(netfd
, LOGIN_PROGRAM
, errno
);
3221 fatal(int f
, char *msg
)
3225 (void) snprintf(buf
, sizeof (buf
), "telnetd: %s.\r\n", msg
);
3226 (void) write(f
, buf
, strlen(buf
));
3232 fatalperror(int f
, char *msg
, int errnum
)
3236 (void) snprintf(buf
, sizeof (buf
),
3237 "%s: %s\r\n", msg
, strerror(errnum
));
3243 * Main loop. Select from pty and network, and
3244 * hand data to telnet receiver finite state machine
3245 * when it receives telnet protocol. Regular data
3246 * flow between pty and network takes place through
3247 * inkernel telnet streams module (telmod).
3250 telnet(int net
, int master
)
3254 struct strioctl telnetmod
;
3257 char binary_out
= 0;
3259 if (ioctl(net
, FIONBIO
, &on
) == -1)
3260 syslog(LOG_INFO
, "ioctl FIONBIO net: %m\n");
3261 if (ioctl(master
, FIONBIO
, &on
) == -1)
3262 syslog(LOG_INFO
, "ioctl FIONBIO pty p: %m\n");
3263 (void) signal(SIGTSTP
, SIG_IGN
);
3264 (void) signal(SIGCHLD
, (void (*)())cleanup
);
3268 * Call telrcv() once to pick up anything received during
3269 * terminal type negotiation.
3277 fd_set ibits
, obits
, xbits
;
3288 * If we couldn't flush all our output to the network,
3289 * keep checking for when we can.
3291 if (nfrontp
- nbackp
)
3292 FD_SET(net
, &obits
);
3294 * Never look for input if there's still
3295 * stuff in the corresponding output buffer
3297 if (pfrontp
- pbackp
) {
3298 FD_SET(master
, &obits
);
3300 FD_SET(net
, &ibits
);
3303 FD_SET(net
, &xbits
);
3306 #define max(x, y) (((x) < (y)) ? (y) : (x))
3309 * make an ioctl to telnet module (net side) to send
3310 * binary mode of telnet daemon. binary_in and
3311 * binary_out are 0 if not in binary mode.
3313 if (binary_in
!= myopts
[TELOPT_BINARY
] ||
3314 binary_out
!= remopts
[TELOPT_BINARY
]) {
3317 if (myopts
[TELOPT_BINARY
] != OPT_NO
)
3318 mode
|= TEL_BINARY_IN
;
3320 if (remopts
[TELOPT_BINARY
] != OPT_NO
)
3321 mode
|= TEL_BINARY_OUT
;
3323 telnetmod
.ic_cmd
= TEL_IOC_MODE
;
3324 telnetmod
.ic_timout
= -1;
3325 telnetmod
.ic_len
= 1;
3326 telnetmod
.ic_dp
= &mode
;
3328 syslog(LOG_DEBUG
, "TEL_IOC_MODE binary has changed\n");
3330 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3331 fatal(net
, "ioctl TEL_IOC_MODE failed\n");
3332 binary_in
= myopts
[TELOPT_BINARY
];
3333 binary_out
= remopts
[TELOPT_BINARY
];
3335 if (state
== TS_DATA
) {
3336 if ((nfrontp
== nbackp
) &&
3337 (pfrontp
== pbackp
)) {
3338 if (ioctl(net
, I_NREAD
, &nsize
) < 0)
3340 "ioctl I_NREAD failed\n", errno
);
3345 * make an ioctl to reinsert remaining data at
3346 * streamhead. After this, ioctl reenables the
3347 * telnet lower put queue. This queue was
3348 * noenabled by telnet module after sending
3349 * protocol/urgent data to telnetd.
3352 telnetmod
.ic_cmd
= TEL_IOC_ENABLE
;
3353 telnetmod
.ic_timout
= -1;
3355 telnetmod
.ic_len
= ncc
+ nsize
;
3356 telnetmod
.ic_dp
= netip
;
3358 telnetmod
.ic_len
= 0;
3359 telnetmod
.ic_dp
= NULL
;
3361 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3362 fatal(net
, "ioctl TEL_IOC_ENABLE \
3365 telmod_init_done
= B_TRUE
;
3368 (void) memset(netibuf
, 0, netibufsize
);
3374 * state not changed to TS_DATA and hence, more to read
3375 * send ioctl to get one more message block.
3377 telnetmod
.ic_cmd
= TEL_IOC_GETBLK
;
3378 telnetmod
.ic_timout
= -1;
3379 telnetmod
.ic_len
= 0;
3380 telnetmod
.ic_dp
= NULL
;
3382 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3383 fatal(net
, "ioctl TEL_IOC_GETBLK failed\n");
3386 if ((c
= select(max(net
, master
) + 1, &ibits
, &obits
, &xbits
,
3389 if (errno
== EINTR
) {
3400 if (FD_ISSET(net
, &xbits
)) {
3405 * Something to read from the network...
3407 if (FD_ISSET(net
, &ibits
)) {
3408 ncc
= read(net
, netibuf
, netibufsize
);
3409 if (ncc
< 0 && errno
== EWOULDBLOCK
)
3419 if (FD_ISSET(net
, &obits
) && (nfrontp
- nbackp
) > 0)
3423 if (FD_ISSET(master
, &obits
) && (pfrontp
- pbackp
) > 0)
3435 if ((&ptyobuf
[BUFSIZ
] - pfrontp
) < 2)
3439 * Once we hit data, we want to transition back to
3440 * in-kernel processing. However, this code is shared
3441 * by getterminaltype()/ttloop() which run before the
3442 * in-kernel plumbing is available. So if we are still
3443 * processing the initial option negotiation, even TS_DATA
3444 * must be processed here.
3446 if (c
!= IAC
&& state
== TS_DATA
&& init_neg_done
) {
3455 /* Strip off \n or \0 after a \r */
3456 if ((c
== 0) || (c
== '\n')) {
3469 * We map \r\n ==> \r, since
3470 * We now map \r\n ==> \r for pragmatic reasons.
3471 * Many client implementations send \r\n when
3472 * the user hits the CarriageReturn key.
3474 * We USED to map \r\n ==> \n, since \r\n says
3475 * that we want to be in column 1 of the next
3478 if (c
== '\r' && (myopts
[TELOPT_BINARY
] == OPT_NO
)) {
3488 * Send the process on the pty side an
3489 * interrupt. Do this with a NULL or
3490 * interrupt char; depending on the tty mode.
3504 write_data_len("\r\n[Yes]\r\n", 9);
3511 struct ltchars tmpltc
;
3513 ptyflush(); /* half-hearted */
3514 if (ioctl(pty
, TIOCGLTC
, &tmpltc
) == -1)
3516 "ioctl TIOCGLTC: %m\n");
3517 if (tmpltc
.t_flushc
!= '\377') {
3518 *pfrontp
++ = tmpltc
.t_flushc
;
3520 netclear(); /* clear buffer back */
3521 write_data("%c%c", (uchar_t
)IAC
,
3524 neturg
= nfrontp
-1; /* off by one XXX */
3526 netflush(); /* XXX.sparker */
3531 * Erase Character and
3539 ptyflush(); /* half-hearted */
3540 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
3542 "ioctl TIOCGETP: %m\n");
3544 b
.sg_erase
: b
.sg_kill
;
3552 * Check for urgent data...
3558 * Begin option subnegotiation...
3597 SB_ACCUM((uchar_t
)IAC
);
3604 suboption(); /* handle sub-option */
3610 if (remopts
[c
] != OPT_YES
)
3616 if (remopts
[c
] != OPT_NO
)
3622 if (myopts
[c
] != OPT_YES
)
3628 if (myopts
[c
] != OPT_NO
) {
3635 syslog(LOG_ERR
, "telnetd: panic state=%d\n", state
);
3636 (void) printf("telnetd: panic state=%d\n", state
);
3643 willoption(int option
)
3646 boolean_t send_reply
= B_TRUE
;
3655 not42
= 0; /* looks like a 4.2 system */
3657 * Now, in a 4.2 system, to break them out of ECHOing
3658 * (to the terminal) mode, we need to send a "WILL ECHO".
3659 * Kludge upon kludge!
3661 if (myopts
[TELOPT_ECHO
] == OPT_YES
) {
3662 dooption(TELOPT_ECHO
);
3674 case TELOPT_XDISPLOC
:
3675 settimer(xdisplocopt
);
3678 case TELOPT_NEW_ENVIRON
:
3679 settimer(environopt
);
3682 case TELOPT_AUTHENTICATION
:
3684 if (remopts
[option
] == OPT_NO
||
3685 negotiate_auth_krb5
== 0)
3691 case TELOPT_OLD_ENVIRON
:
3692 settimer(oenvironopt
);
3695 if (remopts
[option
] == OPT_YES_BUT_ALWAYS_LOOK
) {
3696 remopts
[option
] = OPT_YES
;
3708 case TELOPT_ENCRYPT
:
3709 settimer(encropt
); /* got response to do/dont */
3711 (void) fprintf(stderr
,
3712 "RCVD IAC WILL TELOPT_ENCRYPT\n");
3713 if (krb5_privacy_allowed()) {
3715 if (sent_do_encrypt
)
3716 send_reply
= B_FALSE
;
3718 sent_do_encrypt
= B_TRUE
;
3729 remopts
[option
] = OPT_YES
;
3731 remopts
[option
] = OPT_NO
;
3734 write_data((const char *)fmt
, option
);
3740 wontoption(int option
)
3747 not42
= 1; /* doesn't seem to be a 4.2 system */
3762 case TELOPT_XDISPLOC
:
3763 settimer(xdisplocopt
);
3766 case TELOPT_NEW_ENVIRON
:
3767 settimer(environopt
);
3770 case TELOPT_OLD_ENVIRON
:
3771 settimer(oenvironopt
);
3774 case TELOPT_AUTHENTICATION
:
3776 auth_finished(0, AUTH_REJECT
);
3778 (void) fprintf(stderr
,
3779 "RCVD WONT TELOPT_AUTHENTICATE\n");
3781 remopts
[option
] = OPT_NO
;
3785 case TELOPT_ENCRYPT
:
3787 (void) fprintf(stderr
,
3788 "RCVD IAC WONT TELOPT_ENCRYPT\n");
3789 settimer(encropt
); /* got response to will/wont */
3791 * Remote side cannot send encryption. No reply necessary
3792 * Treat this as if "IAC SB ENCRYPT END IAC SE" were
3793 * received (RFC 2946) and disable crypto.
3795 encrypt_end(TELNET_DIR_DECRYPT
);
3801 remopts
[option
] = OPT_NO
;
3803 write_data((const char *)fmt
, option
);
3808 * We received an "IAC DO ..." message from the client, change our state
3812 dooption(int option
)
3815 boolean_t send_reply
= B_TRUE
;
3824 mode(O_ECHO
|O_CRMOD
, 0);
3839 * Options don't get much easier. Acknowledge the option,
3840 * and then clean up and exit.
3842 write_data((const char *)will
, option
);
3847 case TELOPT_ENCRYPT
:
3849 (void) fprintf(stderr
, "RCVD DO TELOPT_ENCRYPT\n");
3852 * We received a "DO". This indicates that the other side
3853 * wants us to encrypt our data (pending negotiatoin).
3854 * reply with "IAC WILL ENCRYPT" if we are able to send
3857 if (krb5_privacy_allowed() && negotiate_encrypt
) {
3859 if (sent_will_encrypt
)
3860 send_reply
= B_FALSE
;
3862 sent_will_encrypt
= B_TRUE
;
3863 /* return if we already sent "WILL ENCRYPT" */
3864 if (myopts
[option
] == OPT_YES
)
3871 case TELOPT_AUTHENTICATION
:
3873 (void) fprintf(stderr
,
3874 "RCVD DO TELOPT_AUTHENTICATION\n");
3877 * RFC 2941 - only the server can send
3878 * "DO TELOPT_AUTHENTICATION".
3879 * if a server receives this, it must respond with WONT...
3889 myopts
[option
] = OPT_YES
;
3891 myopts
[option
] = OPT_NO
;
3894 write_data((const char *)fmt
, option
);
3900 * We received an "IAC DONT ..." message from client.
3901 * Client does not agree with the option so act accordingly.
3904 dontoption(int option
)
3910 * we should stop echoing, since the client side will be doing
3911 * it, but keep mapping CR since CR-LF will be mapped to it.
3916 case TELOPT_ENCRYPT
:
3918 (void) fprintf(stderr
, "RCVD IAC DONT ENCRYPT\n");
3921 * Remote side cannot receive any encrypted data,
3922 * so dont send any. No reply necessary.
3931 myopts
[option
] = OPT_NO
;
3934 write_data((const char *)wont
, option
);
3941 * Look at the sub-option buffer, and try to be helpful to the other
3950 switch (subchar
= SB_GET()) {
3951 case TELOPT_TTYPE
: { /* Yaaaay! */
3952 static char terminalname
[5+41] = "TERM=";
3954 settimer(ttypesubopt
);
3956 if (SB_GET() != TELQUAL_IS
) {
3957 return; /* ??? XXX but, this is the most robust */
3960 terminaltype
= terminalname
+strlen(terminalname
);
3962 while (terminaltype
< (terminalname
+ sizeof (terminalname
) -
3970 *terminaltype
++ = c
; /* accumulate name */
3973 terminaltype
= terminalname
;
3983 ws
.ws_col
= SB_GET() << 8;
3987 ws
.ws_col
|= SB_GET();
3991 ws
.ws_row
= SB_GET() << 8;
3995 ws
.ws_row
|= SB_GET();
3996 ws
.ws_xpixel
= 0; ws
.ws_ypixel
= 0;
3997 (void) ioctl(pty
, TIOCSWINSZ
, &ws
);
4002 case TELOPT_XDISPLOC
: {
4003 if (SB_EOF() || SB_GET() != TELQUAL_IS
) {
4006 settimer(xdisplocsubopt
);
4007 subpointer
[SB_LEN()] = '\0';
4008 if ((new_env("DISPLAY", subpointer
)) == 1)
4013 case TELOPT_NEW_ENVIRON
:
4014 case TELOPT_OLD_ENVIRON
: {
4016 char *cp
, *varp
, *valp
;
4021 if (c
== TELQUAL_IS
) {
4022 if (subchar
== TELOPT_OLD_ENVIRON
)
4023 settimer(oenvironsubopt
);
4025 settimer(environsubopt
);
4026 } else if (c
!= TELQUAL_INFO
) {
4030 if (subchar
== TELOPT_NEW_ENVIRON
) {
4033 if ((c
== NEW_ENV_VAR
) || (c
== ENV_USERVAR
))
4040 if ((c
== env_ovar
) || (c
== ENV_USERVAR
))
4048 cp
= varp
= (char *)subpointer
;
4053 if (subchar
== TELOPT_OLD_ENVIRON
) {
4056 else if (c
== env_ovalue
)
4063 cp
= valp
= (char *)subpointer
;
4070 if ((new_env(varp
, valp
)) == 1) {
4074 (void) del_env(varp
);
4076 cp
= varp
= (char *)subpointer
;
4092 if ((new_env(varp
, valp
)) == 1) {
4096 (void) del_env(varp
);
4099 } /* end of case TELOPT_NEW_ENVIRON */
4101 case TELOPT_AUTHENTICATION
:
4108 * These are sent server only and cannot be sent by the
4114 (void) fprintf(stderr
,
4115 "RCVD AUTHENTICATION IS "
4118 if (!auth_negotiated
)
4119 auth_is((uchar_t
*)subpointer
, SB_LEN());
4123 (void) fprintf(stderr
,
4124 "RCVD AUTHENTICATION NAME "
4127 if (!auth_negotiated
)
4128 auth_name((uchar_t
*)subpointer
, SB_LEN());
4133 case TELOPT_ENCRYPT
: {
4138 #ifdef ENCRYPT_NAMES
4140 (void) fprintf(stderr
, "RCVD ENCRYPT %s\n",
4142 #endif /* ENCRYPT_NAMES */
4144 case ENCRYPT_SUPPORT
:
4145 encrypt_support(subpointer
, SB_LEN());
4148 encrypt_is((uchar_t
*)subpointer
, SB_LEN());
4151 (void) encrypt_reply(subpointer
, SB_LEN());
4157 encrypt_end(TELNET_DIR_DECRYPT
);
4159 case ENCRYPT_REQSTART
:
4160 encrypt_request_start();
4162 case ENCRYPT_REQEND
:
4164 * We can always send an REQEND so that we cannot
4165 * get stuck encrypting. We should only get this
4166 * if we have been able to get in the correct mode
4169 encrypt_request_end();
4171 case ENCRYPT_ENC_KEYID
:
4172 encrypt_enc_keyid(subpointer
, SB_LEN());
4174 case ENCRYPT_DEC_KEYID
:
4175 encrypt_dec_keyid(subpointer
, SB_LEN());
4189 mode(int on
, int off
)
4191 struct termios tios
;
4194 if (tcgetattr(pty
, &tios
) < 0)
4195 syslog(LOG_INFO
, "tcgetattr: %m\n");
4198 tios
.c_cflag
|= CS8
;
4199 tios
.c_iflag
&= ~IUCLC
;
4200 tios
.c_lflag
&= ~(XCASE
|IEXTEN
);
4203 if ((tios
.c_cflag
& PARENB
) != 0)
4204 tios
.c_cflag
&= ~CS8
;
4205 tios
.c_lflag
|= IEXTEN
;
4209 tios
.c_lflag
|= ECHO
;
4211 tios
.c_lflag
&= ~ECHO
;
4214 tios
.c_iflag
|= ICRNL
;
4215 tios
.c_oflag
|= ONLCR
;
4218 * Because "O_CRMOD" will never be set in "off" we don't have to
4219 * handle this case here.
4222 if (tcsetattr(pty
, TCSANOW
, &tios
) < 0)
4223 syslog(LOG_INFO
, "tcsetattr: %m\n");
4227 * Send interrupt to process on other side of pty.
4228 * If it is in raw mode, just write NULL;
4229 * otherwise, write intr char.
4235 struct tchars tchars
;
4237 ptyflush(); /* half-hearted */
4238 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
4239 syslog(LOG_INFO
, "ioctl TIOCGETP: %m\n");
4240 if (b
.sg_flags
& O_RAW
) {
4244 *pfrontp
++ = ioctl(pty
, TIOCGETC
, &tchars
) < 0 ?
4245 '\177' : tchars
.t_intrc
;
4249 * Send quit to process on other side of pty.
4250 * If it is in raw mode, just write NULL;
4251 * otherwise, write quit char.
4257 struct tchars tchars
;
4259 ptyflush(); /* half-hearted */
4260 (void) ioctl(pty
, TIOCGETP
, &b
);
4261 if (b
.sg_flags
& O_RAW
) {
4265 *pfrontp
++ = ioctl(pty
, TIOCGETC
, &tchars
) < 0 ?
4266 '\034' : tchars
.t_quitc
;
4274 if ((n
= pfrontp
- pbackp
) > 0)
4275 n
= write(master
, pbackp
, n
);
4279 if (pbackp
== pfrontp
)
4280 pbackp
= pfrontp
= ptyobuf
;
4286 * Return the address of the next "item" in the TELNET data
4287 * stream. This will be the address of the next character if
4288 * the current address is a user data character, or it will
4289 * be the address of the character following the TELNET command
4290 * if the current address is a TELNET IAC ("I Am a Command")
4295 nextitem(char *current
)
4297 if ((*current
&0xff) != IAC
) {
4300 switch (*(current
+1)&0xff) {
4306 case SB
: /* loop forever looking for the SE */
4308 char *look
= current
+2;
4311 if ((*look
++&0xff) == IAC
) {
4312 if ((*look
++&0xff) == SE
) {
4327 * We are about to do a TELNET SYNCH operation. Clear
4328 * the path to the network.
4330 * Things are a bit tricky since we may have sent the first
4331 * byte or so of a previous TELNET command into the network.
4332 * So, we have to scan the network buffer from the beginning
4333 * until we are up to where we want to be.
4335 * A side effect of what we do, just to keep things
4336 * simple, is to clear the urgent data pointer. The principal
4337 * caller should be setting the urgent data pointer AFTER calling
4343 char *thisitem
, *next
;
4345 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
4346 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
4350 while ((next
= nextitem(thisitem
)) <= nbackp
) {
4354 /* Now, thisitem is first before/at boundary. */
4356 good
= netobuf
; /* where the good bytes go */
4358 while (nfrontp
> thisitem
) {
4359 if (wewant(thisitem
)) {
4364 next
= nextitem(next
);
4365 } while (wewant(next
) && (nfrontp
> next
));
4366 length
= next
-thisitem
;
4367 (void) memmove(good
, thisitem
, length
);
4371 thisitem
= nextitem(thisitem
);
4376 nfrontp
= good
; /* next byte to be sent */
4383 * Send as much data as possible to the network,
4384 * handling requests for urgent data.
4391 if ((n
= nfrontp
- nbackp
) > 0) {
4393 * if no urgent data, or if the other side appears to be an
4394 * old 4.2 client (and thus unable to survive TCP urgent data),
4395 * write the entire buffer in non-OOB mode.
4397 if ((neturg
== 0) || (not42
== 0)) {
4398 n
= write(net
, nbackp
, n
); /* normal write */
4400 n
= neturg
- nbackp
;
4402 * In 4.2 (and 4.3) systems, there is some question
4403 * about what byte in a sendOOB operation is the "OOB"
4404 * data. To make ourselves compatible, we only send ONE
4405 * byte out of band, the one WE THINK should be OOB
4406 * (though we really have more the TCP philosophy of
4407 * urgent data rather than the Unix philosophy of OOB
4411 /* send URGENT all by itself */
4412 n
= write(net
, nbackp
, n
-1);
4415 n
= send_oob(net
, nbackp
, n
);
4420 if (errno
== EWOULDBLOCK
)
4422 /* should blow this guy away... */
4428 if (nbackp
>= neturg
) {
4431 if (nbackp
== nfrontp
) {
4432 nbackp
= nfrontp
= netobuf
;
4441 * If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
4442 * handle closing differently. We close "net" first and then
4443 * "master" in that order. We do close(net) first because
4444 * we have no other way to disconnect forwarding between the network
4445 * and master. So by issuing the close()'s we ensure that no further
4446 * data rises from TCP. A more complex fix would be adding proper
4447 * support for throwing a "stop" switch for forwarding data between
4448 * logindmux peers. It's possible to block in the close of the tty
4449 * while the network still receives data and the telmod module is
4450 * TEL_STOPPED. A denial-of-service attack generates this case,
4454 if (!telmod_init_done
) {
4456 (void) close(master
);
4468 char user
[sizeof (up
->ut_user
) + 1];
4469 char ttyn
[sizeof (up
->ut_line
) + 1];
4470 char rhost
[sizeof (up
->ut_host
) + 1];
4472 /* while cleaning up don't allow disruption */
4473 (void) signal(SIGCHLD
, SIG_IGN
);
4476 while (up
= getutxent()) {
4477 if (up
->ut_pid
== pid
) {
4478 if (up
->ut_type
== DEAD_PROCESS
) {
4480 * Cleaned up elsewhere.
4486 * call pam_close_session if login changed
4487 * the utmpx user entry from type LOGIN_PROCESS
4488 * to type USER_PROCESS, which happens
4489 * after pam_open_session is called.
4491 if (up
->ut_type
== USER_PROCESS
) {
4492 (void) strlcpy(user
, up
->ut_user
,
4494 (void) strlcpy(ttyn
, up
->ut_line
,
4496 (void) strlcpy(rhost
, up
->ut_host
,
4498 if ((pam_start("telnet", user
, NULL
, &pamh
)) ==
4500 (void) pam_set_item(pamh
, PAM_TTY
,
4502 (void) pam_set_item(pamh
, PAM_RHOST
,
4504 (void) pam_close_session(pamh
, 0);
4505 (void) pam_end(pamh
, PAM_SUCCESS
);
4509 up
->ut_type
= DEAD_PROCESS
;
4510 up
->ut_exit
.e_termination
= WTERMSIG(0);
4511 up
->ut_exit
.e_exit
= WEXITSTATUS(0);
4512 (void) time(&up
->ut_tv
.tv_sec
);
4514 if (modutx(up
) == NULL
) {
4516 * Since modutx failed we'll
4517 * write out the new entry
4520 (void) pututxline(up
);
4521 updwtmpx("wtmpx", up
);
4529 (void) signal(SIGCHLD
, (void (*)())cleanup
);
4533 readstream(int fd
, char *buf
, int offset
)
4535 struct strbuf ctlbuf
, datbuf
;
4536 union T_primitives tpi
;
4539 int bytes_avail
, count
;
4541 (void) memset((char *)&ctlbuf
, 0, sizeof (ctlbuf
));
4542 (void) memset((char *)&datbuf
, 0, sizeof (datbuf
));
4544 ctlbuf
.buf
= (char *)&tpi
;
4545 ctlbuf
.maxlen
= sizeof (tpi
);
4547 if (ioctl(fd
, I_NREAD
, &bytes_avail
) < 0) {
4548 syslog(LOG_ERR
, "I_NREAD returned error %m");
4551 if (bytes_avail
> netibufsize
- offset
) {
4552 count
= netip
- netibuf
;
4553 netibuf
= (char *)realloc(netibuf
,
4554 (unsigned)netibufsize
+ bytes_avail
);
4555 if (netibuf
== NULL
) {
4556 fatal(net
, "netibuf realloc failed\n");
4558 netibufsize
+= bytes_avail
;
4559 netip
= netibuf
+ count
;
4562 datbuf
.buf
= buf
+ offset
;
4563 datbuf
.maxlen
= netibufsize
;
4564 ret
= getmsg(fd
, &ctlbuf
, &datbuf
, &flags
);
4566 syslog(LOG_ERR
, "getmsg returned -1, errno %d\n",
4570 if (ctlbuf
.len
<= 0) {
4571 return (datbuf
.len
);
4574 if (tpi
.type
== T_DATA_REQ
) {
4578 if ((tpi
.type
== T_ORDREL_IND
) || (tpi
.type
== T_DISCON_IND
))
4580 fatal(fd
, "no data or protocol element recognized");
4585 drainstream(int size
)
4590 tsize
= netip
- netibuf
;
4592 if ((tsize
+ ncc
+ size
) > netibufsize
) {
4593 if (!(netibuf
= (char *)realloc(netibuf
,
4594 (unsigned)tsize
+ ncc
+ size
)))
4595 fatalperror(net
, "netibuf realloc failed\n", errno
);
4596 netibufsize
= tsize
+ ncc
+ size
;
4598 netip
= netibuf
+ tsize
;
4601 if ((nbytes
= read(net
, (char *)netip
+ ncc
, size
)) != size
)
4602 syslog(LOG_ERR
, "read %d bytes\n", nbytes
);
4606 * TPI style replacement for socket send() primitive, so we don't require
4607 * sockmod to be on the stream.
4610 send_oob(int fd
, char *ptr
, int count
)
4612 struct T_exdata_req exd_req
;
4613 struct strbuf hdr
, dat
;
4616 exd_req
.PRIM_type
= T_EXDATA_REQ
;
4617 exd_req
.MORE_flag
= 0;
4619 hdr
.buf
= (char *)&exd_req
;
4620 hdr
.len
= sizeof (exd_req
);
4625 ret
= putmsg(fd
, &hdr
, &dat
, 0);
4635 * Set the value of the environmental variable "name" to be
4636 * "value". If rewrite is set, replace any current value.
4639 local_setenv(const char *name
, const char *value
, int rewrite
)
4641 static int alloced
; /* if allocated space before */
4643 int l_value
, offset
;
4646 * Do not allow environment variables which begin with LD_ to be
4647 * inserted into the environment. While normally the dynamic linker
4648 * protects the login program, that is based on the assumption hostile
4649 * invocation of login are from non-root users. However, since telnetd
4650 * runs as root, this cannot be utilized. So instead we simply
4651 * prevent LD_* from being inserted into the environment.
4652 * This also applies to other environment variables that
4653 * are to be ignored in setugid apps.
4654 * Note that at this point name can contain '='!
4655 * Also, do not allow TTYPROMPT to be passed along here.
4657 if (strncmp(name
, "LD_", 3) == 0 ||
4658 strncmp(name
, "NLSPATH", 7) == 0 ||
4659 (strncmp(name
, "TTYPROMPT", 9) == 0 &&
4660 (name
[9] == '\0' || name
[9] == '='))) {
4663 if (*value
== '=') /* no `=' in value */
4665 l_value
= strlen(value
);
4666 if ((c
= __findenv(name
, &offset
))) { /* find if already exists */
4669 if ((int)strlen(c
) >= l_value
) { /* old larger; copy over */
4670 while (*c
++ = *value
++)
4674 } else { /* create new slot */
4678 for (p
= environ
, cnt
= 0; *p
; ++p
, ++cnt
)
4680 if (alloced
) { /* just increase size */
4681 environ
= (char **)realloc((char *)environ
,
4682 (size_t)(sizeof (char *) * (cnt
+ 2)));
4685 } else { /* get new space */
4686 alloced
= 1; /* copy old entries into it */
4687 p
= (char **)malloc((size_t)(sizeof (char *)*
4691 (void) memcpy(p
, environ
, cnt
* sizeof (char *));
4694 environ
[cnt
+ 1] = NULL
;
4697 for (c
= (char *)name
; *c
&& *c
!= '='; ++c
) /* no `=' in name */
4699 if (!(environ
[offset
] = /* name + `=' + value */
4700 malloc((size_t)((int)(c
- name
) + l_value
+ 2))))
4702 for (c
= environ
[offset
]; ((*c
= *name
++) != 0) && (*c
!= '='); ++c
)
4704 for (*c
++ = '='; *c
++ = *value
++; )
4710 * local_unsetenv(name) --
4711 * Delete environmental variable "name".
4714 local_unsetenv(const char *name
)
4719 while (__findenv(name
, &offset
)) /* if set multiple times */
4720 for (p
= &environ
[offset
]; ; ++p
)
4721 if ((*p
= *(p
+ 1)) == 0)
4727 * Returns pointer to value associated with name, if any, else NULL.
4728 * Sets offset to be the offset of the name/value combination in the
4729 * environmental array, for use by local_setenv() and local_unsetenv().
4730 * Explicitly removes '=' in argument name.
4733 __findenv(const char *name
, int *offset
)
4735 extern char **environ
;
4740 if (name
== NULL
|| environ
== NULL
)
4742 for (np
= name
; *np
&& *np
!= '='; ++np
)
4745 for (p
= environ
; (c
= *p
) != NULL
; ++p
)
4746 if (strncmp(c
, name
, len
) == 0 && c
[len
] == '=') {
4747 *offset
= p
- environ
;
4748 return (c
+ len
+ 1);
4757 char evalbuf
[BUFSIZ
];
4759 if (defopen(defaultfile
) == 0) {
4763 flags
= defcntl(DC_GETFLAGS
, 0);
4764 TURNOFF(flags
, DC_CASE
);
4765 (void) defcntl(DC_SETFLAGS
, flags
);
4766 if (cp
= defread(bannervar
)) {
4769 if (strlen(cp
) + strlen("eval echo '") + strlen("'\n")
4770 + 1 < sizeof (evalbuf
)) {
4771 (void) strlcpy(evalbuf
, "eval echo '",
4773 (void) strlcat(evalbuf
, cp
, sizeof (evalbuf
));
4774 (void) strlcat(evalbuf
, "'\n",
4777 if (fp
= popen(evalbuf
, "r")) {
4782 * Pipe I/O atomicity guarantees we
4783 * need only one read.
4785 if ((size
= fread(buf
, 1,
4790 p
= strrchr(buf
, '\n');
4799 /* close default file */
4800 (void) defopen(NULL
);
4805 (void) defopen(NULL
); /* close default file */
4818 * Map the banner: "\n" -> "\r\n" and "\r" -> "\r\0"
4820 for (q
= nfrontp
; p
&& *p
&& q
< nfrontp
+ sizeof (netobuf
) - 1; )
4825 } else if (*p
== '\r') {
4832 nfrontp
+= q
- netobuf
;
4836 * Show banner that getty never gave. By default, this is `uname -sr`.
4838 * The banner includes some null's (for TELNET CR disambiguation),
4839 * so we have to be somewhat complicated.
4847 * Dont show this if the '-h' option was present
4852 if (uname(&u
) == -1)
4855 write_data_len((const char *) BANNER1
, sizeof (BANNER1
) - 1);
4856 write_data_len(u
.sysname
, strlen(u
.sysname
));
4857 write_data_len(" ", 1);
4858 write_data_len(u
.release
, strlen(u
.release
));
4859 write_data_len((const char *)BANNER2
, sizeof (BANNER2
) - 1);
4863 * Verify that the named module is at the top of the stream
4864 * and then pop it off.
4867 removemod(int f
, char *modname
)
4869 char topmodname
[BUFSIZ
];
4871 if (ioctl(f
, I_LOOK
, topmodname
) < 0)
4873 if (strcmp(modname
, topmodname
) != 0) {
4877 if (ioctl(f
, I_POP
, 0) < 0)
4883 write_data(const char *format
, ...)
4889 va_start(args
, format
);
4891 if ((len
= vsnprintf(argp
, sizeof (argp
), format
, args
)) == -1)
4894 write_data_len(argp
, len
);
4899 write_data_len(const char *buf
, int len
)
4901 int remaining
, copied
;
4903 remaining
= BUFSIZ
- (nfrontp
- netobuf
);
4906 * If there's not enough space in netobuf then
4909 if ((len
> BUFSIZ
? BUFSIZ
: len
) > remaining
) {
4911 remaining
= BUFSIZ
- (nfrontp
- netobuf
);
4913 /* Copy as much as we can */
4914 copied
= remaining
> len
? len
: remaining
;
4915 (void) memmove(nfrontp
, buf
, copied
);
4918 remaining
-= copied
;