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>
99 #define TELNETD_OPTS "Ss:a:dEXUhR:M:"
101 #define DEBUG_OPTS "p:e"
103 #define DEBUG_OPTS ""
106 #define OPT_NO 0 /* won't do this option */
107 #define OPT_YES 1 /* will do this option */
108 #define OPT_YES_BUT_ALWAYS_LOOK 2
109 #define OPT_NO_BUT_ALWAYS_LOOK 3
111 #define MAXOPTLEN 256
112 #define MAXUSERNAMELEN 256
114 static char remopts
[MAXOPTLEN
];
115 static char myopts
[MAXOPTLEN
];
116 static uchar_t doopt
[] = { (uchar_t
)IAC
, (uchar_t
)DO
, '%', 'c', 0 };
117 static uchar_t dont
[] = { (uchar_t
)IAC
, (uchar_t
)DONT
, '%', 'c', 0 };
118 static uchar_t will
[] = { (uchar_t
)IAC
, (uchar_t
)WILL
, '%', 'c', 0 };
119 static uchar_t wont
[] = { (uchar_t
)IAC
, (uchar_t
)WONT
, '%', 'c', 0 };
121 * I/O data buffers, pointers, and counters.
123 static char ptyobuf
[BUFSIZ
], *pfrontp
= ptyobuf
, *pbackp
= ptyobuf
;
125 static char *netibuf
, *netip
;
126 static int netibufsize
;
128 #define NIACCUM(c) { *netip++ = c; \
132 static char netobuf
[BUFSIZ
], *nfrontp
= netobuf
, *nbackp
= netobuf
;
133 static char *neturg
= 0; /* one past last bye of urgent data */
134 /* the remote system seems to NOT be an old 4.2 */
135 static int not42
= 1;
136 static char defaultfile
[] = "/etc/default/telnetd";
137 static char bannervar
[] = "BANNER=";
139 static char BANNER1
[] = "\r\n\r\n";
140 static char BANNER2
[] = "\r\n\r\0\r\n\r\0";
143 * buffer for sub-options - enlarged to 4096 to handle credentials
146 static char subbuffer
[4096], *subpointer
= subbuffer
, *subend
= subbuffer
;
147 #define SB_CLEAR() subpointer = subbuffer;
148 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
149 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof (subbuffer))) { \
150 *subpointer++ = (c); \
152 #define SB_GET() ((*subpointer++)&0xff)
153 #define SB_EOF() (subpointer >= subend)
154 #define SB_LEN() (subend - subpointer)
156 #define MAXERRSTRLEN 1024
157 #define MAXPRINCLEN 256
159 extern uint_t
kwarn_add_warning(char *, int);
160 extern uint_t
kwarn_del_warning(char *);
162 static boolean_t auth_debug
= 0;
163 static boolean_t negotiate_auth_krb5
= 1;
164 static boolean_t auth_negotiated
= 0;
165 static int auth_status
= 0;
166 static int auth_level
= 0;
167 static char *AuthenticatingUser
= NULL
;
168 static char *krb5_name
= NULL
;
170 static krb5_address rsaddr
= { 0, 0, 0, NULL
};
171 static krb5_address rsport
= { 0, 0, 0, NULL
};
173 static krb5_context telnet_context
= 0;
174 static krb5_auth_context auth_context
= 0;
176 /* telnetd gets session key from here */
177 static krb5_ticket
*ticket
= NULL
;
178 static krb5_keyblock
*session_key
= NULL
;
179 static char *telnet_srvtab
= NULL
;
187 static AuthInfo auth_list
[] = {
188 {AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
| AUTH_HOW_MUTUAL
|
189 AUTH_ENCRYPT_ON
, "KRB5 MUTUAL CRYPTO"},
190 {AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
| AUTH_HOW_MUTUAL
,
192 {AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
| AUTH_HOW_ONE_WAY
,
197 static AuthInfo NoAuth
= {0, 0, NULL
};
199 static AuthInfo
*authenticated
= NULL
;
201 #define PREAMBLE_SIZE 5 /* for auth_reply_str allocation */
202 #define POSTAMBLE_SIZE 5
203 #define STR_DATA_LEN(len) ((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE)
205 static void auth_name(uchar_t
*, int);
206 static void auth_is(uchar_t
*, int);
208 #define NO_ENCRYPTION 0x00
209 #define SEND_ENCRYPTED 0x01
210 #define RECV_ENCRYPTED 0x02
211 #define ENCRYPT_BOTH_WAYS (SEND_ENCRYPTED | RECV_ENCRYPTED)
213 static telnet_enc_data_t encr_data
;
214 static boolean_t negotiate_encrypt
= B_TRUE
;
215 static boolean_t sent_encrypt_support
= B_FALSE
;
216 static boolean_t sent_will_encrypt
= B_FALSE
;
217 static boolean_t sent_do_encrypt
= B_FALSE
;
218 static boolean_t enc_debug
= 0;
220 static void encrypt_session_key(Session_Key
*key
, cipher_info_t
*cinfo
);
221 static int encrypt_send_encrypt_is();
223 extern void mit_des_fixup_key_parity(Block
);
224 extern int krb5_setenv(const char *, const char *, int);
225 /* need to know what FD to use to talk to the crypto module */
226 static int cryptmod_fd
= -1;
228 #define LOGIN_PROGRAM "/bin/login"
233 #define TS_DATA 0 /* base state */
234 #define TS_IAC 1 /* look for double IAC's */
235 #define TS_CR 2 /* CR-LF ->'s CR */
236 #define TS_SB 3 /* throw away begin's... */
237 #define TS_SE 4 /* ...end's (suboption negotiation) */
238 #define TS_WILL 5 /* will option negotiation */
239 #define TS_WONT 6 /* wont " */
240 #define TS_DO 7 /* do " */
241 #define TS_DONT 8 /* dont " */
244 static int master
; /* master side of pty */
245 static int pty
; /* side of pty that gets ioctls */
248 extern char **environ
;
250 static int SYNCHing
= 0; /* we are in TELNET SYNCH mode */
251 static int state
= TS_DATA
;
253 static int env_ovar
= -1; /* XXX.sparker */
254 static int env_ovalue
= -1; /* XXX.sparker */
255 static char pam_svc_name
[64];
256 static boolean_t telmod_init_done
= B_FALSE
;
258 static void doit(int, struct sockaddr_storage
*);
259 static void willoption(int);
260 static void wontoption(int);
261 static void dooption(int);
262 static void dontoption(int);
263 static void fatal(int, char *);
264 static void fatalperror(int, char *, int);
265 static void mode(int, int);
266 static void interrupt(void);
267 static void drainstream(int);
268 static int readstream(int, char *, int);
269 static int send_oob(int fd
, char *ptr
, int count
);
270 static int local_setenv(const char *name
, const char *value
, int rewrite
);
271 static void local_unsetenv(const char *name
);
272 static void suboption(void);
273 static int removemod(int f
, char *modname
);
274 static void willoption(int option
);
275 static void wontoption(int option
);
276 static void dooption(int option
);
277 static void dontoption(int option
);
278 static void write_data(const char *, ...);
279 static void write_data_len(const char *, int);
280 static void rmut(void);
281 static void cleanup(int);
282 static void telnet(int, int);
283 static void telrcv(void);
284 static void sendbrk(void);
285 static void ptyflush(void);
286 static void netclear(void);
287 static void netflush(void);
288 static void showbanner(void);
289 static void map_banner(char *);
290 static void defbanner(void);
291 static void ttloop(void);
294 * The env_list linked list is used to store the environment variables
295 * until the final exec of login. A malevolent client might try to
296 * send an environment variable intended to affect the telnet daemon's
297 * execution. Right now the BANNER expansion is the only instance.
298 * Note that it is okay to pass the environment variables to login
299 * because login protects itself against environment variables mischief.
303 struct envlist
*next
;
309 static struct envlist
*envlist_head
= NULL
;
312 * The following are some clocks used to decide how to interpret
313 * the relationship between various variables.
318 system
, /* what the current time is */
319 echotoggle
, /* last time user entered echo character */
320 modenegotiated
, /* last time operating mode negotiated */
321 didnetreceive
, /* last time we read data from network */
322 ttypeopt
, /* ttype will/won't received */
323 ttypesubopt
, /* ttype subopt is received */
324 getterminal
, /* time started to get terminal information */
325 xdisplocopt
, /* xdisploc will/wont received */
326 xdisplocsubopt
, /* xdisploc suboption received */
327 nawsopt
, /* window size will/wont received */
328 nawssubopt
, /* window size received */
329 environopt
, /* environment option will/wont received */
330 oenvironopt
, /* "old" environ option will/wont received */
331 environsubopt
, /* environment option suboption received */
332 oenvironsubopt
, /* "old environ option suboption received */
333 gotDM
; /* when did we last see a data mark */
336 int authopt
; /* Authentication option negotiated */
344 static int init_neg_done
= 0;
345 static boolean_t resolve_hostname
= 0;
346 static boolean_t show_hostinfo
= 1;
348 #define settimer(x) (clocks.x = ++clocks.system)
349 #define sequenceIs(x, y) (clocks.x < clocks.y)
351 static void send_will(int);
352 static void send_wont(int);
353 static void send_do(int);
354 static char *__findenv(const char *name
, int *offset
);
358 auth_finished(AuthInfo
*ap
, int result
)
360 if ((authenticated
= ap
) == NULL
) {
361 authenticated
= &NoAuth
;
362 if (myopts
[TELOPT_ENCRYPT
] == OPT_YES
)
363 send_wont(TELOPT_ENCRYPT
);
364 myopts
[TELOPT_ENCRYPT
] = remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
365 encr_data
.encrypt
.autoflag
= 0;
366 } else if (result
!= AUTH_REJECT
&&
367 myopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
368 remopts
[TELOPT_ENCRYPT
] == OPT_YES
) {
371 * Authentication successful, so we have a session key, and
372 * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT.
374 * Can't have sent ENCRYPT SUPPORT yet! And if we're sending it
375 * now it's really only because we did the DO ENCRYPT/WILL
376 * ENCRYPT dance before authentication, which is ok, but not too
377 * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT
378 * dance if authentication fails, though clients typically just
381 write_data("%c%c%c%c%c%c%c",
384 (uchar_t
)TELOPT_ENCRYPT
,
385 (uchar_t
)ENCRYPT_SUPPORT
,
386 (uchar_t
)TELOPT_ENCTYPE_DES_CFB64
,
392 sent_encrypt_support
= B_TRUE
;
395 (void) fprintf(stderr
,
396 "SENT ENCRYPT SUPPORT\n");
398 (void) encrypt_send_encrypt_is();
401 auth_status
= result
;
407 reply_to_client(AuthInfo
*ap
, int type
, void *data
, int len
)
409 uchar_t reply
[BUFSIZ
];
411 uchar_t
*cd
= (uchar_t
*)data
;
413 if (len
== -1 && data
!= NULL
)
414 len
= strlen((char *)data
);
415 else if (len
> (sizeof (reply
) - 9)) {
417 "krb5 auth reply length too large (%d)", len
);
419 (void) fprintf(stderr
,
420 "krb5 auth reply length too large (%d)\n",
423 } else if (data
== NULL
)
428 *p
++ = TELOPT_AUTHENTICATION
;
429 *p
++ = AUTHTYPE_KERBEROS_V5
;
431 *p
++ = ap
->AuthHow
; /* MUTUAL, ONE-WAY, etc */
432 *p
++ = type
; /* RESPONSE or ACCEPT */
434 if ((*p
++ = *cd
++) == IAC
)
440 /* queue the data to be sent */
441 write_data_len((const char *)reply
, p
-reply
);
443 #if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\
444 defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES)
446 (void) fprintf(stderr
, "SENT TELOPT_AUTHENTICATION REPLY "
448 AUTHTYPE_NAME(ap
->AuthName
),
449 AUTHWHO_NAME(ap
->AuthHow
& AUTH_WHO_MASK
),
450 AUTHHOW_NAME(ap
->AuthHow
& AUTH_HOW_MASK
),
453 #endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */
458 /* Decode, decrypt and store the forwarded creds in the local ccache. */
459 static krb5_error_code
460 rd_and_store_forwarded_creds(krb5_context context
,
461 krb5_auth_context auth_context
,
462 krb5_data
*inbuf
, krb5_ticket
*ticket
,
466 krb5_error_code retval
;
467 char ccname
[MAXPATHLEN
];
468 krb5_ccache ccache
= NULL
;
469 char *client_name
= NULL
;
471 if (retval
= krb5_rd_cred(context
, auth_context
, inbuf
, &creds
, NULL
))
474 (void) sprintf(ccname
, "FILE:/tmp/krb5cc_p%ld", getpid());
475 (void) krb5_setenv("KRB5CCNAME", ccname
, 1);
477 if ((retval
= krb5_cc_default(context
, &ccache
)))
480 if ((retval
= krb5_cc_initialize(context
, ccache
,
481 ticket
->enc_part2
->client
)) != 0)
484 if ((retval
= krb5_cc_store_cred(context
, ccache
, *creds
)) != 0)
487 if ((retval
= krb5_cc_close(context
, ccache
)) != 0)
490 /* Register with ktkt_warnd(8) */
491 if ((retval
= krb5_unparse_name(context
, (*creds
)->client
,
494 (void) kwarn_del_warning(client_name
);
495 if (kwarn_add_warning(client_name
, (*creds
)->times
.endtime
) != 0) {
496 syslog(LOG_AUTH
|LOG_NOTICE
,
497 "rd_and_store_forwarded_creds: kwarn_add_warning"
498 " failed: ktkt_warnd(8) down? ");
500 (void) fprintf(stderr
,
501 "kwarn_add_warning failed:"
502 " ktkt_warnd(8) down?\n");
507 if (username
!= NULL
) {
509 * This verifies that the user is valid on the local system,
510 * maps the username from KerberosV5 to unix,
511 * and moves the KRB5CCNAME file to the correct place
512 * /tmp/krb5cc_[uid] with correct ownership (0600 uid gid).
514 * NOTE: the user must be in the gsscred table in order to map
517 (void) krb5_kuserok(context
, ticket
->enc_part2
->client
,
521 (void) fprintf(stderr
,
522 "Successfully stored forwarded creds\n");
525 krb5_free_creds(context
, *creds
);
530 kerberos5_is(AuthInfo
*ap
, uchar_t
*data
, int cnt
)
532 krb5_error_code err
= 0;
533 krb5_principal server
;
534 krb5_keyblock
*newkey
= NULL
;
535 krb5_keytab keytabid
= 0;
538 krb5_authenticator
*authenticator
;
539 char errbuf
[MAXERRSTRLEN
];
549 auth
.data
= (char *)data
;
552 if (auth_context
== NULL
) {
553 err
= krb5_auth_con_init(telnet_context
, &auth_context
);
556 "Error getting krb5 auth "
557 "context: %s", error_message(err
));
562 err
= krb5_auth_con_getrcache(telnet_context
,
565 if (!err
&& !rcache
) {
566 err
= krb5_sname_to_principal(telnet_context
,
571 err
= krb5_get_server_rcache(
573 krb5_princ_component(
578 krb5_free_principal(telnet_context
,
584 "Error allocating krb5 replay cache: %s",
587 err
= krb5_auth_con_setrcache(telnet_context
,
592 "Error creating krb5 "
597 if (!err
&& telnet_srvtab
!= NULL
)
598 err
= krb5_kt_resolve(telnet_context
,
599 telnet_srvtab
, &keytabid
);
601 err
= krb5_rd_req(telnet_context
, &auth_context
, &auth
,
602 NULL
, keytabid
, NULL
, &ticket
);
604 (void) snprintf(errbuf
, sizeof (errbuf
),
605 "Error reading krb5 auth information:"
606 " %s", error_message(err
));
611 * Verify that the correct principal was used
613 if (krb5_princ_component(telnet_context
,
614 ticket
->server
, 0)->length
< MAXPRINCLEN
) {
615 char princ
[MAXPRINCLEN
];
616 (void) strncpy(princ
,
617 krb5_princ_component(telnet_context
,
618 ticket
->server
, 0)->data
,
619 krb5_princ_component(telnet_context
,
620 ticket
->server
, 0)->length
);
621 princ
[krb5_princ_component(telnet_context
,
622 ticket
->server
, 0)->length
] = '\0';
623 if (strcmp("host", princ
)) {
624 if (strlen(princ
) < sizeof (errbuf
) - 39) {
625 (void) snprintf(errbuf
, sizeof (errbuf
),
631 (void) strncpy(errbuf
,
633 "name: principal != "
640 (void) strlcpy(errbuf
, "service name too long",
645 err
= krb5_auth_con_getauthenticator(telnet_context
,
649 (void) snprintf(errbuf
, sizeof (errbuf
),
650 "Failed to get authenticator: %s",
654 if ((ap
->AuthHow
& AUTH_ENCRYPT_MASK
) == AUTH_ENCRYPT_ON
&&
655 !authenticator
->checksum
) {
656 (void) strlcpy(errbuf
,
657 "authenticator is missing checksum",
661 if (authenticator
->checksum
) {
663 krb5_checksum
*cksum
= authenticator
->checksum
;
668 type_check
[0] = ap
->AuthName
;
669 type_check
[1] = ap
->AuthHow
;
671 err
= krb5_auth_con_getkey(telnet_context
,
674 (void) snprintf(errbuf
, sizeof (errbuf
),
675 "Failed to get key from "
681 input
.data
= type_check
;
683 err
= krb5_c_verify_checksum(telnet_context
,
689 err
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
692 (void) snprintf(errbuf
, sizeof (errbuf
),
694 "verification failed: "
699 krb5_free_keyblock(telnet_context
, key
);
702 krb5_free_authenticator(telnet_context
, authenticator
);
703 if ((ap
->AuthHow
& AUTH_HOW_MASK
) == AUTH_HOW_MUTUAL
) {
704 /* do ap_rep stuff here */
705 if ((err
= krb5_mk_rep(telnet_context
, auth_context
,
707 (void) snprintf(errbuf
, sizeof (errbuf
),
709 "Kerberos auth reply: "
714 reply_to_client(ap
, KRB_RESPONSE
, outbuf
.data
,
717 if (krb5_unparse_name(telnet_context
,
718 ticket
->enc_part2
->client
,
721 reply_to_client(ap
, KRB_ACCEPT
, name
, name
? -1 : 0);
724 "\tKerberos5 identifies user as ``%s''\r\n",
728 krb5_name
= (char *)strdup(name
);
730 auth_finished(ap
, AUTH_USER
);
733 (void) krb5_auth_con_getremotesubkey(telnet_context
,
734 auth_context
, &newkey
);
735 if (session_key
!= NULL
) {
736 krb5_free_keyblock(telnet_context
, session_key
);
739 if (newkey
!= NULL
) {
740 (void) krb5_copy_keyblock(telnet_context
,
741 newkey
, &session_key
);
742 krb5_free_keyblock(telnet_context
, newkey
);
744 (void) krb5_copy_keyblock(telnet_context
,
745 ticket
->enc_part2
->session
, &session_key
);
749 * Initialize encryption stuff. Currently, we are only
750 * supporting 8 byte keys and blocks. Check for this later.
753 skey
.length
= DES_BLOCKSIZE
;
754 skey
.data
= session_key
->contents
;
755 encrypt_session_key(&skey
, &encr_data
.encrypt
);
756 encrypt_session_key(&skey
, &encr_data
.decrypt
);
760 inbuf
.data
= (char *)data
;
762 (void) fprintf(stderr
,
763 "RCVD KRB_FORWARD data (%d bytes)\n", cnt
);
765 if (auth_context
!= NULL
) {
768 err
= krb5_auth_con_getrcache(telnet_context
,
769 auth_context
, &rcache
);
770 if (!err
&& !rcache
) {
771 err
= krb5_sname_to_principal(telnet_context
,
772 0, 0, KRB5_NT_SRV_HST
, &server
);
774 err
= krb5_get_server_rcache(
776 krb5_princ_component(
780 krb5_free_principal(telnet_context
,
786 "Error allocating krb5 replay cache: %s",
789 err
= krb5_auth_con_setrcache(telnet_context
,
790 auth_context
, rcache
);
793 "Error creating krb5 replay cache:"
799 * Use the 'rsaddr' and 'rsport' (remote service addr/port)
800 * from the original connection. This data is used to
801 * verify the forwarded credentials.
803 if (!(err
= krb5_auth_con_setaddrs(telnet_context
, auth_context
,
805 err
= krb5_auth_con_setports(telnet_context
,
806 auth_context
, NULL
, &rsport
);
810 * If all is well, store the forwarded creds in
811 * the users local credential cache.
813 err
= rd_and_store_forwarded_creds(telnet_context
,
814 auth_context
, &inbuf
,
818 (void) snprintf(errbuf
, sizeof (errbuf
),
819 "Read forwarded creds failed: %s",
821 syslog(LOG_ERR
, "%s", errbuf
);
823 reply_to_client(ap
, KRB_FORWARD_REJECT
, errbuf
, -1);
825 (void) fprintf(stderr
,
827 "forwarded credentials\r\n");
829 reply_to_client(ap
, KRB_FORWARD_ACCEPT
, NULL
, 0);
831 free(rsaddr
.contents
);
833 free(rsport
.contents
);
836 (void) fprintf(stderr
, "\tForwarded "
837 "credentials obtained\r\n");
841 (void) fprintf(stderr
,
842 "\tUnknown Kerberos option %d\r\n",
844 reply_to_client(ap
, KRB_REJECT
, NULL
, 0);
850 reply_to_client(ap
, KRB_REJECT
, errbuf
, -1);
853 (void) fprintf(stderr
, "\tKerberos V5 error: %s\r\n", errbuf
);
855 syslog(LOG_ERR
, "%s", errbuf
);
857 if (auth_context
!= NULL
) {
858 (void) krb5_auth_con_free(telnet_context
, auth_context
);
868 if (telnet_context
== NULL
) {
869 code
= krb5_init_context(&telnet_context
);
870 if (code
!= 0 && auth_debug
)
872 "Cannot initialize Kerberos V5: %s",
873 error_message(code
));
880 auth_name(uchar_t
*data
, int cnt
)
882 char namebuf
[MAXPRINCLEN
];
886 (void) fprintf(stderr
,
887 "\t(auth_name) Empty NAME in auth "
891 if (cnt
> sizeof (namebuf
)-1) {
893 (void) fprintf(stderr
,
894 "\t(auth_name) NAME exceeds %d bytes\n",
898 (void) memcpy((void *)namebuf
, (void *)data
, cnt
);
901 (void) fprintf(stderr
, "\t(auth_name) name [%s]\n", namebuf
);
902 AuthenticatingUser
= (char *)strdup(namebuf
);
906 auth_is(uchar_t
*data
, int cnt
)
908 AuthInfo
*aptr
= auth_list
;
914 * We failed to negoiate secure authentication
916 if (data
[0] == AUTHTYPE_NULL
) {
917 auth_finished(0, AUTH_REJECT
);
921 while (aptr
->AuthName
!= 0 &&
922 (aptr
->AuthName
!= data
[0] || aptr
->AuthHow
!= data
[1]))
927 (void) fprintf(stderr
, "\t(auth_is) auth type is %s "
928 "(%d bytes)\n", aptr
->AuthString
, cnt
);
930 if (aptr
->AuthName
== AUTHTYPE_KERBEROS_V5
)
931 kerberos5_is(aptr
, data
+2, cnt
-2);
936 krb5_user_status(char *name
, int namelen
, int level
)
938 int retval
= AUTH_USER
;
941 (void) fprintf(stderr
, "\t(krb5_user_status) level = %d "
942 "auth_level = %d user = %s\n",
944 (AuthenticatingUser
!= NULL
? AuthenticatingUser
: ""));
946 if (level
< AUTH_USER
)
949 if (AuthenticatingUser
!= NULL
&&
950 (retval
= krb5_kuserok(telnet_context
, ticket
->enc_part2
->client
,
951 AuthenticatingUser
))) {
952 (void) strncpy(name
, AuthenticatingUser
, namelen
);
957 "Krb5 principal lacks permission to "
958 "access local account for %s",
965 * Wrapper around /dev/urandom
968 getrandom(char *buf
, int buflen
)
970 static int devrandom
= -1;
972 if (devrandom
== -1 &&
973 (devrandom
= open("/dev/urandom", O_RDONLY
)) == -1) {
974 fatalperror(net
, "Unable to open /dev/urandom: ",
979 if (read(devrandom
, buf
, buflen
) == -1) {
980 fatalperror(net
, "Unable to read from /dev/urandom: ",
991 * Initialize the encryption data structures
996 (void) memset(&encr_data
.encrypt
, 0, sizeof (cipher_info_t
));
997 (void) memset(&encr_data
.decrypt
, 0, sizeof (cipher_info_t
));
999 encr_data
.encrypt
.state
= ENCR_STATE_NOT_READY
;
1000 encr_data
.decrypt
.state
= ENCR_STATE_NOT_READY
;
1004 * encrypt_send_request_start
1006 * Request that the remote side automatically start sending
1010 encrypt_send_request_start()
1012 uchar_t buf
[6+TELNET_MAXKEYIDLEN
], *p
;
1018 *p
++ = TELOPT_ENCRYPT
;
1019 *p
++ = ENCRYPT_REQSTART
;
1021 * We are telling the remote side which
1022 * decrypt key we will use so that it may
1023 * encrypt in the same key.
1025 (void) memcpy(p
, encr_data
.decrypt
.keyid
, encr_data
.decrypt
.keyidlen
);
1026 p
+= encr_data
.decrypt
.keyidlen
;
1031 write_data_len((const char *)buf
, p
-buf
);
1034 (void) fprintf(stderr
,
1035 "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
1041 * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
1042 * message, the client is telling us that it will be sending
1043 * encrypted data using the indicated cipher.
1044 * We must initialize the read (decrypt) side of our connection
1047 encrypt_is(uchar_t
*data
, int cnt
)
1050 register int iv_status
= CFB64_IV_OK
;
1051 register int lstate
= 0;
1056 (uchar_t
)TELOPT_ENCRYPT
,
1057 (uchar_t
)ENCRYPT_REPLY
,
1058 (uchar_t
)0, /* placeholder: sbbuf[4] */
1059 (uchar_t
)CFB64_IV_OK
, /* placeholder: sbbuf[5] */
1067 type
= sbbuf
[4] = *data
++;
1071 * 1. Create the proper stream Initialization vector
1072 * - copy the correct 'seed' to IV and output blocks
1073 * - set the correct key schedule
1074 * 2. Generate reply for the other side:
1075 * IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
1076 * [ data ... ] IAC SE
1077 * 3. Tell crypto module: method, direction, IV
1080 case TELOPT_ENCTYPE_DES_CFB64
:
1081 encr_data
.decrypt
.type
= type
;
1083 lstate
= encr_data
.decrypt
.state
;
1085 (void) fprintf(stderr
,
1086 "\t(encrypt_is) initial state = %d\n",
1089 * Before we extract the IV bytes, make sure we got
1092 if (cnt
< sizeof (Block
)) {
1093 iv_status
= CFB64_IV_BAD
;
1095 (void) fprintf(stderr
,
1096 "\t(encrypt_is) Not enough "
1098 lstate
= ENCR_STATE_NOT_READY
;
1100 data
++; /* skip over the CFB64_IV byte */
1101 (void) memcpy(encr_data
.decrypt
.ivec
, data
,
1103 lstate
= ENCR_STATE_IN_PROGRESS
;
1106 case TELOPT_ENCTYPE_NULL
:
1107 encr_data
.decrypt
.type
= type
;
1108 lstate
&= ~ENCR_STATE_NO_RECV_IV
;
1109 lstate
&= ~ENCR_STATE_NO_SEND_IV
;
1111 (void) fprintf(stderr
,
1112 "\t(encrypt_is) We accept NULL encr\n");
1115 iv_status
= CFB64_IV_BAD
;
1116 encr_data
.decrypt
.type
= 0;
1118 (void) fprintf(stderr
,
1119 "\t(encrypt_is) Can't find type (%d) "
1120 "for initial negotiation\r\n",
1122 lstate
= ENCR_STATE_NOT_READY
;
1126 sbbuf
[5] = (uchar_t
)iv_status
; /* either CFB64_IV_OK or BAD */
1128 if (iv_status
== CFB64_IV_OK
) {
1130 * send IV to crypto module and indicate it is for
1133 lstate
&= ~ENCR_STATE_NO_RECV_IV
; /* we received an OK IV */
1134 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we dont send an IV */
1136 /* tell crypto module to disable crypto on "read" stream */
1137 lstate
= ENCR_STATE_NOT_READY
;
1140 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
1142 #ifdef ENCRYPT_NAMES
1144 (void) fprintf(stderr
,
1145 "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
1147 (iv_status
== CFB64_IV_OK
? "CFB64_IV_OK" :
1149 #endif /* ENCRYPT_NAMES */
1150 /* Update the state of the decryption negotiation */
1151 encr_data
.decrypt
.state
= lstate
;
1153 if (lstate
== ENCR_STATE_NOT_READY
)
1154 encr_data
.decrypt
.autoflag
= 0;
1156 if (lstate
== ENCR_STATE_OK
&& encr_data
.decrypt
.autoflag
)
1157 encrypt_send_request_start();
1160 (void) fprintf(stderr
,
1161 "\t(encrypt_is) final DECRYPT state = %d\n",
1162 encr_data
.decrypt
.state
);
1166 * encrypt_send_encrypt_is
1168 * Tell the client what encryption we will use
1169 * and what our IV will be.
1172 encrypt_send_encrypt_is()
1174 register int lstate
;
1175 krb5_error_code kret
;
1176 uchar_t sbbuf
[MAXOPTLEN
], *p
;
1179 lstate
= encr_data
.encrypt
.state
;
1181 if (encr_data
.encrypt
.type
== ENCTYPE_NULL
) {
1183 * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
1190 * - Create a random DES key
1193 * encrypt the IV using itself as the key.
1196 * IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
1200 if (lstate
== ENCR_STATE_NOT_READY
)
1201 lstate
= ENCR_STATE_IN_PROGRESS
;
1202 else if ((lstate
& ENCR_STATE_NO_SEND_IV
) == 0) {
1204 (void) fprintf(stderr
,
1205 "\t(encrypt_send_is) IV already sent,"
1206 " state = %d\n", lstate
);
1210 if (!VALIDKEY(encr_data
.encrypt
.krbdes_key
)) {
1212 * Invalid key, set flag so we try again later
1213 * when we get a good one
1215 encr_data
.encrypt
.need_start
= 1;
1217 (void) fprintf(stderr
,
1218 "\t(encrypt_send_is) No Key, cannot "
1219 "start encryption yet\n");
1223 (void) fprintf(stderr
,
1224 "\t(encrypt_send_is) Creating new feed\n");
1227 * Create a random feed and send it over.
1229 * Use the /dev/[u]random interface to generate
1230 * our encryption IV.
1232 kret
= getrandom((char *)encr_data
.encrypt
.ivec
, sizeof (Block
));
1236 (void) fprintf(stderr
,
1237 "\t(encrypt_send_is) error from "
1238 "getrandom: %d\n", kret
);
1239 syslog(LOG_ERR
, "Failed to create encryption key (err %d)\n");
1240 encr_data
.encrypt
.type
= ENCTYPE_NULL
;
1242 mit_des_fixup_key_parity(encr_data
.encrypt
.ivec
);
1248 *p
++ = TELOPT_ENCRYPT
;
1250 *p
++ = encr_data
.encrypt
.type
;
1254 * Copy the IV bytes individually so that when a
1255 * 255 (telnet IAC) is used, it can be "escaped" by
1256 * adding it twice (telnet RFC 854).
1258 for (i
= 0; i
< sizeof (Block
); i
++)
1259 if ((*p
++ = encr_data
.encrypt
.ivec
[i
]) == IAC
)
1264 write_data_len((const char *)sbbuf
, (size_t)(p
-sbbuf
));
1268 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we sent our IV */
1269 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* dont need decrypt IV */
1271 encr_data
.encrypt
.state
= lstate
;
1275 (void) fprintf(stderr
,
1276 "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
1277 encr_data
.encrypt
.type
);
1278 for (i
= 0; i
< (p
-sbbuf
); i
++)
1279 (void) fprintf(stderr
, "%d ", (int)sbbuf
[i
]);
1280 (void) fprintf(stderr
, "\n");
1289 * Utility routine to send a CRIOCSTOP ioctl to the
1290 * crypto module (cryptmod).
1293 stop_stream(int fd
, int dir
)
1295 struct strioctl crioc
;
1296 uint32_t stopdir
= dir
;
1298 crioc
.ic_cmd
= CRYPTIOCSTOP
;
1299 crioc
.ic_timout
= -1;
1300 crioc
.ic_len
= sizeof (stopdir
);
1301 crioc
.ic_dp
= (char *)&stopdir
;
1303 if (ioctl(fd
, I_STR
, &crioc
)) {
1304 syslog(LOG_ERR
, "Error sending CRYPTIOCSTOP ioctl: %m");
1311 * Utility routine to send a CRYPTIOCSTART ioctl to the
1312 * crypto module (cryptmod). This routine may contain optional
1313 * payload data that the cryptmod will interpret as bytes that
1314 * need to be decrypted and sent back up to the application
1315 * via the data stream.
1318 start_stream(int fd
, int dir
, int datalen
, char *data
)
1320 struct strioctl crioc
;
1322 crioc
.ic_cmd
= (dir
== CRYPT_ENCRYPT
? CRYPTIOCSTARTENC
:
1324 crioc
.ic_timout
= -1;
1325 crioc
.ic_len
= datalen
;
1328 if (ioctl(fd
, I_STR
, &crioc
)) {
1329 syslog(LOG_ERR
, "Error sending CRYPTIOCSTART ioctl: %m");
1334 * encrypt_start_output
1336 * Tell the other side to start encrypting its data
1339 encrypt_start_output()
1343 uchar_t sbbuf
[MAXOPTLEN
];
1344 struct strioctl crioc
;
1345 struct cr_info_t cki
;
1348 * Initialize crypto and send the ENCRYPT_IS msg
1350 lstate
= encrypt_send_encrypt_is();
1352 if (lstate
!= ENCR_STATE_OK
) {
1354 (void) fprintf(stderr
,
1355 "\t(encrypt_start_output) ENCRYPT state "
1364 *p
++ = TELOPT_ENCRYPT
;
1365 *p
++ = ENCRYPT_START
;
1367 (void) memcpy(p
, encr_data
.encrypt
.keyid
, encr_data
.encrypt
.keyidlen
);
1368 p
+= encr_data
.encrypt
.keyidlen
;
1373 /* Flush this data out before we start encrypting */
1374 write_data_len((const char *)sbbuf
, (int)(p
-sbbuf
));
1378 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
1379 "(lstate = %d) data waiting = %d\n",
1380 (int)encr_data
.encrypt
.keyid
[0],
1381 lstate
, nfrontp
-nbackp
);
1383 encr_data
.encrypt
.state
= lstate
;
1386 * tell crypto module what key to use for encrypting
1387 * Note that the ENCRYPT has not yet been enabled, but we
1388 * need to first set the crypto key to use.
1390 cki
.direction_mask
= CRYPT_ENCRYPT
;
1392 if (encr_data
.encrypt
.type
== TELOPT_ENCTYPE_DES_CFB64
) {
1393 cki
.crypto_method
= CRYPT_METHOD_DES_CFB
;
1396 (void) fprintf(stderr
,
1397 "\t(encrypt_start_output) - unknown "
1398 "crypto_method %d\n",
1399 encr_data
.encrypt
.type
);
1400 syslog(LOG_ERR
, "unrecognized crypto encrypt method: %d",
1401 encr_data
.encrypt
.type
);
1407 * If we previously configured this crypto method, we dont want to
1408 * overwrite the key or ivec information already given to the crypto
1409 * module as it will cause the cipher data between the client and server
1410 * to become out of synch and impossible to decipher.
1412 if (encr_data
.encrypt
.setup
== cki
.crypto_method
) {
1416 cki
.keylen
= DES_BLOCKSIZE
;
1417 (void) memcpy(cki
.key
, (void *)encr_data
.encrypt
.krbdes_key
,
1420 cki
.iveclen
= DES_BLOCKSIZE
;
1421 (void) memcpy(cki
.ivec
, (void *)encr_data
.encrypt
.ivec
,
1424 cki
.ivec_usage
= IVEC_ONETIME
;
1427 cki
.option_mask
= 0;
1429 /* Stop encrypt side prior to setup so we dont lose data */
1430 stop_stream(cryptmod_fd
, CRYPT_ENCRYPT
);
1432 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1433 crioc
.ic_timout
= -1;
1434 crioc
.ic_len
= sizeof (struct cr_info_t
);
1435 crioc
.ic_dp
= (char *)&cki
;
1437 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1438 perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
1440 /* Setup completed OK */
1441 encr_data
.encrypt
.setup
= cki
.crypto_method
;
1445 * We do not check for "stuck" data when setting up the
1446 * outbound "encrypt" channel. Any data queued prior to
1447 * this IOCTL will get processed correctly without our help.
1449 start_stream(cryptmod_fd
, CRYPT_ENCRYPT
, 0, NULL
);
1452 * tell crypto module to start encrypting
1455 (void) fprintf(stderr
,
1456 "\t(encrypt_start_output) Encrypting output\n");
1460 * encrypt_request_start
1462 * The client requests that we start encryption immediately after
1463 * successful negotiation
1466 encrypt_request_start(void)
1468 if (encr_data
.encrypt
.type
== ENCTYPE_NULL
) {
1469 encr_data
.encrypt
.autoflag
= 1;
1471 (void) fprintf(stderr
, "\t(encrypt_request_start) "
1472 "autoencrypt = ON\n");
1474 encrypt_start_output();
1481 * ENCRYPT END received, stop decrypting the read stream
1484 encrypt_end(int direction
)
1486 struct cr_info_t cki
;
1487 struct strioctl crioc
;
1490 stopdir
= (direction
== TELNET_DIR_DECRYPT
? CRYPT_DECRYPT
:
1493 stop_stream(cryptmod_fd
, stopdir
);
1496 * Call this function when we wish to disable crypto in
1497 * either direction (ENCRYPT or DECRYPT)
1499 cki
.direction_mask
= (direction
== TELNET_DIR_DECRYPT
? CRYPT_DECRYPT
:
1501 cki
.crypto_method
= CRYPT_METHOD_NONE
;
1502 cki
.option_mask
= 0;
1506 cki
.ivec_usage
= IVEC_ONETIME
;
1508 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1509 crioc
.ic_timout
= -1;
1510 crioc
.ic_len
= sizeof (cki
);
1511 crioc
.ic_dp
= (char *)&cki
;
1513 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1514 perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
1517 start_stream(cryptmod_fd
, stopdir
, 0, NULL
);
1521 * encrypt_request_end
1523 * When we receive a REQEND from the client, it means
1524 * that we are supposed to stop encrypting
1527 encrypt_request_end()
1530 * Tell the other side we are done encrypting
1533 write_data("%c%c%c%c%c%c",
1536 (uchar_t
)TELOPT_ENCRYPT
,
1537 (uchar_t
)ENCRYPT_END
,
1542 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
1545 * Turn off encryption of the write stream
1547 encrypt_end(TELNET_DIR_ENCRYPT
);
1551 * encrypt_send_request_end
1553 * We stop encrypting the write stream and tell the other side about it.
1556 encrypt_send_request_end()
1558 write_data("%c%c%c%c%c%c",
1561 (uchar_t
)TELOPT_ENCRYPT
,
1562 (uchar_t
)ENCRYPT_REQEND
,
1567 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
1573 * The client is going to start sending encrypted data
1574 * using the previously negotiated cipher (see what we set
1575 * when we did the REPLY in encrypt_is).
1580 struct cr_info_t cki
;
1581 struct strioctl crioc
;
1583 char *dataptr
= NULL
;
1585 if (encr_data
.decrypt
.type
== ENCTYPE_NULL
) {
1587 (void) fprintf(stderr
,
1588 "\t(encrypt_start) No DECRYPT method "
1590 encrypt_send_request_end();
1594 cki
.direction_mask
= CRYPT_DECRYPT
;
1596 if (encr_data
.decrypt
.type
== TELOPT_ENCTYPE_DES_CFB64
) {
1597 cki
.crypto_method
= CRYPT_METHOD_DES_CFB
;
1600 (void) fprintf(stderr
,
1601 "\t(encrypt_start) - unknown "
1602 "crypto_method %d\n", encr_data
.decrypt
.type
);
1604 syslog(LOG_ERR
, "unrecognized crypto decrypt method: %d",
1605 encr_data
.decrypt
.type
);
1611 * Don't overwrite previously configured key and ivec info
1613 if (encr_data
.decrypt
.setup
!= cki
.crypto_method
) {
1614 (void) memcpy(cki
.key
, (void *)encr_data
.decrypt
.krbdes_key
,
1616 (void) memcpy(cki
.ivec
, (void *)encr_data
.decrypt
.ivec
,
1619 cki
.keylen
= DES_BLOCKSIZE
;
1620 cki
.iveclen
= DES_BLOCKSIZE
;
1621 cki
.ivec_usage
= IVEC_ONETIME
;
1626 cki
.option_mask
= 0;
1628 stop_stream(cryptmod_fd
, CRYPT_DECRYPT
);
1630 crioc
.ic_cmd
= CRYPTIOCSETUP
;
1631 crioc
.ic_timout
= -1;
1632 crioc
.ic_len
= sizeof (struct cr_info_t
);
1633 crioc
.ic_dp
= (char *)&cki
;
1635 if (ioctl(cryptmod_fd
, I_STR
, &crioc
)) {
1636 syslog(LOG_ERR
, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
1639 encr_data
.decrypt
.setup
= cki
.crypto_method
;
1642 (void) fprintf(stderr
,
1643 "\t(encrypt_start) called CRYPTIOCSETUP for "
1647 * Read any data stuck between the cryptmod and the application
1648 * so we can pass it back down to be properly decrypted after
1649 * this operation finishes.
1651 if (ioctl(cryptmod_fd
, I_NREAD
, &bytes
) < 0) {
1652 syslog(LOG_ERR
, "I_NREAD returned error %m");
1657 * Any data which was read AFTER the ENCRYPT START message
1658 * must be sent back down to be decrypted properly.
1660 * 'ncc' is the number of bytes that have been read but
1661 * not yet processed by the telnet state machine.
1663 * 'bytes' is the number of bytes waiting to be read from
1666 * If either one is a positive value, then those bytes
1667 * must be pulled up and sent back down to be decrypted.
1672 (void) fprintf(stderr
,
1673 "\t(encrypt_start) after drainstream, "
1674 "ncc=%d bytes = %d\n", ncc
, bytes
);
1679 start_stream(cryptmod_fd
, CRYPT_DECRYPT
, bytes
, dataptr
);
1682 * The bytes putback into the stream are no longer
1683 * available to be read by the server, so adjust the
1684 * counter accordingly.
1688 (void) memset(netip
, 0, netibufsize
);
1690 #ifdef ENCRYPT_NAMES
1692 (void) fprintf(stderr
,
1693 "\t(encrypt_start) Start DECRYPT using %s\n",
1694 ENCTYPE_NAME(encr_data
.decrypt
.type
));
1696 #endif /* ENCRYPT_NAMES */
1702 * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
1703 * message from a client.
1705 * Choose an agreeable method (DES_CFB64) and
1706 * respond with TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
1711 encrypt_support(char *data
, int cnt
)
1713 int lstate
= ENCR_STATE_NOT_READY
;
1714 int type
, use_type
= 0;
1716 while (cnt
-- > 0 && use_type
== 0) {
1718 #ifdef ENCRYPT_NAMES
1720 (void) fprintf(stderr
,
1721 "RCVD ENCRYPT SUPPORT %s\n",
1722 ENCTYPE_NAME(type
));
1723 #endif /* ENCRYPT_NAMES */
1727 if (type
== TELOPT_ENCTYPE_DES_CFB64
) {
1731 encr_data
.encrypt
.type
= use_type
;
1733 if (use_type
!= TELOPT_ENCTYPE_NULL
&&
1734 authenticated
!= NULL
&& authenticated
!= &NoAuth
&&
1735 auth_status
!= AUTH_REJECT
) {
1737 /* Authenticated -> have session key -> send ENCRYPT IS */
1738 lstate
= encrypt_send_encrypt_is();
1739 if (lstate
== ENCR_STATE_OK
)
1740 encrypt_start_output();
1741 } else if (use_type
== TELOPT_ENCTYPE_NULL
) {
1743 (void) fprintf(stderr
,
1744 "\t(encrypt_support) Cannot agree "
1745 "on crypto algorithm, output encryption "
1749 * Cannot agree on crypto algorithm
1751 * send "IAC SB ENCRYPT IS NULL IAC SE"
1752 * optionally, also send IAC WONT ENCRYPT
1754 write_data("%c%c%c%c%c%c%c",
1757 (uchar_t
)TELOPT_ENCRYPT
,
1758 (uchar_t
)ENCRYPT_IS
,
1759 (uchar_t
)TELOPT_ENCTYPE_NULL
,
1762 send_wont(TELOPT_ENCRYPT
);
1765 (void) fprintf(stderr
,
1766 "SENT TELOPT_ENCRYPT ENCRYPT_IS "
1769 remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
1771 settimer(encr_support
);
1775 * encrypt_send_keyid
1777 * Sent the key id we will use to the client
1780 encrypt_send_keyid(int dir
, uchar_t
*keyid
, int keylen
, boolean_t saveit
)
1782 uchar_t sbbuf
[128], *p
;
1788 *p
++ = TELOPT_ENCRYPT
;
1789 *p
++ = (dir
== TELNET_DIR_ENCRYPT
? ENCRYPT_ENC_KEYID
:
1793 (void) fprintf(stderr
,
1794 "\t(send_keyid) store %d byte %s keyid\n",
1796 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1799 if (dir
== TELNET_DIR_ENCRYPT
) {
1800 (void) memcpy(encr_data
.encrypt
.keyid
, keyid
, keylen
);
1801 encr_data
.encrypt
.keyidlen
= keylen
;
1803 (void) memcpy(encr_data
.decrypt
.keyid
, keyid
, keylen
);
1804 encr_data
.decrypt
.keyidlen
= keylen
;
1807 (void) memcpy(p
, keyid
, keylen
);
1812 write_data_len((const char *)sbbuf
, (size_t)(p
-sbbuf
));
1816 (void) fprintf(stderr
, "SENT TELOPT_ENCRYPT %s %d\n",
1817 (dir
== TELNET_DIR_ENCRYPT
? "ENC_KEYID" :
1818 "DEC_KEYID"), keyid
[0]);
1824 * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
1825 * message, process it accordingly.
1826 * If the vector is acceptable, tell client we are encrypting and
1827 * enable encryption on our write stream.
1829 * Negotiate the KEYID next..
1833 encrypt_reply(char *data
, int len
)
1835 uchar_t type
= (uchar_t
)(*data
++);
1836 uchar_t result
= (uchar_t
)(*data
);
1839 #ifdef ENCRYPT_NAMES
1841 (void) fprintf(stderr
,
1842 "\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
1844 (result
== CFB64_IV_OK
? "CFB64_IV_OK" :
1845 "CFB64_IV_BAD"), len
);
1846 #endif /* ENCRYPT_NAMES */
1848 lstate
= encr_data
.encrypt
.state
;
1850 (void) fprintf(stderr
,
1851 "\t(encrypt_reply) initial ENCRYPT state = %d\n",
1855 if (lstate
== ENCR_STATE_NOT_READY
)
1856 lstate
= ENCR_STATE_IN_PROGRESS
;
1857 lstate
&= ~ENCR_STATE_NO_RECV_IV
; /* we got the IV */
1858 lstate
&= ~ENCR_STATE_NO_SEND_IV
; /* we dont need to send IV */
1861 * The correct response here is to send the encryption key id
1864 * Send keyid 0 to indicate that we will just use default
1867 encrypt_send_keyid(TELNET_DIR_ENCRYPT
, (uchar_t
*)"\0", 1, 1);
1874 (void) memset(encr_data
.encrypt
.ivec
, 0, sizeof (Block
));
1875 lstate
= ENCR_STATE_NOT_READY
;
1879 (void) fprintf(stderr
,
1880 "\t(encrypt_reply) Got unknown IV value in "
1882 lstate
= ENCR_STATE_NOT_READY
;
1886 encr_data
.encrypt
.state
= lstate
;
1887 if (lstate
== ENCR_STATE_NOT_READY
) {
1888 encr_data
.encrypt
.autoflag
= 0;
1889 encr_data
.encrypt
.type
= ENCTYPE_NULL
;
1891 (void) fprintf(stderr
,
1892 "\t(encrypt_reply) encrypt.autoflag = "
1895 encr_data
.encrypt
.type
= type
;
1896 if ((lstate
== ENCR_STATE_OK
) && encr_data
.encrypt
.autoflag
)
1897 encrypt_start_output();
1901 (void) fprintf(stderr
,
1902 "\t(encrypt_reply) ENCRYPT final state = %d\n",
1907 encrypt_set_keyid_state(uchar_t
*keyid
, int *keyidlen
, int dir
)
1911 lstate
= (dir
== TELNET_DIR_ENCRYPT
? encr_data
.encrypt
.state
:
1912 encr_data
.decrypt
.state
);
1915 (void) fprintf(stderr
,
1916 "\t(set_keyid_state) %s initial state = %d\n",
1917 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1918 "DECRYPT"), lstate
);
1921 * Currently, we only support using the default keyid,
1922 * so it should be an error if the len > 1 or the keyid != 0.
1924 if (*keyidlen
!= 1 || (*keyid
!= '\0')) {
1926 (void) fprintf(stderr
,
1927 "\t(set_keyid_state) unexpected keyid: "
1928 "len=%d value=%d\n", *keyidlen
, *keyid
);
1930 syslog(LOG_ERR
, "rcvd unexpected keyid %d - only keyid of 0 "
1931 "is supported", *keyid
);
1934 * We move to the "IN_PROGRESS" state.
1936 if (lstate
== ENCR_STATE_NOT_READY
)
1937 lstate
= ENCR_STATE_IN_PROGRESS
;
1939 * Clear the NO_KEYID bit because we now have a valid keyid
1941 lstate
&= ~ENCR_STATE_NO_KEYID
;
1945 (void) fprintf(stderr
,
1946 "\t(set_keyid_state) %s final state = %d\n",
1947 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1948 "DECRYPT"), lstate
);
1950 if (dir
== TELNET_DIR_ENCRYPT
)
1951 encr_data
.encrypt
.state
= lstate
;
1953 encr_data
.decrypt
.state
= lstate
;
1959 * Set the keyid value in the key_info structure.
1960 * if necessary send a response to the sender
1963 encrypt_keyid(uchar_t
*newkeyid
, int *keyidlen
, uchar_t
*keyid
,
1966 if (len
> TELNET_MAXNUMKEYS
) {
1968 (void) fprintf(stderr
,
1969 "\t(keyid) keylen too big (%d)\n", len
);
1974 (void) fprintf(stderr
, "\t(keyid) set KEYID for %s len = %d\n",
1975 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
1980 if (*keyidlen
== 0) {
1982 (void) fprintf(stderr
,
1983 "\t(keyid) Got 0 length keyid - "
1988 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
1990 } else if (len
!= *keyidlen
|| memcmp(keyid
, newkeyid
, len
)) {
1992 (void) fprintf(stderr
,
1993 "\t(keyid) Setting new key (%d bytes)\n",
1997 (void) memcpy(newkeyid
, keyid
, len
);
1999 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
2001 encrypt_set_keyid_state(newkeyid
, keyidlen
, dir
);
2004 (void) fprintf(stderr
,
2005 "\t(keyid) %s Key already in place,"
2006 "state = %d autoflag=%d\n",
2007 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" : "DECRYPT"),
2008 (dir
== TELNET_DIR_ENCRYPT
? encr_data
.encrypt
.state
:
2009 encr_data
.decrypt
.state
),
2010 (dir
== TELNET_DIR_ENCRYPT
?
2011 encr_data
.encrypt
.autoflag
:
2012 encr_data
.decrypt
.autoflag
));
2014 /* key already in place */
2015 if ((encr_data
.encrypt
.state
== ENCR_STATE_OK
) &&
2016 dir
== TELNET_DIR_ENCRYPT
&& encr_data
.encrypt
.autoflag
) {
2017 encrypt_start_output();
2023 (void) fprintf(stderr
, "\t(keyid) %s final state = %d\n",
2024 (dir
== TELNET_DIR_ENCRYPT
? "ENCRYPT" :
2026 (dir
== TELNET_DIR_ENCRYPT
?
2027 encr_data
.encrypt
.state
:
2028 encr_data
.decrypt
.state
));
2030 encrypt_send_keyid(dir
, newkeyid
, *keyidlen
, 0);
2036 * We received the ENC_KEYID message from a client indicating that
2037 * the client wishes to verify that the indicated keyid maps to a
2041 encrypt_enc_keyid(char *data
, int cnt
)
2044 * Verify the decrypt keyid is valid
2046 encrypt_keyid(encr_data
.decrypt
.keyid
, &encr_data
.decrypt
.keyidlen
,
2047 (uchar_t
*)data
, cnt
, TELNET_DIR_DECRYPT
);
2053 * We received the DEC_KEYID message from a client indicating that
2054 * the client wants to verify that the indicated keyid maps to a valid key.
2057 encrypt_dec_keyid(char *data
, int cnt
)
2059 encrypt_keyid(encr_data
.encrypt
.keyid
, &encr_data
.encrypt
.keyidlen
,
2060 (uchar_t
*)data
, cnt
, TELNET_DIR_ENCRYPT
);
2064 * encrypt_session_key
2066 * Store the session key in the encryption data record
2069 encrypt_session_key(Session_Key
*key
, cipher_info_t
*cinfo
)
2071 if (key
== NULL
|| key
->type
!= SK_DES
) {
2073 (void) fprintf(stderr
,
2074 "\t(session_key) Cannot set krb5 "
2075 "session key (unknown type = %d)\n",
2076 key
? key
->type
: -1);
2079 (void) fprintf(stderr
,
2080 "\t(session_key) Settting session key "
2083 /* store the key in the cipher info data struct */
2084 (void) memcpy(cinfo
->krbdes_key
, (void *)key
->data
, sizeof (Block
));
2087 * Now look to see if we still need to send the key and start
2090 * If so, go ahead an call it now that we have the key.
2092 if (cinfo
->need_start
) {
2093 if (encrypt_send_encrypt_is() == ENCR_STATE_OK
) {
2094 cinfo
->need_start
= 0;
2102 * Used to add an environment variable and value to the
2103 * linked list structure.
2106 new_env(const char *name
, const char *value
)
2108 struct envlist
*env
;
2110 env
= malloc(sizeof (struct envlist
));
2113 if ((env
->name
= strdup(name
)) == NULL
) {
2117 if ((env
->value
= strdup(value
)) == NULL
) {
2123 env
->next
= envlist_head
;
2131 * Used to delete an environment variable from the linked list
2132 * structure. We just set a flag because we will delete the list
2133 * anyway before we exec login.
2136 del_env(const char *name
)
2138 struct envlist
*env
;
2140 for (env
= envlist_head
; env
; env
= env
->next
) {
2141 if (strcmp(env
->name
, name
) == 0) {
2154 if (fstat(fd
, &stats
) == -1)
2156 return (S_ISSOCK(stats
.st_mode
));
2161 main(int argc
, char *argv
[])
2163 struct sockaddr_storage from
;
2168 ushort_t porttouse
= 0;
2169 boolean_t standalone
= 0;
2170 #endif /* defined(DEBUG) */
2171 extern char *optarg
;
2175 while ((c
= getopt(argc
, argv
, TELNETD_OPTS DEBUG_OPTS
)) != -1) {
2180 * note: alternative port number only used in
2183 porttouse
= atoi(optarg
);
2191 if (strcasecmp(optarg
, "none") == 0) {
2193 } else if (strcasecmp(optarg
, "user") == 0) {
2194 auth_level
= AUTH_USER
;
2195 } else if (strcasecmp(optarg
, "valid") == 0) {
2196 auth_level
= AUTH_VALID
;
2197 } else if (strcasecmp(optarg
, "off") == 0) {
2199 negotiate_auth_krb5
= 0;
2200 } else if (strcasecmp(optarg
, "debug") == 0) {
2204 "unknown authentication level specified "
2205 "with \'-a\' option (%s)", optarg
);
2206 auth_level
= AUTH_USER
;
2210 /* disable authentication negotiation */
2211 negotiate_auth_krb5
= 0;
2215 if (optarg
!= NULL
) {
2216 int ret
= krb5_init();
2219 "Unable to use Kerberos V5 as "
2220 "requested, exiting");
2223 (void) krb5_set_default_realm(telnet_context
,
2226 "using %s as default KRB5 realm", optarg
);
2230 telnet_srvtab
= (char *)strdup(optarg
);
2232 case 'E': /* disable automatic encryption */
2233 negotiate_encrypt
= B_FALSE
;
2236 resolve_hostname
= 1;
2239 if (optarg
== NULL
|| (tos
= atoi(optarg
)) < 0 ||
2241 syslog(LOG_ERR
, "telnetd: illegal tos value: "
2252 syslog(LOG_ERR
, "telnetd: illegal cmd line option %c",
2258 netibufsize
= BUFSIZ
;
2259 if (!(netibuf
= (char *)malloc(netibufsize
)))
2260 syslog(LOG_ERR
, "netibuf malloc failed\n");
2261 (void) memset(netibuf
, 0, netibufsize
);
2268 static struct sockaddr_in6 sin6
= { AF_INET6
};
2272 sin6
.sin6_port
= htons(porttouse
);
2274 sp
= getservbyname("telnet", "tcp");
2276 (void) fprintf(stderr
,
2277 "telnetd: tcp/telnet: "
2278 "unknown service\n");
2281 sin6
.sin6_port
= sp
->s_port
;
2284 s
= socket(AF_INET6
, SOCK_STREAM
, IPPROTO_TCP
);
2286 perror("telnetd: socket");
2289 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, (char *)&option
,
2290 sizeof (option
)) == -1)
2291 perror("setsockopt SO_REUSEADDR");
2292 if (bind(s
, (struct sockaddr
*)&sin6
, sizeof (sin6
)) < 0) {
2296 if (listen(s
, 32) < 0) {
2301 /* automatically reap all child processes */
2302 (void) signal(SIGCHLD
, SIG_IGN
);
2307 foo
= sizeof (sin6
);
2308 ns
= accept(s
, (struct sockaddr
*)&sin6
, &foo
);
2321 (void) signal(SIGCHLD
, SIG_DFL
);
2327 #endif /* defined(DEBUG) */
2329 openlog("telnetd", LOG_PID
| LOG_ODELAY
, LOG_DAEMON
);
2331 issocket
= issock(0);
2333 fatal(0, "stdin is not a socket file descriptor");
2335 fromlen
= (socklen_t
)sizeof (from
);
2336 (void) memset((char *)&from
, 0, sizeof (from
));
2337 if (getpeername(0, (struct sockaddr
*)&from
, &fromlen
)
2339 (void) fprintf(stderr
, "%s: ", argv
[0]);
2340 perror("getpeername");
2341 _exit(EXIT_FAILURE
);
2344 if (setsockopt(0, SOL_SOCKET
, SO_KEEPALIVE
, (const char *)&on
,
2346 syslog(LOG_WARNING
, "setsockopt (SO_KEEPALIVE): %m");
2353 setsockopt(0, IPPROTO_IP
, IP_TOS
,
2354 (char *)&tos
, sizeof (tos
)) < 0 &&
2355 errno
!= ENOPROTOOPT
) {
2356 syslog(LOG_ERR
, "setsockopt (IP_TOS %d): %m", tos
);
2359 if (setsockopt(net
, SOL_SOCKET
, SO_OOBINLINE
, (char *)&on
,
2361 syslog(LOG_WARNING
, "setsockopt (SO_OOBINLINE): %m");
2364 /* set the default PAM service name */
2365 (void) strcpy(pam_svc_name
, "telnet");
2368 return (EXIT_SUCCESS
);
2371 static char *terminaltype
= 0;
2376 * A small subroutine to flush the network output buffer, get some data
2377 * from the network, and pass it through the telnet state machine. We
2378 * also flush the pty input buffer (by dropping its data) if it becomes
2384 if (nfrontp
-nbackp
) {
2388 ncc
= read(net
, netibuf
, netibufsize
);
2392 syslog(LOG_INFO
, "ttloop: read: %m");
2394 } else if (ncc
== 0) {
2395 syslog(LOG_INFO
, "ttloop: peer closed connection\n");
2400 telrcv(); /* state machine */
2402 pfrontp
= pbackp
= ptyobuf
;
2410 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)DO
, (uchar_t
)option
);
2414 send_will(int option
)
2416 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)WILL
, (uchar_t
)option
);
2420 send_wont(int option
)
2422 write_data("%c%c%c", (uchar_t
)IAC
, (uchar_t
)WONT
, (uchar_t
)option
);
2429 * Negotiate automatic authentication, is possible.
2432 getauthtype(char *username
, int *len
)
2434 int init_status
= -1;
2436 init_status
= krb5_init();
2438 if (auth_level
== -1 || init_status
!= 0) {
2439 remopts
[TELOPT_AUTHENTICATION
] = OPT_NO
;
2440 myopts
[TELOPT_AUTHENTICATION
] = OPT_NO
;
2441 negotiate_auth_krb5
= B_FALSE
;
2442 negotiate_encrypt
= B_FALSE
;
2443 return (AUTH_REJECT
);
2446 if (init_status
== 0 && auth_level
!= -1) {
2447 if (negotiate_auth_krb5
) {
2449 * Negotiate Authentication FIRST
2451 send_do(TELOPT_AUTHENTICATION
);
2452 remopts
[TELOPT_AUTHENTICATION
] =
2453 OPT_YES_BUT_ALWAYS_LOOK
;
2455 while (sequenceIs(authopt
, getauth
))
2458 if (remopts
[TELOPT_AUTHENTICATION
] == OPT_YES
) {
2460 * Request KRB5 Mutual authentication and if that fails,
2461 * KRB5 1-way client authentication
2463 uchar_t sbbuf
[MAXOPTLEN
], *p
;
2465 *p
++ = (uchar_t
)IAC
;
2467 *p
++ = (uchar_t
)TELOPT_AUTHENTICATION
;
2468 *p
++ = (uchar_t
)TELQUAL_SEND
;
2469 if (negotiate_auth_krb5
) {
2470 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2471 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2474 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2475 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2477 *p
++ = (uchar_t
)AUTHTYPE_KERBEROS_V5
;
2478 *p
++ = (uchar_t
)(AUTH_WHO_CLIENT
|
2481 *p
++ = (uchar_t
)AUTHTYPE_NULL
;
2483 *p
++ = (uchar_t
)IAC
;
2486 write_data_len((const char *)sbbuf
,
2487 (size_t)(p
- sbbuf
));
2490 (void) fprintf(stderr
,
2491 "SENT TELOPT_AUTHENTICATION "
2494 /* auth_wait returns the authentication level */
2495 /* status = auth_wait(username, len); */
2496 while (sequenceIs(authdone
, getauth
))
2499 * Now check to see if the user is valid or not
2501 if (authenticated
== NULL
|| authenticated
== &NoAuth
)
2502 auth_status
= AUTH_REJECT
;
2505 * We cant be VALID until the user status is
2508 if (auth_status
== AUTH_VALID
)
2509 auth_status
= AUTH_USER
;
2511 if (authenticated
->AuthName
==
2512 AUTHTYPE_KERBEROS_V5
)
2513 auth_status
= krb5_user_status(
2514 username
, *len
, auth_status
);
2518 return (auth_status
);
2524 if (krb5_privacy_allowed() && negotiate_encrypt
) {
2525 if (myopts
[TELOPT_ENCRYPT
] != OPT_YES
) {
2526 if (!sent_will_encrypt
) {
2527 send_will(TELOPT_ENCRYPT
);
2528 sent_will_encrypt
= B_TRUE
;
2531 (void) fprintf(stderr
, "SENT WILL ENCRYPT\n");
2533 if (remopts
[TELOPT_ENCRYPT
] != OPT_YES
) {
2534 if (!sent_do_encrypt
) {
2535 send_do(TELOPT_ENCRYPT
);
2536 sent_do_encrypt
= B_TRUE
;
2537 remopts
[TELOPT_ENCRYPT
] =
2538 OPT_YES_BUT_ALWAYS_LOOK
;
2541 (void) fprintf(stderr
, "SENT DO ENCRYPT\n");
2543 myopts
[TELOPT_ENCRYPT
] = OPT_YES
;
2545 while (sequenceIs(encropt
, getencr
))
2548 if (auth_status
!= AUTH_REJECT
&&
2549 remopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
2550 myopts
[TELOPT_ENCRYPT
] == OPT_YES
) {
2552 if (sent_encrypt_support
== B_FALSE
) {
2553 write_data("%c%c%c%c%c%c%c",
2556 (uchar_t
)TELOPT_ENCRYPT
,
2557 (uchar_t
)ENCRYPT_SUPPORT
,
2558 (uchar_t
)TELOPT_ENCTYPE_DES_CFB64
,
2565 * Now wait for a response to these messages before
2567 * Look for TELOPT_ENCRYPT suboptions
2569 while (sequenceIs(encr_support
, getencr
))
2573 /* Dont need responses to these, so dont wait for them */
2575 remopts
[TELOPT_ENCRYPT
] = OPT_NO
;
2576 myopts
[TELOPT_ENCRYPT
] = OPT_NO
;
2584 * Ask the other end to send along its terminal type.
2585 * Output is the variable terminaltype filled in.
2588 getterminaltype(void)
2591 * The remote side may have already sent this info, so
2592 * dont ask for these options if the other side already
2593 * sent the information.
2595 if (sequenceIs(ttypeopt
, getterminal
)) {
2596 send_do(TELOPT_TTYPE
);
2597 remopts
[TELOPT_TTYPE
] = OPT_YES_BUT_ALWAYS_LOOK
;
2600 if (sequenceIs(nawsopt
, getterminal
)) {
2601 send_do(TELOPT_NAWS
);
2602 remopts
[TELOPT_NAWS
] = OPT_YES_BUT_ALWAYS_LOOK
;
2605 if (sequenceIs(xdisplocopt
, getterminal
)) {
2606 send_do(TELOPT_XDISPLOC
);
2607 remopts
[TELOPT_XDISPLOC
] = OPT_YES_BUT_ALWAYS_LOOK
;
2610 if (sequenceIs(environopt
, getterminal
)) {
2611 send_do(TELOPT_NEW_ENVIRON
);
2612 remopts
[TELOPT_NEW_ENVIRON
] = OPT_YES_BUT_ALWAYS_LOOK
;
2615 if (sequenceIs(oenvironopt
, getterminal
)) {
2616 send_do(TELOPT_OLD_ENVIRON
);
2617 remopts
[TELOPT_OLD_ENVIRON
] = OPT_YES_BUT_ALWAYS_LOOK
;
2620 /* make sure encryption is started here */
2621 while (auth_status
!= AUTH_REJECT
&&
2622 authenticated
!= &NoAuth
&& authenticated
!= NULL
&&
2623 remopts
[TELOPT_ENCRYPT
] == OPT_YES
&&
2624 encr_data
.encrypt
.autoflag
&&
2625 encr_data
.encrypt
.state
!= ENCR_STATE_OK
) {
2627 (void) fprintf(stderr
, "getterminaltype() forcing encrypt\n");
2632 (void) fprintf(stderr
, "getterminaltype() encryption %sstarted\n",
2633 encr_data
.encrypt
.state
== ENCR_STATE_OK
? "" : "not ");
2636 while (sequenceIs(ttypeopt
, getterminal
) ||
2637 sequenceIs(nawsopt
, getterminal
) ||
2638 sequenceIs(xdisplocopt
, getterminal
) ||
2639 sequenceIs(environopt
, getterminal
) ||
2640 sequenceIs(oenvironopt
, getterminal
)) {
2645 if (remopts
[TELOPT_TTYPE
] == OPT_YES
) {
2646 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2647 (uchar_t
)TELOPT_TTYPE
, (uchar_t
)TELQUAL_SEND
,
2648 (uchar_t
)IAC
, (uchar_t
)SE
};
2650 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2652 if (remopts
[TELOPT_XDISPLOC
] == OPT_YES
) {
2653 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2654 (uchar_t
)TELOPT_XDISPLOC
, (uchar_t
)TELQUAL_SEND
,
2655 (uchar_t
)IAC
, (uchar_t
)SE
};
2657 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2659 if (remopts
[TELOPT_NEW_ENVIRON
] == OPT_YES
) {
2660 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2661 (uchar_t
)TELOPT_NEW_ENVIRON
, (uchar_t
)TELQUAL_SEND
,
2662 (uchar_t
)IAC
, (uchar_t
)SE
};
2664 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2666 if (remopts
[TELOPT_OLD_ENVIRON
] == OPT_YES
) {
2667 static uchar_t sbbuf
[] = { (uchar_t
)IAC
, (uchar_t
)SB
,
2668 (uchar_t
)TELOPT_OLD_ENVIRON
, (uchar_t
)TELQUAL_SEND
,
2669 (uchar_t
)IAC
, (uchar_t
)SE
};
2671 write_data_len((const char *)sbbuf
, sizeof (sbbuf
));
2674 if (remopts
[TELOPT_TTYPE
] == OPT_YES
) {
2675 while (sequenceIs(ttypesubopt
, getterminal
)) {
2679 if (remopts
[TELOPT_XDISPLOC
] == OPT_YES
) {
2680 while (sequenceIs(xdisplocsubopt
, getterminal
)) {
2684 if (remopts
[TELOPT_NEW_ENVIRON
] == OPT_YES
) {
2685 while (sequenceIs(environsubopt
, getterminal
)) {
2689 if (remopts
[TELOPT_OLD_ENVIRON
] == OPT_YES
) {
2690 while (sequenceIs(oenvironsubopt
, getterminal
)) {
2700 * Get a pty, scan input lines.
2703 doit(int f
, struct sockaddr_storage
*who
)
2706 char host_name
[MAXHOSTNAMELEN
];
2709 int ptmfd
; /* fd of logindmux connected to pty */
2710 int netfd
; /* fd of logindmux connected to netf */
2712 struct protocol_arg telnetp
;
2713 struct strioctl telnetmod
;
2714 struct envlist
*env
, *next
;
2716 char abuf
[INET6_ADDRSTRLEN
];
2717 struct sockaddr_in
*sin
;
2718 struct sockaddr_in6
*sin6
;
2720 char username
[MAXUSERNAMELEN
];
2725 if ((p
= open("/dev/ptmx", O_RDWR
| O_NOCTTY
)) == -1) {
2726 fatalperror(f
, "open /dev/ptmx", errno
);
2728 if (grantpt(p
) == -1)
2729 fatal(f
, "could not grant slave pty");
2730 if (unlockpt(p
) == -1)
2731 fatal(f
, "could not unlock slave pty");
2732 if ((slavename
= ptsname(p
)) == NULL
)
2733 fatal(f
, "could not enable slave pty");
2735 if ((t
= open(slavename
, O_RDWR
| O_NOCTTY
)) == -1)
2736 fatal(f
, "could not open slave pty");
2737 if (ioctl(t
, I_PUSH
, "ptem") == -1)
2738 fatalperror(f
, "ioctl I_PUSH ptem", errno
);
2739 if (ioctl(t
, I_PUSH
, "ldterm") == -1)
2740 fatalperror(f
, "ioctl I_PUSH ldterm", errno
);
2741 if (ioctl(t
, I_PUSH
, "ttcompat") == -1)
2742 fatalperror(f
, "ioctl I_PUSH ttcompat", errno
);
2748 if (ioctl(t
, TIOCGETP
, &b
) == -1)
2749 syslog(LOG_INFO
, "ioctl TIOCGETP pty t: %m\n");
2750 b
.sg_flags
= O_CRMOD
|O_XTABS
|O_ANYP
;
2751 /* XXX - ispeed and ospeed must be non-zero */
2752 b
.sg_ispeed
= B38400
;
2753 b
.sg_ospeed
= B38400
;
2754 if (ioctl(t
, TIOCSETN
, &b
) == -1)
2755 syslog(LOG_INFO
, "ioctl TIOCSETN pty t: %m\n");
2756 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
2757 syslog(LOG_INFO
, "ioctl TIOCGETP pty pty: %m\n");
2758 b
.sg_flags
&= ~O_ECHO
;
2759 if (ioctl(pty
, TIOCSETN
, &b
) == -1)
2760 syslog(LOG_INFO
, "ioctl TIOCSETN pty pty: %m\n");
2762 if (who
->ss_family
== AF_INET
) {
2763 char *addrbuf
= NULL
;
2764 char *portbuf
= NULL
;
2766 sin
= (struct sockaddr_in
*)who
;
2767 wholen
= sizeof (struct sockaddr_in
);
2769 addrbuf
= (char *)malloc(wholen
);
2770 if (addrbuf
== NULL
)
2771 fatal(f
, "Cannot alloc memory for address info\n");
2772 portbuf
= (char *)malloc(sizeof (sin
->sin_port
));
2773 if (portbuf
== NULL
) {
2775 fatal(f
, "Cannot alloc memory for port info\n");
2778 (void) memcpy(addrbuf
, (const void *)&sin
->sin_addr
, wholen
);
2779 (void) memcpy(portbuf
, (const void *)&sin
->sin_port
,
2780 sizeof (sin
->sin_port
));
2782 free(rsaddr
.contents
);
2784 rsaddr
.contents
= (krb5_octet
*)addrbuf
;
2785 rsaddr
.length
= wholen
;
2786 rsaddr
.addrtype
= ADDRTYPE_INET
;
2788 free(rsport
.contents
);
2790 rsport
.contents
= (krb5_octet
*)portbuf
;
2791 rsport
.length
= sizeof (sin
->sin_port
);
2792 rsport
.addrtype
= ADDRTYPE_IPPORT
;
2793 } else if (who
->ss_family
== AF_INET6
) {
2794 struct in_addr ipv4_addr
;
2795 char *addrbuf
= NULL
;
2796 char *portbuf
= NULL
;
2798 sin6
= (struct sockaddr_in6
*)who
;
2799 wholen
= sizeof (struct sockaddr_in6
);
2801 IN6_V4MAPPED_TO_INADDR(&sin6
->sin6_addr
,
2804 addrbuf
= (char *)malloc(wholen
);
2805 if (addrbuf
== NULL
)
2806 fatal(f
, "Cannot alloc memory for address info\n");
2808 portbuf
= (char *)malloc(sizeof (sin6
->sin6_port
));
2809 if (portbuf
== NULL
) {
2811 fatal(f
, "Cannot alloc memory for port info\n");
2814 (void) memcpy((void *) addrbuf
,
2815 (const void *)&ipv4_addr
,
2818 * If we already used rsaddr.contents, free the previous
2821 free(rsaddr
.contents
);
2823 rsaddr
.contents
= (krb5_octet
*)addrbuf
;
2824 rsaddr
.length
= sizeof (ipv4_addr
);
2825 rsaddr
.addrtype
= ADDRTYPE_INET
;
2827 (void) memcpy((void *) portbuf
, (const void *)&sin6
->sin6_port
,
2828 sizeof (sin6
->sin6_port
));
2830 free(rsport
.contents
);
2832 rsport
.contents
= (krb5_octet
*)portbuf
;
2833 rsport
.length
= sizeof (sin6
->sin6_port
);
2834 rsport
.addrtype
= ADDRTYPE_IPPORT
;
2836 syslog(LOG_ERR
, "unknown address family %d\n",
2838 fatal(f
, "getpeername: unknown address family\n");
2841 if (getnameinfo((const struct sockaddr
*) who
, wholen
, host_name
,
2842 sizeof (host_name
), NULL
, 0, 0) == 0) {
2846 * If the '-U' option was given on the cmd line, we must
2847 * be able to lookup the hostname
2849 if (resolve_hostname
) {
2850 fatal(f
, "Couldn't resolve your address into a "
2851 "host name.\r\nPlease contact your net "
2855 if (who
->ss_family
== AF_INET6
) {
2856 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
2857 struct in_addr ipv4_addr
;
2859 IN6_V4MAPPED_TO_INADDR(&sin6
->sin6_addr
,
2861 host
= (char *)inet_ntop(AF_INET
,
2862 &ipv4_addr
, abuf
, sizeof (abuf
));
2864 host
= (char *)inet_ntop(AF_INET6
,
2865 &sin6
->sin6_addr
, abuf
,
2868 } else if (who
->ss_family
== AF_INET
) {
2869 host
= (char *)inet_ntop(AF_INET
,
2870 &sin
->sin_addr
, abuf
, sizeof (abuf
));
2874 * Note that sockmod has to be removed since readstream assumes
2875 * a "raw" TPI endpoint (e.g. it uses getmsg).
2877 if (removemod(f
, "sockmod") < 0)
2878 fatalperror(f
, "couldn't remove sockmod", errno
);
2883 * Push the crypto module on the stream before 'telmod' so it
2884 * can encrypt/decrypt without interfering with telmod functionality
2885 * We must push it now because many of the crypto options negotiated
2886 * initially must be saved in the crypto module (via IOCTL calls).
2888 if (ioctl(f
, I_PUSH
, "cryptmod") < 0)
2889 fatalperror(f
, "ioctl I_PUSH cryptmod", errno
);
2893 * gotta set the encryption clock now because it is often negotiated
2894 * immediately by the client, and if we wait till after we negotiate
2895 * auth, it will be out of whack with when the WILL/WONT ENCRYPT
2896 * option is received.
2901 * get terminal type.
2904 len
= sizeof (username
);
2906 settimer(getterminal
);
2909 * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
2911 auth_status
= getauthtype(username
, &len
);
2913 * Exchange TELOPT_ENCRYPT options per RFC 2946
2918 if (ioctl(f
, I_PUSH
, "telmod") < 0)
2919 fatalperror(f
, "ioctl I_PUSH telmod", errno
);
2922 * Make sure telmod will pass unrecognized IOCTLs to cryptmod
2926 telnetmod
.ic_cmd
= CRYPTPASSTHRU
;
2927 telnetmod
.ic_timout
= -1;
2928 telnetmod
.ic_len
= sizeof (uchar_t
);
2929 telnetmod
.ic_dp
= (char *)&passthru
;
2931 if (ioctl(f
, I_STR
, &telnetmod
) < 0)
2932 fatal(f
, "ioctl CRPASSTHRU failed\n");
2938 * readstream will do a getmsg till it receives M_PROTO type
2939 * T_DATA_REQ from telnetmodopen(). This signals that all data
2940 * in-flight before telmod was pushed has been received at the
2943 while ((nsize
= readstream(f
, netibuf
, ncc
+ netip
- netibuf
)) > 0) {
2948 fatalperror(f
, "readstream failed\n", errno
);
2952 * open logindmux drivers and link them with network and ptm
2955 if ((ptmfd
= open("/dev/logindmux", O_RDWR
)) == -1) {
2956 fatalperror(f
, "open /dev/logindmux", errno
);
2958 if ((netfd
= open("/dev/logindmux", O_RDWR
)) == -1) {
2959 fatalperror(f
, "open /dev/logindmux", errno
);
2962 if (ioctl(ptmfd
, I_LINK
, p
) < 0)
2963 fatal(f
, "ioctl I_LINK of /dev/ptmx failed\n");
2964 if (ioctl(netfd
, I_LINK
, f
) < 0)
2965 fatal(f
, "ioctl I_LINK of tcp connection failed\n");
2968 * Figure out the device number of ptm's mux fd, and pass that
2971 if (fstat(ptmfd
, &buf
) < 0) {
2972 fatalperror(f
, "fstat ptmfd failed", errno
);
2974 telnetp
.dev
= buf
.st_rdev
;
2977 telnetmod
.ic_cmd
= LOGDMX_IOC_QEXCHANGE
;
2978 telnetmod
.ic_timout
= -1;
2979 telnetmod
.ic_len
= sizeof (struct protocol_arg
);
2980 telnetmod
.ic_dp
= (char *)&telnetp
;
2982 if (ioctl(netfd
, I_STR
, &telnetmod
) < 0)
2983 fatal(netfd
, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
2986 * Figure out the device number of the net's mux fd, and pass that
2989 if (fstat(netfd
, &buf
) < 0) {
2990 fatalperror(f
, "fstat netfd failed", errno
);
2992 telnetp
.dev
= buf
.st_rdev
;
2995 telnetmod
.ic_cmd
= LOGDMX_IOC_QEXCHANGE
;
2996 telnetmod
.ic_timout
= -1;
2997 telnetmod
.ic_len
= sizeof (struct protocol_arg
);
2998 telnetmod
.ic_dp
= (char *)&telnetp
;
3000 if (ioctl(ptmfd
, I_STR
, &telnetmod
) < 0)
3001 fatal(netfd
, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
3005 cryptmod_fd
= netfd
;
3008 * Show banner that getty never gave, but
3009 * only if the user did not automatically authenticate.
3011 if (getenv("USER") == NULL
&& auth_status
< AUTH_USER
)
3015 * If the user automatically authenticated with Kerberos
3016 * we must set the service name that PAM will use. We
3017 * need to do it BEFORE the child fork so that 'cleanup'
3018 * in the parent can call the PAM cleanup stuff with the
3019 * same PAM service that /bin/login will use to authenticate
3022 if (auth_level
>= 0 && auth_status
>= AUTH_USER
&&
3023 (AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
)) {
3024 (void) strcpy(pam_svc_name
, "ktelnet");
3027 * Request to do suppress go ahead.
3029 * Send this before sending the TELOPT_ECHO stuff below because
3030 * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
3031 * that has them turn off local echo mode if SGA is not received first.
3032 * This also has the odd side-effect of causing the client to enable
3033 * encryption and then immediately disable it during the ECHO option
3034 * negotiations. Its just better to to SGA first now that we support
3037 if (!myopts
[TELOPT_SGA
]) {
3038 dooption(TELOPT_SGA
);
3042 * Pretend we got a DO ECHO from the client if we have not
3043 * yet negotiated the ECHO.
3045 if (!myopts
[TELOPT_ECHO
]) {
3046 dooption(TELOPT_ECHO
);
3050 * Is the client side a 4.2 (NOT 4.3) system? We need to know this
3051 * because 4.2 clients are unable to deal with TCP urgent data.
3053 * To find out, we send out a "DO ECHO". If the remote system
3054 * answers "WILL ECHO" it is probably a 4.2 client, and we note
3055 * that fact ("WILL ECHO" ==> that the client will echo what
3056 * WE, the server, sends it; it does NOT mean that the client will
3057 * echo the terminal input).
3059 send_do(TELOPT_ECHO
);
3060 remopts
[TELOPT_ECHO
] = OPT_YES_BUT_ALWAYS_LOOK
;
3062 if ((pid
= fork()) < 0)
3063 fatalperror(netfd
, "fork", errno
);
3065 telnet(net
, master
);
3067 * The child process needs to be the session leader
3068 * and have the pty as its controlling tty. Thus we need
3069 * to re-open the slave side of the pty no without
3070 * the O_NOCTTY flag that we have been careful to
3071 * use up to this point.
3075 tt
= open(line
, O_RDWR
);
3077 fatalperror(netfd
, line
, errno
);
3078 (void) close(netfd
);
3079 (void) close(ptmfd
);
3093 (void) local_setenv("TERM", terminaltype
+5, 1);
3095 * -h : pass on name of host.
3096 * WARNING: -h is accepted by login if and only if
3098 * -p : don't clobber the environment (so terminal type stays set).
3101 /* System V login expects a utmp entry to already be there */
3103 (void) memset((char *)&ut
, 0, sizeof (ut
));
3104 (void) strncpy(ut
.ut_user
, ".telnet", sizeof (ut
.ut_user
));
3105 (void) strncpy(ut
.ut_line
, line
, sizeof (ut
.ut_line
));
3106 ut
.ut_pid
= getpid();
3108 ut
.ut_id
[1] = (char)SC_WILDC
;
3109 ut
.ut_id
[2] = (char)SC_WILDC
;
3110 ut
.ut_id
[3] = (char)SC_WILDC
;
3111 ut
.ut_type
= LOGIN_PROCESS
;
3112 ut
.ut_exit
.e_termination
= 0;
3113 ut
.ut_exit
.e_exit
= 0;
3114 (void) time(&ut
.ut_tv
.tv_sec
);
3115 if (makeutx(&ut
) == NULL
)
3116 syslog(LOG_INFO
, "in.telnetd:\tmakeutx failed");
3120 * Load in the cached environment variables and either
3121 * set/unset them in the environment.
3123 for (next
= envlist_head
; next
; ) {
3126 (void) local_unsetenv(env
->name
);
3128 (void) local_setenv(env
->name
, env
->value
, 1);
3135 if (!username
|| !username
[0])
3136 auth_status
= AUTH_REJECT
; /* we dont know who this is */
3138 /* If the current auth status is less than the required level, exit */
3139 if (auth_status
< auth_level
) {
3140 fatal(net
, "Authentication failed\n");
3145 * If AUTH_VALID (proper authentication REQUIRED and we have
3146 * a krb5_name), exec '/bin/login', make sure it uses the
3147 * correct PAM service name (pam_svc_name). If possible,
3148 * make sure the krb5 authenticated user's name (krb5_name)
3149 * is in the PAM REPOSITORY for krb5.
3151 if (auth_level
>= 0 &&
3152 (auth_status
== AUTH_VALID
|| auth_status
== AUTH_USER
) &&
3153 ((krb5_name
!= NULL
) && strlen(krb5_name
)) &&
3154 ((AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
))) {
3155 (void) execl(LOGIN_PROGRAM
, "login",
3161 "-R", KRB5_REPOSITORY_NAME
,
3162 AuthenticatingUser
, 0);
3163 } else if (auth_level
>= 0 &&
3164 auth_status
>= AUTH_USER
&&
3165 (((AuthenticatingUser
!= NULL
) && strlen(AuthenticatingUser
)) ||
3168 * If we only know the name but not the principal,
3169 * login will have to authenticate further.
3171 (void) execl(LOGIN_PROGRAM
, "login",
3175 "-s", pam_svc_name
, "--",
3176 (AuthenticatingUser
!= NULL
? AuthenticatingUser
:
3177 getenv("USER")), 0);
3179 } else /* default, no auth. info available, login does it all */ {
3180 (void) execl(LOGIN_PROGRAM
, "login",
3181 "-p", "-h", host
, "-d", slavename
, "--",
3185 fatalperror(netfd
, LOGIN_PROGRAM
, errno
);
3190 fatal(int f
, char *msg
)
3194 (void) snprintf(buf
, sizeof (buf
), "telnetd: %s.\r\n", msg
);
3195 (void) write(f
, buf
, strlen(buf
));
3201 fatalperror(int f
, char *msg
, int errnum
)
3205 (void) snprintf(buf
, sizeof (buf
),
3206 "%s: %s\r\n", msg
, strerror(errnum
));
3212 * Main loop. Select from pty and network, and
3213 * hand data to telnet receiver finite state machine
3214 * when it receives telnet protocol. Regular data
3215 * flow between pty and network takes place through
3216 * inkernel telnet streams module (telmod).
3219 telnet(int net
, int master
)
3223 struct strioctl telnetmod
;
3226 char binary_out
= 0;
3228 if (ioctl(net
, FIONBIO
, &on
) == -1)
3229 syslog(LOG_INFO
, "ioctl FIONBIO net: %m\n");
3230 if (ioctl(master
, FIONBIO
, &on
) == -1)
3231 syslog(LOG_INFO
, "ioctl FIONBIO pty p: %m\n");
3232 (void) signal(SIGTSTP
, SIG_IGN
);
3233 (void) signal(SIGCHLD
, (void (*)())cleanup
);
3237 * Call telrcv() once to pick up anything received during
3238 * terminal type negotiation.
3246 fd_set ibits
, obits
, xbits
;
3257 * If we couldn't flush all our output to the network,
3258 * keep checking for when we can.
3260 if (nfrontp
- nbackp
)
3261 FD_SET(net
, &obits
);
3263 * Never look for input if there's still
3264 * stuff in the corresponding output buffer
3266 if (pfrontp
- pbackp
) {
3267 FD_SET(master
, &obits
);
3269 FD_SET(net
, &ibits
);
3272 FD_SET(net
, &xbits
);
3275 #define max(x, y) (((x) < (y)) ? (y) : (x))
3278 * make an ioctl to telnet module (net side) to send
3279 * binary mode of telnet daemon. binary_in and
3280 * binary_out are 0 if not in binary mode.
3282 if (binary_in
!= myopts
[TELOPT_BINARY
] ||
3283 binary_out
!= remopts
[TELOPT_BINARY
]) {
3286 if (myopts
[TELOPT_BINARY
] != OPT_NO
)
3287 mode
|= TEL_BINARY_IN
;
3289 if (remopts
[TELOPT_BINARY
] != OPT_NO
)
3290 mode
|= TEL_BINARY_OUT
;
3292 telnetmod
.ic_cmd
= TEL_IOC_MODE
;
3293 telnetmod
.ic_timout
= -1;
3294 telnetmod
.ic_len
= 1;
3295 telnetmod
.ic_dp
= &mode
;
3297 syslog(LOG_DEBUG
, "TEL_IOC_MODE binary has changed\n");
3299 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3300 fatal(net
, "ioctl TEL_IOC_MODE failed\n");
3301 binary_in
= myopts
[TELOPT_BINARY
];
3302 binary_out
= remopts
[TELOPT_BINARY
];
3304 if (state
== TS_DATA
) {
3305 if ((nfrontp
== nbackp
) &&
3306 (pfrontp
== pbackp
)) {
3307 if (ioctl(net
, I_NREAD
, &nsize
) < 0)
3309 "ioctl I_NREAD failed\n", errno
);
3314 * make an ioctl to reinsert remaining data at
3315 * streamhead. After this, ioctl reenables the
3316 * telnet lower put queue. This queue was
3317 * noenabled by telnet module after sending
3318 * protocol/urgent data to telnetd.
3321 telnetmod
.ic_cmd
= TEL_IOC_ENABLE
;
3322 telnetmod
.ic_timout
= -1;
3324 telnetmod
.ic_len
= ncc
+ nsize
;
3325 telnetmod
.ic_dp
= netip
;
3327 telnetmod
.ic_len
= 0;
3328 telnetmod
.ic_dp
= NULL
;
3330 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3331 fatal(net
, "ioctl TEL_IOC_ENABLE \
3334 telmod_init_done
= B_TRUE
;
3337 (void) memset(netibuf
, 0, netibufsize
);
3343 * state not changed to TS_DATA and hence, more to read
3344 * send ioctl to get one more message block.
3346 telnetmod
.ic_cmd
= TEL_IOC_GETBLK
;
3347 telnetmod
.ic_timout
= -1;
3348 telnetmod
.ic_len
= 0;
3349 telnetmod
.ic_dp
= NULL
;
3351 if (ioctl(net
, I_STR
, &telnetmod
) < 0)
3352 fatal(net
, "ioctl TEL_IOC_GETBLK failed\n");
3355 if ((c
= select(max(net
, master
) + 1, &ibits
, &obits
, &xbits
,
3358 if (errno
== EINTR
) {
3369 if (FD_ISSET(net
, &xbits
)) {
3374 * Something to read from the network...
3376 if (FD_ISSET(net
, &ibits
)) {
3377 ncc
= read(net
, netibuf
, netibufsize
);
3378 if (ncc
< 0 && errno
== EWOULDBLOCK
)
3388 if (FD_ISSET(net
, &obits
) && (nfrontp
- nbackp
) > 0)
3392 if (FD_ISSET(master
, &obits
) && (pfrontp
- pbackp
) > 0)
3404 if ((&ptyobuf
[BUFSIZ
] - pfrontp
) < 2)
3408 * Once we hit data, we want to transition back to
3409 * in-kernel processing. However, this code is shared
3410 * by getterminaltype()/ttloop() which run before the
3411 * in-kernel plumbing is available. So if we are still
3412 * processing the initial option negotiation, even TS_DATA
3413 * must be processed here.
3415 if (c
!= IAC
&& state
== TS_DATA
&& init_neg_done
) {
3424 /* Strip off \n or \0 after a \r */
3425 if ((c
== 0) || (c
== '\n')) {
3438 * We map \r\n ==> \r, since
3439 * We now map \r\n ==> \r for pragmatic reasons.
3440 * Many client implementations send \r\n when
3441 * the user hits the CarriageReturn key.
3443 * We USED to map \r\n ==> \n, since \r\n says
3444 * that we want to be in column 1 of the next
3447 if (c
== '\r' && (myopts
[TELOPT_BINARY
] == OPT_NO
)) {
3457 * Send the process on the pty side an
3458 * interrupt. Do this with a NULL or
3459 * interrupt char; depending on the tty mode.
3473 write_data_len("\r\n[Yes]\r\n", 9);
3480 struct ltchars tmpltc
;
3482 ptyflush(); /* half-hearted */
3483 if (ioctl(pty
, TIOCGLTC
, &tmpltc
) == -1)
3485 "ioctl TIOCGLTC: %m\n");
3486 if (tmpltc
.t_flushc
!= '\377') {
3487 *pfrontp
++ = tmpltc
.t_flushc
;
3489 netclear(); /* clear buffer back */
3490 write_data("%c%c", (uchar_t
)IAC
,
3493 neturg
= nfrontp
-1; /* off by one XXX */
3495 netflush(); /* XXX.sparker */
3500 * Erase Character and
3508 ptyflush(); /* half-hearted */
3509 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
3511 "ioctl TIOCGETP: %m\n");
3513 b
.sg_erase
: b
.sg_kill
;
3521 * Check for urgent data...
3527 * Begin option subnegotiation...
3566 SB_ACCUM((uchar_t
)IAC
);
3573 suboption(); /* handle sub-option */
3579 if (remopts
[c
] != OPT_YES
)
3585 if (remopts
[c
] != OPT_NO
)
3591 if (myopts
[c
] != OPT_YES
)
3597 if (myopts
[c
] != OPT_NO
) {
3604 syslog(LOG_ERR
, "telnetd: panic state=%d\n", state
);
3605 (void) printf("telnetd: panic state=%d\n", state
);
3612 willoption(int option
)
3615 boolean_t send_reply
= B_TRUE
;
3624 not42
= 0; /* looks like a 4.2 system */
3626 * Now, in a 4.2 system, to break them out of ECHOing
3627 * (to the terminal) mode, we need to send a "WILL ECHO".
3628 * Kludge upon kludge!
3630 if (myopts
[TELOPT_ECHO
] == OPT_YES
) {
3631 dooption(TELOPT_ECHO
);
3643 case TELOPT_XDISPLOC
:
3644 settimer(xdisplocopt
);
3647 case TELOPT_NEW_ENVIRON
:
3648 settimer(environopt
);
3651 case TELOPT_AUTHENTICATION
:
3653 if (remopts
[option
] == OPT_NO
||
3654 negotiate_auth_krb5
== 0)
3660 case TELOPT_OLD_ENVIRON
:
3661 settimer(oenvironopt
);
3664 if (remopts
[option
] == OPT_YES_BUT_ALWAYS_LOOK
) {
3665 remopts
[option
] = OPT_YES
;
3677 case TELOPT_ENCRYPT
:
3678 settimer(encropt
); /* got response to do/dont */
3680 (void) fprintf(stderr
,
3681 "RCVD IAC WILL TELOPT_ENCRYPT\n");
3682 if (krb5_privacy_allowed()) {
3684 if (sent_do_encrypt
)
3685 send_reply
= B_FALSE
;
3687 sent_do_encrypt
= B_TRUE
;
3698 remopts
[option
] = OPT_YES
;
3700 remopts
[option
] = OPT_NO
;
3703 write_data((const char *)fmt
, option
);
3709 wontoption(int option
)
3716 not42
= 1; /* doesn't seem to be a 4.2 system */
3731 case TELOPT_XDISPLOC
:
3732 settimer(xdisplocopt
);
3735 case TELOPT_NEW_ENVIRON
:
3736 settimer(environopt
);
3739 case TELOPT_OLD_ENVIRON
:
3740 settimer(oenvironopt
);
3743 case TELOPT_AUTHENTICATION
:
3745 auth_finished(0, AUTH_REJECT
);
3747 (void) fprintf(stderr
,
3748 "RCVD WONT TELOPT_AUTHENTICATE\n");
3750 remopts
[option
] = OPT_NO
;
3754 case TELOPT_ENCRYPT
:
3756 (void) fprintf(stderr
,
3757 "RCVD IAC WONT TELOPT_ENCRYPT\n");
3758 settimer(encropt
); /* got response to will/wont */
3760 * Remote side cannot send encryption. No reply necessary
3761 * Treat this as if "IAC SB ENCRYPT END IAC SE" were
3762 * received (RFC 2946) and disable crypto.
3764 encrypt_end(TELNET_DIR_DECRYPT
);
3770 remopts
[option
] = OPT_NO
;
3772 write_data((const char *)fmt
, option
);
3777 * We received an "IAC DO ..." message from the client, change our state
3781 dooption(int option
)
3784 boolean_t send_reply
= B_TRUE
;
3793 mode(O_ECHO
|O_CRMOD
, 0);
3808 * Options don't get much easier. Acknowledge the option,
3809 * and then clean up and exit.
3811 write_data((const char *)will
, option
);
3816 case TELOPT_ENCRYPT
:
3818 (void) fprintf(stderr
, "RCVD DO TELOPT_ENCRYPT\n");
3821 * We received a "DO". This indicates that the other side
3822 * wants us to encrypt our data (pending negotiatoin).
3823 * reply with "IAC WILL ENCRYPT" if we are able to send
3826 if (krb5_privacy_allowed() && negotiate_encrypt
) {
3828 if (sent_will_encrypt
)
3829 send_reply
= B_FALSE
;
3831 sent_will_encrypt
= B_TRUE
;
3832 /* return if we already sent "WILL ENCRYPT" */
3833 if (myopts
[option
] == OPT_YES
)
3840 case TELOPT_AUTHENTICATION
:
3842 (void) fprintf(stderr
,
3843 "RCVD DO TELOPT_AUTHENTICATION\n");
3846 * RFC 2941 - only the server can send
3847 * "DO TELOPT_AUTHENTICATION".
3848 * if a server receives this, it must respond with WONT...
3858 myopts
[option
] = OPT_YES
;
3860 myopts
[option
] = OPT_NO
;
3863 write_data((const char *)fmt
, option
);
3869 * We received an "IAC DONT ..." message from client.
3870 * Client does not agree with the option so act accordingly.
3873 dontoption(int option
)
3879 * we should stop echoing, since the client side will be doing
3880 * it, but keep mapping CR since CR-LF will be mapped to it.
3885 case TELOPT_ENCRYPT
:
3887 (void) fprintf(stderr
, "RCVD IAC DONT ENCRYPT\n");
3890 * Remote side cannot receive any encrypted data,
3891 * so dont send any. No reply necessary.
3900 myopts
[option
] = OPT_NO
;
3903 write_data((const char *)wont
, option
);
3910 * Look at the sub-option buffer, and try to be helpful to the other
3919 switch (subchar
= SB_GET()) {
3920 case TELOPT_TTYPE
: { /* Yaaaay! */
3921 static char terminalname
[5+41] = "TERM=";
3923 settimer(ttypesubopt
);
3925 if (SB_GET() != TELQUAL_IS
) {
3926 return; /* ??? XXX but, this is the most robust */
3929 terminaltype
= terminalname
+strlen(terminalname
);
3931 while (terminaltype
< (terminalname
+ sizeof (terminalname
) -
3939 *terminaltype
++ = c
; /* accumulate name */
3942 terminaltype
= terminalname
;
3952 ws
.ws_col
= SB_GET() << 8;
3956 ws
.ws_col
|= SB_GET();
3960 ws
.ws_row
= SB_GET() << 8;
3964 ws
.ws_row
|= SB_GET();
3965 ws
.ws_xpixel
= 0; ws
.ws_ypixel
= 0;
3966 (void) ioctl(pty
, TIOCSWINSZ
, &ws
);
3971 case TELOPT_XDISPLOC
: {
3972 if (SB_EOF() || SB_GET() != TELQUAL_IS
) {
3975 settimer(xdisplocsubopt
);
3976 subpointer
[SB_LEN()] = '\0';
3977 if ((new_env("DISPLAY", subpointer
)) == 1)
3982 case TELOPT_NEW_ENVIRON
:
3983 case TELOPT_OLD_ENVIRON
: {
3985 char *cp
, *varp
, *valp
;
3990 if (c
== TELQUAL_IS
) {
3991 if (subchar
== TELOPT_OLD_ENVIRON
)
3992 settimer(oenvironsubopt
);
3994 settimer(environsubopt
);
3995 } else if (c
!= TELQUAL_INFO
) {
3999 if (subchar
== TELOPT_NEW_ENVIRON
) {
4002 if ((c
== NEW_ENV_VAR
) || (c
== ENV_USERVAR
))
4009 if ((c
== env_ovar
) || (c
== ENV_USERVAR
))
4017 cp
= varp
= (char *)subpointer
;
4022 if (subchar
== TELOPT_OLD_ENVIRON
) {
4025 else if (c
== env_ovalue
)
4032 cp
= valp
= (char *)subpointer
;
4039 if ((new_env(varp
, valp
)) == 1) {
4043 (void) del_env(varp
);
4045 cp
= varp
= (char *)subpointer
;
4061 if ((new_env(varp
, valp
)) == 1) {
4065 (void) del_env(varp
);
4068 } /* end of case TELOPT_NEW_ENVIRON */
4070 case TELOPT_AUTHENTICATION
:
4077 * These are sent server only and cannot be sent by the
4083 (void) fprintf(stderr
,
4084 "RCVD AUTHENTICATION IS "
4087 if (!auth_negotiated
)
4088 auth_is((uchar_t
*)subpointer
, SB_LEN());
4092 (void) fprintf(stderr
,
4093 "RCVD AUTHENTICATION NAME "
4096 if (!auth_negotiated
)
4097 auth_name((uchar_t
*)subpointer
, SB_LEN());
4102 case TELOPT_ENCRYPT
: {
4107 #ifdef ENCRYPT_NAMES
4109 (void) fprintf(stderr
, "RCVD ENCRYPT %s\n",
4111 #endif /* ENCRYPT_NAMES */
4113 case ENCRYPT_SUPPORT
:
4114 encrypt_support(subpointer
, SB_LEN());
4117 encrypt_is((uchar_t
*)subpointer
, SB_LEN());
4120 (void) encrypt_reply(subpointer
, SB_LEN());
4126 encrypt_end(TELNET_DIR_DECRYPT
);
4128 case ENCRYPT_REQSTART
:
4129 encrypt_request_start();
4131 case ENCRYPT_REQEND
:
4133 * We can always send an REQEND so that we cannot
4134 * get stuck encrypting. We should only get this
4135 * if we have been able to get in the correct mode
4138 encrypt_request_end();
4140 case ENCRYPT_ENC_KEYID
:
4141 encrypt_enc_keyid(subpointer
, SB_LEN());
4143 case ENCRYPT_DEC_KEYID
:
4144 encrypt_dec_keyid(subpointer
, SB_LEN());
4158 mode(int on
, int off
)
4160 struct termios tios
;
4163 if (tcgetattr(pty
, &tios
) < 0)
4164 syslog(LOG_INFO
, "tcgetattr: %m\n");
4167 tios
.c_cflag
|= CS8
;
4168 tios
.c_iflag
&= ~IUCLC
;
4169 tios
.c_lflag
&= ~(XCASE
|IEXTEN
);
4172 if ((tios
.c_cflag
& PARENB
) != 0)
4173 tios
.c_cflag
&= ~CS8
;
4174 tios
.c_lflag
|= IEXTEN
;
4178 tios
.c_lflag
|= ECHO
;
4180 tios
.c_lflag
&= ~ECHO
;
4183 tios
.c_iflag
|= ICRNL
;
4184 tios
.c_oflag
|= ONLCR
;
4187 * Because "O_CRMOD" will never be set in "off" we don't have to
4188 * handle this case here.
4191 if (tcsetattr(pty
, TCSANOW
, &tios
) < 0)
4192 syslog(LOG_INFO
, "tcsetattr: %m\n");
4196 * Send interrupt to process on other side of pty.
4197 * If it is in raw mode, just write NULL;
4198 * otherwise, write intr char.
4204 struct tchars tchars
;
4206 ptyflush(); /* half-hearted */
4207 if (ioctl(pty
, TIOCGETP
, &b
) == -1)
4208 syslog(LOG_INFO
, "ioctl TIOCGETP: %m\n");
4209 if (b
.sg_flags
& O_RAW
) {
4213 *pfrontp
++ = ioctl(pty
, TIOCGETC
, &tchars
) < 0 ?
4214 '\177' : tchars
.t_intrc
;
4218 * Send quit to process on other side of pty.
4219 * If it is in raw mode, just write NULL;
4220 * otherwise, write quit char.
4226 struct tchars tchars
;
4228 ptyflush(); /* half-hearted */
4229 (void) ioctl(pty
, TIOCGETP
, &b
);
4230 if (b
.sg_flags
& O_RAW
) {
4234 *pfrontp
++ = ioctl(pty
, TIOCGETC
, &tchars
) < 0 ?
4235 '\034' : tchars
.t_quitc
;
4243 if ((n
= pfrontp
- pbackp
) > 0)
4244 n
= write(master
, pbackp
, n
);
4248 if (pbackp
== pfrontp
)
4249 pbackp
= pfrontp
= ptyobuf
;
4255 * Return the address of the next "item" in the TELNET data
4256 * stream. This will be the address of the next character if
4257 * the current address is a user data character, or it will
4258 * be the address of the character following the TELNET command
4259 * if the current address is a TELNET IAC ("I Am a Command")
4264 nextitem(char *current
)
4266 if ((*current
&0xff) != IAC
) {
4269 switch (*(current
+1)&0xff) {
4275 case SB
: /* loop forever looking for the SE */
4277 char *look
= current
+2;
4280 if ((*look
++&0xff) == IAC
) {
4281 if ((*look
++&0xff) == SE
) {
4296 * We are about to do a TELNET SYNCH operation. Clear
4297 * the path to the network.
4299 * Things are a bit tricky since we may have sent the first
4300 * byte or so of a previous TELNET command into the network.
4301 * So, we have to scan the network buffer from the beginning
4302 * until we are up to where we want to be.
4304 * A side effect of what we do, just to keep things
4305 * simple, is to clear the urgent data pointer. The principal
4306 * caller should be setting the urgent data pointer AFTER calling
4312 char *thisitem
, *next
;
4314 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
4315 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
4319 while ((next
= nextitem(thisitem
)) <= nbackp
) {
4323 /* Now, thisitem is first before/at boundary. */
4325 good
= netobuf
; /* where the good bytes go */
4327 while (nfrontp
> thisitem
) {
4328 if (wewant(thisitem
)) {
4333 next
= nextitem(next
);
4334 } while (wewant(next
) && (nfrontp
> next
));
4335 length
= next
-thisitem
;
4336 (void) memmove(good
, thisitem
, length
);
4340 thisitem
= nextitem(thisitem
);
4345 nfrontp
= good
; /* next byte to be sent */
4352 * Send as much data as possible to the network,
4353 * handling requests for urgent data.
4360 if ((n
= nfrontp
- nbackp
) > 0) {
4362 * if no urgent data, or if the other side appears to be an
4363 * old 4.2 client (and thus unable to survive TCP urgent data),
4364 * write the entire buffer in non-OOB mode.
4366 if ((neturg
== 0) || (not42
== 0)) {
4367 n
= write(net
, nbackp
, n
); /* normal write */
4369 n
= neturg
- nbackp
;
4371 * In 4.2 (and 4.3) systems, there is some question
4372 * about what byte in a sendOOB operation is the "OOB"
4373 * data. To make ourselves compatible, we only send ONE
4374 * byte out of band, the one WE THINK should be OOB
4375 * (though we really have more the TCP philosophy of
4376 * urgent data rather than the Unix philosophy of OOB
4380 /* send URGENT all by itself */
4381 n
= write(net
, nbackp
, n
-1);
4384 n
= send_oob(net
, nbackp
, n
);
4389 if (errno
== EWOULDBLOCK
)
4391 /* should blow this guy away... */
4397 if (nbackp
>= neturg
) {
4400 if (nbackp
== nfrontp
) {
4401 nbackp
= nfrontp
= netobuf
;
4410 * If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
4411 * handle closing differently. We close "net" first and then
4412 * "master" in that order. We do close(net) first because
4413 * we have no other way to disconnect forwarding between the network
4414 * and master. So by issuing the close()'s we ensure that no further
4415 * data rises from TCP. A more complex fix would be adding proper
4416 * support for throwing a "stop" switch for forwarding data between
4417 * logindmux peers. It's possible to block in the close of the tty
4418 * while the network still receives data and the telmod module is
4419 * TEL_STOPPED. A denial-of-service attack generates this case,
4423 if (!telmod_init_done
) {
4425 (void) close(master
);
4437 char user
[sizeof (up
->ut_user
) + 1];
4438 char ttyn
[sizeof (up
->ut_line
) + 1];
4439 char rhost
[sizeof (up
->ut_host
) + 1];
4441 /* while cleaning up don't allow disruption */
4442 (void) signal(SIGCHLD
, SIG_IGN
);
4445 while (up
= getutxent()) {
4446 if (up
->ut_pid
== pid
) {
4447 if (up
->ut_type
== DEAD_PROCESS
) {
4449 * Cleaned up elsewhere.
4455 * call pam_close_session if login changed
4456 * the utmpx user entry from type LOGIN_PROCESS
4457 * to type USER_PROCESS, which happens
4458 * after pam_open_session is called.
4460 if (up
->ut_type
== USER_PROCESS
) {
4461 (void) strlcpy(user
, up
->ut_user
,
4463 (void) strlcpy(ttyn
, up
->ut_line
,
4465 (void) strlcpy(rhost
, up
->ut_host
,
4467 if ((pam_start("telnet", user
, NULL
, &pamh
)) ==
4469 (void) pam_set_item(pamh
, PAM_TTY
,
4471 (void) pam_set_item(pamh
, PAM_RHOST
,
4473 (void) pam_close_session(pamh
, 0);
4474 (void) pam_end(pamh
, PAM_SUCCESS
);
4478 up
->ut_type
= DEAD_PROCESS
;
4479 up
->ut_exit
.e_termination
= WTERMSIG(0);
4480 up
->ut_exit
.e_exit
= WEXITSTATUS(0);
4481 (void) time(&up
->ut_tv
.tv_sec
);
4483 if (modutx(up
) == NULL
) {
4485 * Since modutx failed we'll
4486 * write out the new entry
4489 (void) pututxline(up
);
4490 updwtmpx("wtmpx", up
);
4498 (void) signal(SIGCHLD
, (void (*)())cleanup
);
4502 readstream(int fd
, char *buf
, int offset
)
4504 struct strbuf ctlbuf
, datbuf
;
4505 union T_primitives tpi
;
4508 int bytes_avail
, count
;
4510 (void) memset((char *)&ctlbuf
, 0, sizeof (ctlbuf
));
4511 (void) memset((char *)&datbuf
, 0, sizeof (datbuf
));
4513 ctlbuf
.buf
= (char *)&tpi
;
4514 ctlbuf
.maxlen
= sizeof (tpi
);
4516 if (ioctl(fd
, I_NREAD
, &bytes_avail
) < 0) {
4517 syslog(LOG_ERR
, "I_NREAD returned error %m");
4520 if (bytes_avail
> netibufsize
- offset
) {
4521 count
= netip
- netibuf
;
4522 netibuf
= (char *)realloc(netibuf
,
4523 (unsigned)netibufsize
+ bytes_avail
);
4524 if (netibuf
== NULL
) {
4525 fatal(net
, "netibuf realloc failed\n");
4527 netibufsize
+= bytes_avail
;
4528 netip
= netibuf
+ count
;
4531 datbuf
.buf
= buf
+ offset
;
4532 datbuf
.maxlen
= netibufsize
;
4533 ret
= getmsg(fd
, &ctlbuf
, &datbuf
, &flags
);
4535 syslog(LOG_ERR
, "getmsg returned -1, errno %d\n",
4539 if (ctlbuf
.len
<= 0) {
4540 return (datbuf
.len
);
4543 if (tpi
.type
== T_DATA_REQ
) {
4547 if ((tpi
.type
== T_ORDREL_IND
) || (tpi
.type
== T_DISCON_IND
))
4549 fatal(fd
, "no data or protocol element recognized");
4554 drainstream(int size
)
4559 tsize
= netip
- netibuf
;
4561 if ((tsize
+ ncc
+ size
) > netibufsize
) {
4562 if (!(netibuf
= (char *)realloc(netibuf
,
4563 (unsigned)tsize
+ ncc
+ size
)))
4564 fatalperror(net
, "netibuf realloc failed\n", errno
);
4565 netibufsize
= tsize
+ ncc
+ size
;
4567 netip
= netibuf
+ tsize
;
4570 if ((nbytes
= read(net
, (char *)netip
+ ncc
, size
)) != size
)
4571 syslog(LOG_ERR
, "read %d bytes\n", nbytes
);
4575 * TPI style replacement for socket send() primitive, so we don't require
4576 * sockmod to be on the stream.
4579 send_oob(int fd
, char *ptr
, int count
)
4581 struct T_exdata_req exd_req
;
4582 struct strbuf hdr
, dat
;
4585 exd_req
.PRIM_type
= T_EXDATA_REQ
;
4586 exd_req
.MORE_flag
= 0;
4588 hdr
.buf
= (char *)&exd_req
;
4589 hdr
.len
= sizeof (exd_req
);
4594 ret
= putmsg(fd
, &hdr
, &dat
, 0);
4604 * Set the value of the environmental variable "name" to be
4605 * "value". If rewrite is set, replace any current value.
4608 local_setenv(const char *name
, const char *value
, int rewrite
)
4610 static int alloced
; /* if allocated space before */
4612 int l_value
, offset
;
4615 * Do not allow environment variables which begin with LD_ to be
4616 * inserted into the environment. While normally the dynamic linker
4617 * protects the login program, that is based on the assumption hostile
4618 * invocation of login are from non-root users. However, since telnetd
4619 * runs as root, this cannot be utilized. So instead we simply
4620 * prevent LD_* from being inserted into the environment.
4621 * This also applies to other environment variables that
4622 * are to be ignored in setugid apps.
4623 * Note that at this point name can contain '='!
4624 * Also, do not allow TTYPROMPT to be passed along here.
4626 if (strncmp(name
, "LD_", 3) == 0 ||
4627 strncmp(name
, "NLSPATH", 7) == 0 ||
4628 (strncmp(name
, "TTYPROMPT", 9) == 0 &&
4629 (name
[9] == '\0' || name
[9] == '='))) {
4632 if (*value
== '=') /* no `=' in value */
4634 l_value
= strlen(value
);
4635 if ((c
= __findenv(name
, &offset
))) { /* find if already exists */
4638 if ((int)strlen(c
) >= l_value
) { /* old larger; copy over */
4639 while (*c
++ = *value
++)
4643 } else { /* create new slot */
4647 for (p
= environ
, cnt
= 0; *p
; ++p
, ++cnt
)
4649 if (alloced
) { /* just increase size */
4650 environ
= (char **)realloc((char *)environ
,
4651 (size_t)(sizeof (char *) * (cnt
+ 2)));
4654 } else { /* get new space */
4655 alloced
= 1; /* copy old entries into it */
4656 p
= (char **)malloc((size_t)(sizeof (char *)*
4660 (void) memcpy(p
, environ
, cnt
* sizeof (char *));
4663 environ
[cnt
+ 1] = NULL
;
4666 for (c
= (char *)name
; *c
&& *c
!= '='; ++c
) /* no `=' in name */
4668 if (!(environ
[offset
] = /* name + `=' + value */
4669 malloc((size_t)((int)(c
- name
) + l_value
+ 2))))
4671 for (c
= environ
[offset
]; ((*c
= *name
++) != 0) && (*c
!= '='); ++c
)
4673 for (*c
++ = '='; *c
++ = *value
++; )
4679 * local_unsetenv(name) --
4680 * Delete environmental variable "name".
4683 local_unsetenv(const char *name
)
4688 while (__findenv(name
, &offset
)) /* if set multiple times */
4689 for (p
= &environ
[offset
]; ; ++p
)
4690 if ((*p
= *(p
+ 1)) == 0)
4696 * Returns pointer to value associated with name, if any, else NULL.
4697 * Sets offset to be the offset of the name/value combination in the
4698 * environmental array, for use by local_setenv() and local_unsetenv().
4699 * Explicitly removes '=' in argument name.
4702 __findenv(const char *name
, int *offset
)
4704 extern char **environ
;
4709 if (name
== NULL
|| environ
== NULL
)
4711 for (np
= name
; *np
&& *np
!= '='; ++np
)
4714 for (p
= environ
; (c
= *p
) != NULL
; ++p
)
4715 if (strncmp(c
, name
, len
) == 0 && c
[len
] == '=') {
4716 *offset
= p
- environ
;
4717 return (c
+ len
+ 1);
4726 char evalbuf
[BUFSIZ
];
4728 if (defopen(defaultfile
) == 0) {
4732 flags
= defcntl(DC_GETFLAGS
, 0);
4733 TURNOFF(flags
, DC_CASE
);
4734 (void) defcntl(DC_SETFLAGS
, flags
);
4735 if (cp
= defread(bannervar
)) {
4738 if (strlen(cp
) + strlen("eval echo '") + strlen("'\n")
4739 + 1 < sizeof (evalbuf
)) {
4740 (void) strlcpy(evalbuf
, "eval echo '",
4742 (void) strlcat(evalbuf
, cp
, sizeof (evalbuf
));
4743 (void) strlcat(evalbuf
, "'\n",
4746 if (fp
= popen(evalbuf
, "r")) {
4751 * Pipe I/O atomicity guarantees we
4752 * need only one read.
4754 if ((size
= fread(buf
, 1,
4759 p
= strrchr(buf
, '\n');
4768 /* close default file */
4769 (void) defopen(NULL
);
4774 (void) defopen(NULL
); /* close default file */
4787 * Map the banner: "\n" -> "\r\n" and "\r" -> "\r\0"
4789 for (q
= nfrontp
; p
&& *p
&& q
< nfrontp
+ sizeof (netobuf
) - 1; )
4794 } else if (*p
== '\r') {
4801 nfrontp
+= q
- netobuf
;
4805 * Show banner that getty never gave. By default, this is `uname -sr`.
4807 * The banner includes some null's (for TELNET CR disambiguation),
4808 * so we have to be somewhat complicated.
4816 * Dont show this if the '-h' option was present
4821 if (uname(&u
) == -1)
4824 write_data_len((const char *) BANNER1
, sizeof (BANNER1
) - 1);
4825 write_data_len(u
.sysname
, strlen(u
.sysname
));
4826 write_data_len(" ", 1);
4827 write_data_len(u
.release
, strlen(u
.release
));
4828 write_data_len((const char *)BANNER2
, sizeof (BANNER2
) - 1);
4832 * Verify that the named module is at the top of the stream
4833 * and then pop it off.
4836 removemod(int f
, char *modname
)
4838 char topmodname
[BUFSIZ
];
4840 if (ioctl(f
, I_LOOK
, topmodname
) < 0)
4842 if (strcmp(modname
, topmodname
) != 0) {
4846 if (ioctl(f
, I_POP
, 0) < 0)
4852 write_data(const char *format
, ...)
4858 va_start(args
, format
);
4860 if ((len
= vsnprintf(argp
, sizeof (argp
), format
, args
)) == -1)
4863 write_data_len(argp
, len
);
4868 write_data_len(const char *buf
, int len
)
4870 int remaining
, copied
;
4872 remaining
= BUFSIZ
- (nfrontp
- netobuf
);
4875 * If there's not enough space in netobuf then
4878 if ((len
> BUFSIZ
? BUFSIZ
: len
) > remaining
) {
4880 remaining
= BUFSIZ
- (nfrontp
- netobuf
);
4882 /* Copy as much as we can */
4883 copied
= remaining
> len
? len
: remaining
;
4884 (void) memmove(nfrontp
, buf
, copied
);
4887 remaining
-= copied
;