Index: head/contrib/telnet/arpa/telnet.h =================================================================== --- head/contrib/telnet/arpa/telnet.h (revision 87138) +++ head/contrib/telnet/arpa/telnet.h (revision 87139) @@ -1,342 +1,342 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)telnet.h 8.2 (Berkeley) 12/15/93 * $FreeBSD$ */ #ifndef _ARPA_TELNET_H_ #define _ARPA_TELNET_H_ /* * Definitions for the TELNET protocol. */ #define IAC 255 /* interpret as command: */ #define DONT 254 /* you are not to use option */ #define DO 253 /* please, you use option */ #define WONT 252 /* I won't use option */ #define WILL 251 /* I will use option */ #define SB 250 /* interpret as subnegotiation */ #define GA 249 /* you may reverse the line */ #define EL 248 /* erase the current line */ #define EC 247 /* erase the current character */ #define AYT 246 /* are you there */ #define AO 245 /* abort output--but let prog finish */ #define IP 244 /* interrupt process--permanently */ #define BREAK 243 /* break */ #define DM 242 /* data mark--for connect. cleaning */ #define NOP 241 /* nop */ #define SE 240 /* end sub negotiation */ #define EOR 239 /* end of record (transparent mode) */ #define ABORT 238 /* Abort process */ #define SUSP 237 /* Suspend process */ #define xEOF 236 /* End of file: EOF is already used... */ #define SYNCH 242 /* for telfunc calls */ #ifdef TELCMDS -char *telcmds[] = { +const char *telcmds[] = { "EOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0 }; #else extern char *telcmds[]; #endif #define TELCMD_FIRST xEOF #define TELCMD_LAST IAC #define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ (unsigned int)(x) >= TELCMD_FIRST) #define TELCMD(x) telcmds[(x)-TELCMD_FIRST] /* telnet options */ #define TELOPT_BINARY 0 /* 8-bit data path */ #define TELOPT_ECHO 1 /* echo */ #define TELOPT_RCP 2 /* prepare to reconnect */ #define TELOPT_SGA 3 /* suppress go ahead */ #define TELOPT_NAMS 4 /* approximate message size */ #define TELOPT_STATUS 5 /* give status */ #define TELOPT_TM 6 /* timing mark */ #define TELOPT_RCTE 7 /* remote controlled transmission and echo */ #define TELOPT_NAOL 8 /* negotiate about output line width */ #define TELOPT_NAOP 9 /* negotiate about output page size */ #define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ #define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ #define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ #define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ #define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ #define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ #define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ #define TELOPT_XASCII 17 /* extended ascic character set */ #define TELOPT_LOGOUT 18 /* force logout */ #define TELOPT_BM 19 /* byte macro */ #define TELOPT_DET 20 /* data entry terminal */ #define TELOPT_SUPDUP 21 /* supdup protocol */ #define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ #define TELOPT_SNDLOC 23 /* send location */ #define TELOPT_TTYPE 24 /* terminal type */ #define TELOPT_EOR 25 /* end or record */ #define TELOPT_TUID 26 /* TACACS user identification */ #define TELOPT_OUTMRK 27 /* output marking */ #define TELOPT_TTYLOC 28 /* terminal location number */ #define TELOPT_3270REGIME 29 /* 3270 regime */ #define TELOPT_X3PAD 30 /* X.3 PAD */ #define TELOPT_NAWS 31 /* window size */ #define TELOPT_TSPEED 32 /* terminal speed */ #define TELOPT_LFLOW 33 /* remote flow control */ #define TELOPT_LINEMODE 34 /* Linemode option */ #define TELOPT_XDISPLOC 35 /* X Display Location */ #define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ #define TELOPT_AUTHENTICATION 37/* Authenticate */ #define TELOPT_ENCRYPT 38 /* Encryption option */ #define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ #define TELOPT_EXOPL 255 /* extended-options-list */ #define NTELOPTS (1+TELOPT_NEW_ENVIRON) #ifdef TELOPTS -char *telopts[NTELOPTS+1] = { +const char *telopts[NTELOPTS+1] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON", 0 }; #define TELOPT_FIRST TELOPT_BINARY #define TELOPT_LAST TELOPT_NEW_ENVIRON #define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) #define TELOPT(x) telopts[(x)-TELOPT_FIRST] #endif /* sub-option qualifiers */ #define TELQUAL_IS 0 /* option is... */ #define TELQUAL_SEND 1 /* send option */ #define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ #define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ #define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ #define LFLOW_OFF 0 /* Disable remote flow control */ #define LFLOW_ON 1 /* Enable remote flow control */ #define LFLOW_RESTART_ANY 2 /* Restart output on any char */ #define LFLOW_RESTART_XON 3 /* Restart output only on XON */ /* * LINEMODE suboptions */ #define LM_MODE 1 #define LM_FORWARDMASK 2 #define LM_SLC 3 #define MODE_EDIT 0x01 #define MODE_TRAPSIG 0x02 #define MODE_ACK 0x04 #define MODE_SOFT_TAB 0x08 #define MODE_LIT_ECHO 0x10 #define MODE_MASK 0x1f /* Not part of protocol, but needed to simplify things... */ #define MODE_FLOW 0x0100 #define MODE_ECHO 0x0200 #define MODE_INBIN 0x0400 #define MODE_OUTBIN 0x0800 #define MODE_FORCE 0x1000 #define SLC_SYNCH 1 #define SLC_BRK 2 #define SLC_IP 3 #define SLC_AO 4 #define SLC_AYT 5 #define SLC_EOR 6 #define SLC_ABORT 7 #define SLC_EOF 8 #define SLC_SUSP 9 #define SLC_EC 10 #define SLC_EL 11 #define SLC_EW 12 #define SLC_RP 13 #define SLC_LNEXT 14 #define SLC_XON 15 #define SLC_XOFF 16 #define SLC_FORW1 17 #define SLC_FORW2 18 #define SLC_MCL 19 #define SLC_MCR 20 #define SLC_MCWL 21 #define SLC_MCWR 22 #define SLC_MCBOL 23 #define SLC_MCEOL 24 #define SLC_INSRT 25 #define SLC_OVER 26 #define SLC_ECR 27 #define SLC_EWR 28 #define SLC_EBOL 29 #define SLC_EEOL 30 #define NSLC 30 /* * For backwards compatibility, we define SLC_NAMES to be the * list of names if SLC_NAMES is not defined. */ #define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ "LNEXT", "XON", "XOFF", "FORW1", "FORW2", \ "MCL", "MCR", "MCWL", "MCWR", "MCBOL", \ "MCEOL", "INSRT", "OVER", "ECR", "EWR", \ "EBOL", "EEOL", \ 0 #ifdef SLC_NAMES -char *slc_names[] = { +const char *slc_names[] = { SLC_NAMELIST }; #else extern char *slc_names[]; #define SLC_NAMES SLC_NAMELIST #endif #define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) #define SLC_NAME(x) slc_names[x] #define SLC_NOSUPPORT 0 #define SLC_CANTCHANGE 1 #define SLC_VARIABLE 2 #define SLC_DEFAULT 3 #define SLC_LEVELBITS 0x03 #define SLC_FUNC 0 #define SLC_FLAGS 1 #define SLC_VALUE 2 #define SLC_ACK 0x80 #define SLC_FLUSHIN 0x40 #define SLC_FLUSHOUT 0x20 #define OLD_ENV_VAR 1 #define OLD_ENV_VALUE 0 #define NEW_ENV_VAR 0 #define NEW_ENV_VALUE 1 #define ENV_ESC 2 #define ENV_USERVAR 3 /* * AUTHENTICATION suboptions */ /* * Who is authenticating who ... */ #define AUTH_WHO_CLIENT 0 /* Client authenticating server */ #define AUTH_WHO_SERVER 1 /* Server authenticating client */ #define AUTH_WHO_MASK 1 /* * amount of authentication done */ #define AUTH_HOW_ONE_WAY 0 #define AUTH_HOW_MUTUAL 2 #define AUTH_HOW_MASK 2 #define AUTHTYPE_NULL 0 #define AUTHTYPE_KERBEROS_V4 1 #define AUTHTYPE_KERBEROS_V5 2 #define AUTHTYPE_SPX 3 #define AUTHTYPE_MINK 4 #define AUTHTYPE_SRA 6 #define AUTHTYPE_CNT 7 #define AUTHTYPE_TEST 99 #ifdef AUTH_NAMES -char *authtype_names[] = { +const char *authtype_names[] = { "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", NULL, "SRA", 0 }; #else extern char *authtype_names[]; #endif #define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) #define AUTHTYPE_NAME(x) authtype_names[x] /* * ENCRYPTion suboptions */ #define ENCRYPT_IS 0 /* I pick encryption type ... */ #define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ #define ENCRYPT_REPLY 2 /* Initial setup response */ #define ENCRYPT_START 3 /* Am starting to send encrypted */ #define ENCRYPT_END 4 /* Am ending encrypted */ #define ENCRYPT_REQSTART 5 /* Request you start encrypting */ #define ENCRYPT_REQEND 6 /* Request you end encrypting */ #define ENCRYPT_ENC_KEYID 7 #define ENCRYPT_DEC_KEYID 8 #define ENCRYPT_CNT 9 #define ENCTYPE_ANY 0 #define ENCTYPE_DES_CFB64 1 #define ENCTYPE_DES_OFB64 2 #define ENCTYPE_CNT 3 #ifdef ENCRYPT_NAMES -char *encrypt_names[] = { +const char *encrypt_names[] = { "IS", "SUPPORT", "REPLY", "START", "END", "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", 0 }; -char *enctype_names[] = { +const char *enctype_names[] = { "ANY", "DES_CFB64", "DES_OFB64", 0 }; #else extern char *encrypt_names[]; extern char *enctype_names[]; #endif #define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) #define ENCRYPT_NAME(x) encrypt_names[x] #define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) #define ENCTYPE_NAME(x) enctype_names[x] #endif /* !_TELNET_H_ */ Index: head/contrib/telnet/libtelnet/spx.c =================================================================== --- head/contrib/telnet/libtelnet/spx.c (revision 87138) +++ head/contrib/telnet/libtelnet/spx.c (nonexistent) @@ -1,592 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)spx.c 8.2 (Berkeley) 5/30/95"; -#endif -#endif /* not lint */ - -#ifdef SPX -/* - * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION - * ALL RIGHTS RESERVED - * - * "Digital Equipment Corporation authorizes the reproduction, - * distribution and modification of this software subject to the following - * restrictions: - * - * 1. Any partial or whole copy of this software, or any modification - * thereof, must include this copyright notice in its entirety. - * - * 2. This software is supplied "as is" with no warranty of any kind, - * expressed or implied, for any purpose, including any warranty of fitness - * or merchantibility. DIGITAL assumes no responsibility for the use or - * reliability of this software, nor promises to provide any form of - * support for it on any basis. - * - * 3. Distribution of this software is authorized only if no profit or - * remuneration of any kind is received in exchange for such distribution. - * - * 4. This software produces public key authentication certificates - * bearing an expiration date established by DIGITAL and RSA Data - * Security, Inc. It may cease to generate certificates after the expiration - * date. Any modification of this software that changes or defeats - * the expiration date or its effect is unauthorized. - * - * 5. Software that will renew or extend the expiration date of - * authentication certificates produced by this software may be obtained - * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA - * 94065, (415)595-8782, or from DIGITAL" - * - */ - -#include -#include -#include -#include "gssapi_defs.h" -#ifdef __STDC__ -#include -#endif -#ifdef NO_STRING_H -#include -#else -#include -#endif - -#include -#include "encrypt.h" -#include "auth.h" -#include "misc.h" - -extern auth_debug_mode; - -static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, - AUTHTYPE_SPX, }; -static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, - TELQUAL_NAME, }; - -#define SPX_AUTH 0 /* Authentication data follows */ -#define SPX_REJECT 1 /* Rejected (reason might follow) */ -#define SPX_ACCEPT 2 /* Accepted */ - -#ifdef ENCRYPTION -static Block session_key = { 0 }; -#endif /* ENCRYPTION */ -static Block challenge = { 0 }; - - -/*******************************************************************/ - -gss_OID_set actual_mechs; -gss_OID actual_mech_type, output_name_type; -int major_status, status, msg_ctx = 0, new_status; -int req_flags = 0, ret_flags, lifetime_rec; -gss_cred_id_t gss_cred_handle; -gss_ctx_id_t actual_ctxhandle, context_handle; -gss_buffer_desc output_token, input_token, input_name_buffer; -gss_buffer_desc status_string; -gss_name_t desired_targname, src_name; -gss_channel_bindings input_chan_bindings; -char lhostname[GSS_C_MAX_PRINTABLE_NAME]; -char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; -int to_addr=0, from_addr=0; -char *address; -gss_buffer_desc fullname_buffer; -gss_OID fullname_type; -gss_cred_id_t gss_delegated_cred_handle; - -/*******************************************************************/ - - - - static int -Data(ap, type, d, c) - Authenticator *ap; - int type; - void *d; - int c; -{ - unsigned char *p = str_data + 4; - unsigned char *cd = (unsigned char *)d; - - if (c == -1) - c = strlen((char *)cd); - - if (0) { - printf("%s:%d: [%d] (%d)", - str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", - str_data[3], - type, c); - printd(d, c); - printf("\r\n"); - } - *p++ = ap->type; - *p++ = ap->way; - *p++ = type; - while (c-- > 0) { - if ((*p++ = *cd++) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - if (str_data[3] == TELQUAL_IS) - printsub('>', &str_data[2], p - (&str_data[2])); - return(net_write(str_data, p - str_data)); -} - - int -spx_init(ap, server) - Authenticator *ap; - int server; -{ - gss_cred_id_t tmp_cred_handle; - - if (server) { - str_data[3] = TELQUAL_REPLY; - gethostname(lhostname, sizeof(lhostname)); - strcpy(targ_printable, "SERVICE:rcmd@"); - strcat(targ_printable, lhostname); - input_name_buffer.length = strlen(targ_printable); - input_name_buffer.value = targ_printable; - major_status = gss_import_name(&status, - &input_name_buffer, - GSS_C_NULL_OID, - &desired_targname); - major_status = gss_acquire_cred(&status, - desired_targname, - 0, - GSS_C_NULL_OID_SET, - GSS_C_ACCEPT, - &tmp_cred_handle, - &actual_mechs, - &lifetime_rec); - if (major_status != GSS_S_COMPLETE) return(0); - } else { - str_data[3] = TELQUAL_IS; - } - return(1); -} - - int -spx_send(ap) - Authenticator *ap; -{ - Block enckey; - int r; - - gss_OID actual_mech_type, output_name_type; - int msg_ctx = 0, new_status, status; - int req_flags = 0, ret_flags, lifetime_rec, major_status; - gss_buffer_desc output_token, input_token, input_name_buffer; - gss_buffer_desc output_name_buffer, status_string; - gss_name_t desired_targname; - gss_channel_bindings input_chan_bindings; - char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; - int from_addr=0, to_addr=0, myhostlen, j; - int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0; - char *address; - - printf("[ Trying SPX ... ]\n"); - strcpy(targ_printable, "SERVICE:rcmd@"); - strcat(targ_printable, RemoteHostName); - - input_name_buffer.length = strlen(targ_printable); - input_name_buffer.value = targ_printable; - - if (!UserNameRequested) { - return(0); - } - - major_status = gss_import_name(&status, - &input_name_buffer, - GSS_C_NULL_OID, - &desired_targname); - - - major_status = gss_display_name(&status, - desired_targname, - &output_name_buffer, - &output_name_type); - - printf("target is '%s'\n", output_name_buffer.value); fflush(stdout); - - major_status = gss_release_buffer(&status, &output_name_buffer); - - input_chan_bindings = (gss_channel_bindings) - malloc(sizeof(gss_channel_bindings_desc)); - - input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; - input_chan_bindings->initiator_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->initiator_address.value = (char *) address; - address[0] = ((from_addr & 0xff000000) >> 24); - address[1] = ((from_addr & 0xff0000) >> 16); - address[2] = ((from_addr & 0xff00) >> 8); - address[3] = (from_addr & 0xff); - input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; - input_chan_bindings->acceptor_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->acceptor_address.value = (char *) address; - address[0] = ((to_addr & 0xff000000) >> 24); - address[1] = ((to_addr & 0xff0000) >> 16); - address[2] = ((to_addr & 0xff00) >> 8); - address[3] = (to_addr & 0xff); - input_chan_bindings->application_data.length = 0; - - req_flags = 0; - if (deleg_flag) req_flags = req_flags | 1; - if (mutual_flag) req_flags = req_flags | 2; - if (replay_flag) req_flags = req_flags | 4; - if (seq_flag) req_flags = req_flags | 8; - - major_status = gss_init_sec_context(&status, /* minor status */ - GSS_C_NO_CREDENTIAL, /* cred handle */ - &actual_ctxhandle, /* ctx handle */ - desired_targname, /* target name */ - GSS_C_NULL_OID, /* mech type */ - req_flags, /* req flags */ - 0, /* time req */ - input_chan_bindings, /* chan binding */ - GSS_C_NO_BUFFER, /* input token */ - &actual_mech_type, /* actual mech */ - &output_token, /* output token */ - &ret_flags, /* ret flags */ - &lifetime_rec); /* time rec */ - - if ((major_status != GSS_S_COMPLETE) && - (major_status != GSS_S_CONTINUE_NEEDED)) { - gss_display_status(&new_status, - status, - GSS_C_MECH_CODE, - GSS_C_NULL_OID, - &msg_ctx, - &status_string); - printf("%s\n", status_string.value); - return(0); - } - - if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { - return(0); - } - - if (!Data(ap, SPX_AUTH, (void *)output_token.value, output_token.length)) { - return(0); - } - - return(1); -} - - void -spx_is(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; -{ - Session_Key skey; - Block datablock; - int r; - - if (cnt-- < 1) - return; - switch (*data++) { - case SPX_AUTH: - input_token.length = cnt; - input_token.value = (char *) data; - - gethostname(lhostname, sizeof(lhostname)); - - strcpy(targ_printable, "SERVICE:rcmd@"); - strcat(targ_printable, lhostname); - - input_name_buffer.length = strlen(targ_printable); - input_name_buffer.value = targ_printable; - - major_status = gss_import_name(&status, - &input_name_buffer, - GSS_C_NULL_OID, - &desired_targname); - - major_status = gss_acquire_cred(&status, - desired_targname, - 0, - GSS_C_NULL_OID_SET, - GSS_C_ACCEPT, - &gss_cred_handle, - &actual_mechs, - &lifetime_rec); - - major_status = gss_release_name(&status, desired_targname); - - input_chan_bindings = (gss_channel_bindings) - malloc(sizeof(gss_channel_bindings_desc)); - - input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; - input_chan_bindings->initiator_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->initiator_address.value = (char *) address; - address[0] = ((from_addr & 0xff000000) >> 24); - address[1] = ((from_addr & 0xff0000) >> 16); - address[2] = ((from_addr & 0xff00) >> 8); - address[3] = (from_addr & 0xff); - input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; - input_chan_bindings->acceptor_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->acceptor_address.value = (char *) address; - address[0] = ((to_addr & 0xff000000) >> 24); - address[1] = ((to_addr & 0xff0000) >> 16); - address[2] = ((to_addr & 0xff00) >> 8); - address[3] = (to_addr & 0xff); - input_chan_bindings->application_data.length = 0; - - major_status = gss_accept_sec_context(&status, - &context_handle, - gss_cred_handle, - &input_token, - input_chan_bindings, - &src_name, - &actual_mech_type, - &output_token, - &ret_flags, - &lifetime_rec, - &gss_delegated_cred_handle); - - - if (major_status != GSS_S_COMPLETE) { - - major_status = gss_display_name(&status, - src_name, - &fullname_buffer, - &fullname_type); - Data(ap, SPX_REJECT, (void *)"auth failed", -1); - auth_finished(ap, AUTH_REJECT); - return; - } - - major_status = gss_display_name(&status, - src_name, - &fullname_buffer, - &fullname_type); - - - Data(ap, SPX_ACCEPT, (void *)output_token.value, output_token.length); - auth_finished(ap, AUTH_USER); - break; - - default: - Data(ap, SPX_REJECT, 0, 0); - break; - } -} - - - void -spx_reply(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; -{ - Session_Key skey; - - if (cnt-- < 1) - return; - switch (*data++) { - case SPX_REJECT: - if (cnt > 0) { - printf("[ SPX refuses authentication because %.*s ]\r\n", - cnt, data); - } else - printf("[ SPX refuses authentication ]\r\n"); - auth_send_retry(); - return; - case SPX_ACCEPT: - printf("[ SPX accepts you ]\n"); - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* - * Send over the encrypted challenge. - */ - input_token.value = (char *) data; - input_token.length = cnt; - - major_status = gss_init_sec_context(&status, /* minor stat */ - GSS_C_NO_CREDENTIAL, /* cred handle */ - &actual_ctxhandle, /* ctx handle */ - desired_targname, /* target name */ - GSS_C_NULL_OID, /* mech type */ - req_flags, /* req flags */ - 0, /* time req */ - input_chan_bindings, /* chan binding */ - &input_token, /* input token */ - &actual_mech_type, /* actual mech */ - &output_token, /* output token */ - &ret_flags, /* ret flags */ - &lifetime_rec); /* time rec */ - - if (major_status != GSS_S_COMPLETE) { - gss_display_status(&new_status, - status, - GSS_C_MECH_CODE, - GSS_C_NULL_OID, - &msg_ctx, - &status_string); - printf("[ SPX mutual response fails ... '%s' ]\r\n", - status_string.value); - auth_send_retry(); - return; - } - } - auth_finished(ap, AUTH_USER); - return; - - default: - return; - } -} - - int -spx_status(ap, name, level) - Authenticator *ap; - char *name; - int level; -{ - - gss_buffer_desc fullname_buffer, acl_file_buffer; - gss_OID fullname_type; - char acl_file[160], fullname[160]; - int major_status, status = 0; - struct passwd *pwd; - - /* - * hard code fullname to - * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan" - * and acl_file to "~kannan/.sphinx" - */ - - pwd = getpwnam(UserNameRequested); - if (pwd == NULL) { - return(AUTH_USER); /* not authenticated */ - } - - strcpy(acl_file, pwd->pw_dir); - strcat(acl_file, "/.sphinx"); - acl_file_buffer.value = acl_file; - acl_file_buffer.length = strlen(acl_file); - - major_status = gss_display_name(&status, - src_name, - &fullname_buffer, - &fullname_type); - - if (level < AUTH_USER) - return(level); - - major_status = gss__check_acl(&status, &fullname_buffer, - &acl_file_buffer); - - if (major_status == GSS_S_COMPLETE) { - strcpy(name, UserNameRequested); - return(AUTH_VALID); - } else { - return(AUTH_USER); - } - -} - -#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} -#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - - void -spx_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; -{ - char lbuf[32]; - register int i; - - buf[buflen-1] = '\0'; /* make sure its NULL terminated */ - buflen -= 1; - - switch(data[3]) { - case SPX_REJECT: /* Rejected (reason might follow) */ - strncpy((char *)buf, " REJECT ", buflen); - goto common; - - case SPX_ACCEPT: /* Accepted (name might follow) */ - strncpy((char *)buf, " ACCEPT ", buflen); - common: - BUMP(buf, buflen); - if (cnt <= 4) - break; - ADDC(buf, buflen, '"'); - for (i = 4; i < cnt; i++) - ADDC(buf, buflen, data[i]); - ADDC(buf, buflen, '"'); - ADDC(buf, buflen, '\0'); - break; - - case SPX_AUTH: /* Authentication data follows */ - strncpy((char *)buf, " AUTH", buflen); - goto common2; - - default: - sprintf(lbuf, " %d (unknown)", data[3]); - strncpy((char *)buf, lbuf, buflen); - common2: - BUMP(buf, buflen); - for (i = 4; i < cnt; i++) { - sprintf(lbuf, " %d", data[i]); - strncpy((char *)buf, lbuf, buflen); - BUMP(buf, buflen); - } - break; - } -} - -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); -} -#endif Property changes on: head/contrib/telnet/libtelnet/spx.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/contrib/telnet/libtelnet/auth-proto.h =================================================================== --- head/contrib/telnet/libtelnet/auth-proto.h (revision 87138) +++ head/contrib/telnet/libtelnet/auth-proto.h (revision 87139) @@ -1,109 +1,119 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)auth-proto.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #if !defined(P) #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #endif -#if defined(AUTHENTICATION) -Authenticator *findauthenticator P((int, int)); +#ifdef AUTHENTICATION -void auth_init P((char *, int)); -int auth_cmd P((int, char **)); -void auth_request P((void)); -void auth_send P((unsigned char *, int)); -void auth_send_retry P((void)); -void auth_is P((unsigned char *, int)); -void auth_reply P((unsigned char *, int)); -void auth_finished P((Authenticator *, int)); -int auth_wait P((char *)); -void auth_disable_name P((char *)); -void auth_gen_printsub P((unsigned char *, int, unsigned char *, int)); -void auth_name P((unsigned char *, int)); -void auth_printsub P((unsigned char *, int, unsigned char *, int)); -int auth_sendname P((unsigned char *, int)); -void auth_encrypt_user P((char *)); +Authenticator *findauthenticator(int, int); +void auth_init(const char *, int); +int auth_cmd(int, char **); +void auth_request(void); +void auth_send(unsigned char *, int); +void auth_send_retry(void); +void auth_is(unsigned char *, int); +void auth_reply(unsigned char *, int); +void auth_finished(Authenticator *, int); +int auth_wait(char *); +void auth_disable_name(char *); +void auth_gen_printsub(unsigned char *, int, unsigned char *, int); +void auth_name(unsigned char *, int); +void auth_printsub(unsigned char *, int, unsigned char *, int); +int auth_sendname(unsigned char *, int); +void auth_encrypt_user(char *); +int auth_disable(char *); +int auth_enable(char *); +int auth_togdebug(int); +int auth_status(void); + +int getauthmask(char *, int *); + #ifdef KRB4 -int kerberos4_init P((Authenticator *, int)); -int kerberos4_send P((Authenticator *)); -void kerberos4_is P((Authenticator *, unsigned char *, int)); -void kerberos4_reply P((Authenticator *, unsigned char *, int)); -int kerberos4_status P((Authenticator *, char *, int)); -void kerberos4_printsub P((unsigned char *, int, unsigned char *, int)); +int kerberos4_init(Authenticator *, int); +int kerberos4_send(Authenticator *); +void kerberos4_is(Authenticator *, unsigned char *, int); +void kerberos4_reply(Authenticator *, unsigned char *, int); +int kerberos4_status(Authenticator *, char *, int); +void kerberos4_printsub(unsigned char *, int, unsigned char *, int); #endif #ifdef KRB5 -int kerberos5_init P((Authenticator *, int)); -int kerberos5_send P((Authenticator *)); -void kerberos5_is P((Authenticator *, unsigned char *, int)); -void kerberos5_reply P((Authenticator *, unsigned char *, int)); -int kerberos5_status P((Authenticator *, char *, int)); -void kerberos5_printsub P((unsigned char *, int, unsigned char *, int)); +int kerberos5_init(Authenticator *, int); +int kerberos5_send_mutual(Authenticator *); +int kerberos5_send_oneway(Authenticator *); +void kerberos5_is(Authenticator *, unsigned char *, int); +void kerberos5_reply(Authenticator *, unsigned char *, int); +int kerberos5_status(Authenticator *, char *, int level); +void kerberos5_printsub(unsigned char *, int, unsigned char *, int); #endif + #ifdef SRA -int sra_init P((Authenticator *, int)); -int sra_send P((Authenticator *)); -void sra_is P((Authenticator *, unsigned char *, int)); -void sra_reply P((Authenticator *, unsigned char *, int)); -int sra_status P((Authenticator *, char *, int)); -void sra_printsub P((unsigned char *, int, unsigned char *, int)); +int sra_init(Authenticator *, int); +int sra_send(Authenticator *); +void sra_is(Authenticator *, unsigned char *, int); +void sra_reply(Authenticator *, unsigned char *, int); +int sra_status(Authenticator *, char *, int); +void sra_printsub(unsigned char *, int, unsigned char *, int); #endif + #endif Index: head/contrib/telnet/libtelnet/auth.c =================================================================== --- head/contrib/telnet/libtelnet/auth.c (revision 87138) +++ head/contrib/telnet/libtelnet/auth.c (revision 87139) @@ -1,689 +1,623 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)auth.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ -#if defined(AUTHENTICATION) -#include +#ifdef AUTHENTICATION +#define AUTH_NAMES #include #include -#define AUTH_NAMES -#include -#ifdef __STDC__ +#include #include -#include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif +#include +#include #include "encrypt.h" #include "auth.h" #include "misc-proto.h" #include "auth-proto.h" -#define typemask(x) (1<<((x)-1)) +#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) #ifdef KRB4_ENCPWD extern krb4encpwd_init(); extern krb4encpwd_send(); extern krb4encpwd_is(); extern krb4encpwd_reply(); extern krb4encpwd_status(); extern krb4encpwd_printsub(); #endif #ifdef RSA_ENCPWD extern rsaencpwd_init(); extern rsaencpwd_send(); extern rsaencpwd_is(); extern rsaencpwd_reply(); extern rsaencpwd_status(); extern rsaencpwd_printsub(); #endif int auth_debug_mode = 0; -static char *Name = "Noname"; +static const char *Name = "Noname"; static int Server = 0; static Authenticator *authenticated = 0; static int authenticating = 0; static int validuser = 0; static unsigned char _auth_send_data[256]; static unsigned char *auth_send_data; static int auth_send_cnt = 0; int auth_onoff(char *type, int on); void auth_encrypt_user(char *name); /* * Authentication types supported. Plese note that these are stored * in priority order, i.e. try the first one first. */ Authenticator authenticators[] = { -#ifdef SPX - { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, - spx_init, - spx_send, - spx_is, - spx_reply, - spx_status, - spx_printsub }, - { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - spx_init, - spx_send, - spx_is, - spx_reply, - spx_status, - spx_printsub }, -#endif #ifdef KRB5 # ifdef ENCRYPTION { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, kerberos5_init, - kerberos5_send, + kerberos5_send_mutual, kerberos5_is, kerberos5_reply, kerberos5_status, kerberos5_printsub }, # endif /* ENCRYPTION */ { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, kerberos5_init, - kerberos5_send, + kerberos5_send_oneway, kerberos5_is, kerberos5_reply, kerberos5_status, kerberos5_printsub }, #endif #ifdef KRB4 # ifdef ENCRYPTION { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, kerberos4_init, kerberos4_send, kerberos4_is, kerberos4_reply, kerberos4_status, kerberos4_printsub }, # endif /* ENCRYPTION */ { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, kerberos4_init, kerberos4_send, kerberos4_is, kerberos4_reply, kerberos4_status, kerberos4_printsub }, #endif #ifdef KRB4_ENCPWD { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, krb4encpwd_init, krb4encpwd_send, krb4encpwd_is, krb4encpwd_reply, krb4encpwd_status, krb4encpwd_printsub }, #endif #ifdef RSA_ENCPWD { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, rsaencpwd_init, rsaencpwd_send, rsaencpwd_is, rsaencpwd_reply, rsaencpwd_status, rsaencpwd_printsub }, #endif #ifdef SRA { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, sra_init, sra_send, sra_is, sra_reply, sra_status, sra_printsub }, #endif - { 0, }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, }; -static Authenticator NoAuth = { 0 }; +static Authenticator NoAuth = { 0, 0, 0, 0, 0, 0, 0, 0 }; static int i_support = 0; static int i_wont_support = 0; - Authenticator * -findauthenticator(type, way) - int type; - int way; +Authenticator * +findauthenticator(int type, int way) { Authenticator *ap = authenticators; while (ap->type && (ap->type != type || ap->way != way)) ++ap; return(ap->type ? ap : 0); } - void -auth_init(name, server) - char *name; - int server; +void +auth_init(const char *name, int server) { Authenticator *ap = authenticators; Server = server; Name = name; i_support = 0; authenticated = 0; authenticating = 0; while (ap->type) { if (!ap->init || (*ap->init)(ap, server)) { i_support |= typemask(ap->type); if (auth_debug_mode) printf(">>>%s: I support auth type %d %d\r\n", Name, ap->type, ap->way); } else if (auth_debug_mode) printf(">>>%s: Init failed: auth type %d %d\r\n", Name, ap->type, ap->way); ++ap; } } - void -auth_disable_name(name) - char *name; +void +auth_disable_name(char *name) { int x; for (x = 0; x < AUTHTYPE_CNT; ++x) { if (AUTHTYPE_NAME(x) && !strcasecmp(name, AUTHTYPE_NAME(x))) { i_wont_support |= typemask(x); break; } } } - int -getauthmask(type, maskp) - char *type; - int *maskp; +int +getauthmask(char *type, int *maskp) { - register int x; + int x; if (AUTHTYPE_NAME(0) && !strcasecmp(type, AUTHTYPE_NAME(0))) { *maskp = -1; return(1); } for (x = 1; x < AUTHTYPE_CNT; ++x) { if (AUTHTYPE_NAME(x) && !strcasecmp(type, AUTHTYPE_NAME(x))) { *maskp = typemask(x); return(1); } } return(0); } - int -auth_enable(type) - char *type; +int +auth_enable(char *type) { return(auth_onoff(type, 1)); } - int -auth_disable(type) - char *type; +int +auth_disable(char *type) { return(auth_onoff(type, 0)); } - int -auth_onoff(type, on) - char *type; - int on; +int +auth_onoff(char *type, int on) { int i, mask = -1; Authenticator *ap; if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) { printf("auth %s 'type'\n", on ? "enable" : "disable"); printf("Where 'type' is one of:\n"); printf("\t%s\n", AUTHTYPE_NAME(0)); mask = 0; for (ap = authenticators; ap->type; ap++) { if ((mask & (i = typemask(ap->type))) != 0) continue; mask |= i; printf("\t%s\n", AUTHTYPE_NAME(ap->type)); } return(0); } if (!getauthmask(type, &mask)) { printf("%s: invalid authentication type\n", type); return(0); } if (on) i_wont_support &= ~mask; else i_wont_support |= mask; return(1); } - int -auth_togdebug(on) - int on; +int +auth_togdebug(int on) { if (on < 0) auth_debug_mode ^= 1; else auth_debug_mode = on; printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled"); return(1); } - int -auth_status() +int +auth_status(void) { Authenticator *ap; int i, mask; if (i_wont_support == -1) printf("Authentication disabled\n"); else printf("Authentication enabled\n"); mask = 0; for (ap = authenticators; ap->type; ap++) { if ((mask & (i = typemask(ap->type))) != 0) continue; mask |= i; printf("%s: %s\n", AUTHTYPE_NAME(ap->type), (i_wont_support & typemask(ap->type)) ? "disabled" : "enabled"); } return(1); } /* * This routine is called by the server to start authentication * negotiation. */ - void -auth_request() +void +auth_request(void) { static unsigned char str_request[64] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_SEND, }; Authenticator *ap = authenticators; unsigned char *e = str_request + 4; if (!authenticating) { authenticating = 1; while (ap->type) { if (i_support & ~i_wont_support & typemask(ap->type)) { if (auth_debug_mode) { printf(">>>%s: Sending type %d %d\r\n", Name, ap->type, ap->way); } *e++ = ap->type; *e++ = ap->way; } ++ap; } *e++ = IAC; *e++ = SE; net_write(str_request, e - str_request); printsub('>', &str_request[2], e - str_request - 2); } } /* * This is called when an AUTH SEND is received. * It should never arrive on the server side (as only the server can * send an AUTH SEND). * You should probably respond to it if you can... * * If you want to respond to the types out of order (i.e. even * if he sends LOGIN KERBEROS and you support both, you respond * with KERBEROS instead of LOGIN (which is against what the * protocol says)) you will have to hack this code... */ - void -auth_send(data, cnt) - unsigned char *data; - int cnt; +void +auth_send(unsigned char *data, int cnt) { Authenticator *ap; static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_IS, AUTHTYPE_NULL, 0, IAC, SE }; if (Server) { if (auth_debug_mode) { printf(">>>%s: auth_send called!\r\n", Name); } return; } if (auth_debug_mode) { printf(">>>%s: auth_send got:", Name); printd(data, cnt); printf("\r\n"); } /* * Save the data, if it is new, so that we can continue looking * at it if the authorization we try doesn't work */ if (data < _auth_send_data || data > _auth_send_data + sizeof(_auth_send_data)) { - auth_send_cnt = cnt > sizeof(_auth_send_data) + auth_send_cnt = (size_t)cnt > sizeof(_auth_send_data) ? sizeof(_auth_send_data) : cnt; memmove((void *)_auth_send_data, (void *)data, auth_send_cnt); auth_send_data = _auth_send_data; } else { /* * This is probably a no-op, but we just make sure */ auth_send_data = data; auth_send_cnt = cnt; } while ((auth_send_cnt -= 2) >= 0) { if (auth_debug_mode) printf(">>>%s: He supports %d\r\n", Name, *auth_send_data); if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) { ap = findauthenticator(auth_send_data[0], auth_send_data[1]); if (ap && ap->send) { if (auth_debug_mode) printf(">>>%s: Trying %d %d\r\n", Name, auth_send_data[0], auth_send_data[1]); if ((*ap->send)(ap)) { /* * Okay, we found one we like * and did it. * we can go home now. */ if (auth_debug_mode) printf(">>>%s: Using type %d\r\n", Name, *auth_send_data); auth_send_data += 2; return; } } /* else * just continue on and look for the * next one if we didn't do anything. */ } auth_send_data += 2; } net_write(str_none, sizeof(str_none)); printsub('>', &str_none[2], sizeof(str_none) - 2); if (auth_debug_mode) printf(">>>%s: Sent failure message\r\n", Name); auth_finished(0, AUTH_REJECT); -#ifdef KANNAN - /* - * We requested strong authentication, however no mechanisms worked. - * Therefore, exit on client end. - */ - printf("Unable to securely authenticate user ... exit\n"); - exit(0); -#endif /* KANNAN */ } - void -auth_send_retry() +void +auth_send_retry(void) { /* * if auth_send_cnt <= 0 then auth_send will end up rejecting * the authentication and informing the other side of this. */ auth_send(auth_send_data, auth_send_cnt); } - void -auth_is(data, cnt) - unsigned char *data; - int cnt; +void +auth_is(unsigned char *data, int cnt) { Authenticator *ap; if (cnt < 2) return; if (data[0] == AUTHTYPE_NULL) { auth_finished(0, AUTH_REJECT); return; } if ((ap = findauthenticator(data[0], data[1]))) { if (ap->is) (*ap->is)(ap, data+2, cnt-2); } else if (auth_debug_mode) printf(">>>%s: Invalid authentication in IS: %d\r\n", Name, *data); } - void -auth_reply(data, cnt) - unsigned char *data; - int cnt; +void +auth_reply(unsigned char *data, int cnt) { Authenticator *ap; if (cnt < 2) return; if ((ap = findauthenticator(data[0], data[1]))) { if (ap->reply) (*ap->reply)(ap, data+2, cnt-2); } else if (auth_debug_mode) printf(">>>%s: Invalid authentication in SEND: %d\r\n", Name, *data); } - void -auth_name(data, cnt) - unsigned char *data; - int cnt; +void +auth_name(unsigned char *data, int cnt) { unsigned char savename[256]; if (cnt < 1) { if (auth_debug_mode) printf(">>>%s: Empty name in NAME\r\n", Name); return; } - if (cnt > sizeof(savename) - 1) { + if ((size_t)cnt > sizeof(savename) - 1) { if (auth_debug_mode) printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n", Name, cnt, sizeof(savename)-1); return; } memmove((void *)savename, (void *)data, cnt); savename[cnt] = '\0'; /* Null terminate */ if (auth_debug_mode) printf(">>>%s: Got NAME [%s]\r\n", Name, savename); auth_encrypt_user(savename); } - int -auth_sendname(cp, len) - unsigned char *cp; - int len; +int +auth_sendname(unsigned char *cp, int len) { static unsigned char str_request[256+6] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; - register unsigned char *e = str_request + 4; - register unsigned char *ee = &str_request[sizeof(str_request)-2]; + unsigned char *e = str_request + 4; + unsigned char *ee = &str_request[sizeof(str_request)-2]; while (--len >= 0) { if ((*e++ = *cp++) == IAC) *e++ = IAC; if (e >= ee) return(0); } *e++ = IAC; *e++ = SE; net_write(str_request, e - str_request); printsub('>', &str_request[2], e - &str_request[2]); return(1); } - void -auth_finished(ap, result) - Authenticator *ap; - int result; +void +auth_finished(Authenticator *ap, int result) { if (!(authenticated = ap)) authenticated = &NoAuth; validuser = result; } - /* ARGSUSED */ - static void -auth_intr(sig) - int sig; +/* ARGSUSED */ +static void +auth_intr(int sig __unused) { auth_finished(0, AUTH_REJECT); } - int -auth_wait(name) - char *name; +int +auth_wait(char *name) { if (auth_debug_mode) printf(">>>%s: in auth_wait.\r\n", Name); if (Server && !authenticating) return(0); (void) signal(SIGALRM, auth_intr); alarm(30); while (!authenticated) if (telnet_spin()) break; alarm(0); (void) signal(SIGALRM, SIG_DFL); /* * Now check to see if the user is valid or not */ if (!authenticated || authenticated == &NoAuth) return(AUTH_REJECT); if (validuser == AUTH_VALID) validuser = AUTH_USER; if (authenticated->status) validuser = (*authenticated->status)(authenticated, name, validuser); return(validuser); } - void -auth_debug(mode) - int mode; +void +auth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - auth_debug_mode = mode; -} - - void -auth_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; -{ Authenticator *ap; if ((ap = findauthenticator(data[1], data[2])) && ap->printsub) (*ap->printsub)(data, cnt, buf, buflen); else auth_gen_printsub(data, cnt, buf, buflen); } - void -auth_gen_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - register unsigned char *cp; + unsigned char *cp; unsigned char tbuf[16]; cnt -= 3; data += 3; buf[buflen-1] = '\0'; buf[buflen-2] = '*'; buflen -= 2; for (; cnt > 0; cnt--, data++) { sprintf((char *)tbuf, " %d", *data); for (cp = tbuf; *cp && buflen > 0; --buflen) *buf++ = *cp++; if (buflen <= 0) return; } *buf = '\0'; } #endif Index: head/contrib/telnet/libtelnet/auth.h =================================================================== --- head/contrib/telnet/libtelnet/auth.h (revision 87138) +++ head/contrib/telnet/libtelnet/auth.h (revision 87139) @@ -1,88 +1,80 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)auth.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifndef __AUTH__ #define __AUTH__ #define AUTH_REJECT 0 /* Rejected */ #define AUTH_UNKNOWN 1 /* We don't know who he is, but he's okay */ #define AUTH_OTHER 2 /* We know him, but not his name */ #define AUTH_USER 3 /* We know he name */ #define AUTH_VALID 4 /* We know him, and he needs no password */ -#if !defined(P) -#ifdef __STDC__ -#define P(x) x -#else -#define P(x) () -#endif -#endif - typedef struct XauthP { int type; int way; - int (*init) P((struct XauthP *, int)); - int (*send) P((struct XauthP *)); - void (*is) P((struct XauthP *, unsigned char *, int)); - void (*reply) P((struct XauthP *, unsigned char *, int)); - int (*status) P((struct XauthP *, char *, int)); - void (*printsub) P((unsigned char *, int, unsigned char *, int)); + int (*init)(struct XauthP *, int); + int (*send)(struct XauthP *); + void (*is)(struct XauthP *, unsigned char *, int); + void (*reply)(struct XauthP *, unsigned char *, int); + int (*status)(struct XauthP *, char *, int); + void (*printsub)(unsigned char *, int, unsigned char *, int); } Authenticator; #include "auth-proto.h" extern int auth_debug_mode; #endif Index: head/contrib/telnet/libtelnet/enc-proto.h =================================================================== --- head/contrib/telnet/libtelnet/enc-proto.h (revision 87138) +++ head/contrib/telnet/libtelnet/enc-proto.h (revision 87139) @@ -1,129 +1,133 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)enc-proto.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #if !defined(P) #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #endif #ifdef ENCRYPTION -void encrypt_init P((char *, int)); -Encryptions *findencryption P((int)); -void encrypt_send_supprt P((void)); -void encrypt_auto P((int)); -void decrypt_auto P((int)); -void encrypt_is P((unsigned char *, int)); -void encrypt_reply P((unsigned char *, int)); -void encrypt_start_input P((int)); -void encrypt_session_key P((Session_Key *, int)); -void encrypt_end_input P((void)); -void encrypt_start_output P((int)); -void encrypt_end_output P((void)); -void encrypt_send_request_start P((void)); -void encrypt_send_request_end P((void)); -void encrypt_send_end P((void)); -void encrypt_wait P((void)); -void encrypt_send_support P((void)); -void encrypt_send_keyid P((int, unsigned char *, int, int)); -void encrypt_start P((unsigned char *, int)); -void encrypt_end P((void)); -void encrypt_support P((unsigned char *, int)); -void encrypt_request_start P((unsigned char *, int)); -void encrypt_request_end P((void)); -void encrypt_enc_keyid P((unsigned char *, int)); -void encrypt_dec_keyid P((unsigned char *, int)); -void encrypt_printsub P((unsigned char *, int, unsigned char *, int)); -int net_write P((unsigned char *, int)); +void encrypt_init(const char *, int); +Encryptions *findencryption(int); +void encrypt_send_supprt(void); +void encrypt_auto(int); +void decrypt_auto(int); +void encrypt_is(unsigned char *, int); +void encrypt_reply(unsigned char *, int); +void encrypt_start_input(int); +void encrypt_session_key(Session_Key *, int); +void encrypt_end_input(void); +void encrypt_start_output(int); +void encrypt_end_output(void); +void encrypt_send_request_start(void); +void encrypt_send_request_end(void); +void encrypt_send_end(void); +void encrypt_wait(void); +void encrypt_send_support(void); +void encrypt_send_keyid(int, const char *, int, int); +void encrypt_start(unsigned char *, int); +void encrypt_end(void); +void encrypt_support(unsigned char *, int); +void encrypt_request_start(unsigned char *, int); +void encrypt_request_end(void); +void encrypt_enc_keyid(unsigned char *, int); +void encrypt_dec_keyid(unsigned char *, int); +void encrypt_printsub(unsigned char *, int, unsigned char *, int); +void encrypt_gen_printsub(unsigned char *, int, unsigned char *, int); +void encrypt_display(void); -#ifndef TELENTD -int encrypt_cmd P((int, char **)); -void encrypt_display P((void)); -#endif +void fb64_printsub(unsigned char *, int, unsigned char *, int, const char *); -#ifdef DES_ENCRYPTION -void krbdes_encrypt P((unsigned char *, int)); -int krbdes_decrypt P((int)); -int krbdes_is P((unsigned char *, int)); -int krbdes_reply P((unsigned char *, int)); -void krbdes_init P((int)); -int krbdes_start P((int, int)); -void krbdes_session P((Session_Key *, int)); -void krbdes_printsub P((unsigned char *, int, unsigned char *, int)); +int EncryptEnable(char *, char *); +int EncryptDisable(char *, char *); +int EncryptStatus(void); +int EncryptDebug(int); +int EncryptVerbose(int); +int EncryptAutoEnc(int); +int EncryptAutoDec(int); -void cfb64_encrypt P((unsigned char *, int)); -int cfb64_decrypt P((int)); -void cfb64_init P((int)); -int cfb64_start P((int, int)); -int cfb64_is P((unsigned char *, int)); -int cfb64_reply P((unsigned char *, int)); -void cfb64_session P((Session_Key *, int)); -int cfb64_keyid P((int, unsigned char *, int *)); -void cfb64_printsub P((unsigned char *, int, unsigned char *, int)); +void krbdes_encrypt(unsigned char *, int); +int krbdes_decrypt(int); +int krbdes_is(unsigned char *, int); +int krbdes_reply(unsigned char *, int); +void krbdes_init(int); +int krbdes_start(int, int); +void krbdes_session(Session_Key *, int); +void krbdes_printsub(unsigned char *, int, unsigned char *, int); -void ofb64_encrypt P((unsigned char *, int)); -int ofb64_decrypt P((int)); -void ofb64_init P((int)); -int ofb64_start P((int, int)); -int ofb64_is P((unsigned char *, int)); -int ofb64_reply P((unsigned char *, int)); -void ofb64_session P((Session_Key *, int)); -int ofb64_keyid P((int, unsigned char *, int *)); -void ofb64_printsub P((unsigned char *, int, unsigned char *, int)); -#endif /* DES_ENCRYPTION */ +void cfb64_encrypt(unsigned char *, int); +int cfb64_decrypt(int); +void cfb64_init(int); +int cfb64_start(int, int); +int cfb64_is(unsigned char *, int); +int cfb64_reply(unsigned char *, int); +void cfb64_session(Session_Key *, int); +int cfb64_keyid(int, unsigned char *, int *); +void cfb64_printsub(unsigned char *, int, unsigned char *, int); + +void ofb64_encrypt(unsigned char *, int); +int ofb64_decrypt(int); +void ofb64_init(int); +int ofb64_start(int, int); +int ofb64_is(unsigned char *, int); +int ofb64_reply(unsigned char *, int); +void ofb64_session(Session_Key *, int); +int ofb64_keyid(int, unsigned char *, int *); +void ofb64_printsub(unsigned char *, int, unsigned char *, int); #endif /* ENCRYPTION */ Index: head/contrib/telnet/libtelnet/enc_des.c =================================================================== --- head/contrib/telnet/libtelnet/enc_des.c (revision 87138) +++ head/contrib/telnet/libtelnet/enc_des.c (revision 87139) @@ -1,726 +1,670 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ #ifdef ENCRYPTION # ifdef AUTHENTICATION -# ifdef DES_ENCRYPTION #include +#include #include -#ifdef __STDC__ #include -#endif - -#include #include + #include "encrypt.h" #include "key-proto.h" #include "misc-proto.h" extern int encrypt_debug_mode; void des_set_random_generator_seed(des_cblock *); /* XXX */ #define CFB 0 #define OFB 1 #define NO_SEND_IV 1 #define NO_RECV_IV 2 #define NO_KEYID 4 #define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) #define SUCCESS 0 #define FAILED -1 struct fb { Block krbdes_key; Schedule krbdes_sched; Block temp_feed; unsigned char fb_feed[64]; int need_start; int state[2]; int keyid[2]; int once; struct stinfo { Block str_output; Block str_feed; Block str_iv; Block str_ikey; Schedule str_sched; int str_index; int str_flagshift; } streams[2]; }; static struct fb fb[2]; struct keyidlist { - char *keyid; + const char *keyid; int keyidlen; char *key; int keylen; int flags; } keyidlist [] = { { "\0", 1, 0, 0, 0 }, /* default key of zero */ { 0, 0, 0, 0, 0 } }; #define KEYFLAG_MASK 03 #define KEYFLAG_NOINIT 00 #define KEYFLAG_INIT 01 #define KEYFLAG_OK 02 #define KEYFLAG_BAD 03 #define KEYFLAG_SHIFT 2 #define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) #define FB64_IV 1 #define FB64_IV_OK 2 #define FB64_IV_BAD 3 void fb64_stream_iv P((Block, struct stinfo *)); void fb64_init P((struct fb *)); static int fb64_start P((struct fb *, int, int)); int fb64_is P((unsigned char *, int, struct fb *)); int fb64_reply P((unsigned char *, int, struct fb *)); static void fb64_session P((Session_Key *, int, struct fb *)); void fb64_stream_key P((Block, struct stinfo *)); int fb64_keyid P((int, unsigned char *, int *, struct fb *)); - void -cfb64_init(server) - int server; +void +cfb64_init(int server __unused) { fb64_init(&fb[CFB]); fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); } - void -ofb64_init(server) - int server; +void +ofb64_init(int server __unused) { fb64_init(&fb[OFB]); fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); } - void -fb64_init(fbp) - register struct fb *fbp; +void +fb64_init(struct fb *fbp) { memset((void *)fbp, 0, sizeof(*fbp)); fbp->state[0] = fbp->state[1] = FAILED; fbp->fb_feed[0] = IAC; fbp->fb_feed[1] = SB; fbp->fb_feed[2] = TELOPT_ENCRYPT; fbp->fb_feed[3] = ENCRYPT_IS; } /* * Returns: * -1: some error. Negotiation is done, encryption not ready. * 0: Successful, initial negotiation all done. * 1: successful, negotiation not done yet. * 2: Not yet. Other things (like getting the key from * Kerberos) have to happen before we can continue. */ - int -cfb64_start(dir, server) - int dir; - int server; +int +cfb64_start(int dir, int server) { return(fb64_start(&fb[CFB], dir, server)); } - int -ofb64_start(dir, server) - int dir; - int server; + +int +ofb64_start(int dir, int server) { return(fb64_start(&fb[OFB], dir, server)); } - static int -fb64_start(fbp, dir, server) - struct fb *fbp; - int dir; - int server; +static int +fb64_start(struct fb *fbp, int dir, int server __unused) { - int x; + size_t x; unsigned char *p; - register int state; + int state; switch (dir) { case DIR_DECRYPT: /* * This is simply a request to have the other side * start output (our input). He will negotiate an * IV so we need not look for it. */ state = fbp->state[dir-1]; if (state == FAILED) state = IN_PROGRESS; break; case DIR_ENCRYPT: state = fbp->state[dir-1]; if (state == FAILED) state = IN_PROGRESS; else if ((state & NO_SEND_IV) == 0) break; if (!VALIDKEY(fbp->krbdes_key)) { fbp->need_start = 1; break; } state &= ~NO_SEND_IV; state |= NO_RECV_IV; if (encrypt_debug_mode) printf("Creating new feed\r\n"); /* * Create a random feed and send it over. */ des_new_random_key((Block *)fbp->temp_feed); des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed, fbp->krbdes_sched, 1); p = fbp->fb_feed + 3; *p++ = ENCRYPT_IS; p++; *p++ = FB64_IV; for (x = 0; x < sizeof(Block); ++x) { if ((*p++ = fbp->temp_feed[x]) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); net_write(fbp->fb_feed, p - fbp->fb_feed); break; default: return(FAILED); } return(fbp->state[dir-1] = state); } /* * Returns: * -1: some error. Negotiation is done, encryption not ready. * 0: Successful, initial negotiation all done. * 1: successful, negotiation not done yet. */ - int -cfb64_is(data, cnt) - unsigned char *data; - int cnt; +int +cfb64_is(unsigned char *data, int cnt) { return(fb64_is(data, cnt, &fb[CFB])); } - int -ofb64_is(data, cnt) - unsigned char *data; - int cnt; + +int +ofb64_is(unsigned char *data, int cnt) { return(fb64_is(data, cnt, &fb[OFB])); } - int -fb64_is(data, cnt, fbp) - unsigned char *data; - int cnt; - struct fb *fbp; +int +fb64_is(unsigned char *data, int cnt, struct fb *fbp) { unsigned char *p; - register int state = fbp->state[DIR_DECRYPT-1]; + int state = fbp->state[DIR_DECRYPT-1]; if (cnt-- < 1) goto failure; switch (*data++) { case FB64_IV: if (cnt != sizeof(Block)) { if (encrypt_debug_mode) printf("CFB64: initial vector failed on size\r\n"); state = FAILED; goto failure; } if (encrypt_debug_mode) printf("CFB64: initial vector received\r\n"); if (encrypt_debug_mode) printf("Initializing Decrypt stream\r\n"); fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); p = fbp->fb_feed + 3; *p++ = ENCRYPT_REPLY; p++; *p++ = FB64_IV_OK; *p++ = IAC; *p++ = SE; printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); net_write(fbp->fb_feed, p - fbp->fb_feed); state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; break; default: if (encrypt_debug_mode) { printf("Unknown option type: %d\r\n", *(data-1)); printd(data, cnt); printf("\r\n"); } /* FALL THROUGH */ failure: /* * We failed. Send an FB64_IV_BAD option * to the other side so it will know that * things failed. */ p = fbp->fb_feed + 3; *p++ = ENCRYPT_REPLY; p++; *p++ = FB64_IV_BAD; *p++ = IAC; *p++ = SE; printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); net_write(fbp->fb_feed, p - fbp->fb_feed); break; } return(fbp->state[DIR_DECRYPT-1] = state); } /* * Returns: * -1: some error. Negotiation is done, encryption not ready. * 0: Successful, initial negotiation all done. * 1: successful, negotiation not done yet. */ - int -cfb64_reply(data, cnt) - unsigned char *data; - int cnt; +int +cfb64_reply(unsigned char *data, int cnt) { return(fb64_reply(data, cnt, &fb[CFB])); } - int -ofb64_reply(data, cnt) - unsigned char *data; - int cnt; + +int +ofb64_reply(unsigned char *data, int cnt) { return(fb64_reply(data, cnt, &fb[OFB])); } - - int -fb64_reply(data, cnt, fbp) - unsigned char *data; - int cnt; - struct fb *fbp; +int +fb64_reply(unsigned char *data, int cnt, struct fb *fbp) { - register int state = fbp->state[DIR_ENCRYPT-1]; + int state = fbp->state[DIR_ENCRYPT-1]; if (cnt-- < 1) goto failure; switch (*data++) { case FB64_IV_OK: fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); if (state == FAILED) state = IN_PROGRESS; state &= ~NO_RECV_IV; - encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); + encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1); break; case FB64_IV_BAD: memset(fbp->temp_feed, 0, sizeof(Block)); fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); state = FAILED; break; default: if (encrypt_debug_mode) { printf("Unknown option type: %d\r\n", data[-1]); printd(data, cnt); printf("\r\n"); } /* FALL THROUGH */ failure: state = FAILED; break; } return(fbp->state[DIR_ENCRYPT-1] = state); } - void -cfb64_session(key, server) - Session_Key *key; - int server; +void +cfb64_session(Session_Key *key, int server) { fb64_session(key, server, &fb[CFB]); } - void -ofb64_session(key, server) - Session_Key *key; - int server; +void +ofb64_session(Session_Key *key, int server) { fb64_session(key, server, &fb[OFB]); } - static void -fb64_session(key, server, fbp) - Session_Key *key; - int server; - struct fb *fbp; +static void +fb64_session(Session_Key *key, int server, struct fb *fbp) { - if (!key || key->type != SK_DES) { if (encrypt_debug_mode) printf("Can't set krbdes's session key (%d != %d)\r\n", key ? key->type : -1, SK_DES); return; } memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block)); fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); if (fbp->once == 0) { des_set_random_generator_seed((Block *)fbp->krbdes_key); fbp->once = 1; } des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched); /* * Now look to see if krbdes_start() was was waiting for * the key to show up. If so, go ahead an call it now * that we have the key. */ if (fbp->need_start) { fbp->need_start = 0; fb64_start(fbp, DIR_ENCRYPT, server); } } /* * We only accept a keyid of 0. If we get a keyid of * 0, then mark the state as SUCCESS. */ - int -cfb64_keyid(dir, kp, lenp) - int dir, *lenp; - unsigned char *kp; +int +cfb64_keyid(int dir, unsigned char *kp, int *lenp) { return(fb64_keyid(dir, kp, lenp, &fb[CFB])); } - int -ofb64_keyid(dir, kp, lenp) - int dir, *lenp; - unsigned char *kp; +int +ofb64_keyid(int dir, unsigned char *kp, int *lenp) { return(fb64_keyid(dir, kp, lenp, &fb[OFB])); } - int -fb64_keyid(dir, kp, lenp, fbp) - int dir, *lenp; - unsigned char *kp; - struct fb *fbp; +int +fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp) { - register int state = fbp->state[dir-1]; + int state = fbp->state[dir-1]; if (*lenp != 1 || (*kp != '\0')) { *lenp = 0; return(state); } if (state == FAILED) state = IN_PROGRESS; state &= ~NO_KEYID; return(fbp->state[dir-1] = state); } - void -fb64_printsub(data, cnt, buf, buflen, type) - unsigned char *data, *buf, *type; - int cnt, buflen; +void +fb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type) { char lbuf[32]; - register int i; + int i; char *cp; buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ buflen -= 1; switch(data[2]) { case FB64_IV: sprintf(lbuf, "%s_IV", type); cp = lbuf; goto common; case FB64_IV_OK: sprintf(lbuf, "%s_IV_OK", type); cp = lbuf; goto common; case FB64_IV_BAD: sprintf(lbuf, "%s_IV_BAD", type); cp = lbuf; goto common; default: sprintf(lbuf, " %d (unknown)", data[2]); cp = lbuf; common: for (; (buflen > 0) && (*buf = *cp++); buf++) buflen--; for (i = 3; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) buflen--; } break; } } - void -cfb64_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +cfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { fb64_printsub(data, cnt, buf, buflen, "CFB64"); } - void -ofb64_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +ofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { fb64_printsub(data, cnt, buf, buflen, "OFB64"); } - void -fb64_stream_iv(seed, stp) - Block seed; - register struct stinfo *stp; +void +fb64_stream_iv(Block seed, struct stinfo *stp) { memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); des_key_sched((Block *)stp->str_ikey, stp->str_sched); stp->str_index = sizeof(Block); } - void -fb64_stream_key(key, stp) - Block key; - register struct stinfo *stp; +void +fb64_stream_key(Block key, struct stinfo *stp) { memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); des_key_sched((Block *)key, stp->str_sched); memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); stp->str_index = sizeof(Block); } /* * DES 64 bit Cipher Feedback * * key --->+-----+ * +->| DES |--+ * | +-----+ | * | v * INPUT --(--------->(+)+---> DATA * | | * +-------------+ * * * Given: * iV: Initial vector, 64 bits (8 bytes) long. * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. * * V0 = DES(iV, key) * On = Dn ^ Vn * V(n+1) = DES(On, key) */ - void -cfb64_encrypt(s, c) - register unsigned char *s; - int c; +void +cfb64_encrypt(unsigned char *s, int c) { - register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; - register int index; + struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; + int idx; - index = stp->str_index; + idx = stp->str_index; while (c-- > 0) { - if (index == sizeof(Block)) { + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); - index = 0; + idx = 0; } /* On encryption, we store (feed ^ data) which is cypher */ - *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); + *s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s); s++; - index++; + idx++; } - stp->str_index = index; + stp->str_index = idx; } - int -cfb64_decrypt(data) - int data; +int +cfb64_decrypt(int data) { - register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; - int index; + struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; + int idx; if (data == -1) { /* * Back up one byte. It is assumed that we will * never back up more than one byte. If we do, this * may or may not work. */ if (stp->str_index) --stp->str_index; return(0); } - index = stp->str_index++; - if (index == sizeof(Block)) { + idx = stp->str_index++; + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); stp->str_index = 1; /* Next time will be 1 */ - index = 0; /* But now use 0 */ + idx = 0; /* But now use 0 */ } /* On decryption we store (data) which is cypher. */ - stp->str_output[index] = data; - return(data ^ stp->str_feed[index]); + stp->str_output[idx] = data; + return(data ^ stp->str_feed[idx]); } /* * DES 64 bit Output Feedback * * key --->+-----+ * +->| DES |--+ * | +-----+ | * +-----------+ * v * INPUT -------->(+) ----> DATA * * Given: * iV: Initial vector, 64 bits (8 bytes) long. * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. * * V0 = DES(iV, key) * V(n+1) = DES(Vn, key) * On = Dn ^ Vn */ - void -ofb64_encrypt(s, c) - register unsigned char *s; - int c; +void +ofb64_encrypt(unsigned char *s, int c) { - register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; - register int index; + struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; + int idx; - index = stp->str_index; + idx = stp->str_index; while (c-- > 0) { - if (index == sizeof(Block)) { + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); - index = 0; + idx = 0; } - *s++ ^= stp->str_feed[index]; - index++; + *s++ ^= stp->str_feed[idx]; + idx++; } - stp->str_index = index; + stp->str_index = idx; } - int -ofb64_decrypt(data) - int data; +int +ofb64_decrypt(int data) { - register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; - int index; + struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; + int idx; if (data == -1) { /* * Back up one byte. It is assumed that we will * never back up more than one byte. If we do, this * may or may not work. */ if (stp->str_index) --stp->str_index; return(0); } - index = stp->str_index++; - if (index == sizeof(Block)) { + idx = stp->str_index++; + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); stp->str_index = 1; /* Next time will be 1 */ - index = 0; /* But now use 0 */ + idx = 0; /* But now use 0 */ } - return(data ^ stp->str_feed[index]); + return(data ^ stp->str_feed[idx]); } -# endif /* DES_ENCRYPTION */ # endif /* AUTHENTICATION */ #endif /* ENCRYPTION */ Index: head/contrib/telnet/libtelnet/encrypt.c =================================================================== --- head/contrib/telnet/libtelnet/encrypt.c (revision 87138) +++ head/contrib/telnet/libtelnet/encrypt.c (revision 87139) @@ -1,1028 +1,952 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static const char sccsid[] = "@(#)encrypt.c 8.2 (Berkeley) 5/30/95"; #endif #endif /* not lint */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifdef ENCRYPTION #define ENCRYPT_NAMES -#include #include +#include +#include +#include #include "encrypt.h" #include "misc.h" -#ifdef __STDC__ -#include -#endif -#ifdef NO_STRING_H -#include -#else -#include -#endif - /* * These functions pointers point to the current routines * for encrypting and decrypting data. */ void (*encrypt_output) P((unsigned char *, int)); int (*decrypt_input) P((int)); int EncryptType(char *type, char *mode); int EncryptStart(char *mode); int EncryptStop(char *mode); int EncryptStartInput(void); int EncryptStartOutput(void); int EncryptStopInput(void); int EncryptStopOutput(void); -int Ambiguous(char **s); -int isprefix(char *s1, char *s2); -char **genget(char *name, char **table, int stlen); - int encrypt_debug_mode = 0; static int decrypt_mode = 0; static int encrypt_mode = 0; static int encrypt_verbose = 0; static int autoencrypt = 0; static int autodecrypt = 0; static int havesessionkey = 0; static int Server = 0; -static char *Name = "Noname"; +static const char *Name = "Noname"; #define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) static long i_support_encrypt = 0 -#ifdef DES_ENCRYPTION | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) -#endif |0; static long i_support_decrypt = 0 -#ifdef DES_ENCRYPTION | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) -#endif |0; static long i_wont_support_encrypt = 0; static long i_wont_support_decrypt = 0; #define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) #define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) static long remote_supports_encrypt = 0; static long remote_supports_decrypt = 0; static Encryptions encryptions[] = { -#ifdef DES_ENCRYPTION { "DES_CFB64", ENCTYPE_DES_CFB64, cfb64_encrypt, cfb64_decrypt, cfb64_init, cfb64_start, cfb64_is, cfb64_reply, cfb64_session, cfb64_keyid, cfb64_printsub }, { "DES_OFB64", ENCTYPE_DES_OFB64, ofb64_encrypt, ofb64_decrypt, ofb64_init, ofb64_start, ofb64_is, ofb64_reply, ofb64_session, ofb64_keyid, ofb64_printsub }, -#endif /* DES_ENCRYPTION */ - { 0, }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, ENCRYPT_SUPPORT }; static unsigned char str_suplen = 0; static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; - Encryptions * -findencryption(type) - int type; +Encryptions * +findencryption(int type) { Encryptions *ep = encryptions; - if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) + if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & (unsigned)typemask(type))) return(0); while (ep->type && ep->type != type) ++ep; return(ep->type ? ep : 0); } - Encryptions * -finddecryption(type) - int type; +static Encryptions * +finddecryption(int type) { Encryptions *ep = encryptions; - if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) + if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)typemask(type))) return(0); while (ep->type && ep->type != type) ++ep; return(ep->type ? ep : 0); } #define MAXKEYLEN 64 static struct key_info { unsigned char keyid[MAXKEYLEN]; int keylen; int dir; int *modep; - Encryptions *(*getcrypt)(); + Encryptions *(*getcrypt)(int); } ki[2] = { { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, }; static void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len); - void -encrypt_init(name, server) - char *name; - int server; +void +encrypt_init(const char *name, int server) { Encryptions *ep = encryptions; Name = name; Server = server; i_support_encrypt = i_support_decrypt = 0; remote_supports_encrypt = remote_supports_decrypt = 0; encrypt_mode = 0; decrypt_mode = 0; encrypt_output = 0; decrypt_input = 0; -#ifdef notdef - encrypt_verbose = !server; -#endif str_suplen = 4; while (ep->type) { if (encrypt_debug_mode) printf(">>>%s: I will support %s\r\n", Name, ENCTYPE_NAME(ep->type)); i_support_encrypt |= typemask(ep->type); i_support_decrypt |= typemask(ep->type); if ((i_wont_support_decrypt & typemask(ep->type)) == 0) if ((str_send[str_suplen++] = ep->type) == IAC) str_send[str_suplen++] = IAC; if (ep->init) (*ep->init)(Server); ++ep; } str_send[str_suplen++] = IAC; str_send[str_suplen++] = SE; } - void -encrypt_list_types() +static void +encrypt_list_types(void) { Encryptions *ep = encryptions; printf("Valid encryption types:\n"); while (ep->type) { printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type); ++ep; } } - int -EncryptEnable(type, mode) - char *type, *mode; +int +EncryptEnable(char *type, char *mode) { if (isprefix(type, "help") || isprefix(type, "?")) { printf("Usage: encrypt enable [input|output]\n"); encrypt_list_types(); return(0); } if (EncryptType(type, mode)) return(EncryptStart(mode)); return(0); } - int -EncryptDisable(type, mode) - char *type, *mode; +int +EncryptDisable(char *type, char *mode) { - register Encryptions *ep; + Encryptions *ep; int ret = 0; if (isprefix(type, "help") || isprefix(type, "?")) { printf("Usage: encrypt disable [input|output]\n"); encrypt_list_types(); } else if ((ep = (Encryptions *)genget(type, (char **)encryptions, sizeof(Encryptions))) == 0) { printf("%s: invalid encryption type\n", type); } else if (Ambiguous((char **)ep)) { printf("Ambiguous type '%s'\n", type); } else { if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { if (decrypt_mode == ep->type) EncryptStopInput(); i_wont_support_decrypt |= typemask(ep->type); ret = 1; } if ((mode == 0) || (isprefix(mode, "output"))) { if (encrypt_mode == ep->type) EncryptStopOutput(); i_wont_support_encrypt |= typemask(ep->type); ret = 1; } if (ret == 0) printf("%s: invalid encryption mode\n", mode); } return(ret); } - int -EncryptType(type, mode) - char *type; - char *mode; +int +EncryptType(char *type, char *mode) { - register Encryptions *ep; + Encryptions *ep; int ret = 0; if (isprefix(type, "help") || isprefix(type, "?")) { printf("Usage: encrypt type [input|output]\n"); encrypt_list_types(); } else if ((ep = (Encryptions *)genget(type, (char **)encryptions, sizeof(Encryptions))) == 0) { printf("%s: invalid encryption type\n", type); } else if (Ambiguous((char **)ep)) { printf("Ambiguous type '%s'\n", type); } else { if ((mode == 0) || isprefix(mode, "input")) { decrypt_mode = ep->type; i_wont_support_decrypt &= ~typemask(ep->type); ret = 1; } if ((mode == 0) || isprefix(mode, "output")) { encrypt_mode = ep->type; i_wont_support_encrypt &= ~typemask(ep->type); ret = 1; } if (ret == 0) printf("%s: invalid encryption mode\n", mode); } return(ret); } - int -EncryptStart(mode) - char *mode; +int +EncryptStart(char *mode) { - register int ret = 0; + int ret = 0; if (mode) { if (isprefix(mode, "input")) return(EncryptStartInput()); if (isprefix(mode, "output")) return(EncryptStartOutput()); if (isprefix(mode, "help") || isprefix(mode, "?")) { printf("Usage: encrypt start [input|output]\n"); return(0); } printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode); return(0); } ret += EncryptStartInput(); ret += EncryptStartOutput(); return(ret); } - int -EncryptStartInput() +int +EncryptStartInput(void) { if (decrypt_mode) { encrypt_send_request_start(); return(1); } printf("No previous decryption mode, decryption not enabled\r\n"); return(0); } - int -EncryptStartOutput() +int +EncryptStartOutput(void) { if (encrypt_mode) { encrypt_start_output(encrypt_mode); return(1); } printf("No previous encryption mode, encryption not enabled\r\n"); return(0); } - int -EncryptStop(mode) - char *mode; +int +EncryptStop(char *mode) { int ret = 0; if (mode) { if (isprefix(mode, "input")) return(EncryptStopInput()); if (isprefix(mode, "output")) return(EncryptStopOutput()); if (isprefix(mode, "help") || isprefix(mode, "?")) { printf("Usage: encrypt stop [input|output]\n"); return(0); } printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode); return(0); } ret += EncryptStopInput(); ret += EncryptStopOutput(); return(ret); } - int -EncryptStopInput() +int +EncryptStopInput(void) { encrypt_send_request_end(); return(1); } - int -EncryptStopOutput() +int +EncryptStopOutput(void) { encrypt_send_end(); return(1); } - void -encrypt_display() +void +encrypt_display(void) { if (encrypt_output) printf("Currently encrypting output with %s\r\n", ENCTYPE_NAME(encrypt_mode)); if (decrypt_input) printf("Currently decrypting input with %s\r\n", ENCTYPE_NAME(decrypt_mode)); } - int -EncryptStatus() +int +EncryptStatus(void) { if (encrypt_output) printf("Currently encrypting output with %s\r\n", ENCTYPE_NAME(encrypt_mode)); else if (encrypt_mode) { printf("Currently output is clear text.\r\n"); printf("Last encryption mode was %s\r\n", ENCTYPE_NAME(encrypt_mode)); } if (decrypt_input) { printf("Currently decrypting input with %s\r\n", ENCTYPE_NAME(decrypt_mode)); } else if (decrypt_mode) { printf("Currently input is clear text.\r\n"); printf("Last decryption mode was %s\r\n", ENCTYPE_NAME(decrypt_mode)); } return 1; } - void -encrypt_send_support() +void +encrypt_send_support(void) { if (str_suplen) { /* * If the user has requested that decryption start * immediatly, then send a "REQUEST START" before * we negotiate the type. */ if (!Server && autodecrypt) encrypt_send_request_start(); net_write(str_send, str_suplen); printsub('>', &str_send[2], str_suplen - 2); str_suplen = 0; } } - int -EncryptDebug(on) - int on; +int +EncryptDebug(int on) { if (on < 0) encrypt_debug_mode ^= 1; else encrypt_debug_mode = on; printf("Encryption debugging %s\r\n", encrypt_debug_mode ? "enabled" : "disabled"); return(1); } - int -EncryptVerbose(on) - int on; +int +EncryptVerbose(int on) { if (on < 0) encrypt_verbose ^= 1; else encrypt_verbose = on; printf("Encryption %s verbose\r\n", encrypt_verbose ? "is" : "is not"); return(1); } - int -EncryptAutoEnc(on) - int on; +int +EncryptAutoEnc(int on) { encrypt_auto(on); printf("Automatic encryption of output is %s\r\n", autoencrypt ? "enabled" : "disabled"); return(1); } - int -EncryptAutoDec(on) - int on; +int +EncryptAutoDec(int on) { decrypt_auto(on); printf("Automatic decryption of input is %s\r\n", autodecrypt ? "enabled" : "disabled"); return(1); } /* * Called when ENCRYPT SUPPORT is received. */ - void -encrypt_support(typelist, cnt) - unsigned char *typelist; - int cnt; +void +encrypt_support(unsigned char *typelist, int cnt) { - register int type, use_type = 0; + int type, use_type = 0; Encryptions *ep; /* * Forget anything the other side has previously told us. */ remote_supports_decrypt = 0; while (cnt-- > 0) { type = *typelist++; if (encrypt_debug_mode) printf(">>>%s: He is supporting %s (%d)\r\n", Name, ENCTYPE_NAME(type), type); if ((type < ENCTYPE_CNT) && (I_SUPPORT_ENCRYPT & typemask(type))) { remote_supports_decrypt |= typemask(type); if (use_type == 0) use_type = type; } } if (use_type) { ep = findencryption(use_type); if (!ep) return; type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0; if (encrypt_debug_mode) printf(">>>%s: (*ep->start)() returned %d\r\n", Name, type); if (type < 0) return; encrypt_mode = use_type; if (type == 0) encrypt_start_output(use_type); } } - void -encrypt_is(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_is(unsigned char *data, int cnt) { Encryptions *ep; - register int type, ret; + int type, ret; if (--cnt < 0) return; type = *data++; if (type < ENCTYPE_CNT) remote_supports_encrypt |= typemask(type); if (!(ep = finddecryption(type))) { if (encrypt_debug_mode) printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); return; } if (!ep->is) { if (encrypt_debug_mode) printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); ret = 0; } else { ret = (*ep->is)(data, cnt); if (encrypt_debug_mode) printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt, (ret < 0) ? "FAIL " : (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); } if (ret < 0) { autodecrypt = 0; } else { decrypt_mode = type; if (ret == 0 && autodecrypt) encrypt_send_request_start(); } } - void -encrypt_reply(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_reply(unsigned char *data, int cnt) { Encryptions *ep; - register int ret, type; + int ret, type; if (--cnt < 0) return; type = *data++; if (!(ep = findencryption(type))) { if (encrypt_debug_mode) printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); return; } if (!ep->reply) { if (encrypt_debug_mode) printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); ret = 0; } else { ret = (*ep->reply)(data, cnt); if (encrypt_debug_mode) printf("(*ep->reply)(%p, %d) returned %s(%d)\n", data, cnt, (ret < 0) ? "FAIL " : (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); } if (encrypt_debug_mode) printf(">>>%s: encrypt_reply returned %d\n", Name, ret); if (ret < 0) { autoencrypt = 0; } else { encrypt_mode = type; if (ret == 0 && autoencrypt) encrypt_start_output(type); } } /* * Called when a ENCRYPT START command is received. */ - void -encrypt_start(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_start(unsigned char *data __unused, int cnt __unused) { Encryptions *ep; if (!decrypt_mode) { /* * Something is wrong. We should not get a START * command without having already picked our * decryption scheme. Send a REQUEST-END to * attempt to clear the channel... */ printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); encrypt_send_request_end(); return; } if ((ep = finddecryption(decrypt_mode))) { decrypt_input = ep->input; if (encrypt_verbose) printf("[ Input is now decrypted with type %s ]\r\n", ENCTYPE_NAME(decrypt_mode)); if (encrypt_debug_mode) printf(">>>%s: Start to decrypt input with type %s\r\n", Name, ENCTYPE_NAME(decrypt_mode)); } else { printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", Name, ENCTYPE_NAME_OK(decrypt_mode) ? ENCTYPE_NAME(decrypt_mode) : "(unknown)", decrypt_mode); encrypt_send_request_end(); } } - void -encrypt_session_key(key, server) - Session_Key *key; - int server; +void +encrypt_session_key( Session_Key *key, int server) { Encryptions *ep = encryptions; havesessionkey = 1; while (ep->type) { if (ep->session) (*ep->session)(key, server); -#ifdef notdef - if (!encrypt_output && autoencrypt && !server) - encrypt_start_output(ep->type); - if (!decrypt_input && autodecrypt && !server) - encrypt_send_request_start(); -#endif ++ep; } } /* * Called when ENCRYPT END is received. */ - void -encrypt_end() +void +encrypt_end(void) { decrypt_input = 0; if (encrypt_debug_mode) printf(">>>%s: Input is back to clear text\r\n", Name); if (encrypt_verbose) printf("[ Input is now clear text ]\r\n"); } /* * Called when ENCRYPT REQUEST-END is received. */ - void -encrypt_request_end() +void +encrypt_request_end(void) { encrypt_send_end(); } /* * Called when ENCRYPT REQUEST-START is received. If we receive * this before a type is picked, then that indicates that the * other side wants us to start encrypting data as soon as we * can. */ - void -encrypt_request_start(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_request_start(unsigned char *data __unused, int cnt __unused) { if (encrypt_mode == 0) { if (Server) autoencrypt = 1; return; } encrypt_start_output(encrypt_mode); } static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; - void -encrypt_enc_keyid(keyid, len) - unsigned char *keyid; - int len; +void +encrypt_enc_keyid(unsigned char *keyid, int len) { encrypt_keyid(&ki[1], keyid, len); } - void -encrypt_dec_keyid(keyid, len) - unsigned char *keyid; - int len; +void +encrypt_dec_keyid(unsigned char *keyid, int len) { encrypt_keyid(&ki[0], keyid, len); } - void -encrypt_keyid(kp, keyid, len) - struct key_info *kp; - unsigned char *keyid; - int len; +void +encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len) { Encryptions *ep; int dir = kp->dir; - register int ret = 0; + int ret = 0; if (!(ep = (*kp->getcrypt)(*kp->modep))) { if (len == 0) return; kp->keylen = 0; } else if (len == 0) { /* * Empty option, indicates a failure. */ if (kp->keylen == 0) return; kp->keylen = 0; if (ep->keyid) (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); } else if ((len != kp->keylen) || (memcmp(keyid, kp->keyid, len) != 0)) { /* * Length or contents are different */ kp->keylen = len; memmove(kp->keyid, keyid, len); if (ep->keyid) (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); } else { if (ep->keyid) ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) encrypt_start_output(*kp->modep); return; } encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); } - void -encrypt_send_keyid(dir, keyid, keylen, saveit) - int dir; - unsigned char *keyid; - int keylen; - int saveit; +void +encrypt_send_keyid(int dir, const char *keyid, int keylen, int saveit) { unsigned char *strp; str_keyid[3] = (dir == DIR_ENCRYPT) ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; if (saveit) { struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; memmove(kp->keyid, keyid, keylen); kp->keylen = keylen; } for (strp = &str_keyid[4]; keylen > 0; --keylen) { if ((*strp++ = *keyid++) == IAC) *strp++ = IAC; } *strp++ = IAC; *strp++ = SE; net_write(str_keyid, strp - str_keyid); printsub('>', &str_keyid[2], strp - str_keyid - 2); } - void -encrypt_auto(on) - int on; +void +encrypt_auto(int on) { if (on < 0) autoencrypt ^= 1; else autoencrypt = on ? 1 : 0; } - void -decrypt_auto(on) - int on; +void +decrypt_auto(int on) { if (on < 0) autodecrypt ^= 1; else autodecrypt = on ? 1 : 0; } - void -encrypt_start_output(type) - int type; +void +encrypt_start_output(int type) { Encryptions *ep; - register unsigned char *p; - register int i; + unsigned char *p; + int i; if (!(ep = findencryption(type))) { if (encrypt_debug_mode) { printf(">>>%s: Can't encrypt with type %s (%d)\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); } return; } if (ep->start) { i = (*ep->start)(DIR_ENCRYPT, Server); if (encrypt_debug_mode) { printf(">>>%s: Encrypt start: %s (%d) %s\r\n", Name, (i < 0) ? "failed" : "initial negotiation in progress", i, ENCTYPE_NAME(type)); } if (i) return; } p = str_start + 3; *p++ = ENCRYPT_START; for (i = 0; i < ki[0].keylen; ++i) { if ((*p++ = ki[0].keyid[i]) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; net_write(str_start, p - str_start); net_encrypt(); printsub('>', &str_start[2], p - &str_start[2]); /* * If we are already encrypting in some mode, then * encrypt the ring (which includes our request) in * the old mode, mark it all as "clear text" and then * switch to the new mode. */ encrypt_output = ep->output; encrypt_mode = type; if (encrypt_debug_mode) printf(">>>%s: Started to encrypt output with type %s\r\n", Name, ENCTYPE_NAME(type)); if (encrypt_verbose) printf("[ Output is now encrypted with type %s ]\r\n", ENCTYPE_NAME(type)); } - void -encrypt_send_end() +void +encrypt_send_end(void) { if (!encrypt_output) return; str_end[3] = ENCRYPT_END; net_write(str_end, sizeof(str_end)); net_encrypt(); printsub('>', &str_end[2], sizeof(str_end) - 2); /* * Encrypt the output buffer now because it will not be done by * netflush... */ encrypt_output = 0; if (encrypt_debug_mode) printf(">>>%s: Output is back to clear text\r\n", Name); if (encrypt_verbose) printf("[ Output is now clear text ]\r\n"); } - void -encrypt_send_request_start() +void +encrypt_send_request_start(void) { - register unsigned char *p; - register int i; + unsigned char *p; + int i; p = &str_start[3]; *p++ = ENCRYPT_REQSTART; for (i = 0; i < ki[1].keylen; ++i) { if ((*p++ = ki[1].keyid[i]) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; net_write(str_start, p - str_start); printsub('>', &str_start[2], p - &str_start[2]); if (encrypt_debug_mode) printf(">>>%s: Request input to be encrypted\r\n", Name); } - void -encrypt_send_request_end() +void +encrypt_send_request_end(void) { str_end[3] = ENCRYPT_REQEND; net_write(str_end, sizeof(str_end)); printsub('>', &str_end[2], sizeof(str_end) - 2); if (encrypt_debug_mode) printf(">>>%s: Request input to be clear text\r\n", Name); } - void -encrypt_wait() +void +encrypt_wait(void) { if (encrypt_debug_mode) printf(">>>%s: in encrypt_wait\r\n", Name); if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt)) return; while (autoencrypt && !encrypt_output) if (telnet_spin()) return; } - void -encrypt_debug(mode) - int mode; +void +encrypt_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - encrypt_debug_mode = mode; -} - - void -encrypt_gen_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; -{ char tbuf[16], *cp; cnt -= 2; data += 2; buf[buflen-1] = '\0'; buf[buflen-2] = '*'; buflen -= 2;; for (; cnt > 0; cnt--, data++) { sprintf(tbuf, " %d", *data); for (cp = tbuf; *cp && buflen > 0; --buflen) *buf++ = *cp++; if (buflen <= 0) return; } *buf = '\0'; } - void -encrypt_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { Encryptions *ep; - register int type = data[1]; + int type = data[1]; for (ep = encryptions; ep->type && ep->type != type; ep++) ; if (ep->printsub) (*ep->printsub)(data, cnt, buf, buflen); else encrypt_gen_printsub(data, cnt, buf, buflen); } #endif /* ENCRYPTION */ Index: head/contrib/telnet/libtelnet/encrypt.h =================================================================== --- head/contrib/telnet/libtelnet/encrypt.h (revision 87138) +++ head/contrib/telnet/libtelnet/encrypt.h (revision 87139) @@ -1,114 +1,106 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)encrypt.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifdef ENCRYPTION # ifndef __ENCRYPTION__ # define __ENCRYPTION__ #define DIR_DECRYPT 1 #define DIR_ENCRYPT 2 #include typedef unsigned char Block[8]; typedef unsigned char *BlockT; #if 0 typedef struct { Block __; } Schedule[16]; #else #define Schedule des_key_schedule #endif #define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \ key[4] | key[5] | key[6] | key[7]) #define SAMEKEY(k1, k2) (!bcmp((void *)k1, (void *)k2, sizeof(Block))) typedef struct { short type; int length; unsigned char *data; } Session_Key; -# if !defined(P) -# ifdef __STDC__ -# define P(x) x -# else -# define P(x) () -# endif -# endif - typedef struct { - char *name; + const char *name; int type; - void (*output) P((unsigned char *, int)); - int (*input) P((int)); - void (*init) P((int)); - int (*start) P((int, int)); - int (*is) P((unsigned char *, int)); - int (*reply) P((unsigned char *, int)); - void (*session) P((Session_Key *, int)); - int (*keyid) P((int, unsigned char *, int *)); - void (*printsub) P((unsigned char *, int, unsigned char *, int)); + void (*output)(unsigned char *, int); + int (*input)(int); + void (*init)(int); + int (*start)(int, int); + int (*is)(unsigned char *, int); + int (*reply)(unsigned char *, int); + void (*session)(Session_Key *, int); + int (*keyid)(int, unsigned char *, int *); + void (*printsub)(unsigned char *, int, unsigned char *, int); } Encryptions; #define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */ #include "enc-proto.h" extern int encrypt_debug_mode; -extern int (*decrypt_input) P((int)); -extern void (*encrypt_output) P((unsigned char *, int)); +extern int (*decrypt_input)(int); +extern void (*encrypt_output)(unsigned char *, int); # endif /* __ENCRYPTION__ */ #endif /* ENCRYPTION */ Index: head/contrib/telnet/libtelnet/genget.c =================================================================== --- head/contrib/telnet/libtelnet/genget.c (revision 87138) +++ head/contrib/telnet/libtelnet/genget.c (revision 87139) @@ -1,104 +1,107 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static const char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95"; #endif #endif /* not lint */ #include +#include "misc-proto.h" + #define LOWER(x) (isupper(x) ? tolower(x) : (x)) /* * The prefix function returns 0 if *s1 is not a prefix * of *s2. If *s1 exactly matches *s2, the negative of * the length is returned. If *s1 is a prefix of *s2, * the length of *s1 is returned. */ int -isprefix(char *s1, char *s2) +isprefix(char *s1, const char *s2) { char *os1; char c1, c2; if (*s1 == '\0') return(-1); os1 = s1; c1 = *s1; c2 = *s2; while (LOWER(c1) == LOWER(c2)) { if (c1 == '\0') break; c1 = *++s1; c2 = *++s2; } return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); } static char *ambiguous; /* special return value for command routines */ char ** genget(char *name, char **table, int stlen) { char **c, **found; int n; if (name == 0) return 0; found = 0; for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { if ((n = isprefix(name, *c)) == 0) continue; if (n < 0) /* exact match */ return(c); if (found) return(&ambiguous); found = c; } return(found); } /* * Function call version of Ambiguous() */ int -Ambiguous(char *s) +Ambiguous(char **s) { - return((char **)s == &ambiguous); + return(s == &ambiguous); } Index: head/contrib/telnet/libtelnet/getent.c =================================================================== --- head/contrib/telnet/libtelnet/getent.c (revision 87138) +++ head/contrib/telnet/libtelnet/getent.c (revision 87139) @@ -1,76 +1,76 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static char sccsid[] = "@(#)getent.c 8.2 (Berkeley) 12/15/93"; #endif #endif /* not lint */ -#ifdef HAS_CGETENT #include -#endif +#include +#include "misc-proto.h" + static char *area; +static char gettytab[] = "/etc/gettytab"; /*ARGSUSED*/ int -getent(char *cp, char *name) +getent(char *cp __unused, const char *name) { -#ifdef HAS_CGETENT - char *dba[2]; + int retval; + char *tempnam, *dba[2] = { gettytab, NULL }; - dba[0] = "/etc/gettytab"; - dba[1] = 0; - return((cgetent(&area, dba, name) == 0) ? 1 : 0); -#else - return(0); -#endif + tempnam = strdup(name); + retval = cgetent(&area, dba, tempnam) == 0 ? 1 : 0; + free(tempnam); + return(retval); } -#ifndef SOLARIS /*ARGSUSED*/ char * -Getstr(char *id, char **cpp) +Getstr(const char *id, char **cpp __unused) { -# ifdef HAS_CGETENT - char *answer; - return((cgetstr(area, id, &answer) > 0) ? answer : 0); -# else - return(0); -# endif + int retval; + char *answer, *tempid; + + tempid = strdup(id); + retval = cgetstr(area, tempid, &answer); + free(tempid); + return((retval > 0) ? answer : NULL); } -#endif Index: head/contrib/telnet/libtelnet/kerberos.c =================================================================== --- head/contrib/telnet/libtelnet/kerberos.c (revision 87138) +++ head/contrib/telnet/libtelnet/kerberos.c (revision 87139) @@ -1,555 +1,512 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)kerberos.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifdef KRB4 #include #include -#include #include /* BSD wont include this in krb.h, so we do it here */ #include -#ifdef __STDC__ +#include #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif #include "encrypt.h" #include "auth.h" #include "misc.h" int kerberos4_cksum P((unsigned char *, int)); int kuserok P((AUTH_DAT *, char *)); -extern auth_debug_mode; +extern int auth_debug_mode; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KERBEROS_V4, }; #define KRB_AUTH 0 /* Authentication data follows */ #define KRB_REJECT 1 /* Rejected (reason might follow) */ #define KRB_ACCEPT 2 /* Accepted */ #define KRB_CHALLENGE 3 /* Challenge for mutual auth. */ #define KRB_RESPONSE 4 /* Response for mutual auth. */ -#define KRB_SERVICE_NAME "rcmd" - static KTEXT_ST auth; static char name[ANAME_SZ]; -static AUTH_DAT adat = { 0 }; +static AUTH_DAT adat = { 0, "", "", "", 0, {}, 0, 0, 0, { 0, "", 0 } }; #ifdef ENCRYPTION static Block session_key = { 0 }; static des_key_schedule sched; static Block challenge = { 0 }; #endif /* ENCRYPTION */ - static int -Data(ap, type, d, c) - Authenticator *ap; - int type; - void *d; - int c; +static char krb_service_name[] = "rcmd"; +static char empty[] = ""; + +static int +Data(Authenticator *ap, int type, const unsigned char *d, int c) { unsigned char *p = str_data + 4; - unsigned char *cd = (unsigned char *)d; + const unsigned char *cd = d; if (c == -1) - c = strlen((char *)cd); + c = strlen(cd); if (auth_debug_mode) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } - int -kerberos4_init(ap, server) - Authenticator *ap; - int server; +int +kerberos4_init(Authenticator *ap __unused, int server) { FILE *fp; if (server) { str_data[3] = TELQUAL_REPLY; if ((fp = fopen(KEYFILE, "r")) == NULL) return(0); fclose(fp); } else { str_data[3] = TELQUAL_IS; } return(1); } char dst_realm_buf[REALM_SZ], *dest_realm = NULL; int dst_realm_sz = REALM_SZ; - int -kerberos4_send(ap) - Authenticator *ap; +int +kerberos4_send(Authenticator *ap) { - KTEXT_ST auth; + KTEXT_ST lauth; char instance[INST_SZ]; char *realm; - char *krb_realmofhost(); - char *krb_get_phost(); CREDENTIALS cred; int r; printf("[ Trying KERBEROS4 ... ]\n"); if (!UserNameRequested) { if (auth_debug_mode) { printf("Kerberos V4: no user name supplied\r\n"); } return(0); } memset(instance, 0, sizeof(instance)); if ((realm = krb_get_phost(RemoteHostName))) strncpy(instance, realm, sizeof(instance)); instance[sizeof(instance)-1] = '\0'; realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName); if (!realm) { printf("Kerberos V4: no realm for %s\r\n", RemoteHostName); return(0); } - if ((r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L))) { + if ((r = krb_mk_req(&lauth, krb_service_name, instance, realm, 0L))) { printf("mk_req failed: %s\r\n", krb_err_txt[r]); return(0); } - if ((r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred))) { + if ((r = krb_get_cred(krb_service_name, instance, realm, &cred))) { printf("get_cred failed: %s\r\n", krb_err_txt[r]); return(0); } if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { if (auth_debug_mode) printf("Not enough room for user name\r\n"); return(0); } if (auth_debug_mode) - printf("Sent %d bytes of authentication data\r\n", auth.length); - if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) { + printf("Sent %d bytes of authentication data\r\n", lauth.length); + if (!Data(ap, KRB_AUTH, (void *)lauth.dat, lauth.length)) { if (auth_debug_mode) printf("Not enough room for authentication data\r\n"); return(0); } #ifdef ENCRYPTION /* * If we are doing mutual authentication, get set up to send * the challenge, and verify it when the response comes back. */ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { register int i; des_key_sched(&cred.session, sched); des_init_random_number_generator(&cred.session); des_new_random_key(&session_key); des_ecb_encrypt(&session_key, &session_key, sched, 0); des_ecb_encrypt(&session_key, &challenge, sched, 0); /* * Increment the challenge by 1, and encrypt it for * later comparison. */ for (i = 7; i >= 0; --i) { register int x; x = (unsigned int)challenge[i] + 1; challenge[i] = x; /* ignore overflow */ if (x < 256) /* if no overflow, all done */ break; } des_ecb_encrypt(&challenge, &challenge, sched, 1); } #endif /* ENCRYPTION */ if (auth_debug_mode) { - printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); - printd(auth.dat, auth.length); + printf("CK: %d:", kerberos4_cksum(lauth.dat, lauth.length)); + printd(lauth.dat, lauth.length); printf("\r\n"); printf("Sent Kerberos V4 credentials to server\r\n"); } return(1); } - void -kerberos4_is(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; +void +kerberos4_is(Authenticator *ap, unsigned char *data, int cnt) { #ifdef ENCRYPTION Session_Key skey; Block datablock; #endif /* ENCRYPTION */ char realm[REALM_SZ]; char instance[INST_SZ]; int r; if (cnt-- < 1) return; switch (*data++) { case KRB_AUTH: if (krb_get_lrealm(realm, 1) != KSUCCESS) { - Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1); + Data(ap, KRB_REJECT, "No local V4 Realm.", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("No local realm\r\n"); return; } memmove((void *)auth.dat, (void *)data, auth.length = cnt); if (auth_debug_mode) { printf("Got %d bytes of authentication data\r\n", cnt); printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); printd(auth.dat, auth.length); printf("\r\n"); } instance[0] = '*'; instance[1] = 0; - if ((r = krb_rd_req(&auth, KRB_SERVICE_NAME, - instance, 0, &adat, ""))) { + if ((r = krb_rd_req(&auth, krb_service_name, + instance, 0, &adat, empty))) { if (auth_debug_mode) printf("Kerberos failed him as %s\r\n", name); - Data(ap, KRB_REJECT, (void *)krb_err_txt[r], -1); + Data(ap, KRB_REJECT, krb_err_txt[r], -1); auth_finished(ap, AUTH_REJECT); return; } #ifdef ENCRYPTION memmove((void *)session_key, (void *)adat.session, sizeof(Block)); #endif /* ENCRYPTION */ krb_kntoln(&adat, name); if (UserNameRequested && !kuserok(&adat, UserNameRequested)) - Data(ap, KRB_ACCEPT, (void *)0, 0); + Data(ap, KRB_ACCEPT, NULL, 0); else - Data(ap, KRB_REJECT, - (void *)"user is not authorized", -1); + Data(ap, KRB_REJECT, "user is not authorized", -1); auth_finished(ap, AUTH_USER); break; case KRB_CHALLENGE: #ifndef ENCRYPTION - Data(ap, KRB_RESPONSE, (void *)0, 0); + Data(ap, KRB_RESPONSE, NULL, 0); #else /* ENCRYPTION */ if (!VALIDKEY(session_key)) { /* * We don't have a valid session key, so just * send back a response with an empty session * key. */ - Data(ap, KRB_RESPONSE, (void *)0, 0); + Data(ap, KRB_RESPONSE, NULL, 0); break; } /* * Initialize the random number generator since it's * used later on by the encryption routine. */ des_init_random_number_generator(&session_key); des_key_sched(&session_key, sched); memmove((void *)datablock, (void *)data, sizeof(Block)); /* * Take the received encrypted challenge, and encrypt * it again to get a unique session_key for the * ENCRYPT option. */ des_ecb_encrypt(&datablock, &session_key, sched, 1); skey.type = SK_DES; skey.length = 8; skey.data = session_key; encrypt_session_key(&skey, 1); /* * Now decrypt the received encrypted challenge, * increment by one, re-encrypt it and send it back. */ des_ecb_encrypt(&datablock, &challenge, sched, 0); for (r = 7; r >= 0; r--) { register int t; t = (unsigned int)challenge[r] + 1; challenge[r] = t; /* ignore overflow */ if (t < 256) /* if no overflow, all done */ break; } des_ecb_encrypt(&challenge, &challenge, sched, 1); - Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge)); + Data(ap, KRB_RESPONSE, challenge, sizeof(challenge)); #endif /* ENCRYPTION */ break; default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); - Data(ap, KRB_REJECT, 0, 0); + Data(ap, KRB_REJECT, NULL, 0); break; } } - void -kerberos4_reply(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; +void +kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt) { #ifdef ENCRYPTION Session_Key skey; #endif /* ENCRYPTION */ if (cnt-- < 1) return; switch (*data++) { case KRB_REJECT: if (cnt > 0) { printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n", cnt, data); } else printf("[ Kerberos V4 refuses authentication ]\r\n"); auth_send_retry(); return; case KRB_ACCEPT: printf("[ Kerberos V4 accepts you ]\n"); if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { /* * Send over the encrypted challenge. */ #ifndef ENCRYPTION - Data(ap, KRB_CHALLENGE, (void *)0, 0); + Data(ap, KRB_CHALLENGE, NULL, 0); #else /* ENCRYPTION */ - Data(ap, KRB_CHALLENGE, (void *)session_key, + Data(ap, KRB_CHALLENGE, session_key, sizeof(session_key)); des_ecb_encrypt(&session_key, &session_key, sched, 1); skey.type = SK_DES; skey.length = 8; skey.data = session_key; encrypt_session_key(&skey, 0); #endif /* ENCRYPTION */ return; } auth_finished(ap, AUTH_USER); return; case KRB_RESPONSE: #ifdef ENCRYPTION /* * Verify that the response to the challenge is correct. */ if ((cnt != sizeof(Block)) || (0 != memcmp((void *)data, (void *)challenge, sizeof(challenge)))) { #endif /* ENCRYPTION */ printf("[ Kerberos V4 challenge failed!!! ]\r\n"); auth_send_retry(); return; #ifdef ENCRYPTION } printf("[ Kerberos V4 challenge successful ]\r\n"); auth_finished(ap, AUTH_USER); #endif /* ENCRYPTION */ break; default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); return; } } - int -kerberos4_status(ap, name, level) - Authenticator *ap; - char *name; - int level; +int +kerberos4_status(Authenticator *ap __unused, char *nam, int level) { if (level < AUTH_USER) return(level); if (UserNameRequested && !kuserok(&adat, UserNameRequested)) { - strcpy(name, UserNameRequested); + strcpy(nam, UserNameRequested); return(AUTH_VALID); } else return(AUTH_USER); } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - void -kerberos4_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +kerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { char lbuf[32]; register int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case KRB_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case KRB_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case KRB_AUTH: /* Authentication data follows */ strncpy((char *)buf, " AUTH", buflen); goto common2; case KRB_CHALLENGE: strncpy((char *)buf, " CHALLENGE", buflen); goto common2; case KRB_RESPONSE: strncpy((char *)buf, " RESPONSE", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } - int -kerberos4_cksum(d, n) - unsigned char *d; - int n; +int +kerberos4_cksum(unsigned char *d, int n) { int ck = 0; /* * A comment is probably needed here for those not * well versed in the "C" language. Yes, this is * supposed to be a "switch" with the body of the * "switch" being a "while" statement. The whole * purpose of the switch is to allow us to jump into * the middle of the while() loop, and then not have * to do any more switch()s. * * Some compilers will spit out a warning message * about the loop not being entered at the top. */ switch (n&03) while (n > 0) { case 0: ck ^= (int)*d++ << 24; --n; case 3: ck ^= (int)*d++ << 16; --n; case 2: ck ^= (int)*d++ << 8; --n; case 1: ck ^= (int)*d++; --n; } return(ck); -} -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); } #endif Index: head/contrib/telnet/libtelnet/kerberos5.c =================================================================== --- head/contrib/telnet/libtelnet/kerberos5.c (revision 87138) +++ head/contrib/telnet/libtelnet/kerberos5.c (revision 87139) @@ -1,758 +1,801 @@ -/* - * $Source: /mit/krb5/.cvsroot/src/appl/telnet/libtelnet/kerberos5.c,v $ - * $Author: tytso $ - * $Id: kerberos5.c,v 1.1 1997/09/04 06:11:15 markm Exp $ - */ - -#include -__FBSDID("$FreeBSD$"); - /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#ifndef lint -static const char sccsid[] = "@(#)kerberos5.c 8.3 (Berkeley) 5/30/95"; -#endif /* not lint */ - /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ +#include +__FBSDID("$FreeBSD$"); + #ifdef KRB5 + #include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#define Authenticator k5_Authenticator +#include +#undef Authenticator -/* kerberos 5 include files (ext-proto.h) will get an appropriate stdlib.h - and string.h/strings.h */ - #include "encrypt.h" #include "auth.h" #include "misc.h" -extern int auth_debug_mode; - -#ifdef FORWARD int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ /* These values need to be the same as those defined in telnet/main.c. */ /* Either define them in both places, or put in some common header file. */ #define OPTS_FORWARD_CREDS 0x00000002 #define OPTS_FORWARDABLE_CREDS 0x00000001 -void kerberos5_forward(); +void kerberos5_forward (Authenticator *); -#endif /* FORWARD */ - static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KERBEROS_V5, }; -/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, - TELQUAL_NAME, };*/ #define KRB_AUTH 0 /* Authentication data follows */ #define KRB_REJECT 1 /* Rejected (reason might follow) */ #define KRB_ACCEPT 2 /* Accepted */ #define KRB_RESPONSE 3 /* Response for mutual auth. */ -#ifdef FORWARD #define KRB_FORWARD 4 /* Forwarded credentials follow */ #define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ #define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ -#endif /* FORWARD */ static krb5_data auth; - /* telnetd gets session key from here */ -static krb5_tkt_authent *authdat = NULL; -/* telnet matches the AP_REQ and AP_REP with this */ -static krb5_authenticator authenticator; +static krb5_ticket *ticket; -/* some compilers can't hack void *, so we use the Kerberos krb5_pointer, - which is either void * or char *, depending on the compiler. */ +static krb5_context context; +static krb5_auth_context auth_context; -#define Voidptr krb5_pointer +static int +Data(Authenticator *ap, int type, const char *d, int c) +{ + unsigned char *p = str_data + 4; + const unsigned char *cd = d; -Block session_key; + if (c == -1) + c = strlen(cd); - static int -Data(ap, type, d, c) - Authenticator *ap; - int type; - Voidptr d; - int c; + if (auth_debug_mode) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - &str_data[2]); + return(net_write(str_data, p - str_data)); +} + +int +kerberos5_init(Authenticator *ap __unused, int server) { - unsigned char *p = str_data + 4; - unsigned char *cd = (unsigned char *)d; + krb5_error_code ret; - if (c == -1) - c = strlen((char *)cd); + ret = krb5_init_context(&context); + if (ret) + return 0; + if (server) { + krb5_keytab kt; + krb5_kt_cursor cursor; - if (auth_debug_mode) { - printf("%s:%d: [%d] (%d)", - str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", - str_data[3], - type, c); - printd(d, c); - printf("\r\n"); + ret = krb5_kt_default(context, &kt); + if (ret) + return 0; + + ret = krb5_kt_start_seq_get (context, kt, &cursor); + if (ret) { + krb5_kt_close (context, kt); + return 0; } - *p++ = ap->type; - *p++ = ap->way; - *p++ = type; - while (c-- > 0) { - if ((*p++ = *cd++) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - if (str_data[3] == TELQUAL_IS) - printsub('>', &str_data[2], p - &str_data[2]); - return(net_write(str_data, p - str_data)); -} + krb5_kt_end_seq_get (context, kt, &cursor); + krb5_kt_close (context, kt); - int -kerberos5_init(ap, server) - Authenticator *ap; - int server; -{ - if (server) - str_data[3] = TELQUAL_REPLY; - else - str_data[3] = TELQUAL_IS; - krb5_init_ets(); - return(1); + str_data[3] = TELQUAL_REPLY; + } else + str_data[3] = TELQUAL_IS; + return(1); } - int -kerberos5_send(ap) - Authenticator *ap; +extern int net; + +static int +kerberos5_send(const char *name, Authenticator *ap) { - char **realms; - char *name; - char *p1, *p2; - krb5_checksum ksum; - krb5_octet sum[CRC32_CKSUM_LENGTH]; - krb5_principal server; - krb5_error_code r; - krb5_ccache ccache; - krb5_creds creds; /* telnet gets session key from here */ - extern krb5_flags krb5_kdc_default_options; - int ap_opts; + krb5_error_code ret; + krb5_ccache ccache; + int ap_opts; + krb5_data cksum_data; + char foo[2]; + + if (!UserNameRequested) { + if (auth_debug_mode) { + printf("Kerberos V5: no user name supplied\r\n"); + } + return(0); + } + + ret = krb5_cc_default(context, &ccache); + if (ret) { + if (auth_debug_mode) { + printf("Kerberos V5: could not get default ccache: %s\r\n", + krb5_get_err_text (context, ret)); + } + return 0; + } + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) + ap_opts = AP_OPTS_MUTUAL_REQUIRED; + else + ap_opts = 0; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) { + if (auth_debug_mode) { + printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } -#ifdef ENCRYPTION - krb5_keyblock *newkey = 0; -#endif /* ENCRYPTION */ + ret = krb5_auth_con_setaddrs_from_fd (context, + auth_context, + &net); + if (ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } - ksum.checksum_type = CKSUMTYPE_CRC32; - ksum.contents = sum; - ksum.length = sizeof(sum); - memset((Voidptr )sum, 0, sizeof(sum)); + krb5_auth_setkeytype (context, auth_context, KEYTYPE_DES); - if (!UserNameRequested) { - if (auth_debug_mode) { - printf("Kerberos V5: no user name supplied\r\n"); - } - return(0); - } + foo[0] = ap->type; + foo[1] = ap->way; - if (r = krb5_cc_default(&ccache)) { - if (auth_debug_mode) { - printf("Kerberos V5: could not get default ccache\r\n"); - } - return(0); - } + cksum_data.length = sizeof(foo); + cksum_data.data = foo; - if ((name = malloc(strlen(RemoteHostName)+1)) == NULL) { - if (auth_debug_mode) - printf("Out of memory for hostname in Kerberos V5\r\n"); - return(0); - } - if (r = krb5_get_host_realm(RemoteHostName, &realms)) { - if (auth_debug_mode) - printf("Kerberos V5: no realm for %s\r\n", RemoteHostName); - free(name); - return(0); - } + { + krb5_principal service; + char sname[128]; - p1 = RemoteHostName; - p2 = name; - while (*p2 = *p1++) { - if (isupper(*p2)) - *p2 |= 040; - ++p2; + ret = krb5_sname_to_principal (context, + RemoteHostName, + NULL, + KRB5_NT_SRV_HST, + &service); + if(ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_sname_to_principal(%s) failed (%s)\r\n", + RemoteHostName, krb5_get_err_text(context, ret)); + } + return 0; } + ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname)); + if(ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_unparse_name_fixed failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return 0; + } + printf("[ Trying %s (%s)... ]\r\n", name, sname); + ret = krb5_mk_req_exact(context, &auth_context, ap_opts, + service, + &cksum_data, ccache, &auth); + krb5_free_principal (context, service); - if (r = krb5_build_principal_ext(&server, - strlen(realms[0]), realms[0], - 4, "host", - p2 - name, name, - 0)) { - if (auth_debug_mode) { - printf("Kerberos V5: failure setting up principal (%s)\r\n", - error_message(r)); - } - free(name); - krb5_free_host_realm(realms); - return(0); + } + if (ret) { + if (1 || auth_debug_mode) { + printf("Kerberos V5: mk_req failed (%s)\r\n", + krb5_get_err_text(context, ret)); } + return(0); + } + if (!auth_sendname((unsigned char *)UserNameRequested, + strlen(UserNameRequested))) { + if (auth_debug_mode) + printf("Not enough room for user name\r\n"); + return(0); + } + if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + return(0); + } + if (auth_debug_mode) { + printf("Sent Kerberos V5 credentials to server\r\n"); + } + return(1); +} - memset((char *)&creds, 0, sizeof(creds)); - creds.server = server; +int +kerberos5_send_mutual(Authenticator *ap) +{ + return kerberos5_send("mutual KERBEROS5", ap); +} - if (r = krb5_cc_get_principal(ccache, &creds.client)) { - if (auth_debug_mode) { - printf("Kerberos V5: failure on principal (%s)\r\n", - error_message(r)); - } - free(name); - krb5_free_principal(server); - krb5_free_host_realm(realms); - return(0); +int +kerberos5_send_oneway(Authenticator *ap) +{ + return kerberos5_send("KERBEROS5", ap); +} + +void +kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) +{ + krb5_error_code ret; + krb5_data outbuf; + krb5_keyblock *key_block; + char *name; + krb5_principal server; + int zero = 0; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_AUTH: + auth.data = (char *)data; + auth.length = cnt; + + auth_context = NULL; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; } - if (r = krb5_get_credentials(krb5_kdc_default_options, ccache, &creds)) { - if (auth_debug_mode) { - printf("Kerberos V5: failure on credentials(%d)\r\n",r); - } - free(name); - krb5_free_host_realm(realms); - krb5_free_principal(server); - return(0); + ret = krb5_auth_con_setaddrs_from_fd (context, + auth_context, + &zero); + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; } - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) - ap_opts = AP_OPTS_MUTUAL_REQUIRED; - else - ap_opts = 0; + ret = krb5_sock_to_principal (context, + 0, + "host", + KRB5_NT_SRV_HST, + &server); + if (ret) { + Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_sock_to_principal failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; + } - r = krb5_mk_req_extended(ap_opts, &ksum, krb5_kdc_default_options, 0, -#ifdef ENCRYPTION - &newkey, -#else /* ENCRYPTION */ - 0, -#endif /* ENCRYPTION */ - ccache, &creds, &authenticator, &auth); - /* don't let the key get freed if we clean up the authenticator */ - authenticator.subkey = 0; + ret = krb5_rd_req(context, + &auth_context, + &auth, + server, + NULL, + NULL, + &ticket); - free(name); - krb5_free_host_realm(realms); - krb5_free_principal(server); -#ifdef ENCRYPTION - if (newkey) { - /* keep the key in our private storage, but don't use it - yet---see kerberos5_reply() below */ - if (newkey->keytype != KEYTYPE_DES) { - if (creds.keyblock.keytype == KEYTYPE_DES) - /* use the session key in credentials instead */ - memmove((char *)session_key, - (char *)creds.keyblock.contents, sizeof(Block)); - else - /* XXX ? */; - } else { - memmove((char *)session_key, (char *)newkey->contents, - sizeof(Block)); - } - krb5_free_keyblock(newkey); + krb5_free_principal (context, server); + if (ret) { + char *errbuf; + + asprintf(&errbuf, + "Read req failed: %s", + krb5_get_err_text(context, ret)); + Data(ap, KRB_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("%s\r\n", errbuf); + free (errbuf); + return; } -#endif /* ENCRYPTION */ - if (r) { - if (auth_debug_mode) { - printf("Kerberos V5: mk_req failed (%s)\r\n", - error_message(r)); - } - return(0); - } + + { + char foo[2]; + + foo[0] = ap->type; + foo[1] = ap->way; + + ret = krb5_verify_authenticator_checksum(context, + auth_context, + foo, + sizeof(foo)); - if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + if (ret) { + char *errbuf; + asprintf(&errbuf, "Bad checksum: %s", + krb5_get_err_text(context, ret)); + Data(ap, KRB_REJECT, errbuf, -1); if (auth_debug_mode) - printf("Not enough room for user name\r\n"); - return(0); + printf ("%s\r\n", errbuf); + free(errbuf); + return; + } } - if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { - if (auth_debug_mode) - printf("Not enough room for authentication data\r\n"); - return(0); + ret = krb5_auth_con_getremotesubkey (context, + auth_context, + &key_block); + + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_auth_con_getremotesubkey failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; } - if (auth_debug_mode) { - printf("Sent Kerberos V5 credentials to server\r\n"); - } - return(1); -} - void -kerberos5_is(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; -{ - int r; - struct hostent *hp; - char *p1, *p2; - static char *realm = NULL; - krb5_principal server; - krb5_ap_rep_enc_part reply; - krb5_data outbuf; -#ifdef ENCRYPTION - Session_Key skey; -#endif /* ENCRYPTION */ - char *name; - char *getenv(); - krb5_data inbuf; - - if (cnt-- < 1) + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + ret = krb5_mk_rep(context, auth_context, &outbuf); + if (ret) { + Data(ap, KRB_REJECT, + "krb5_mk_rep failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_mk_rep failed (%s)\r\n", + krb5_get_err_text(context, ret)); return; - switch (*data++) { - case KRB_AUTH: - auth.data = (char *)data; - auth.length = cnt; + } + Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); + } + if (krb5_unparse_name(context, ticket->client, &name)) + name = 0; - if (!(hp = gethostbyname(LocalHostName))) { - if (auth_debug_mode) - printf("Cannot resolve local host name\r\n"); - Data(ap, KRB_REJECT, "Unknown local hostname.", -1); - auth_finished(ap, AUTH_REJECT); - return; - } + if(UserNameRequested && krb5_kuserok(context, + ticket->client, + UserNameRequested)) { + Data(ap, KRB_ACCEPT, name, name ? -1 : 0); + if (auth_debug_mode) { + printf("Kerberos5 identifies him as ``%s''\r\n", + name ? name : ""); + } - if (!realm && (krb5_get_default_realm(&realm))) { - if (auth_debug_mode) - printf("Could not get default realm\r\n"); - Data(ap, KRB_REJECT, "Could not get default realm.", -1); - auth_finished(ap, AUTH_REJECT); - return; - } + if(key_block->keytype == ETYPE_DES_CBC_MD5 || + key_block->keytype == ETYPE_DES_CBC_MD4 || + key_block->keytype == ETYPE_DES_CBC_CRC) { + Session_Key skey; - if ((name = malloc(strlen(hp->h_name)+1)) == NULL) { - if (auth_debug_mode) - printf("Out of memory for hostname in Kerberos V5\r\n"); - Data(ap, KRB_REJECT, "Out of memory.", -1); - auth_finished(ap, AUTH_REJECT); - return; - } + skey.type = SK_DES; + skey.length = 8; + skey.data = key_block->keyvalue.data; + encrypt_session_key(&skey, 0); + } - p1 = hp->h_name; - p2 = name; + } else { + char *msg; - while (*p2 = *p1++) { - if (isupper(*p2)) - *p2 |= 040; - ++p2; - } + asprintf (&msg, "user `%s' is not authorized to " + "login as `%s'", + name ? name : "", + UserNameRequested ? UserNameRequested : ""); + if (msg == NULL) + Data(ap, KRB_REJECT, NULL, 0); + else { + Data(ap, KRB_REJECT, (void *)msg, -1); + free(msg); + } + auth_finished (ap, AUTH_REJECT); + krb5_free_keyblock_contents(context, key_block); + break; + } + auth_finished(ap, AUTH_USER); + krb5_free_keyblock_contents(context, key_block); + + break; + case KRB_FORWARD: { + struct passwd *pwd; + char ccname[1024]; /* XXX */ + krb5_data inbuf; + krb5_ccache ccache; + inbuf.data = (char *)data; + inbuf.length = cnt; - if (authdat) - krb5_free_tkt_authent(authdat); + pwd = getpwnam (UserNameRequested); + if (pwd == NULL) + break; - r = krb5_build_principal_ext(&server, - strlen(realm), realm, - 4, "host", - p2 - name, name, - 0); - if (!r) { - r = krb5_rd_req_simple(&auth, server, 0, &authdat); - krb5_free_principal(server); - } - if (r) { - char errbuf[128]; + snprintf (ccname, sizeof(ccname), + "FILE:/tmp/krb5cc_%u", pwd->pw_uid); - errout: - authdat = 0; - (void) strcpy(errbuf, "Read req failed: "); - (void) strcat(errbuf, error_message(r)); - Data(ap, KRB_REJECT, errbuf, -1); - if (auth_debug_mode) - printf("%s\r\n", errbuf); - return; - } - free(name); - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* do ap_rep stuff here */ - reply.ctime = authdat->authenticator->ctime; - reply.cusec = authdat->authenticator->cusec; - reply.subkey = 0; /* use the one he gave us, so don't - need to return one here */ - reply.seq_number = 0; /* we don't do seq #'s. */ + ret = krb5_cc_resolve (context, ccname, &ccache); + if (ret) { + if (auth_debug_mode) + printf ("Kerberos V5: could not get ccache: %s\r\n", + krb5_get_err_text(context, ret)); + break; + } - if (r = krb5_mk_rep(&reply, - authdat->authenticator->subkey ? - authdat->authenticator->subkey : - authdat->ticket->enc_part2->session, - &outbuf)) { - goto errout; - } - Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); - } - if (krb5_unparse_name(authdat->ticket->enc_part2 ->client, - &name)) - name = 0; - Data(ap, KRB_ACCEPT, name, name ? -1 : 0); - if (auth_debug_mode) { - printf("Kerberos5 identifies him as ``%s''\r\n", - name ? name : ""); - } - auth_finished(ap, AUTH_USER); + ret = krb5_cc_initialize (context, + ccache, + ticket->client); + if (ret) { + if (auth_debug_mode) + printf ("Kerberos V5: could not init ccache: %s\r\n", + krb5_get_err_text(context, ret)); + break; + } - free(name); - if (authdat->authenticator->subkey && - authdat->authenticator->subkey->keytype == KEYTYPE_DES) { - memmove((Voidptr )session_key, - (Voidptr )authdat->authenticator->subkey->contents, - sizeof(Block)); - } else if (authdat->ticket->enc_part2->session->keytype == - KEYTYPE_DES) { - memmove((Voidptr )session_key, - (Voidptr )authdat->ticket->enc_part2->session->contents, - sizeof(Block)); - } else - break; +#if defined(DCE) + esetenv("KRB5CCNAME", ccname, 1); +#endif + ret = krb5_rd_cred2 (context, + auth_context, + ccache, + &inbuf); + if(ret) { + char *errbuf; -#ifdef ENCRYPTION - skey.type = SK_DES; - skey.length = 8; - skey.data = session_key; - encrypt_session_key(&skey, 1); -#endif /* ENCRYPTION */ - break; -#ifdef FORWARD - case KRB_FORWARD: - inbuf.data = (char *)data; - inbuf.length = cnt; - if (r = rd_and_store_for_creds(&inbuf, authdat->ticket, - UserNameRequested)) { - char errbuf[128]; - - (void) strcpy(errbuf, "Read forwarded creds failed: "); - (void) strcat(errbuf, error_message(r)); - Data(ap, KRB_FORWARD_REJECT, errbuf, -1); - if (auth_debug_mode) - printf("Could not read forwarded credentials\r\n"); - } - else - Data(ap, KRB_FORWARD_ACCEPT, 0, 0); - if (auth_debug_mode) - printf("Forwarded credentials obtained\r\n"); - break; -#endif /* FORWARD */ - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - Data(ap, KRB_REJECT, 0, 0); - break; + asprintf (&errbuf, + "Read forwarded creds failed: %s", + krb5_get_err_text (context, ret)); + if(errbuf == NULL) + Data(ap, KRB_FORWARD_REJECT, NULL, 0); + else + Data(ap, KRB_FORWARD_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("Could not read forwarded credentials: %s\r\n", + errbuf); + free (errbuf); + } else { + Data(ap, KRB_FORWARD_ACCEPT, 0, 0); +#if defined(DCE) + dfsfwd = 1; +#endif } + chown (ccname + 5, pwd->pw_uid, -1); + if (auth_debug_mode) + printf("Forwarded credentials obtained\r\n"); + break; + } + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + Data(ap, KRB_REJECT, 0, 0); + break; + } } - void -kerberos5_reply(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; +void +kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) { + static int mutual_complete = 0; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_REJECT: + if (cnt > 0) { + printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ Kerberos V5 refuses authentication ]\r\n"); + auth_send_retry(); + return; + case KRB_ACCEPT: { + krb5_error_code ret; Session_Key skey; - static int mutual_complete = 0; + krb5_keyblock *keyblock; + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && + !mutual_complete) { + printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); + auth_send_retry(); + return; + } + if (cnt) + printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data); + else + printf("[ Kerberos V5 accepts you ]\r\n"); + + ret = krb5_auth_con_getlocalsubkey (context, + auth_context, + &keyblock); + if (ret) + ret = krb5_auth_con_getkey (context, + auth_context, + &keyblock); + if(ret) { + printf("[ krb5_auth_con_getkey: %s ]\r\n", + krb5_get_err_text(context, ret)); + auth_send_retry(); + return; + } + + skey.type = SK_DES; + skey.length = 8; + skey.data = keyblock->keyvalue.data; + encrypt_session_key(&skey, 0); + krb5_free_keyblock_contents (context, keyblock); + auth_finished(ap, AUTH_USER); + if (forward_flags & OPTS_FORWARD_CREDS) + kerberos5_forward(ap); + break; + } + case KRB_RESPONSE: + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* the rest of the reply should contain a krb_ap_rep */ + krb5_ap_rep_enc_part *reply; + krb5_data inbuf; + krb5_error_code ret; + + inbuf.length = cnt; + inbuf.data = (char *)data; - if (cnt-- < 1) - return; - switch (*data++) { - case KRB_REJECT: - if (cnt > 0) { - printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", - cnt, data); - } else - printf("[ Kerberos V5 refuses authentication ]\r\n"); - auth_send_retry(); - return; - case KRB_ACCEPT: - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && - !mutual_complete) { - printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n"); - auth_send_retry(); - return; - } - if (cnt) - printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data); - else - printf("[ Kerberos V5 accepts you ]\n"); - auth_finished(ap, AUTH_USER); -#ifdef FORWARD - if (forward_flags & OPTS_FORWARD_CREDS) - kerberos5_forward(ap); -#endif /* FORWARD */ - break; - case KRB_RESPONSE: - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* the rest of the reply should contain a krb_ap_rep */ - krb5_ap_rep_enc_part *reply; - krb5_data inbuf; - krb5_error_code r; - krb5_keyblock tmpkey; - - inbuf.length = cnt; - inbuf.data = (char *)data; - - tmpkey.keytype = KEYTYPE_DES; - tmpkey.contents = session_key; - tmpkey.length = sizeof(Block); - - if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) { - printf("[ Mutual authentication failed: %s ]\n", - error_message(r)); - auth_send_retry(); - return; - } - if (reply->ctime != authenticator.ctime || - reply->cusec != authenticator.cusec) { - printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n"); - auth_send_retry(); - return; - } - krb5_free_ap_rep_enc_part(reply); -#ifdef ENCRYPTION - skey.type = SK_DES; - skey.length = 8; - skey.data = session_key; - encrypt_session_key(&skey, 0); -#endif /* ENCRYPTION */ - mutual_complete = 1; - } - return; -#ifdef FORWARD - case KRB_FORWARD_ACCEPT: - printf("[ Kerberos V5 accepted forwarded credentials ]\n"); - return; - case KRB_FORWARD_REJECT: - printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", - cnt, data); - return; -#endif /* FORWARD */ - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - return; + ret = krb5_rd_rep(context, auth_context, &inbuf, &reply); + if (ret) { + printf("[ Mutual authentication failed: %s ]\r\n", + krb5_get_err_text (context, ret)); + auth_send_retry(); + return; + } + krb5_free_ap_rep_enc_part(context, reply); + mutual_complete = 1; } + return; + case KRB_FORWARD_ACCEPT: + printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); + return; + case KRB_FORWARD_REJECT: + printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", + cnt, data); + return; + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + return; + } } - int -kerberos5_status(ap, name, level) - Authenticator *ap; - char *name; - int level; +int +kerberos5_status(Authenticator *ap __unused, char *name, int level) { - if (level < AUTH_USER) - return(level); + if (level < AUTH_USER) + return(level); - if (UserNameRequested && - krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested)) + if (UserNameRequested && + krb5_kuserok(context, + ticket->client, + UserNameRequested)) { - strcpy(name, UserNameRequested); - return(AUTH_VALID); + strcpy(name, UserNameRequested); + return(AUTH_VALID); } else - return(AUTH_USER); + return(AUTH_USER); } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - void -kerberos5_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - char lbuf[32]; - register int i; + int i; - buf[buflen-1] = '\0'; /* make sure its NULL terminated */ - buflen -= 1; + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; - switch(data[3]) { - case KRB_REJECT: /* Rejected (reason might follow) */ - strncpy((char *)buf, " REJECT ", buflen); - goto common; + switch(data[3]) { + case KRB_REJECT: /* Rejected (reason might follow) */ + strlcpy((char *)buf, " REJECT ", buflen); + goto common; - case KRB_ACCEPT: /* Accepted (name might follow) */ - strncpy((char *)buf, " ACCEPT ", buflen); - common: - BUMP(buf, buflen); - if (cnt <= 4) - break; - ADDC(buf, buflen, '"'); - for (i = 4; i < cnt; i++) - ADDC(buf, buflen, data[i]); - ADDC(buf, buflen, '"'); - ADDC(buf, buflen, '\0'); - break; + case KRB_ACCEPT: /* Accepted (name might follow) */ + strlcpy((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; - case KRB_AUTH: /* Authentication data follows */ - strncpy((char *)buf, " AUTH", buflen); - goto common2; + case KRB_AUTH: /* Authentication data follows */ + strlcpy((char *)buf, " AUTH", buflen); + goto common2; - case KRB_RESPONSE: - strncpy((char *)buf, " RESPONSE", buflen); - goto common2; + case KRB_RESPONSE: + strlcpy((char *)buf, " RESPONSE", buflen); + goto common2; -#ifdef FORWARD - case KRB_FORWARD: /* Forwarded credentials follow */ - strncpy((char *)buf, " FORWARD", buflen); - goto common2; + case KRB_FORWARD: /* Forwarded credentials follow */ + strlcpy((char *)buf, " FORWARD", buflen); + goto common2; - case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ - strncpy((char *)buf, " FORWARD_ACCEPT", buflen); - goto common2; + case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ + strlcpy((char *)buf, " FORWARD_ACCEPT", buflen); + goto common2; - case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ - /* (reason might follow) */ - strncpy((char *)buf, " FORWARD_REJECT", buflen); - goto common2; -#endif /* FORWARD */ + case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ + /* (reason might follow) */ + strlcpy((char *)buf, " FORWARD_REJECT", buflen); + goto common2; - default: - sprintf(lbuf, " %d (unknown)", data[3]); - strncpy((char *)buf, lbuf, buflen); - common2: - BUMP(buf, buflen); - for (i = 4; i < cnt; i++) { - sprintf(lbuf, " %d", data[i]); - strncpy((char *)buf, lbuf, buflen); - BUMP(buf, buflen); - } - break; + default: + snprintf(buf, buflen, " %d (unknown)", data[3]); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + snprintf(buf, buflen, " %d", data[i]); + BUMP(buf, buflen); } + break; + } } -#ifdef FORWARD - void -kerberos5_forward(ap) - Authenticator *ap; +void +kerberos5_forward(Authenticator *ap) { - struct hostent *hp; - krb5_creds *local_creds; - krb5_error_code r; - krb5_data forw_creds; - extern krb5_cksumtype krb5_kdc_req_sumtype; - krb5_ccache ccache; - int i; + krb5_error_code ret; + krb5_ccache ccache; + krb5_creds creds; + krb5_kdc_flags flags; + krb5_data out_data; + krb5_principal principal; - if (!(local_creds = (krb5_creds *) - calloc(1, sizeof(*local_creds)))) { + ret = krb5_cc_default (context, &ccache); + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: could not allocate memory for credentials\r\n"); + printf ("KerberosV5: could not get default ccache: %s\r\n", + krb5_get_err_text (context, ret)); return; } - if (r = krb5_sname_to_principal(RemoteHostName, "host", 1, - &local_creds->server)) { + ret = krb5_cc_get_principal (context, ccache, &principal); + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: could not build server name - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); + printf ("KerberosV5: could not get principal: %s\r\n", + krb5_get_err_text (context, ret)); return; } - if (r = krb5_cc_default(&ccache)) { - if (auth_debug_mode) - printf("Kerberos V5: could not get default ccache - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); - return; - } + memset (&creds, 0, sizeof(creds)); - if (r = krb5_cc_get_principal(ccache, &local_creds->client)) { - if (auth_debug_mode) - printf("Kerberos V5: could not get default principal - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); - return; - } + creds.client = principal; + + ret = krb5_build_principal (context, + &creds.server, + strlen(principal->realm), + principal->realm, + "krbtgt", + principal->realm, + NULL); - /* Get ticket from credentials cache */ - if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) { + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: could not obtain credentials - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); + printf ("KerberosV5: could not get principal: %s\r\n", + krb5_get_err_text (context, ret)); return; } - if (r = get_for_creds(ETYPE_DES_CBC_CRC, - krb5_kdc_req_sumtype, - RemoteHostName, - local_creds->client, - &local_creds->keyblock, - forward_flags & OPTS_FORWARDABLE_CREDS, - &forw_creds)) { + creds.times.endtime = 0; + + flags.i = 0; + flags.b.forwarded = 1; + if (forward_flags & OPTS_FORWARDABLE_CREDS) + flags.b.forwardable = 1; + + ret = krb5_get_forwarded_creds (context, + auth_context, + ccache, + flags.i, + RemoteHostName, + &creds, + &out_data); + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: error getting forwarded creds - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); + printf ("Kerberos V5: error getting forwarded creds: %s\r\n", + krb5_get_err_text (context, ret)); return; } - /* Send forwarded credentials */ - if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) { + if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) { if (auth_debug_mode) - printf("Not enough room for authentication data\r\n"); - } - else { + printf("Not enough room for authentication data\r\n"); + } else { if (auth_debug_mode) - printf("Forwarded local Kerberos V5 credentials to server\r\n"); + printf("Forwarded local Kerberos V5 credentials to server\r\n"); } +} - krb5_free_creds(local_creds); +#if defined(DCE) +/* if this was a K5 authentication try and join a PAG for the user. */ +void +kerberos5_dfspag(void) +{ + if (dfsk5ok) { + dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client, + UserNameRequested); + } } -#endif /* FORWARD */ +#endif #endif /* KRB5 */ Index: head/contrib/telnet/libtelnet/key-proto.h =================================================================== --- head/contrib/telnet/libtelnet/key-proto.h (revision 87138) +++ head/contrib/telnet/libtelnet/key-proto.h (revision 87139) @@ -1,71 +1,65 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)key-proto.h 8.1 (Berkeley) 6/4/93 */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. + * + * $FreeBSD$ */ #ifndef __KEY_PROTO__ #define __KEY_PROTO__ -#if !defined(P) -#ifdef __STDC__ -#define P(x) x -#else -#define P(x) () -#endif -#endif - -int key_file_exists P((void)); -void key_lookup P((unsigned char *, Block)); -void key_stream_init P((Block, Block, int)); -unsigned char key_stream P((int, int)); +int key_file_exists(void); +void key_lookup(unsigned char *, Block); +void key_stream_init(Block, Block, int); +unsigned char key_stream(int, int); #endif Index: head/contrib/telnet/libtelnet/krb4encpwd.c =================================================================== --- head/contrib/telnet/libtelnet/krb4encpwd.c (revision 87138) +++ head/contrib/telnet/libtelnet/krb4encpwd.c (revision 87139) @@ -1,448 +1,428 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static char sccsid[] = "@(#)krb4encpwd.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ #ifdef KRB4_ENCPWD /* * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION * ALL RIGHTS RESERVED * * "Digital Equipment Corporation authorizes the reproduction, * distribution and modification of this software subject to the following * restrictions: * * 1. Any partial or whole copy of this software, or any modification * thereof, must include this copyright notice in its entirety. * * 2. This software is supplied "as is" with no warranty of any kind, * expressed or implied, for any purpose, including any warranty of fitness * or merchantibility. DIGITAL assumes no responsibility for the use or * reliability of this software, nor promises to provide any form of * support for it on any basis. * * 3. Distribution of this software is authorized only if no profit or * remuneration of any kind is received in exchange for such distribution. * * 4. This software produces public key authentication certificates * bearing an expiration date established by DIGITAL and RSA Data * Security, Inc. It may cease to generate certificates after the expiration * date. Any modification of this software that changes or defeats * the expiration date or its effect is unauthorized. * * 5. Software that will renew or extend the expiration date of * authentication certificates produced by this software may be obtained * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA * 94065, (415)595-8782, or from DIGITAL" * */ #include +#include #include +#include #include #include - -#include -#include -#ifdef __STDC__ #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif #include "encrypt.h" #include "auth.h" #include "misc.h" int krb_mk_encpwd_req P((KTEXT, char *, char *, char *, char *, char *, char *)); int krb_rd_encpwd_req P((KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *)); extern auth_debug_mode; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KRB4_ENCPWD, }; static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; #define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */ #define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ #define KRB4_ENCPWD_ACCEPT 2 /* Accepted */ #define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */ #define KRB4_ENCPWD_ACK 4 /* Acknowledge */ #define KRB_SERVICE_NAME "rcmd" static KTEXT_ST auth; static char name[ANAME_SZ]; static char user_passwd[ANAME_SZ]; static AUTH_DAT adat = { 0 }; #ifdef ENCRYPTION static Block session_key = { 0 }; #endif /* ENCRYPTION */ static char challenge[REALM_SZ]; static int Data(ap, type, d, c) Authenticator *ap; int type; void *d; int c; { unsigned char *p = str_data + 4; unsigned char *cd = (unsigned char *)d; if (c == -1) c = strlen((char *)cd); if (0) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } int krb4encpwd_init(ap, server) Authenticator *ap; int server; { char hostname[80], *cp, *realm; C_Block skey; if (server) { str_data[3] = TELQUAL_REPLY; } else { str_data[3] = TELQUAL_IS; gethostname(hostname, sizeof(hostname)); realm = krb_realmofhost(hostname); cp = strchr(hostname, '.'); if (*cp != NULL) *cp = NULL; if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0, KEYFILE, (char *)skey)) { return(0); } } return(1); } int krb4encpwd_send(ap) Authenticator *ap; { printf("[ Trying KRB4ENCPWD ... ]\n"); if (!UserNameRequested) { return(0); } if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { return(0); } if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) { return(0); } return(1); } void krb4encpwd_is(ap, data, cnt) Authenticator *ap; unsigned char *data; int cnt; { Session_Key skey; Block datablock; char r_passwd[ANAME_SZ], r_user[ANAME_SZ]; char lhostname[ANAME_SZ], *cp; int r; time_t now; if (cnt-- < 1) return; switch (*data++) { case KRB4_ENCPWD_AUTH: memmove((void *)auth.dat, (void *)data, auth.length = cnt); gethostname(lhostname, sizeof(lhostname)); if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) { Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1); auth_finished(ap, AUTH_REJECT); return; } auth_encrypt_userpwd(r_passwd); if (passwdok(UserNameRequested, UserPassword) == 0) { /* * illegal username and password */ Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1); auth_finished(ap, AUTH_REJECT); return; } memmove((void *)session_key, (void *)adat.session, sizeof(Block)); Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0); auth_finished(ap, AUTH_USER); break; case KRB4_ENCPWD_CHALLENGE: /* * Take the received random challenge text and save * for future authentication. */ memmove((void *)challenge, (void *)data, sizeof(Block)); break; case KRB4_ENCPWD_ACK: /* * Receive ack, if mutual then send random challenge */ /* * If we are doing mutual authentication, get set up to send * the challenge, and verify it when the response comes back. */ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { register int i; time(&now); sprintf(challenge, "%x", now); Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge)); } break; default: Data(ap, KRB4_ENCPWD_REJECT, 0, 0); break; } } void krb4encpwd_reply(ap, data, cnt) Authenticator *ap; unsigned char *data; int cnt; { Session_Key skey; KTEXT_ST krb_token; Block enckey; CREDENTIALS cred; int r; char randchal[REALM_SZ], instance[ANAME_SZ], *cp; char hostname[80], *realm; if (cnt-- < 1) return; switch (*data++) { case KRB4_ENCPWD_REJECT: if (cnt > 0) { printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n", cnt, data); } else printf("[ KRB4_ENCPWD refuses authentication ]\r\n"); auth_send_retry(); return; case KRB4_ENCPWD_ACCEPT: printf("[ KRB4_ENCPWD accepts you ]\n"); auth_finished(ap, AUTH_USER); return; case KRB4_ENCPWD_CHALLENGE: /* * Verify that the response to the challenge is correct. */ gethostname(hostname, sizeof(hostname)); realm = krb_realmofhost(hostname); memmove((void *)challenge, (void *)data, cnt); memset(user_passwd, 0, sizeof(user_passwd)); local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); UserPassword = user_passwd; Challenge = challenge; strcpy(instance, RemoteHostName); if ((cp = strchr(instance, '.')) != 0) *cp = '\0'; if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) { krb_token.length = 0; } if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) { return; } break; default: return; } } int krb4encpwd_status(ap, name, level) Authenticator *ap; char *name; int level; { if (level < AUTH_USER) return(level); if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) { strcpy(name, UserNameRequested); return(AUTH_VALID); } else { return(AUTH_USER); } } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} void krb4encpwd_printsub(data, cnt, buf, buflen) unsigned char *data, *buf; int cnt, buflen; { char lbuf[32]; register int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case KRB4_ENCPWD_AUTH: /* Authentication data follows */ strncpy((char *)buf, " AUTH", buflen); goto common2; case KRB4_ENCPWD_CHALLENGE: strncpy((char *)buf, " CHALLENGE", buflen); goto common2; case KRB4_ENCPWD_ACK: strncpy((char *)buf, " ACK", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } int passwdok(name, passwd) char *name, *passwd; { char *crypt(); char *salt, *p; struct passwd *pwd; int passwdok_status = 0; if (pwd = getpwnam(name)) salt = pwd->pw_passwd; else salt = "xx"; p = crypt(passwd, salt); if (pwd && !strcmp(p, pwd->pw_passwd)) { passwdok_status = 1; } else passwdok_status = 0; return(passwdok_status); } -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); -} #endif Index: head/contrib/telnet/libtelnet/misc-proto.h =================================================================== --- head/contrib/telnet/libtelnet/misc-proto.h (revision 87138) +++ head/contrib/telnet/libtelnet/misc-proto.h (revision 87139) @@ -1,81 +1,88 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)misc-proto.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifndef __MISC_PROTO__ #define __MISC_PROTO__ #if !defined(P) #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #endif -void auth_encrypt_init P((char *, char *, char *, int)); -void auth_encrypt_connect P((int)); -void printd P((unsigned char *, int)); +void auth_encrypt_init(char *, char *, const char *, int); +void auth_encrypt_connect(int); +void printd(const unsigned char *, int); +int isprefix(char *, const char *); +char **genget(char *, char **, int); +int Ambiguous(char **); + +int getent(char *, const char *); +char *Getstr(const char *, char **); + /* * These functions are imported from the application */ -int net_write P((unsigned char *, int)); -void net_encrypt P((void)); -int telnet_spin P((void)); -char *telnet_getenv P((char *)); -char *telnet_gets P((char *, char *, int, int)); -void printsub P((int, unsigned char *, int)); +int net_write(unsigned char *, int); +void net_encrypt(void); +int telnet_spin(void); +char *telnet_getenv(char *); +char *telnet_gets(const char *, char *, int, int); +void printsub(char, unsigned char *, int); #endif Index: head/contrib/telnet/libtelnet/misc.c =================================================================== --- head/contrib/telnet/libtelnet/misc.c (revision 87138) +++ head/contrib/telnet/libtelnet/misc.c (revision 87139) @@ -1,107 +1,108 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93"; #endif #endif /* not lint */ #include #include +#include + #include "misc.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include "auth.h" #endif #ifdef ENCRYPTION #include "encrypt.h" #endif /* ENCRYPTION */ char *RemoteHostName; char *LocalHostName; char *UserNameRequested = 0; int ConnectedCount = 0; - void -auth_encrypt_init(local, remote, name, server) - char *local; - char *remote; - char *name; - int server; +#ifndef AUTHENTICATION +#define undef1 __unused +#else +#define undef1 +#endif + +void +auth_encrypt_init(char *local, char *remote, const char *name undef1, int server undef1) { RemoteHostName = remote; LocalHostName = local; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION auth_init(name, server); #endif #ifdef ENCRYPTION encrypt_init(name, server); #endif /* ENCRYPTION */ if (UserNameRequested) { free(UserNameRequested); UserNameRequested = 0; } } - void -auth_encrypt_user(name) - char *name; +#ifdef ENCRYPTION +void +auth_encrypt_user(char *name) { - extern char *strdup(); - if (UserNameRequested) free(UserNameRequested); UserNameRequested = name ? strdup(name) : 0; } - void -auth_encrypt_connect(cnt) - int cnt; +void +auth_encrypt_connect(int cnt __unused) { } +#endif /* ENCRYPTION */ - void -printd(data, cnt) - unsigned char *data; - int cnt; +void +printd(const unsigned char *data, int cnt) { if (cnt > 16) cnt = 16; while (cnt-- > 0) { printf(" %02x", *data); ++data; } } Index: head/contrib/telnet/libtelnet/pk.c =================================================================== --- head/contrib/telnet/libtelnet/pk.c (revision 87138) +++ head/contrib/telnet/libtelnet/pk.c (revision 87139) @@ -1,272 +1,269 @@ /*- * Copyright (c) 1991, 1993 * Dave Safford. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ +#include + +__FBSDID("$FreeBSD$"); + /* public key routines */ /* functions: genkeys(char *public, char *secret) common_key(char *secret, char *public, desData *deskey) pk_encode(char *in, *out, DesData *deskey); pk_decode(char *in, *out, DesData *deskey); where char public[HEXKEYBYTES + 1]; char secret[HEXKEYBYTES + 1]; */ -#include -__FBSDID("$FreeBSD$"); - #include #include #include #include +#include #include + #include "mp.h" #include "pk.h" -#if defined(SOLARIS2) || defined(LINUX) || defined(__FreeBSD__) -#include -#endif static void adjust(char keyout[HEXKEYBYTES+1], char *keyin); /* * Choose top 128 bits of the common key to use as our idea key. */ static void extractideakey(MINT *ck, IdeaData *ideakey) { MINT *a; MINT *z; short r; int i; short base = (1 << 8); char *k; z = itom(0); a = itom(0); madd(ck, z, a); for (i = 0; i < ((KEYSIZE - 128) / 8); i++) { sdiv(a, base, a, &r); } k = (char *)ideakey; for (i = 0; i < 16; i++) { sdiv(a, base, a, &r); *k++ = r; } mfree(z); mfree(a); } /* * Choose middle 64 bits of the common key to use as our des key, possibly * overwriting the lower order bits by setting parity. */ static void extractdeskey(MINT *ck, DesData *deskey) { MINT *a; MINT *z; short r; int i; short base = (1 << 8); char *k; z = itom(0); a = itom(0); madd(ck, z, a); for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { sdiv(a, base, a, &r); } k = (char *)deskey; for (i = 0; i < 8; i++) { sdiv(a, base, a, &r); *k++ = r; } mfree(z); mfree(a); } /* * get common key from my secret key and his public key */ void common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey) { MINT *public; MINT *secret; MINT *common; MINT *modulus = xtom(HEXMODULUS); public = xtom(xpublic); secret = xtom(xsecret); common = itom(0); pow(public, secret, modulus, common); extractdeskey(common, deskey); extractideakey(common, ideakey); -#if DES_OSTHOLM - des_fixup_key_parity(deskey); -#else des_set_odd_parity(deskey); -#endif mfree(common); mfree(secret); mfree(public); mfree(modulus); } /* * Generate a seed */ -void +static void getseed(char *seed, int seedsize) { int i; srandomdev(); for (i = 0; i < seedsize; i++) { seed[i] = random() & 0xff; } } /* * Generate a random public/secret key pair */ void genkeys(char *public, char *secret) { - int i; + size_t i; # define BASEBITS (8*sizeof(short) - 1) # define BASE (1 << BASEBITS) MINT *pk = itom(0); MINT *sk = itom(0); MINT *tmp; MINT *base = itom(BASE); MINT *root = itom(PROOT); MINT *modulus = xtom(HEXMODULUS); short r; unsigned short seed[KEYSIZE/BASEBITS + 1]; char *xkey; getseed((char *)seed, sizeof(seed)); for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { r = seed[i] % BASE; tmp = itom(r); mult(sk, base, sk); madd(sk, tmp, sk); mfree(tmp); } tmp = itom(0); mdiv(sk, modulus, tmp, sk); mfree(tmp); pow(root, sk, modulus, pk); xkey = mtox(sk); adjust(secret, xkey); xkey = mtox(pk); adjust(public, xkey); mfree(sk); mfree(base); mfree(pk); mfree(root); mfree(modulus); } /* * Adjust the input key so that it is 0-filled on the left */ static void adjust(char keyout[HEXKEYBYTES+1], char *keyin) { char *p; char *s; for (p = keyin; *p; p++) ; for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { *s = *p; } while (s >= keyout) { *s-- = '0'; } } static char hextab[17] = "0123456789ABCDEF"; /* given a DES key, cbc encrypt and translate input to terminated hex */ void pk_encode(char *in, char *out, DesData *key) { char buf[256]; DesData i; des_key_schedule k; int l,op,deslen; memset(&i,0,sizeof(i)); memset(buf,0,sizeof(buf)); deslen = ((strlen(in) + 7)/8)*8; des_key_sched(key, k); des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT); for (l=0,op=0;l> 4]; out[op++] = hextab[(buf[l] & 0x0f)]; } out[op] = '\0'; } /* given a DES key, translate input from hex and decrypt */ void pk_decode(char *in, char *out, DesData *key) { char buf[256]; DesData i; des_key_schedule k; - int l,n1,n2,op; + int n1,n2,op; + size_t l; memset(&i,0,sizeof(i)); memset(buf,0,sizeof(buf)); for (l=0,op=0;l '9') n1 = in[op] - 'A' + 10; else n1 = in[op] - '0'; if (in[op+1] > '9') n2 = in[op+1] - 'A' + 10; else n2 = in[op+1] - '0'; buf[l] = n1*16 +n2; } des_key_sched(key, k); des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT); out[strlen(in)/2] = '\0'; } Index: head/contrib/telnet/libtelnet/pk.h =================================================================== --- head/contrib/telnet/libtelnet/pk.h (revision 87138) +++ head/contrib/telnet/libtelnet/pk.h (revision 87139) @@ -1,72 +1,59 @@ /*- * Copyright (c) 1991, 1993 * Dave Safford. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* header for the des routines that we will use */ typedef unsigned char byte, DesData[ 8], IdeaData[16]; -#if 0 -typedef unsigned long word, DesKeys[32]; -#else #define DesKeys des_key_schedule -#endif #define DES_DECRYPT 0 #define DES_ENCRYPT 1 -#if 0 -extern void des_fixup_key_parity(); /* (DesData *key) */ -extern int des_key_sched(); /* (DesData *key, DesKeys *m) */ -extern int des_ecb_encrypt(); /* (DesData *src, *dst, DesKeys *m, int mode) */ -extern int des_cbc_encrypt(); /* (char *src, *dst, int length, - DesKeys *m, DesData *init, int mode) */ -#endif - /* public key routines */ /* functions: genkeys(char *public, char *secret) common_key(char *secret, char *public, desData *deskey) where char public[HEXKEYBYTES + 1]; char secret[HEXKEYBYTES + 1]; */ #define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b" #define HEXKEYBYTES 48 #define KEYSIZE 192 #define KEYBYTES 24 #define PROOT 3 extern void genkeys(char *public, char *secret); extern void common_key(char *secret, char *public, IdeaData *common, DesData *deskey); extern void pk_encode(char *in, char *out, DesData *deskey); extern void pk_decode(char *in, char *out, DesData *deskey); - Index: head/contrib/telnet/libtelnet/read_password.c =================================================================== --- head/contrib/telnet/libtelnet/read_password.c (revision 87138) +++ head/contrib/telnet/libtelnet/read_password.c (revision 87139) @@ -1,150 +1,151 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static char sccsid[] = "@(#)read_password.c 8.3 (Berkeley) 5/30/95"; #endif #endif /* not lint */ /* * $Source: /mit/kerberos/src/lib/des/RCS/read_password.c,v $ * $Author: jon $ * * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute * of Technology. * * For copying and distribution information, please see the file * . * * This routine prints the supplied string to standard * output as a prompt, and reads a password string without * echoing. */ #if defined(RSA_ENCPWD) || defined(KRB4_ENCPWD) #include #include #include #include #include static jmp_buf env; /*** Routines ****************************************************** */ /* * This version just returns the string, doesn't map to key. * * Returns 0 on success, non-zero on failure. */ int local_des_read_pw_string(s,max,prompt,verify) char *s; int max; char *prompt; int verify; { int ok = 0; char *ptr; jmp_buf old_env; struct sgttyb tty_state; char key_string[BUFSIZ]; if (max > BUFSIZ) { return -1; } /* XXX assume jmp_buf is typedef'ed to an array */ memmove((char *)env, (char *)old_env, sizeof(env)); if (setjmp(env)) goto lose; /* save terminal state*/ if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1) return -1; /* push_signals(); */ /* Turn off echo */ tty_state.sg_flags &= ~ECHO; if (ioctl(0,TIOCSETP,(char *)&tty_state) == -1) return -1; while (!ok) { (void) printf("%s", prompt); (void) fflush(stdout); while (!fgets(s, max, stdin)); if ((ptr = strchr(s, '\n'))) *ptr = '\0'; if (verify) { printf("\nVerifying, please re-enter %s",prompt); (void) fflush(stdout); if (!fgets(key_string, sizeof(key_string), stdin)) { clearerr(stdin); continue; } if ((ptr = strchr(key_string, '\n'))) *ptr = '\0'; if (strcmp(s,key_string)) { printf("\n\07\07Mismatch - try again\n"); (void) fflush(stdout); continue; } } ok = 1; } lose: if (!ok) memset(s, 0, max); printf("\n"); /* turn echo back on */ tty_state.sg_flags |= ECHO; if (ioctl(0,TIOCSETP,(char *)&tty_state)) ok = 0; /* pop_signals(); */ memmove((char *)old_env, (char *)env, sizeof(env)); if (verify) memset(key_string, 0, sizeof (key_string)); s[max-1] = 0; /* force termination */ return !ok; /* return nonzero if not okay */ } #endif /* defined(RSA_ENCPWD) || defined(KRB4_ENCPWD) */ Index: head/contrib/telnet/libtelnet/rsaencpwd.c =================================================================== --- head/contrib/telnet/libtelnet/rsaencpwd.c (revision 87138) +++ head/contrib/telnet/libtelnet/rsaencpwd.c (revision 87139) @@ -1,495 +1,475 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static char sccsid[] = "@(#)rsaencpwd.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ #ifdef RSA_ENCPWD /* * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION * ALL RIGHTS RESERVED * * "Digital Equipment Corporation authorizes the reproduction, * distribution and modification of this software subject to the following * restrictions: * * 1. Any partial or whole copy of this software, or any modification * thereof, must include this copyright notice in its entirety. * * 2. This software is supplied "as is" with no warranty of any kind, * expressed or implied, for any purpose, including any warranty of fitness * or merchantibility. DIGITAL assumes no responsibility for the use or * reliability of this software, nor promises to provide any form of * support for it on any basis. * * 3. Distribution of this software is authorized only if no profit or * remuneration of any kind is received in exchange for such distribution. * * 4. This software produces public key authentication certificates * bearing an expiration date established by DIGITAL and RSA Data * Security, Inc. It may cease to generate certificates after the expiration * date. Any modification of this software that changes or defeats * the expiration date or its effect is unauthorized. * * 5. Software that will renew or extend the expiration date of * authentication certificates produced by this software may be obtained * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA * 94065, (415)595-8782, or from DIGITAL" * */ #include #include #include #include - -#ifdef __STDC__ #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif #include "encrypt.h" #include "auth.h" #include "misc.h" #include "cdc.h" extern auth_debug_mode; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_RSA_ENCPWD, }; static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; #define RSA_ENCPWD_AUTH 0 /* Authentication data follows */ #define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ #define RSA_ENCPWD_ACCEPT 2 /* Accepted */ #define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */ #define NAME_SZ 40 #define CHAL_SZ 20 #define PWD_SZ 40 static KTEXT_ST auth; static char name[NAME_SZ]; static char user_passwd[PWD_SZ]; static char key_file[2*NAME_SZ]; static char lhostname[NAME_SZ]; static char challenge[CHAL_SZ]; static int challenge_len; static int Data(ap, type, d, c) Authenticator *ap; int type; void *d; int c; { unsigned char *p = str_data + 4; unsigned char *cd = (unsigned char *)d; if (c == -1) c = strlen((char *)cd); if (0) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; if (type != NULL) *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } int rsaencpwd_init(ap, server) Authenticator *ap; int server; { char *cp; FILE *fp; if (server) { str_data[3] = TELQUAL_REPLY; memset(key_file, 0, sizeof(key_file)); gethostname(lhostname, sizeof(lhostname)); if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; strcpy(key_file, "/etc/."); strcat(key_file, lhostname); strcat(key_file, "_privkey"); if ((fp=fopen(key_file, "r"))==NULL) return(0); fclose(fp); } else { str_data[3] = TELQUAL_IS; } return(1); } int rsaencpwd_send(ap) Authenticator *ap; { printf("[ Trying RSAENCPWD ... ]\n"); if (!UserNameRequested) { return(0); } if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { return(0); } if (!Data(ap, NULL, (void *)NULL, 0)) { return(0); } return(1); } void rsaencpwd_is(ap, data, cnt) Authenticator *ap; unsigned char *data; int cnt; { Session_Key skey; Block datablock; char r_passwd[PWD_SZ], r_user[NAME_SZ]; char *cp, key[160]; char chalkey[160], *ptr; FILE *fp; int r, i, j, chalkey_len, len; time_t now; cnt--; switch (*data++) { case RSA_ENCPWD_AUTH: memmove((void *)auth.dat, (void *)data, auth.length = cnt); if ((fp=fopen(key_file, "r"))==NULL) { Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); auth_finished(ap, AUTH_REJECT); return; } /* * get privkey */ fscanf(fp, "%x;", &len); for (i=0;iway & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) { register int i; time(&now); if ((now % 2) == 0) { sprintf(challenge, "%x", now); challenge_len = strlen(challenge); } else { strcpy(challenge, "randchal"); challenge_len = 8; } if ((fp=fopen(key_file, "r"))==NULL) { Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); auth_finished(ap, AUTH_REJECT); return; } /* * skip privkey */ fscanf(fp, "%x;", &len); for (i=0;i 0) { printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n", cnt, data); } else printf("[ RSA_ENCPWD refuses authentication ]\r\n"); auth_send_retry(); return; case RSA_ENCPWD_ACCEPT: printf("[ RSA_ENCPWD accepts you ]\n"); auth_finished(ap, AUTH_USER); return; case RSA_ENCPWD_CHALLENGEKEY: /* * Verify that the response to the challenge is correct. */ memmove((void *)chalkey, (void *)data, cnt); ptr = (char *) &chalkey[0]; ptr += DecodeHeaderLength(chalkey); if (*ptr != 0x04) { return; } *ptr++; challenge_len = DecodeValueLength(ptr); ptr += NumEncodeLengthOctets(challenge_len); memmove(challenge, ptr, challenge_len); ptr += challenge_len; if (*ptr != 0x04) { return; } *ptr++; pubkey_len = DecodeValueLength(ptr); ptr += NumEncodeLengthOctets(pubkey_len); memmove(pubkey, ptr, pubkey_len); memset(user_passwd, 0, sizeof(user_passwd)); local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); UserPassword = user_passwd; Challenge = challenge; r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey); if (r < 0) { token.length = 1; } if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) { return; } break; default: return; } } int rsaencpwd_status(ap, name, level) Authenticator *ap; char *name; int level; { if (level < AUTH_USER) return(level); if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) { strcpy(name, UserNameRequested); return(AUTH_VALID); } else { return(AUTH_USER); } } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} void rsaencpwd_printsub(data, cnt, buf, buflen) unsigned char *data, *buf; int cnt, buflen; { char lbuf[32]; register int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case RSA_ENCPWD_AUTH: /* Authentication data follows */ strncpy((char *)buf, " AUTH", buflen); goto common2; case RSA_ENCPWD_CHALLENGEKEY: strncpy((char *)buf, " CHALLENGEKEY", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } int rsaencpwd_passwdok(name, passwd) char *name, *passwd; { char *crypt(); char *salt, *p; struct passwd *pwd; int passwdok_status = 0; if (pwd = getpwnam(name)) salt = pwd->pw_passwd; else salt = "xx"; p = crypt(passwd, salt); if (pwd && !strcmp(p, pwd->pw_passwd)) { passwdok_status = 1; } else passwdok_status = 0; return(passwdok_status); } -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); -} #endif Index: head/contrib/telnet/libtelnet/sra.c =================================================================== --- head/contrib/telnet/libtelnet/sra.c (revision 87138) +++ head/contrib/telnet/libtelnet/sra.c (revision 87139) @@ -1,669 +1,602 @@ /*- * Copyright (c) 1991, 1993 * Dave Safford. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include + __FBSDID("$FreeBSD$"); #ifdef SRA +#ifdef ENCRYPTION #include #include +#include #include -#ifdef __STDC__ #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif +#include +#include -#if !defined(NOPAM) +#ifndef NOPAM #include #else #include #endif -#include -#include -#include - #include "auth.h" #include "misc.h" #include "encrypt.h" #include "pk.h" char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1]; -char *user,*pass,*xuser,*xpass; +char *user, *pass, *xuser, *xpass; DesData ck; IdeaData ik; extern int auth_debug_mode; extern char *line; static int sra_valid = 0; static int passwd_sent = 0; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_SRA, }; #define SRA_KEY 0 #define SRA_USER 1 #define SRA_CONTINUE 2 #define SRA_PASS 3 #define SRA_ACCEPT 4 #define SRA_REJECT 5 -static int check_user(const char *, const char *); +static int check_user(char *, char *); /* support routine to send out authentication message */ static int Data(Authenticator *ap, int type, void *d, int c) { unsigned char *p = str_data + 4; unsigned char *cd = (unsigned char *)d; if (c == -1) c = strlen((char *)cd); if (auth_debug_mode) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } int -sra_init(Authenticator *ap, int server) +sra_init(Authenticator *ap __unused, int server) { if (server) str_data[3] = TELQUAL_REPLY; else str_data[3] = TELQUAL_IS; user = (char *)malloc(256); xuser = (char *)malloc(513); pass = (char *)malloc(256); xpass = (char *)malloc(513); if (user == NULL || xuser == NULL || pass == NULL || xpass == NULL) return 0; /* malloc failed */ passwd_sent = 0; genkeys(pka,ska); return(1); } /* client received a go-ahead for sra */ int sra_send(Authenticator *ap) { /* send PKA */ if (auth_debug_mode) printf("Sent PKA to server.\r\n" ); printf("Trying SRA secure login:\r\n"); if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { if (auth_debug_mode) printf("Not enough room for authentication data\r\n"); return(0); } return(1); } /* server received an IS -- could be SRA KEY, USER, or PASS */ void sra_is(Authenticator *ap, unsigned char *data, int cnt) { int valid; Session_Key skey; if (cnt-- < 1) goto bad; switch (*data++) { case SRA_KEY: if (cnt < HEXKEYBYTES) { Data(ap, SRA_REJECT, (void *)0, 0); auth_finished(ap, AUTH_USER); if (auth_debug_mode) { printf("SRA user rejected for bad PKB\r\n"); } return; } if (auth_debug_mode) printf("Sent pka\r\n"); if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { if (auth_debug_mode) printf("Not enough room\r\n"); return; } memcpy(pkb,data,HEXKEYBYTES); pkb[HEXKEYBYTES] = '\0'; common_key(ska,pkb,&ik,&ck); return; case SRA_USER: /* decode KAB(u) */ if (cnt > 512) /* Attempted buffer overflow */ break; memcpy(xuser,data,cnt); xuser[cnt] = '\0'; pk_decode(xuser,user,&ck); auth_encrypt_user(user); Data(ap, SRA_CONTINUE, (void *)0, 0); return; case SRA_PASS: if (cnt > 512) /* Attempted buffer overflow */ break; /* decode KAB(P) */ memcpy(xpass,data,cnt); xpass[cnt] = '\0'; pk_decode(xpass,pass,&ck); /* check user's password */ valid = check_user(user,pass); if(valid) { Data(ap, SRA_ACCEPT, (void *)0, 0); -#ifdef DES_ENCRYPTION skey.data = ck; skey.type = SK_DES; skey.length = 8; encrypt_session_key(&skey, 1); -#endif sra_valid = 1; auth_finished(ap, AUTH_VALID); if (auth_debug_mode) { printf("SRA user accepted\r\n"); } } else { Data(ap, SRA_CONTINUE, (void *)0, 0); /* Data(ap, SRA_REJECT, (void *)0, 0); sra_valid = 0; auth_finished(ap, AUTH_REJECT); */ if (auth_debug_mode) { printf("SRA user failed\r\n"); } } return; default: if (auth_debug_mode) printf("Unknown SRA option %d\r\n", data[-1]); } bad: Data(ap, SRA_REJECT, 0, 0); sra_valid = 0; auth_finished(ap, AUTH_REJECT); } /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */ void sra_reply(Authenticator *ap, unsigned char *data, int cnt) { - extern char *telnet_gets(); char uprompt[256],tuser[256]; Session_Key skey; - int i; + size_t i; if (cnt-- < 1) return; switch (*data++) { case SRA_KEY: /* calculate common key */ if (cnt < HEXKEYBYTES) { if (auth_debug_mode) { printf("SRA user rejected for bad PKB\r\n"); } return; } memcpy(pkb,data,HEXKEYBYTES); pkb[HEXKEYBYTES] = '\0'; common_key(ska,pkb,&ik,&ck); enc_user: /* encode user */ memset(tuser,0,sizeof(tuser)); sprintf(uprompt,"User (%s): ",UserNameRequested); telnet_gets(uprompt,tuser,255,1); if (tuser[0] == '\n' || tuser[0] == '\r' ) strcpy(user,UserNameRequested); else { /* telnet_gets leaves the newline on */ for(i=0;i 0) {*(buf)++ = (c); --(len);} void sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { char lbuf[32]; - register int i; + int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case SRA_CONTINUE: strncpy((char *)buf, " CONTINUE ", buflen); goto common; case SRA_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case SRA_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case SRA_KEY: /* Authentication data follows */ strncpy((char *)buf, " KEY ", buflen); goto common2; case SRA_USER: strncpy((char *)buf, " USER ", buflen); goto common2; case SRA_PASS: strncpy((char *)buf, " PASS ", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } -struct passwd *pw; - -/* - * Helper function for sgetpwnam(). - */ -char * -sgetsave(char *s) -{ - char *new = malloc((unsigned) strlen(s) + 1); - - if (new == NULL) { - return(NULL); - } - (void) strcpy(new, s); - return (new); -} - -struct passwd * -sgetpwnam(char *name) -{ - static struct passwd save; - register struct passwd *p; - char *sgetsave(); - - if ((p = getpwnam(name)) == NULL) - return (p); - if (save.pw_name) { - free(save.pw_name); - free(save.pw_passwd); - free(save.pw_gecos); - free(save.pw_dir); - free(save.pw_shell); - } - save = *p; - save.pw_name = sgetsave(p->pw_name); - save.pw_passwd = sgetsave(p->pw_passwd); - save.pw_gecos = sgetsave(p->pw_gecos); - save.pw_dir = sgetsave(p->pw_dir); - save.pw_shell = sgetsave(p->pw_shell); -#if 0 -syslog(LOG_WARNING,"%s\n",save.pw_name); -syslog(LOG_WARNING,"%s\n",save.pw_passwd); -syslog(LOG_WARNING,"%s\n",save.pw_gecos); -syslog(LOG_WARNING,"%s\n",save.pw_dir); -#endif -#ifdef USE_SHADOW - { - struct spwd *sp; - sp = getspnam(name); - free(save.pw_passwd); - save.pw_passwd = sgetsave(sp->sp_pwdp); - } -#endif - return (&save); -} - static int -isroot(const char *user) +isroot(const char *usr) { - struct passwd *pw; + struct passwd *pwd; - if ((pw=getpwnam(user))==NULL) + if ((pwd=getpwnam(usr))==NULL) return 0; - return (!pw->pw_uid); + return (!pwd->pw_uid); } static int rootterm(char *ttyn) { struct ttyent *t; return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); } #ifdef NOPAM static int -check_user(const char *name, const char *pass) +check_user(char *name, char *cred) { - register char *cp; + char *cp; char *xpasswd, *salt; if (isroot(name) && !rootterm(line)) { crypt("AA","*"); /* Waste some time to simulate success */ return(0); } if (pw = sgetpwnam(name)) { if (pw->pw_shell == NULL) { pw = (struct passwd *) NULL; return(0); } salt = pw->pw_passwd; - xpasswd = crypt(pass, salt); + xpasswd = crypt(cred, salt); /* The strcmp does not catch null passwords! */ if (pw == NULL || *pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) { pw = (struct passwd *) NULL; return(0); } return(1); } return(0); } #else /* * The following is stolen from ftpd, which stole it from the imap-uw * PAM module and login.c. It is needed because we can't really * "converse" with the user, having already gone to the trouble of * getting their username and password through an encrypted channel. */ #define COPY_STRING(s) (s ? strdup(s):NULL) struct cred_t { const char *uname; const char *pass; }; typedef struct cred_t cred_t; -int -auth_conv(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata) +static int +auth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata) { int i; cred_t *cred = (cred_t *) appdata; struct pam_response *reply = malloc(sizeof(struct pam_response) * num_msg); if (reply == NULL) return PAM_BUF_ERR; for (i = 0; i < num_msg; i++) { switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON: /* assume want user name */ reply[i].resp_retcode = PAM_SUCCESS; reply[i].resp = COPY_STRING(cred->uname); /* PAM frees resp. */ break; case PAM_PROMPT_ECHO_OFF: /* assume want password */ reply[i].resp_retcode = PAM_SUCCESS; reply[i].resp = COPY_STRING(cred->pass); /* PAM frees resp. */ break; case PAM_TEXT_INFO: case PAM_ERROR_MSG: reply[i].resp_retcode = PAM_SUCCESS; reply[i].resp = NULL; break; default: /* unknown message style */ free(reply); return PAM_CONV_ERR; } } *resp = reply; return PAM_SUCCESS; } /* * The PAM version as a side effect may put a new username in *name. */ static int -check_user(const char *name, const char *pass) +check_user(char *name, char *cred) { pam_handle_t *pamh = NULL; const void *item; int rval; int e; - cred_t auth_cred = { name, pass }; + cred_t auth_cred = { name, cred }; struct pam_conv conv = { &auth_conv, &auth_cred }; e = pam_start("telnetd", name, &conv, &pamh); if (e != PAM_SUCCESS) { syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e)); return 0; } #if 0 /* Where can we find this value? */ e = pam_set_item(pamh, PAM_RHOST, remotehost); if (e != PAM_SUCCESS) { syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s", pam_strerror(pamh, e)); return 0; } #endif e = pam_authenticate(pamh, 0); switch (e) { case PAM_SUCCESS: /* * With PAM we support the concept of a "template" * user. The user enters a login name which is * authenticated by PAM, usually via a remote service * such as RADIUS or TACACS+. If authentication * succeeds, a different but related "template" name * is used for setting the credentials, shell, and * home directory. The name the user enters need only * exist on the remote authentication server, but the * template name must be present in the local password * database. * * This is supported by two various mechanisms in the * individual modules. However, from the application's * point of view, the template user is always passed * back as a changed value of the PAM_USER item. */ if ((e = pam_get_item(pamh, PAM_USER, &item)) == PAM_SUCCESS) { - strcpy((char *) name, (const char *) item); + strcpy(name, item); } else syslog(LOG_ERR, "Couldn't get PAM_USER: %s", pam_strerror(pamh, e)); if (isroot(name) && !rootterm(line)) rval = 0; else rval = 1; break; case PAM_AUTH_ERR: case PAM_USER_UNKNOWN: case PAM_MAXTRIES: rval = 0; break; default: syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e)); rval = 0; break; } if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); rval = 0; } return rval; } #endif -#endif - +#endif /* ENCRYPTION */ +#endif /* SRA */ Index: head/contrib/telnet/telnet/tn3270.c =================================================================== --- head/contrib/telnet/telnet/tn3270.c (revision 87138) +++ head/contrib/telnet/telnet/tn3270.c (nonexistent) @@ -1,416 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)tn3270.c 8.2 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; -#endif -#endif /* not lint */ - -#include -#include - -#include "general.h" - -#include "defines.h" -#include "ring.h" -#include "externs.h" -#include "fdset.h" - -#if defined(TN3270) - -#include "../ctlr/screen.h" -#include "../general/globals.h" - -#include "../sys_curses/telextrn.h" -#include "../ctlr/externs.h" - -#if defined(unix) -int - HaveInput, /* There is input available to scan */ - cursesdata, /* Do we dump curses data? */ - sigiocount; /* Number of times we got a SIGIO */ - -char tline[200]; -char *transcom = 0; /* transparent mode command (default: none) */ -#endif /* defined(unix) */ - -char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; - -static char sb_terminal[] = { IAC, SB, - TELOPT_TTYPE, TELQUAL_IS, - 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', - IAC, SE }; -#define SBTERMMODEL 13 - -static int - Sent3270TerminalType; /* Have we said we are a 3270? */ - -#endif /* defined(TN3270) */ - - - void -init_3270() -{ -#if defined(TN3270) -#if defined(unix) - HaveInput = 0; - sigiocount = 0; -#endif /* defined(unix) */ - Sent3270TerminalType = 0; - Ifrontp = Ibackp = Ibuf; - init_ctlr(); /* Initialize some things */ - init_keyboard(); - init_screen(); - init_system(); -#endif /* defined(TN3270) */ -} - - -#if defined(TN3270) - -/* - * DataToNetwork - queue up some data to go to network. If "done" is set, - * then when last byte is queued, we add on an IAC EOR sequence (so, - * don't call us with "done" until you want that done...) - * - * We actually do send all the data to the network buffer, since our - * only client needs for us to do that. - */ - - int -DataToNetwork(buffer, count, done) - register char *buffer; /* where the data is */ - register int count; /* how much to send */ - int done; /* is this the last of a logical block */ -{ - register int loop, c; - int origCount; - - origCount = count; - - while (count) { - /* If not enough room for EORs, IACs, etc., wait */ - if (NETROOM() < 6) { - fd_set o; - - FD_ZERO(&o); - netflush(); - while (NETROOM() < 6) { - FD_SET(net, &o); - (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, - (struct timeval *) 0); - netflush(); - } - } - c = ring_empty_count(&netoring); - if (c > count) { - c = count; - } - loop = c; - while (loop) { - if (((unsigned char)*buffer) == IAC) { - break; - } - buffer++; - loop--; - } - if ((c = c-loop)) { - ring_supply_data(&netoring, buffer-c, c); - count -= c; - } - if (loop) { - NET2ADD(IAC, IAC); - count--; - buffer++; - } - } - - if (done) { - NET2ADD(IAC, EOR); - netflush(); /* try to move along as quickly as ... */ - } - return(origCount - count); -} - - -#if defined(unix) - void -inputAvailable(signo) - int signo; -{ - HaveInput = 1; - sigiocount++; -} -#endif /* defined(unix) */ - - void -outputPurge() -{ - (void) ttyflush(1); -} - - -/* - * The following routines are places where the various tn3270 - * routines make calls into telnet.c. - */ - -/* - * DataToTerminal - queue up some data to go to terminal. - * - * Note: there are people who call us and depend on our processing - * *all* the data at one time (thus the select). - */ - - int -DataToTerminal(buffer, count) - register char *buffer; /* where the data is */ - register int count; /* how much to send */ -{ - register int c; - int origCount; - - origCount = count; - - while (count) { - if (TTYROOM() == 0) { -#if defined(unix) - fd_set o; - - FD_ZERO(&o); -#endif /* defined(unix) */ - (void) ttyflush(0); - while (TTYROOM() == 0) { -#if defined(unix) - FD_SET(tout, &o); - (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, - (struct timeval *) 0); -#endif /* defined(unix) */ - (void) ttyflush(0); - } - } - c = TTYROOM(); - if (c > count) { - c = count; - } - ring_supply_data(&ttyoring, buffer, c); - count -= c; - buffer += c; - } - return(origCount); -} - - -/* - * Push3270 - Try to send data along the 3270 output (to screen) direction. - */ - - int -Push3270() -{ - int save = ring_full_count(&netiring); - - if (save) { - if (Ifrontp+save > Ibuf+sizeof Ibuf) { - if (Ibackp != Ibuf) { - memmove(Ibuf, Ibackp, Ifrontp-Ibackp); - Ifrontp -= (Ibackp-Ibuf); - Ibackp = Ibuf; - } - } - if (Ifrontp+save < Ibuf+sizeof Ibuf) { - (void)telrcv(); - } - } - return save != ring_full_count(&netiring); -} - - -/* - * Finish3270 - get the last dregs of 3270 data out to the terminal - * before quitting. - */ - - void -Finish3270() -{ - while (Push3270() || !DoTerminalOutput()) { -#if defined(unix) - HaveInput = 0; -#endif /* defined(unix) */ - ; - } -} - - -/* StringToTerminal - output a null terminated string to the terminal */ - - void -StringToTerminal(s) - char *s; -{ - int count; - - count = strlen(s); - if (count) { - (void) DataToTerminal(s, count); /* we know it always goes... */ - } -} - - -#if ((!defined(NOT43)) || defined(PUTCHAR)) -/* _putchar - output a single character to the terminal. This name is so that - * curses(3x) can call us to send out data. - */ - - void -_putchar(c) - char c; -{ -#if defined(sun) /* SunOS 4.0 bug */ - c &= 0x7f; -#endif /* defined(sun) */ - if (cursesdata) { - Dump('>', &c, 1); - } - if (!TTYROOM()) { - (void) DataToTerminal(&c, 1); - } else { - TTYADD(c); - } -} -#endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ - - void -SetIn3270() -{ - if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY) - && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) { - if (!In3270) { - In3270 = 1; - Init3270(); /* Initialize 3270 functions */ - /* initialize terminal key mapping */ - InitTerminal(); /* Start terminal going */ - setconnmode(0); - } - } else { - if (In3270) { - StopScreen(1); - In3270 = 0; - Stop3270(); /* Tell 3270 we aren't here anymore */ - setconnmode(0); - } - } -} - -/* - * tn3270_ttype() - * - * Send a response to a terminal type negotiation. - * - * Return '0' if no more responses to send; '1' if a response sent. - */ - - int -tn3270_ttype() -{ - /* - * Try to send a 3270 type terminal name. Decide which one based - * on the format of our screen, and (in the future) color - * capaiblities. - */ - InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ - if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { - Sent3270TerminalType = 1; - if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { - MaxNumberLines = 27; - MaxNumberColumns = 132; - sb_terminal[SBTERMMODEL] = '5'; - } else if (MaxNumberLines >= 43) { - MaxNumberLines = 43; - MaxNumberColumns = 80; - sb_terminal[SBTERMMODEL] = '4'; - } else if (MaxNumberLines >= 32) { - MaxNumberLines = 32; - MaxNumberColumns = 80; - sb_terminal[SBTERMMODEL] = '3'; - } else { - MaxNumberLines = 24; - MaxNumberColumns = 80; - sb_terminal[SBTERMMODEL] = '2'; - } - NumberLines = 24; /* before we start out... */ - NumberColumns = 80; - ScreenSize = NumberLines*NumberColumns; - if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { - ExitString("Programming error: MAXSCREENSIZE too small.\n", - 1); - /*NOTREACHED*/ - } - printsub('>', sb_terminal+2, sizeof sb_terminal-2); - ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); - return 1; - } else { - return 0; - } -} - -#if defined(unix) - int -settranscom(argc, argv) - int argc; - char *argv[]; -{ - int i; - - if (argc == 1 && transcom) { - transcom = 0; - } - if (argc == 1) { - return 1; - } - transcom = tline; - (void) strcpy(transcom, argv[1]); - for (i = 2; i < argc; ++i) { - (void) strcat(transcom, " "); - (void) strcat(transcom, argv[i]); - } - return 1; -} -#endif /* defined(unix) */ - -#endif /* defined(TN3270) */ Property changes on: head/contrib/telnet/telnet/tn3270.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/contrib/telnet/telnet/authenc.c =================================================================== --- head/contrib/telnet/telnet/authenc.c (revision 87138) +++ head/contrib/telnet/telnet/authenc.c (revision 87139) @@ -1,116 +1,111 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)authenc.c 8.1 (Berkeley) 6/6/93"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION #include #include +#include +#include #include #include #include "general.h" #include "ring.h" #include "externs.h" #include "defines.h" #include "types.h" - int -net_write(str, len) - unsigned char *str; - int len; +int +net_write(unsigned char *str, int len) { if (NETROOM() > len) { ring_supply_data(&netoring, str, len); if (str[0] == IAC && str[1] == SE) printsub('>', &str[2], len-2); return(len); } return(0); } - void -net_encrypt() +void +net_encrypt(void) { #ifdef ENCRYPTION if (encrypt_output) ring_encrypt(&netoring, encrypt_output); else ring_clearto(&netoring); #endif /* ENCRYPTION */ } - int -telnet_spin() +int +telnet_spin(void) { return(-1); } - char * -telnet_getenv(val) - char *val; +char * +telnet_getenv(char *val) { return((char *)env_getvalue((unsigned char *)val)); } - char * -telnet_gets(prompt, result, length, echo) - char *prompt; - char *result; - int length; - int echo; +char * +telnet_gets(const char *prom, char *result, int length, int echo) { - extern char *getpass(); extern int globalmode; int om = globalmode; char *res; TerminalNewMode(-1); if (echo) { - printf("%s", prompt); + printf("%s", prom); res = fgets(result, length, stdin); - } else if ((res = getpass(prompt))) { + } else if ((res = getpass(prom))) { strncpy(result, res, length); res = result; } TerminalNewMode(om); return(res); } -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif /* ENCRYPTION */ +#endif /* AUTHENTICATION */ Index: head/contrib/telnet/telnet/commands.c =================================================================== --- head/contrib/telnet/telnet/commands.c (revision 87138) +++ head/contrib/telnet/telnet/commands.c (revision 87139) @@ -1,3225 +1,3005 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint static const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95"; -#endif /* not lint */ +#endif -#if defined(unix) #include #include #include -#else -#include -#endif /* defined(unix) */ #include #include -#include -#include -#include #include -#include -#include +#include #include -#include +#include +#include +#include +#include #include +#include +#include #include #include #include "general.h" #include "ring.h" #include "externs.h" #include "defines.h" #include "types.h" +#include "misc.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif #include -# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) -# include -# endif /* vax */ #include #include #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif MAXHOSTNAMELEN +typedef int (*intrtn_t)(int, char **); + +#ifdef AUTHENTICATION +extern int auth_togdebug P((int)); +#endif +#ifdef ENCRYPTION +extern int EncryptAutoEnc P((int)); +extern int EncryptAutoDec P((int)); +extern int EncryptDebug P((int)); +extern int EncryptVerbose P((int)); +#endif /* ENCRYPTION */ #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ char *hostname; static char _hostname[MAXHOSTNAMELEN]; -extern char *getenv(); +static int help(int, char **); +static int call(intrtn_t, ...); +static void cmdrc(char *, char *); +static int switch_af(struct addrinfo **); +static int togglehelp(void); +static int send_tncmd(void (*)(int, int), const char *, char *); +static int setmod(int); +static int clearmode(int); +static int modehelp(void); +static int sourceroute(struct addrinfo *, char *, char **, int *, int *, int *); -extern int isprefix(); -extern char **genget(); -extern int Ambiguous(); - -static int help(int argc, char *argv[]); -static int call(); -static void cmdrc(char *m1, char *m2); -static int switch_af(struct addrinfo **aip); -int quit(void); - typedef struct { - char *name; /* command name */ - char *help; /* help string (NULL for no help) */ - int (*handler)(); /* routine which executes command */ + const char *name; /* command name */ + const char *help; /* help string (NULL for no help) */ + int (*handler)(int, char **); /* routine which executes command */ int needconnect; /* Do we need to be connected to execute? */ } Command; static char line[256]; static char saveline[256]; static int margc; static char *margv[20]; -#if defined(OPIE) +#ifdef OPIE #include #define PATH_OPIEKEY "/usr/bin/opiekey" - int -opie_calc(argc, argv) - int argc; - char **argv; +static int +opie_calc(int argc, char *argv[]) { int status; if(argc != 3) { printf("%s sequence challenge\n", argv[0]); - return; + return (0); } switch(fork()) { case 0: execv(PATH_OPIEKEY, argv); exit (1); case -1: perror("fork"); break; default: (void) wait(&status); if (WIFEXITED(status)) return (WEXITSTATUS(status)); - return (0); } + return (0); } #endif - static void -makeargv() +static void +makeargv(void) { - register char *cp, *cp2, c; - register char **argp = margv; + char *cp, *cp2, c; + char **argp = margv; margc = 0; cp = line; if (*cp == '!') { /* Special case shell escape */ strcpy(saveline, line); /* save for shell command */ - *argp++ = "!"; /* No room in string to get this */ + *argp++ = strdup("!"); /* No room in string to get this */ margc++; cp++; } while ((c = *cp)) { - register int inquote = 0; + int inquote = 0; while (isspace(c)) c = *++cp; if (c == '\0') break; *argp++ = cp; margc += 1; for (cp2 = cp; c != '\0'; c = *++cp) { if (inquote) { if (c == inquote) { inquote = 0; continue; } } else { if (c == '\\') { if ((c = *++cp) == '\0') break; } else if (c == '"') { inquote = '"'; continue; } else if (c == '\'') { inquote = '\''; continue; } else if (isspace(c)) break; } *cp2++ = c; } *cp2 = '\0'; if (c == '\0') break; cp++; } *argp++ = 0; } /* * Make a character string into a number. * * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). */ - static int -special(s) - register char *s; +static int +special(char *s) { - register char c; + char c; char b; switch (*s) { case '^': b = *++s; if (b == '?') { c = b | 0x40; /* DEL */ } else { c = b & 0x1f; } break; default: c = *s; break; } return c; } /* * Construct a control character sequence * for a special character. */ - static char * -control(c) - register cc_t c; +static const char * +control(cc_t c) { static char buf[5]; /* * The only way I could get the Sun 3.5 compiler * to shut up about * if ((unsigned int)c >= 0x80) * was to assign "c" to an unsigned int variable... * Arggg.... */ - register unsigned int uic = (unsigned int)c; + unsigned int uic = (unsigned int)c; if (uic == 0x7f) return ("^?"); if (c == (cc_t)_POSIX_VDISABLE) { return "off"; } if (uic >= 0x80) { buf[0] = '\\'; buf[1] = ((c>>6)&07) + '0'; buf[2] = ((c>>3)&07) + '0'; buf[3] = (c&07) + '0'; buf[4] = 0; } else if (uic >= 0x20) { buf[0] = c; buf[1] = 0; } else { buf[0] = '^'; buf[1] = '@'+c; buf[2] = 0; } return (buf); } - - /* * The following are data structures and routines for * the "send" command. * */ struct sendlist { - char *name; /* How user refers to it (case independent) */ - char *help; /* Help information (0 ==> no help) */ + const char *name; /* How user refers to it (case independent) */ + const char *help; /* Help information (0 ==> no help) */ int needconnect; /* Need to be connected */ int narg; /* Number of arguments */ - int (*handler)(); /* Routine to perform (for special ops) */ + int (*handler)(char *, ...); /* Routine to perform (for special ops) */ int nbyte; /* Number of bytes to send this command */ int what; /* Character to be sent (<0 ==> special) */ }; static int send_esc P((void)), send_help P((void)), send_docmd P((char *)), send_dontcmd P((char *)), send_willcmd P((char *)), send_wontcmd P((char *)); static struct sendlist Sendlist[] = { - { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, - { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, - { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, - { "break", 0, 1, 0, 0, 2, BREAK }, - { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, - { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, - { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, - { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, - { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, - { "intp", 0, 1, 0, 0, 2, IP }, - { "interrupt", 0, 1, 0, 0, 2, IP }, - { "intr", 0, 1, 0, 0, 2, IP }, - { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, - { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, - { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, - { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, - { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, - { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, - { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, - { "?", "Display send options", 0, 0, send_help, 0, 0 }, - { "help", 0, 0, 0, send_help, 0, 0 }, - { "do", 0, 0, 1, send_docmd, 3, 0 }, - { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, - { "will", 0, 0, 1, send_willcmd, 3, 0 }, - { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, - { 0 } + { "ao", "Send Telnet Abort output", 1, 0, NULL, 2, AO }, + { "ayt", "Send Telnet 'Are You There'", 1, 0, NULL, 2, AYT }, + { "brk", "Send Telnet Break", 1, 0, NULL, 2, BREAK }, + { "break", NULL, 1, 0, NULL, 2, BREAK }, + { "ec", "Send Telnet Erase Character", 1, 0, NULL, 2, EC }, + { "el", "Send Telnet Erase Line", 1, 0, NULL, 2, EL }, + { "escape", "Send current escape character",1, 0, (int (*)(char *, ...))send_esc, 1, 0 }, + { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, NULL, 2, GA }, + { "ip", "Send Telnet Interrupt Process",1, 0, NULL, 2, IP }, + { "intp", NULL, 1, 0, NULL, 2, IP }, + { "interrupt", NULL, 1, 0, NULL, 2, IP }, + { "intr", NULL, 1, 0, NULL, 2, IP }, + { "nop", "Send Telnet 'No operation'", 1, 0, NULL, 2, NOP }, + { "eor", "Send Telnet 'End of Record'", 1, 0, NULL, 2, EOR }, + { "abort", "Send Telnet 'Abort Process'", 1, 0, NULL, 2, ABORT }, + { "susp", "Send Telnet 'Suspend Process'",1, 0, NULL, 2, SUSP }, + { "eof", "Send Telnet End of File Character", 1, 0, NULL, 2, xEOF }, + { "synch", "Perform Telnet 'Synch operation'", 1, 0, (int (*)(char *, ...))dosynch, 2, 0 }, + { "getstatus", "Send request for STATUS", 1, 0, (int (*)(char *, ...))get_status, 6, 0 }, + { "?", "Display send options", 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, + { "help", NULL, 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, + { "do", NULL, 0, 1, (int (*)(char *, ...))send_docmd, 3, 0 }, + { "dont", NULL, 0, 1, (int (*)(char *, ...))send_dontcmd, 3, 0 }, + { "will", NULL, 0, 1, (int (*)(char *, ...))send_willcmd, 3, 0 }, + { "wont", NULL, 0, 1, (int (*)(char *, ...))send_wontcmd, 3, 0 }, + { NULL, NULL, 0, 0, NULL, 0, 0 } }; #define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ sizeof(struct sendlist))) - static int -sendcmd(argc, argv) - int argc; - char **argv; +static int +sendcmd(int argc, char *argv[]) { int count; /* how many bytes we are going to need to send */ int i; struct sendlist *s; /* pointer to current command */ int success = 0; int needconnect = 0; if (argc < 2) { printf("need at least one argument for 'send' command\n"); printf("'send ?' for help\n"); return 0; } /* * First, validate all the send arguments. * In addition, we see how much space we are going to need, and * whether or not we will be doing a "SYNCH" operation (which * flushes the network queue). */ count = 0; for (i = 1; i < argc; i++) { s = GETSEND(argv[i]); if (s == 0) { printf("Unknown send argument '%s'\n'send ?' for help.\n", argv[i]); return 0; - } else if (Ambiguous(s)) { + } else if (Ambiguous((void *)s)) { printf("Ambiguous send argument '%s'\n'send ?' for help.\n", argv[i]); return 0; } if (i + s->narg >= argc) { fprintf(stderr, "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", s->narg, s->narg == 1 ? "" : "s", s->name, s->name); return 0; } count += s->nbyte; - if (s->handler == send_help) { + if ((void *)s->handler == (void *)send_help) { send_help(); return 0; } i += s->narg; needconnect += s->needconnect; } if (!connected && needconnect) { printf("?Need to be connected first.\n"); printf("'send ?' for help\n"); return 0; } /* Now, do we have enough room? */ if (NETROOM() < count) { printf("There is not enough room in the buffer TO the network\n"); printf("to process your request. Nothing will be done.\n"); printf("('send synch' will throw away most data in the network\n"); printf("buffer, if this might help.)\n"); return 0; } /* OK, they are all OK, now go through again and actually send */ count = 0; for (i = 1; i < argc; i++) { if ((s = GETSEND(argv[i])) == 0) { fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); - (void) quit(); + quit(); /*NOTREACHED*/ } if (s->handler) { count++; success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, (s->narg > 1) ? argv[i+2] : 0); i += s->narg; } else { NET2ADD(IAC, s->what); printoption("SENT", IAC, s->what); } } return (count == success); } - static int -send_esc() +static int +send_esc(void) { NETADD(escape); return 1; } - static int -send_docmd(name) - char *name; +static int +send_docmd(char *name) { return(send_tncmd(send_do, "do", name)); } - static int +static int send_dontcmd(name) char *name; { return(send_tncmd(send_dont, "dont", name)); } - static int -send_willcmd(name) - char *name; + +static int +send_willcmd(char *name) { return(send_tncmd(send_will, "will", name)); } - static int -send_wontcmd(name) - char *name; + +static int +send_wontcmd(char *name) { return(send_tncmd(send_wont, "wont", name)); } - int -send_tncmd(func, cmd, name) - void (*func)(); - char *cmd, *name; +static int +send_tncmd(void (*func)(int, int), const char *cmd, char *name) { char **cpp; extern char *telopts[]; - register int val = 0; + int val = 0; if (isprefix(name, "help") || isprefix(name, "?")) { - register int col, len; + int col, len; printf("Usage: send %s \n", cmd); printf("\"value\" must be from 0 to 255\n"); printf("Valid options are:\n\t"); col = 8; for (cpp = telopts; *cpp; cpp++) { len = strlen(*cpp) + 3; if (col + len > 65) { printf("\n\t"); col = 8; } printf(" \"%s\"", *cpp); col += len; } printf("\n"); return 0; } cpp = (char **)genget(name, telopts, sizeof(char *)); if (Ambiguous(cpp)) { fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", name, cmd); return 0; } if (cpp) { val = cpp - telopts; } else { - register char *cp = name; + char *cp = name; while (*cp >= '0' && *cp <= '9') { val *= 10; val += *cp - '0'; cp++; } if (*cp != 0) { fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", name, cmd); return 0; } else if (val < 0 || val > 255) { fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", name, cmd); return 0; } } if (!connected) { printf("?Need to be connected first.\n"); return 0; } (*func)(val, 1); return 1; } - static int -send_help() +static int +send_help(void) { struct sendlist *s; /* pointer to current command */ for (s = Sendlist; s->name; s++) { if (s->help) printf("%-15s %s\n", s->name, s->help); } return(0); } /* * The following are the routines and data structures referred * to by the arguments to the "toggle" command. */ - static int -lclchars() +static int +lclchars(void) { donelclchars = 1; return 1; } - static int -togdebug() +static int +togdebug(void) { #ifndef NOT43 if (net > 0 && (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { perror("setsockopt (SO_DEBUG)"); } #else /* NOT43 */ if (debug) { if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) perror("setsockopt (SO_DEBUG)"); } else printf("Cannot turn off socket debugging\n"); #endif /* NOT43 */ return 1; } - static int -togcrlf() +static int +togcrlf(void) { if (crlf) { printf("Will send carriage returns as telnet .\n"); } else { printf("Will send carriage returns as telnet .\n"); } return 1; } int binmode; - static int -togbinary(val) - int val; +static int +togbinary(int val) { donebinarytoggle = 1; if (val >= 0) { binmode = val; } else { if (my_want_state_is_will(TELOPT_BINARY) && my_want_state_is_do(TELOPT_BINARY)) { binmode = 1; } else if (my_want_state_is_wont(TELOPT_BINARY) && my_want_state_is_dont(TELOPT_BINARY)) { binmode = 0; } val = binmode ? 0 : 1; } if (val == 1) { if (my_want_state_is_will(TELOPT_BINARY) && my_want_state_is_do(TELOPT_BINARY)) { printf("Already operating in binary mode with remote host.\n"); } else { printf("Negotiating binary mode with remote host.\n"); tel_enter_binary(3); } } else { if (my_want_state_is_wont(TELOPT_BINARY) && my_want_state_is_dont(TELOPT_BINARY)) { printf("Already in network ascii mode with remote host.\n"); } else { printf("Negotiating network ascii mode with remote host.\n"); tel_leave_binary(3); } } return 1; } - static int -togrbinary(val) - int val; +static int +togrbinary(int val) { donebinarytoggle = 1; if (val == -1) val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; if (val == 1) { if (my_want_state_is_do(TELOPT_BINARY)) { printf("Already receiving in binary mode.\n"); } else { printf("Negotiating binary mode on input.\n"); tel_enter_binary(1); } } else { if (my_want_state_is_dont(TELOPT_BINARY)) { printf("Already receiving in network ascii mode.\n"); } else { printf("Negotiating network ascii mode on input.\n"); tel_leave_binary(1); } } return 1; } - static int -togxbinary(val) - int val; +static int +togxbinary(int val) { donebinarytoggle = 1; if (val == -1) val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; if (val == 1) { if (my_want_state_is_will(TELOPT_BINARY)) { printf("Already transmitting in binary mode.\n"); } else { printf("Negotiating binary mode on output.\n"); tel_enter_binary(2); } } else { if (my_want_state_is_wont(TELOPT_BINARY)) { printf("Already transmitting in network ascii mode.\n"); } else { printf("Negotiating network ascii mode on output.\n"); tel_leave_binary(2); } } return 1; } - -static int togglehelp P((void)); -#if defined(AUTHENTICATION) -extern int auth_togdebug P((int)); -#endif -#ifdef ENCRYPTION -extern int EncryptAutoEnc P((int)); -extern int EncryptAutoDec P((int)); -extern int EncryptDebug P((int)); -extern int EncryptVerbose P((int)); -#endif /* ENCRYPTION */ - struct togglelist { - char *name; /* name of toggle */ - char *help; /* help message */ - int (*handler)(); /* routine to do actual setting */ + const char *name; /* name of toggle */ + const char *help; /* help message */ + int (*handler)(int); /* routine to do actual setting */ int *variable; - char *actionexplanation; + const char *actionexplanation; }; static struct togglelist Togglelist[] = { { "autoflush", "flushing of output when sending interrupt characters", 0, &autoflush, "flush output when sending interrupt characters" }, { "autosynch", "automatic sending of interrupt characters in urgent mode", 0, &autosynch, "send interrupt characters in urgent mode" }, -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION { "autologin", "automatic sending of login and/or authentication info", 0, &autologin, "send login name and/or authentication information" }, { "authdebug", "Toggle authentication debugging", auth_togdebug, 0, "print authentication debugging information" }, #endif #ifdef ENCRYPTION { "autoencrypt", "automatic encryption of data stream", EncryptAutoEnc, 0, "automatically encrypt output" }, { "autodecrypt", "automatic decryption of data stream", EncryptAutoDec, 0, "automatically decrypt input" }, { "verbose_encrypt", "Toggle verbose encryption output", EncryptVerbose, 0, "print verbose encryption output" }, { "encdebug", "Toggle encryption debugging", EncryptDebug, 0, "print encryption debugging information" }, #endif /* ENCRYPTION */ { "skiprc", "don't read ~/.telnetrc file", 0, &skiprc, "skip reading of ~/.telnetrc file" }, { "binary", "sending and receiving of binary data", togbinary, 0, 0 }, { "inbinary", "receiving of binary data", togrbinary, 0, 0 }, { "outbinary", "sending of binary data", togxbinary, 0, 0 }, { "crlf", "sending carriage returns as telnet ", - togcrlf, + (int (*)(int))togcrlf, &crlf, 0 }, { "crmod", "mapping of received carriage returns", 0, &crmod, "map carriage return on output" }, { "localchars", "local recognition of certain control characters", - lclchars, + (int (*)(int))lclchars, &localchars, "recognize certain control characters" }, - { " ", "", 0 }, /* empty line */ -#if defined(unix) && defined(TN3270) - { "apitrace", - "(debugging) toggle tracing of API transactions", - 0, - &apitrace, - "trace API transactions" }, - { "cursesdata", - "(debugging) toggle printing of hexadecimal curses data", - 0, - &cursesdata, - "print hexadecimal representation of curses data" }, -#endif /* defined(unix) && defined(TN3270) */ + { " ", "", NULL, NULL, NULL }, /* empty line */ { "debug", "debugging", - togdebug, + (int (*)(int))togdebug, &debug, "turn on socket level debugging" }, { "netdata", "printing of hexadecimal network data (debugging)", 0, &netdata, "print hexadecimal representation of network traffic" }, { "prettydump", "output of \"netdata\" to user readable format (debugging)", 0, &prettydump, "print user readable output for \"netdata\"" }, { "options", "viewing of options processing (debugging)", 0, &showoptions, "show option processing" }, -#if defined(unix) { "termdata", "(debugging) toggle printing of hexadecimal terminal data", 0, &termdata, "print hexadecimal representation of terminal traffic" }, -#endif /* defined(unix) */ { "?", - 0, - togglehelp }, + NULL, + (int (*)(int))togglehelp, + NULL, + NULL }, + { NULL, NULL, NULL, NULL, NULL }, { "help", - 0, - togglehelp }, - { 0 } + NULL, + (int (*)(int))togglehelp, + NULL, + NULL }, + { NULL, NULL, NULL, NULL, NULL } }; - static int -togglehelp() +static int +togglehelp(void) { struct togglelist *c; for (c = Togglelist; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s toggle %s\n", c->name, c->help); else printf("\n"); } } printf("\n"); printf("%-15s %s\n", "?", "display help information"); return 0; } - static void -settogglehelp(set) - int set; +static void +settogglehelp(int set) { struct togglelist *c; for (c = Togglelist; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", c->help); else printf("\n"); } } } #define GETTOGGLE(name) (struct togglelist *) \ genget(name, (char **) Togglelist, sizeof(struct togglelist)) - static int -toggle(argc, argv) - int argc; - char *argv[]; +static int +toggle(int argc, char *argv[]) { int retval = 1; char *name; struct togglelist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); return 0; } argc--; argv++; while (argc--) { name = *argv++; c = GETTOGGLE(name); - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", name); return 0; } else if (c == 0) { fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", name); return 0; } else { if (c->variable) { *c->variable = !*c->variable; /* invert it */ if (c->actionexplanation) { printf("%s %s.\n", *c->variable? "Will" : "Won't", c->actionexplanation); } } if (c->handler) { retval &= (*c->handler)(-1); } } } return retval; } /* * The following perform the "set" command. */ #ifdef USE_TERMIO -struct termio new_tc = { 0 }; +struct termio new_tc = { 0, 0, 0, 0, {}, 0, 0 }; #endif struct setlist { - char *name; /* name */ - char *help; /* help information */ - void (*handler)(); + const char *name; /* name */ + const char *help; /* help information */ + void (*handler)(char *); cc_t *charp; /* where it is located at */ }; static struct setlist Setlist[] = { #ifdef KLUDGELINEMODE - { "echo", "character to toggle local echoing on/off", 0, &echoc }, + { "echo", "character to toggle local echoing on/off", NULL, &echoc }, #endif - { "escape", "character to escape back to telnet command mode", 0, &escape }, + { "escape", "character to escape back to telnet command mode", NULL, &escape }, { "rlogin", "rlogin escape character", 0, &rlogin }, { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, - { " ", "" }, - { " ", "The following need 'localchars' to be toggled true", 0, 0 }, - { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp }, - { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, - { "quit", "character to cause an Abort process", 0, termQuitCharp }, - { "eof", "character to cause an EOF ", 0, termEofCharp }, - { " ", "" }, - { " ", "The following are for local editing in linemode", 0, 0 }, - { "erase", "character to use to erase a character", 0, termEraseCharp }, - { "kill", "character to use to erase a line", 0, termKillCharp }, - { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, - { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, - { "reprint", "character to use for line reprint", 0, termRprntCharp }, - { "worderase", "character to use to erase a word", 0, termWerasCharp }, - { "start", "character to use for XON", 0, termStartCharp }, - { "stop", "character to use for XOFF", 0, termStopCharp }, - { "forw1", "alternate end of line character", 0, termForw1Charp }, - { "forw2", "alternate end of line character", 0, termForw2Charp }, - { "ayt", "alternate AYT character", 0, termAytCharp }, - { 0 } + { " ", "", NULL, NULL }, + { " ", "The following need 'localchars' to be toggled true", NULL, NULL }, + { "flushoutput", "character to cause an Abort Output", NULL, termFlushCharp }, + { "interrupt", "character to cause an Interrupt Process", NULL, termIntCharp }, + { "quit", "character to cause an Abort process", NULL, termQuitCharp }, + { "eof", "character to cause an EOF ", NULL, termEofCharp }, + { " ", "", NULL, NULL }, + { " ", "The following are for local editing in linemode", NULL, NULL }, + { "erase", "character to use to erase a character", NULL, termEraseCharp }, + { "kill", "character to use to erase a line", NULL, termKillCharp }, + { "lnext", "character to use for literal next", NULL, termLiteralNextCharp }, + { "susp", "character to cause a Suspend Process", NULL, termSuspCharp }, + { "reprint", "character to use for line reprint", NULL, termRprntCharp }, + { "worderase", "character to use to erase a word", NULL, termWerasCharp }, + { "start", "character to use for XON", NULL, termStartCharp }, + { "stop", "character to use for XOFF", NULL, termStopCharp }, + { "forw1", "alternate end of line character", NULL, termForw1Charp }, + { "forw2", "alternate end of line character", NULL, termForw2Charp }, + { "ayt", "alternate AYT character", NULL, termAytCharp }, + { NULL, NULL, NULL, NULL } }; - static struct setlist * -getset(name) - char *name; +static struct setlist * +getset(char *name) { return (struct setlist *) genget(name, (char **) Setlist, sizeof(struct setlist)); } - void -set_escape_char(s) - char *s; +void +set_escape_char(char *s) { if (rlogin != _POSIX_VDISABLE) { rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; printf("Telnet rlogin escape character is '%s'.\n", control(rlogin)); } else { escape = (s && *s) ? special(s) : _POSIX_VDISABLE; printf("Telnet escape character is '%s'.\n", control(escape)); } } - static int -setcmd(argc, argv) - int argc; - char *argv[]; +static int +setcmd(int argc, char *argv[]) { int value; struct setlist *ct; struct togglelist *c; if (argc < 2 || argc > 3) { printf("Format is 'set Name Value'\n'set ?' for help.\n"); return 0; } if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { for (ct = Setlist; ct->name; ct++) printf("%-15s %s\n", ct->name, ct->help); printf("\n"); settogglehelp(1); printf("%-15s %s\n", "?", "display help information"); return 0; } ct = getset(argv[1]); if (ct == 0) { c = GETTOGGLE(argv[1]); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", argv[1]); return 0; - } else if (Ambiguous(c)) { + } else if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); return 0; } if (c->variable) { if ((argc == 2) || (strcmp("on", argv[2]) == 0)) *c->variable = 1; else if (strcmp("off", argv[2]) == 0) *c->variable = 0; else { printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); return 0; } if (c->actionexplanation) { printf("%s %s.\n", *c->variable? "Will" : "Won't", c->actionexplanation); } } if (c->handler) (*c->handler)(1); } else if (argc != 3) { printf("Format is 'set Name Value'\n'set ?' for help.\n"); return 0; - } else if (Ambiguous(ct)) { + } else if (Ambiguous((void *)ct)) { fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); return 0; } else if (ct->handler) { (*ct->handler)(argv[2]); printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); } else { if (strcmp("off", argv[2])) { value = special(argv[2]); } else { value = _POSIX_VDISABLE; } *(ct->charp) = (cc_t)value; printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); } slc_check(); return 1; } - static int -unsetcmd(argc, argv) - int argc; - char *argv[]; +static int +unsetcmd(int argc, char *argv[]) { struct setlist *ct; struct togglelist *c; - register char *name; + char *name; if (argc < 2) { fprintf(stderr, "Need an argument to 'unset' command. 'unset ?' for help.\n"); return 0; } if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { for (ct = Setlist; ct->name; ct++) printf("%-15s %s\n", ct->name, ct->help); printf("\n"); settogglehelp(0); printf("%-15s %s\n", "?", "display help information"); return 0; } argc--; argv++; while (argc--) { name = *argv++; ct = getset(name); if (ct == 0) { c = GETTOGGLE(name); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", name); return 0; - } else if (Ambiguous(c)) { + } else if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", name); return 0; } if (c->variable) { *c->variable = 0; if (c->actionexplanation) { printf("%s %s.\n", *c->variable? "Will" : "Won't", c->actionexplanation); } } if (c->handler) (*c->handler)(0); - } else if (Ambiguous(ct)) { + } else if (Ambiguous((void *)ct)) { fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", name); return 0; } else if (ct->handler) { (*ct->handler)(0); printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); } else { *(ct->charp) = _POSIX_VDISABLE; printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); } } return 1; } /* * The following are the data structures and routines for the * 'mode' command. */ #ifdef KLUDGELINEMODE extern int kludgelinemode; - static int -dokludgemode() +static int +dokludgemode(void) { kludgelinemode = 1; send_wont(TELOPT_LINEMODE, 1); send_dont(TELOPT_SGA, 1); send_dont(TELOPT_ECHO, 1); return 1; } #endif - static int -dolinemode() +static int +dolinemode(void) { #ifdef KLUDGELINEMODE if (kludgelinemode) send_dont(TELOPT_SGA, 1); #endif send_will(TELOPT_LINEMODE, 1); send_dont(TELOPT_ECHO, 1); return 1; } - static int -docharmode() +static int +docharmode(void) { #ifdef KLUDGELINEMODE if (kludgelinemode) send_do(TELOPT_SGA, 1); else #endif send_wont(TELOPT_LINEMODE, 1); send_do(TELOPT_ECHO, 1); return 1; } - static int -dolmmode(bit, on) - int bit, on; +static int +dolmmode(int bit, int on) { unsigned char c; extern int linemode; if (my_want_state_is_wont(TELOPT_LINEMODE)) { printf("?Need to have LINEMODE option enabled first.\n"); printf("'mode ?' for help.\n"); return 0; } if (on) c = (linemode | bit); else c = (linemode & ~bit); lm_mode(&c, 1, 1); return 1; } - int -setmod(bit) +static int +setmod(int bit) { return dolmmode(bit, 1); } - int -clearmode(bit) +static int +clearmode(int bit) { return dolmmode(bit, 0); } struct modelist { - char *name; /* command name */ - char *help; /* help string */ - int (*handler)(); /* routine which executes command */ + const char *name; /* command name */ + const char *help; /* help string */ + int (*handler)(int);/* routine which executes command */ int needconnect; /* Do we need to be connected to execute? */ int arg1; }; -extern int modehelp(); - static struct modelist ModeList[] = { - { "character", "Disable LINEMODE option", docharmode, 1 }, + { "character", "Disable LINEMODE option", (int (*)(int))docharmode, 1, 0 }, #ifdef KLUDGELINEMODE - { "", "(or disable obsolete line-by-line mode)", 0 }, + { "", "(or disable obsolete line-by-line mode)", NULL, 0, 0 }, #endif - { "line", "Enable LINEMODE option", dolinemode, 1 }, + { "line", "Enable LINEMODE option", (int (*)(int))dolinemode, 1, 0 }, #ifdef KLUDGELINEMODE - { "", "(or enable obsolete line-by-line mode)", 0 }, + { "", "(or enable obsolete line-by-line mode)", NULL, 0, 0 }, #endif - { "", "", 0 }, - { "", "These require the LINEMODE option to be enabled", 0 }, + { "", "", NULL, 0, 0 }, + { "", "These require the LINEMODE option to be enabled", NULL, 0, 0 }, { "isig", "Enable signal trapping", setmod, 1, MODE_TRAPSIG }, { "+isig", 0, setmod, 1, MODE_TRAPSIG }, { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, { "edit", "Enable character editing", setmod, 1, MODE_EDIT }, { "+edit", 0, setmod, 1, MODE_EDIT }, { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, { "softtabs", "Enable tab expansion", setmod, 1, MODE_SOFT_TAB }, { "+softtabs", 0, setmod, 1, MODE_SOFT_TAB }, { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO }, { "+litecho", 0, setmod, 1, MODE_LIT_ECHO }, { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, - { "help", 0, modehelp, 0 }, + { "help", 0, (int (*)(int))modehelp, 0, 0 }, #ifdef KLUDGELINEMODE - { "kludgeline", 0, dokludgemode, 1 }, + { "kludgeline", 0, (int (*)(int))dokludgemode, 1, 0 }, #endif - { "", "", 0 }, - { "?", "Print help information", modehelp, 0 }, - { 0 }, + { "", "", NULL, 0, 0 }, + { "?", "Print help information", (int (*)(int))modehelp, 0, 0 }, + { NULL, NULL, NULL, 0, 0 }, }; - int -modehelp() +static int +modehelp(void) { struct modelist *mt; printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); for (mt = ModeList; mt->name; mt++) { if (mt->help) { if (*mt->help) printf("%-15s %s\n", mt->name, mt->help); else printf("\n"); } } return 0; } #define GETMODECMD(name) (struct modelist *) \ genget(name, (char **) ModeList, sizeof(struct modelist)) - static int -modecmd(argc, argv) - int argc; - char *argv[]; +static int +modecmd(int argc, char *argv[]) { struct modelist *mt; if (argc != 2) { printf("'mode' command requires an argument\n"); printf("'mode ?' for help.\n"); } else if ((mt = GETMODECMD(argv[1])) == 0) { fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); - } else if (Ambiguous(mt)) { + } else if (Ambiguous((void *)mt)) { fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); } else if (mt->needconnect && !connected) { printf("?Need to be connected first.\n"); printf("'mode ?' for help.\n"); } else if (mt->handler) { return (*mt->handler)(mt->arg1); } return 0; } /* * The following data structures and routines implement the * "display" command. */ - static int -display(argc, argv) - int argc; - char *argv[]; +static int +display(int argc, char *argv[]) { struct togglelist *tl; struct setlist *sl; #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ if (*tl->variable) { \ printf("will"); \ } else { \ printf("won't"); \ } \ printf(" %s.\n", tl->actionexplanation); \ } #define doset(sl) if (sl->name && *sl->name != ' ') { \ if (sl->handler == 0) \ printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ else \ printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ } if (argc == 1) { for (tl = Togglelist; tl->name; tl++) { dotog(tl); } printf("\n"); for (sl = Setlist; sl->name; sl++) { doset(sl); } } else { int i; for (i = 1; i < argc; i++) { sl = getset(argv[i]); tl = GETTOGGLE(argv[i]); - if (Ambiguous(sl) || Ambiguous(tl)) { + if (Ambiguous((void *)sl) || Ambiguous((void *)tl)) { printf("?Ambiguous argument '%s'.\n", argv[i]); return 0; } else if (!sl && !tl) { printf("?Unknown argument '%s'.\n", argv[i]); return 0; } else { if (tl) { dotog(tl); } if (sl) { doset(sl); } } } } /*@*/optionstatus(); #ifdef ENCRYPTION EncryptStatus(); #endif /* ENCRYPTION */ return 1; #undef doset #undef dotog } /* * The following are the data structures, and many of the routines, * relating to command processing. */ /* * Set the escape character. */ - static int -setescape(argc, argv) - int argc; - char *argv[]; +static int +setescape(int argc, char *argv[]) { - register char *arg; + char *arg; char buf[50]; printf( "Deprecated usage - please use 'set escape%s%s' in the future.\n", (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); if (argc > 2) arg = argv[1]; else { printf("new escape character: "); (void) fgets(buf, sizeof(buf), stdin); arg = buf; } if (arg[0] != '\0') escape = arg[0]; - if (!In3270) { - printf("Escape character is '%s'.\n", control(escape)); - } (void) fflush(stdout); return 1; } - /*VARARGS*/ - static int -togcrmod() +static int +togcrmod(void) { crmod = !crmod; printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); (void) fflush(stdout); return 1; } - /*VARARGS*/ - int -suspend() +static int +suspend(void) { #ifdef SIGTSTP setcommandmode(); { - long oldrows, oldcols, newrows, newcols, err; + long oldrows, oldcols, newrows, newcols, err_; - err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; (void) kill(0, SIGTSTP); /* * If we didn't get the window size before the SUSPEND, but we * can get them now (?), then send the NAWS to make sure that * we are set up for the right window size. */ if (TerminalWindowSize(&newrows, &newcols) && connected && - (err || ((oldrows != newrows) || (oldcols != newcols)))) { + (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { sendnaws(); } } /* reget parameters in case they were changed */ TerminalSaveState(); setconnmode(0); #else printf("Suspend is not supported. Try the '!' command instead\n"); #endif return 1; } -#if !defined(TN3270) - /*ARGSUSED*/ - int -shell(argc, argv) - int argc; - char *argv[]; +static int +shell(int argc, char *argv[] __unused) { - long oldrows, oldcols, newrows, newcols, err; + long oldrows, oldcols, newrows, newcols, err_; setcommandmode(); - err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; switch(vfork()) { case -1: perror("Fork failed\n"); break; case 0: { /* * Fire up the shell in the child. */ - register char *shellp, *shellname; + const char *shellp, *shellname; shellp = getenv("SHELL"); if (shellp == NULL) shellp = "/bin/sh"; if ((shellname = strrchr(shellp, '/')) == 0) shellname = shellp; else shellname++; if (argc > 1) execl(shellp, shellname, "-c", &saveline[1], (char *)0); else execl(shellp, shellname, (char *)0); perror("Execl"); _exit(1); } default: (void)wait((int *)0); /* Wait for the shell to complete */ if (TerminalWindowSize(&newrows, &newcols) && connected && - (err || ((oldrows != newrows) || (oldcols != newcols)))) { + (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { sendnaws(); } break; } return 1; } -#else /* !defined(TN3270) */ -extern int shell(); -#endif /* !defined(TN3270) */ - /*VARARGS*/ - static int -bye(argc, argv) - int argc; /* Number of arguments */ - char *argv[]; /* arguments */ +static int +bye(int argc, char *argv[]) { extern int resettermname; if (connected) { (void) shutdown(net, 2); printf("Connection closed.\n"); (void) NetClose(net); connected = 0; resettermname = 1; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION auth_encrypt_connect(connected); -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif +#endif /* reset options */ tninit(); -#if defined(TN3270) - SetIn3270(); /* Get out of 3270 mode */ -#endif /* defined(TN3270) */ } if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { longjmp(toplevel, 1); /* NOTREACHED */ } return 1; /* Keep lint, etc., happy */ } -/*VARARGS*/ - int -quit() +void +quit(void) { (void) call(bye, "bye", "fromquit", 0); Exit(0); - /*NOTREACHED*/ } -/*VARARGS*/ - int -logout() +static int +logout(void) { send_do(TELOPT_LOGOUT, 1); (void) netflush(); return 1; } /* * The SLC command. */ struct slclist { - char *name; - char *help; - void (*handler)(); + const char *name; + const char *help; + void (*handler)(int); int arg; }; -static void slc_help(); +static void slc_help(void); struct slclist SlcList[] = { { "export", "Use local special character definitions", - slc_mode_export, 0 }, + (void (*)(int))slc_mode_export, 0 }, { "import", "Use remote special character definitions", slc_mode_import, 1 }, { "check", "Verify remote special character definitions", slc_mode_import, 0 }, - { "help", 0, slc_help, 0 }, - { "?", "Print help information", slc_help, 0 }, - { 0 }, + { "help", NULL, (void (*)(int))slc_help, 0 }, + { "?", "Print help information", (void (*)(int))slc_help, 0 }, + { NULL, NULL, NULL, 0 }, }; - static void -slc_help() +static void +slc_help(void) { struct slclist *c; for (c = SlcList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } } - static struct slclist * -getslc(name) - char *name; +static struct slclist * +getslc(char *name) { return (struct slclist *) genget(name, (char **) SlcList, sizeof(struct slclist)); } - static int -slccmd(argc, argv) - int argc; - char *argv[]; +static int +slccmd(int argc, char *argv[]) { struct slclist *c; if (argc != 2) { fprintf(stderr, "Need an argument to 'slc' command. 'slc ?' for help.\n"); return 0; } c = getslc(argv[1]); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", argv[1]); return 0; } (*c->handler)(c->arg); slcstate(); return 1; } /* * The ENVIRON command. */ struct envlist { - char *name; - char *help; - void (*handler)(); + const char *name; + const char *help; + void (*handler)(unsigned char *, unsigned char *); int narg; }; extern struct env_lst * - env_define P((unsigned char *, unsigned char *)); + env_define P((const unsigned char *, unsigned char *)); extern void env_undefine P((unsigned char *)), - env_export P((unsigned char *)), - env_unexport P((unsigned char *)), + env_export P((const unsigned char *)), + env_unexport P((const unsigned char *)), env_send P((unsigned char *)), #if defined(OLD_ENVIRON) && defined(ENV_HACK) env_varval P((unsigned char *)), #endif env_list P((void)); static void env_help P((void)); struct envlist EnvList[] = { { "define", "Define an environment variable", - (void (*)())env_define, 2 }, + (void (*)(unsigned char *, unsigned char *))env_define, 2 }, { "undefine", "Undefine an environment variable", - env_undefine, 1 }, + (void (*)(unsigned char *, unsigned char *))env_undefine, 1 }, { "export", "Mark an environment variable for automatic export", - env_export, 1 }, + (void (*)(unsigned char *, unsigned char *))env_export, 1 }, { "unexport", "Don't mark an environment variable for automatic export", - env_unexport, 1 }, - { "send", "Send an environment variable", env_send, 1 }, + (void (*)(unsigned char *, unsigned char *))env_unexport, 1 }, + { "send", "Send an environment variable", (void (*)(unsigned char *, unsigned char *))env_send, 1 }, { "list", "List the current environment variables", - env_list, 0 }, + (void (*)(unsigned char *, unsigned char *))env_list, 0 }, #if defined(OLD_ENVIRON) && defined(ENV_HACK) { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", - env_varval, 1 }, + (void (*)(unsigned char *, unsigned char *))env_varval, 1 }, #endif - { "help", 0, env_help, 0 }, - { "?", "Print help information", env_help, 0 }, - { 0 }, + { "help", NULL, (void (*)(unsigned char *, unsigned char *))env_help, 0 }, + { "?", "Print help information", (void (*)(unsigned char *, unsigned char *))env_help, 0 }, + { NULL, NULL, NULL, 0 }, }; - static void -env_help() +static void +env_help(void) { struct envlist *c; for (c = EnvList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } } - static struct envlist * -getenvcmd(name) - char *name; +static struct envlist * +getenvcmd(char *name) { return (struct envlist *) genget(name, (char **) EnvList, sizeof(struct envlist)); } - int -env_cmd(argc, argv) - int argc; - char *argv[]; +static int +env_cmd(int argc, char *argv[]) { struct envlist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'environ' command. 'environ ?' for help.\n"); return 0; } c = getenvcmd(argv[1]); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", argv[1]); return 0; } if (c->narg + 2 != argc) { fprintf(stderr, "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", c->narg < argc + 2 ? "only " : "", c->narg, c->narg == 1 ? "" : "s", c->name); return 0; } (*c->handler)(argv[2], argv[3]); return 1; } struct env_lst { struct env_lst *next; /* pointer to next structure */ struct env_lst *prev; /* pointer to previous structure */ unsigned char *var; /* pointer to variable name */ unsigned char *value; /* pointer to variable value */ int export; /* 1 -> export with default list of variables */ int welldefined; /* A well defined variable */ }; struct env_lst envlisthead; - struct env_lst * -env_find(var) - unsigned char *var; +static struct env_lst * +env_find(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; for (ep = envlisthead.next; ep; ep = ep->next) { - if (strcmp((char *)ep->var, (char *)var) == 0) + if (strcmp(ep->var, var) == 0) return(ep); } return(NULL); } - void -env_init() +void +env_init(void) { extern char **environ; - register char **epp, *cp; - register struct env_lst *ep; + char **epp, *cp; + struct env_lst *ep; for (epp = environ; *epp; epp++) { if ((cp = strchr(*epp, '='))) { *cp = '\0'; ep = env_define((unsigned char *)*epp, (unsigned char *)cp+1); ep->export = 0; *cp = '='; } } /* * Special case for DISPLAY variable. If it is ":0.0" or * "unix:0.0", we have to get rid of "unix" and insert our * hostname. */ if ((ep = env_find("DISPLAY")) && ((*ep->value == ':') || (strncmp((char *)ep->value, "unix:", 5) == 0))) { char hbuf[256+1]; char *cp2 = strchr((char *)ep->value, ':'); gethostname(hbuf, 256); hbuf[256] = '\0'; cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); sprintf((char *)cp, "%s%s", hbuf, cp2); free(ep->value); ep->value = (unsigned char *)cp; } /* * If USER is not defined, but LOGNAME is, then add * USER with the value from LOGNAME. By default, we * don't export the USER variable. */ if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { - env_define((unsigned char *)"USER", ep->value); - env_unexport((unsigned char *)"USER"); + env_define("USER", ep->value); + env_unexport("USER"); } - env_export((unsigned char *)"DISPLAY"); - env_export((unsigned char *)"PRINTER"); + env_export("DISPLAY"); + env_export("PRINTER"); } - struct env_lst * -env_define(var, value) - unsigned char *var, *value; +struct env_lst * +env_define(const unsigned char *var, unsigned char *value) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) { if (ep->var) free(ep->var); if (ep->value) free(ep->value); } else { ep = (struct env_lst *)malloc(sizeof(struct env_lst)); ep->next = envlisthead.next; envlisthead.next = ep; ep->prev = &envlisthead; if (ep->next) ep->next->prev = ep; } ep->welldefined = opt_welldefined(var); ep->export = 1; - ep->var = (unsigned char *)strdup((char *)var); - ep->value = (unsigned char *)strdup((char *)value); + ep->var = strdup(var); + ep->value = strdup(value); return(ep); } - void -env_undefine(var) - unsigned char *var; +void +env_undefine(unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) { ep->prev->next = ep->next; if (ep->next) ep->next->prev = ep->prev; if (ep->var) free(ep->var); if (ep->value) free(ep->value); free(ep); } } - void -env_export(var) - unsigned char *var; +void +env_export(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) ep->export = 1; } - void -env_unexport(var) - unsigned char *var; +void +env_unexport(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) ep->export = 0; } - void -env_send(var) - unsigned char *var; +void +env_send(unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if (my_state_is_wont(TELOPT_NEW_ENVIRON) #ifdef OLD_ENVIRON && my_state_is_wont(TELOPT_OLD_ENVIRON) #endif ) { fprintf(stderr, "Cannot send '%s': Telnet ENVIRON option not enabled\n", var); return; } ep = env_find(var); if (ep == 0) { fprintf(stderr, "Cannot send '%s': variable not defined\n", var); return; } env_opt_start_info(); env_opt_add(ep->var); env_opt_end(0); } - void -env_list() +void +env_list(void) { - register struct env_lst *ep; + struct env_lst *ep; for (ep = envlisthead.next; ep; ep = ep->next) { printf("%c %-20s %s\n", ep->export ? '*' : ' ', ep->var, ep->value); } } - unsigned char * -env_default(init, welldefined) - int init; +unsigned char * +env_default(int init, int welldefined) { static struct env_lst *nep = NULL; if (init) { nep = &envlisthead; return(NULL); } if (nep) { while ((nep = nep->next)) { if (nep->export && (nep->welldefined == welldefined)) return(nep->var); } } return(NULL); } - unsigned char * -env_getvalue(var) - unsigned char *var; +unsigned char * +env_getvalue(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) return(ep->value); return(NULL); } #if defined(OLD_ENVIRON) && defined(ENV_HACK) - void -env_varval(what) - unsigned char *what; +void +env_varval(unsigned char *what) { extern int old_env_var, old_env_value, env_auto; int len = strlen((char *)what); if (len == 0) goto unknown; if (strncasecmp((char *)what, "status", len) == 0) { if (env_auto) printf("%s%s", "VAR and VALUE are/will be ", "determined automatically\n"); if (old_env_var == OLD_ENV_VAR) printf("VAR and VALUE set to correct definitions\n"); else printf("VAR and VALUE definitions are reversed\n"); } else if (strncasecmp((char *)what, "auto", len) == 0) { env_auto = 1; old_env_var = OLD_ENV_VALUE; old_env_value = OLD_ENV_VAR; } else if (strncasecmp((char *)what, "right", len) == 0) { env_auto = 0; old_env_var = OLD_ENV_VAR; old_env_value = OLD_ENV_VALUE; } else if (strncasecmp((char *)what, "wrong", len) == 0) { env_auto = 0; old_env_var = OLD_ENV_VALUE; old_env_value = OLD_ENV_VAR; } else { unknown: printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); } } #endif -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION /* * The AUTHENTICATE command. */ struct authlist { - char *name; - char *help; - int (*handler)(); + const char *name; + const char *help; + int (*handler)(char *); int narg; }; extern int auth_enable P((char *)), auth_disable P((char *)), auth_status P((void)); static int auth_help P((void)); struct authlist AuthList[] = { { "status", "Display current status of authentication information", - auth_status, 0 }, + (int (*)(char *))auth_status, 0 }, { "disable", "Disable an authentication type ('auth disable ?' for more)", auth_disable, 1 }, { "enable", "Enable an authentication type ('auth enable ?' for more)", auth_enable, 1 }, - { "help", 0, auth_help, 0 }, - { "?", "Print help information", auth_help, 0 }, - { 0 }, + { "help", NULL, (int (*)(char *))auth_help, 0 }, + { "?", "Print help information", (int (*)(char *))auth_help, 0 }, + { NULL, NULL, NULL, 0 }, }; - static int -auth_help() +static int +auth_help(void) { struct authlist *c; for (c = AuthList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } return 0; } - int -auth_cmd(argc, argv) - int argc; - char *argv[]; +int +auth_cmd(int argc, char *argv[]) { struct authlist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'auth' command. 'auth ?' for help.\n"); return 0; } c = (struct authlist *) genget(argv[1], (char **) AuthList, sizeof(struct authlist)); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", argv[1]); return 0; } if (c->narg + 2 != argc) { fprintf(stderr, "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", c->narg < argc + 2 ? "only " : "", c->narg, c->narg == 1 ? "" : "s", c->name); return 0; } - return((*c->handler)(argv[2], argv[3])); + return((*c->handler)(argv[2])); } #endif #ifdef ENCRYPTION /* * The ENCRYPT command. */ struct encryptlist { - char *name; - char *help; - int (*handler)(); + const char *name; + const char *help; + int (*handler)(char *, char *); int needconnect; int minarg; int maxarg; }; extern int EncryptEnable P((char *, char *)), EncryptDisable P((char *, char *)), EncryptType P((char *, char *)), EncryptStart P((char *)), EncryptStartInput P((void)), EncryptStartOutput P((void)), EncryptStop P((char *)), EncryptStopInput P((void)), EncryptStopOutput P((void)), EncryptStatus P((void)); static int EncryptHelp P((void)); struct encryptlist EncryptList[] = { { "enable", "Enable encryption. ('encrypt enable ?' for more)", EncryptEnable, 1, 1, 2 }, { "disable", "Disable encryption. ('encrypt enable ?' for more)", EncryptDisable, 0, 1, 2 }, { "type", "Set encryption type. ('encrypt type ?' for more)", EncryptType, 0, 1, 1 }, { "start", "Start encryption. ('encrypt start ?' for more)", - EncryptStart, 1, 0, 1 }, + (int (*)(char *, char *))EncryptStart, 1, 0, 1 }, { "stop", "Stop encryption. ('encrypt stop ?' for more)", - EncryptStop, 1, 0, 1 }, + (int (*)(char *, char *))EncryptStop, 1, 0, 1 }, { "input", "Start encrypting the input stream", - EncryptStartInput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStartInput, 1, 0, 0 }, { "-input", "Stop encrypting the input stream", - EncryptStopInput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStopInput, 1, 0, 0 }, { "output", "Start encrypting the output stream", - EncryptStartOutput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStartOutput, 1, 0, 0 }, { "-output", "Stop encrypting the output stream", - EncryptStopOutput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStopOutput, 1, 0, 0 }, { "status", "Display current status of authentication information", - EncryptStatus, 0, 0, 0 }, - { "help", 0, EncryptHelp, 0, 0, 0 }, - { "?", "Print help information", EncryptHelp, 0, 0, 0 }, - { 0 }, + (int (*)(char *, char *))EncryptStatus, 0, 0, 0 }, + { "help", NULL, (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, + { "?", "Print help information", (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, + { NULL, NULL, NULL, 0, 0, 0 }, }; - static int -EncryptHelp() +static int +EncryptHelp(void) { struct encryptlist *c; for (c = EncryptList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } return 0; } - int -encrypt_cmd(argc, argv) - int argc; - char *argv[]; +static int +encrypt_cmd(int argc, char *argv[]) { struct encryptlist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); return 0; } c = (struct encryptlist *) genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", argv[1]); return 0; } argc -= 2; if (argc < c->minarg || argc > c->maxarg) { if (c->minarg == c->maxarg) { fprintf(stderr, "Need %s%d argument%s ", c->minarg < argc ? "only " : "", c->minarg, c->minarg == 1 ? "" : "s"); } else { fprintf(stderr, "Need %s%d-%d arguments ", c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); } fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", c->name); return 0; } if (c->needconnect && !connected) { if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { printf("?Need to be connected first.\n"); return 0; } } return ((*c->handler)(argc > 0 ? argv[2] : 0, - argc > 1 ? argv[3] : 0, - argc > 2 ? argv[4] : 0)); + argc > 1 ? argv[3] : 0)); } #endif /* ENCRYPTION */ -#if defined(unix) && defined(TN3270) - static void -filestuff(fd) - int fd; -{ - int res; - -#ifdef F_GETOWN - setconnmode(0); - res = fcntl(fd, F_GETOWN, 0); - setcommandmode(); - - if (res == -1) { - perror("fcntl"); - return; - } - printf("\tOwner is %d.\n", res); -#endif - - setconnmode(0); - res = fcntl(fd, F_GETFL, 0); - setcommandmode(); - - if (res == -1) { - perror("fcntl"); - return; - } -#ifdef notdef - printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); -#endif -} -#endif /* defined(unix) && defined(TN3270) */ - /* * Print status about the connection. */ - /*ARGSUSED*/ - static int -status(argc, argv) - int argc; - char *argv[]; +/*ARGSUSED*/ +static int +status(int argc, char *argv[]) { if (connected) { printf("Connected to %s.\n", hostname); if ((argc < 2) || strcmp(argv[1], "notmuch")) { int mode = getconnmode(); if (my_want_state_is_will(TELOPT_LINEMODE)) { printf("Operating with LINEMODE option\n"); printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); printf("%s catching of signals\n", (mode&MODE_TRAPSIG) ? "Local" : "No"); slcstate(); #ifdef KLUDGELINEMODE } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { printf("Operating in obsolete linemode\n"); #endif } else { printf("Operating in single character mode\n"); if (localchars) printf("Catching signals locally\n"); } printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); if (my_want_state_is_will(TELOPT_LFLOW)) printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); #ifdef ENCRYPTION encrypt_display(); #endif /* ENCRYPTION */ } } else { printf("No connection.\n"); } -# if !defined(TN3270) printf("Escape character is '%s'.\n", control(escape)); (void) fflush(stdout); -# else /* !defined(TN3270) */ - if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { - printf("Escape character is '%s'.\n", control(escape)); - } -# if defined(unix) - if ((argc >= 2) && !strcmp(argv[1], "everything")) { - printf("SIGIO received %d time%s.\n", - sigiocount, (sigiocount == 1)? "":"s"); - if (In3270) { - printf("Process ID %d, process group %d.\n", - getpid(), getpgrp(getpid())); - printf("Terminal input:\n"); - filestuff(tin); - printf("Terminal output:\n"); - filestuff(tout); - printf("Network socket:\n"); - filestuff(net); - } - } - if (In3270 && transcom) { - printf("Transparent mode command is '%s'.\n", transcom); - } -# endif /* defined(unix) */ - (void) fflush(stdout); - if (In3270) { - return 0; - } -# endif /* defined(TN3270) */ return 1; } #ifdef SIGINFO /* * Function that gets called when SIGINFO is received. */ - void -ayt_status() +void +ayt_status(void) { (void) call(status, "status", "notmuch", 0); } #endif static const char * -sockaddr_ntop(sa) - struct sockaddr *sa; +sockaddr_ntop(struct sockaddr *sa) { void *addr; static char addrbuf[INET6_ADDRSTRLEN]; switch (sa->sa_family) { case AF_INET: addr = &((struct sockaddr_in *)sa)->sin_addr; break; case AF_UNIX: addr = &((struct sockaddr_un *)sa)->sun_path; break; #ifdef INET6 case AF_INET6: addr = &((struct sockaddr_in6 *)sa)->sin6_addr; break; #endif default: return NULL; } inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); return addrbuf; } #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) static int -setpolicy(net, res, policy) - int net; - struct addrinfo *res; - char *policy; +setpolicy(int lnet, struct addrinfo *res, char *policy) { char *buf; int level; int optname; if (policy == NULL) return 0; buf = ipsec_set_policy(policy, strlen(policy)); if (buf == NULL) { printf("%s\n", ipsec_strerror()); return -1; } level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; - if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){ + if (setsockopt(lnet, level, optname, buf, ipsec_get_policylen(buf)) < 0){ perror("setsockopt"); return -1; } free(buf); + return 0; } #endif #ifdef INET6 /* * When an Address Family related error happend, check if retry with * another AF is possible or not. * Return 1, if retry with another af is OK. Else, return 0. */ static int -switch_af(aip) - struct addrinfo **aip; +switch_af(struct addrinfo **aip) { int nextaf; struct addrinfo *ai; ai = *aip; nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET; do ai=ai->ai_next; while (ai != NULL && ai->ai_family != nextaf); *aip = ai; if (*aip != NULL) { return 1; } return 0; } #endif - int -tn(argc, argv) - int argc; - char *argv[]; +int +tn(int argc, char *argv[]) { char *srp = 0; int proto, opt; - int sourceroute(), srlen; + int srlen; int srcroute = 0, result; char *cmd, *hostp = 0, *portp = 0, *user = 0; char *src_addr = NULL; struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL; int error = 0, af_error = 0; if (connected) { printf("?Already connected to %s\n", hostname); setuid(getuid()); return 0; } if (argc < 2) { (void) strcpy(line, "open "); printf("(to) "); (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); makeargv(); argc = margc; argv = margv; } cmd = *argv; --argc; ++argv; while (argc) { if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) goto usage; if (strcmp(*argv, "-l") == 0) { --argc; ++argv; if (argc == 0) goto usage; user = *argv++; --argc; continue; } if (strcmp(*argv, "-a") == 0) { --argc; ++argv; autologin = 1; continue; } if (strcmp(*argv, "-s") == 0) { --argc; ++argv; if (argc == 0) goto usage; src_addr = *argv++; --argc; continue; } if (hostp == 0) { hostp = *argv++; --argc; continue; } if (portp == 0) { portp = *argv++; --argc; continue; } usage: printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd); setuid(getuid()); return 0; } if (hostp == 0) goto usage; if (src_addr != NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(src_addr, 0, &hints, &src_res); if (error == EAI_NODATA) { hints.ai_flags = 0; error = getaddrinfo(src_addr, 0, &hints, &src_res); } if (error != 0) { fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "%s: %s\n", src_addr, strerror(errno)); setuid(getuid()); return 0; } src_res0 = src_res; } if (hostp[0] == '/') { struct sockaddr_un su; if (strlen(hostp) >= sizeof(su.sun_path)) { fprintf(stderr, "hostname too long for unix domain socket: %s", hostp); goto fail; } memset(&su, 0, sizeof su); su.sun_family = AF_UNIX; strncpy(su.sun_path, hostp, sizeof su.sun_path); - printf("Trying %s...\n", &su.sun_path); + printf("Trying %s...\n", hostp); net = socket(PF_UNIX, SOCK_STREAM, 0); if ( net < 0) { perror("socket"); goto fail; } if (connect(net, (struct sockaddr *)&su, sizeof su) == -1) { perror(su.sun_path); (void) NetClose(net); goto fail; } goto af_unix; } else if (hostp[0] == '@' || hostp[0] == '!') { if ( #ifdef INET6 family == AF_INET6 || #endif (hostname = strrchr(hostp, ':')) == NULL) hostname = strrchr(hostp, '@'); hostname++; srcroute = 1; } else hostname = hostp; if (!portp) { telnetport = 1; - portp = "telnet"; + portp = strdup("telnet"); } else if (*portp == '-') { portp++; telnetport = 1; } else telnetport = 0; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(hostname, portp, &hints, &res); if (error) { hints.ai_flags = AI_CANONNAME; error = getaddrinfo(hostname, portp, &hints, &res); } if (error != 0) { fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "%s: %s\n", hostname, strerror(errno)); setuid(getuid()); goto fail; } if (hints.ai_flags == AI_NUMERICHOST) { /* hostname has numeric */ int gni_err = 1; if (doaddrlookup) gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len, _hostname, sizeof(_hostname) - 1, NULL, 0, NI_NAMEREQD); if (gni_err != 0) (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); _hostname[sizeof(_hostname)-1] = '\0'; hostname = _hostname; } else { /* hostname has FQDN */ if (srcroute != 0) (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1); else if (res->ai_canonname != NULL) strcpy(_hostname, res->ai_canonname); else (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); _hostname[sizeof(_hostname)-1] = '\0'; hostname = _hostname; } res0 = res; af_again: if (srcroute != 0) { static char hostbuf[BUFSIZ]; if (af_error == 0) { /* save intermediate hostnames for retry */ strncpy(hostbuf, hostp, BUFSIZ - 1); hostbuf[BUFSIZ - 1] = '\0'; } else hostp = hostbuf; srp = 0; result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); if (result == 0) { #ifdef INET6 if (family == AF_UNSPEC && af_error == 0 && switch_af(&res) == 1) { af_error = 1; goto af_again; } #endif setuid(getuid()); goto fail; } else if (result == -1) { printf("Bad source route option: %s\n", hostp); setuid(getuid()); goto fail; } } do { printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); setuid(getuid()); if (net < 0) { #ifdef INET6 if (family == AF_UNSPEC && af_error == 0 && switch_af(&res) == 1) { af_error = 1; goto af_again; } #endif perror("telnet: socket"); goto fail; } if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0) perror("setsockopt (source route)"); #if defined(IPPROTO_IP) && defined(IP_TOS) if (res->ai_family == PF_INET) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = IPTOS_LOWDELAY; if (tos && (setsockopt(net, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) && (errno != ENOPROTOOPT)) perror("telnet: setsockopt (IP_TOS) (ignored)"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { perror("setsockopt (SO_DEBUG)"); } if (src_addr != NULL) { for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next) if (src_res->ai_family == res->ai_family) break; if (src_res == NULL) src_res = src_res0; if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) { #ifdef INET6 if (family == AF_UNSPEC && af_error == 0 && switch_af(&res) == 1) { af_error = 1; (void) NetClose(net); goto af_again; } #endif perror("bind"); (void) NetClose(net); goto fail; } } #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) if (setpolicy(net, res, ipsec_policy_in) < 0) { (void) NetClose(net); goto fail; } if (setpolicy(net, res, ipsec_policy_out) < 0) { (void) NetClose(net); goto fail; } #endif if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { struct addrinfo *next; next = res->ai_next; /* If already an af failed, only try same af. */ if (af_error != 0) while (next != NULL && next->ai_family != res->ai_family) next = next->ai_next; warn("connect to address %s", sockaddr_ntop(res->ai_addr)); if (next != NULL) { res = next; (void) NetClose(net); continue; } warnx("Unable to connect to remote host"); (void) NetClose(net); goto fail; } connected++; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION auth_encrypt_connect(connected); -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif +#endif } while (connected == 0); freeaddrinfo(res0); if (src_res0 != NULL) freeaddrinfo(src_res0); cmdrc(hostp, hostname); af_unix: if (autologin && user == NULL) { struct passwd *pw; user = getenv("USER"); if (user == NULL || ((pw = getpwnam(user)) && pw->pw_uid != getuid())) { if ((pw = getpwuid(getuid()))) user = pw->pw_name; else user = NULL; } } if (user) { - env_define((unsigned char *)"USER", (unsigned char *)user); - env_export((unsigned char *)"USER"); + env_define("USER", user); + env_export("USER"); } (void) call(status, "status", "notmuch", 0); if (setjmp(peerdied) == 0) telnet(user); (void) NetClose(net); ExitString("Connection closed by foreign host.\n",1); /*NOTREACHED*/ fail: if (res0 != NULL) freeaddrinfo(res0); if (src_res0 != NULL) freeaddrinfo(src_res0); return 0; } #define HELPINDENT (sizeof ("connect")) static char openhelp[] = "connect to a site", closehelp[] = "close current connection", logouthelp[] = "forcibly logout remote user and close the connection", quithelp[] = "exit telnet", statushelp[] = "print status information", helphelp[] = "print help information", sendhelp[] = "transmit special characters ('send ?' for more)", sethelp[] = "set operating parameters ('set ?' for more)", unsethelp[] = "unset operating parameters ('unset ?' for more)", togglestring[] ="toggle operating parameters ('toggle ?' for more)", slchelp[] = "change state of special charaters ('slc ?' for more)", displayhelp[] = "display operating parameters", -#if defined(TN3270) && defined(unix) - transcomhelp[] = "specify Unix command for transparent mode pipe", -#endif /* defined(TN3270) && defined(unix) */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION authhelp[] = "turn on (off) authentication ('auth ?' for more)", #endif #ifdef ENCRYPTION encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", #endif /* ENCRYPTION */ -#if defined(unix) zhelp[] = "suspend telnet", -#endif /* defined(unix) */ -#if defined(OPIE) +#ifdef OPIE opiehelp[] = "compute response to OPIE challenge", #endif shellhelp[] = "invoke a subshell", envhelp[] = "change environment variables ('environ ?' for more)", modestring[] = "try to enter line or character mode ('mode ?' for more)"; static Command cmdtab[] = { { "close", closehelp, bye, 1 }, - { "logout", logouthelp, logout, 1 }, + { "logout", logouthelp, (int (*)(int, char **))logout, 1 }, { "display", displayhelp, display, 0 }, { "mode", modestring, modecmd, 0 }, { "telnet", openhelp, tn, 0 }, { "open", openhelp, tn, 0 }, - { "quit", quithelp, quit, 0 }, + { "quit", quithelp, (int (*)(int, char **))quit, 0 }, { "send", sendhelp, sendcmd, 0 }, { "set", sethelp, setcmd, 0 }, { "unset", unsethelp, unsetcmd, 0 }, { "status", statushelp, status, 0 }, { "toggle", togglestring, toggle, 0 }, { "slc", slchelp, slccmd, 0 }, -#if defined(TN3270) && defined(unix) - { "transcom", transcomhelp, settranscom, 0 }, -#endif /* defined(TN3270) && defined(unix) */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION { "auth", authhelp, auth_cmd, 0 }, #endif #ifdef ENCRYPTION { "encrypt", encrypthelp, encrypt_cmd, 0 }, #endif /* ENCRYPTION */ -#if defined(unix) - { "z", zhelp, suspend, 0 }, -#endif /* defined(unix) */ -#if defined(TN3270) + { "z", zhelp, (int (*)(int, char **))suspend, 0 }, { "!", shellhelp, shell, 1 }, -#else - { "!", shellhelp, shell, 0 }, -#endif { "environ", envhelp, env_cmd, 0 }, { "?", helphelp, help, 0 }, -#if defined(OPIE) +#ifdef OPIE { "opie", opiehelp, opie_calc, 0 }, #endif - { 0, 0, 0, 0 } + { NULL, NULL, NULL, 0 } }; static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; static char escapehelp[] = "deprecated command -- use 'set escape' instead"; static Command cmdtab2[] = { { "help", 0, help, 0 }, { "escape", escapehelp, setescape, 0 }, - { "crmod", crmodhelp, togcrmod, 0 }, - { 0, 0, 0, 0 } + { "crmod", crmodhelp, (int (*)(int, char **))togcrmod, 0 }, + { NULL, NULL, NULL, 0 } }; /* * Call routine with argc, argv set from args (terminated by 0). */ - /*VARARGS1*/ - static int -call(va_alist) - va_dcl +static int +call(intrtn_t routine, ...) { va_list ap; - typedef int (*intrtn_t)(); - intrtn_t routine; char *args[100]; int argno = 0; - va_start(ap); - routine = (va_arg(ap, intrtn_t)); - while ((args[argno++] = va_arg(ap, char *)) != 0) { - ; - } + va_start(ap, routine); + while ((args[argno++] = va_arg(ap, char *)) != 0); va_end(ap); return (*routine)(argno-1, args); } - static Command * -getcmd(name) - char *name; +static Command * +getcmd(char *name) { Command *cm; if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) return cm; return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); } - void -command(top, tbuf, cnt) - int top; - char *tbuf; - int cnt; +void +command(int top, const char *tbuf, int cnt) { - register Command *c; + Command *c; setcommandmode(); if (!top) { putchar('\n'); -#if defined(unix) } else { (void) signal(SIGINT, SIG_DFL); (void) signal(SIGQUIT, SIG_DFL); -#endif /* defined(unix) */ } for (;;) { if (rlogin == _POSIX_VDISABLE) printf("%s> ", prompt); if (tbuf) { - register char *cp; + char *cp; cp = line; while (cnt > 0 && (*cp++ = *tbuf++) != '\n') cnt--; tbuf = 0; if (cp == line || *--cp != '\n' || cp == line) goto getline; *cp = '\0'; if (rlogin == _POSIX_VDISABLE) printf("%s\n", line); } else { getline: if (rlogin != _POSIX_VDISABLE) printf("%s> ", prompt); if (fgets(line, sizeof(line), stdin) == NULL) { if (feof(stdin) || ferror(stdin)) { (void) quit(); /*NOTREACHED*/ } break; } } if (line[0] == 0) break; makeargv(); if (margv[0] == 0) { break; } c = getcmd(margv[0]); - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { printf("?Ambiguous command\n"); continue; } if (c == 0) { printf("?Invalid command\n"); continue; } if (c->needconnect && !connected) { printf("?Need to be connected first.\n"); continue; } if ((*c->handler)(margc, margv)) { break; } } if (!top) { if (!connected) { longjmp(toplevel, 1); /*NOTREACHED*/ } -#if defined(TN3270) - if (shell_active == 0) { - setconnmode(0); - } -#else /* defined(TN3270) */ setconnmode(0); -#endif /* defined(TN3270) */ } } /* * Help command. */ - static int -help(argc, argv) - int argc; - char *argv[]; +static int +help(int argc, char *argv[]) { - register Command *c; + Command *c; if (argc == 1) { printf("Commands may be abbreviated. Commands are:\n\n"); for (c = cmdtab; c->name; c++) if (c->help) { printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); } return 0; } else while (--argc > 0) { - register char *arg; + char *arg; arg = *++argv; c = getcmd(arg); - if (Ambiguous(c)) + if (Ambiguous((void *)c)) printf("?Ambiguous help command %s\n", arg); else if (c == (Command *)0) printf("?Invalid help command %s\n", arg); else printf("%s\n", c->help); } return 0; } static char *rcname = 0; static char rcbuf[128]; - void -cmdrc(m1, m2) - char *m1, *m2; +void +cmdrc(char *m1, char *m2) { - register Command *c; + Command *c; FILE *rcfile; int gotmachine = 0; int l1 = strlen(m1); int l2 = strlen(m2); char m1save[MAXHOSTNAMELEN]; if (skiprc) return; strlcpy(m1save, m1, sizeof(m1save)); m1 = m1save; if (rcname == 0) { rcname = getenv("HOME"); if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf)) strcpy(rcbuf, rcname); else rcbuf[0] = '\0'; strcat(rcbuf, "/.telnetrc"); rcname = rcbuf; } if ((rcfile = fopen(rcname, "r")) == 0) { return; } for (;;) { if (fgets(line, sizeof(line), rcfile) == NULL) break; if (line[0] == 0) break; if (line[0] == '#') continue; if (gotmachine) { if (!isspace(line[0])) gotmachine = 0; } if (gotmachine == 0) { if (isspace(line[0])) continue; if (strncasecmp(line, m1, l1) == 0) strncpy(line, &line[l1], sizeof(line) - l1); else if (strncasecmp(line, m2, l2) == 0) strncpy(line, &line[l2], sizeof(line) - l2); else if (strncasecmp(line, "DEFAULT", 7) == 0) strncpy(line, &line[7], sizeof(line) - 7); else continue; if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') continue; gotmachine = 1; } makeargv(); if (margv[0] == 0) continue; c = getcmd(margv[0]); - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { printf("?Ambiguous command: %s\n", margv[0]); continue; } if (c == 0) { printf("?Invalid command: %s\n", margv[0]); continue; } /* * This should never happen... */ if (c->needconnect && !connected) { printf("?Need to be connected first for %s.\n", margv[0]); continue; } (*c->handler)(margc, margv); } fclose(rcfile); } /* * Source route is handed in as * [!]@hop1@hop2...[@|:]dst * If the leading ! is present, it is a * strict source route, otherwise it is * assmed to be a loose source route. * * We fill in the source route option as * hop1,hop2,hop3...dest * and return a pointer to hop1, which will * be the address to connect() to. * * Arguments: * * res: ponter to addrinfo structure which contains sockaddr to * the host to connect to. * * arg: pointer to route list to decipher * * cpp: If *cpp is not equal to NULL, this is a * pointer to a pointer to a character array * that should be filled in with the option. * * lenp: pointer to an integer that contains the * length of *cpp if *cpp != NULL. * * protop: pointer to an integer that should be filled in with * appropriate protocol for setsockopt, as socket * protocol family. * * optp: pointer to an integer that should be filled in with * appropriate option for setsockopt, as socket protocol * family. * * Return values: * * If the return value is 1, then all operations are * successful. If the * return value is -1, there was a syntax error in the * option, either unknown characters, or too many hosts. * If the return value is 0, one of the hostnames in the * path is unknown, and *cpp is set to point to the bad * hostname. * * *cpp: If *cpp was equal to NULL, it will be filled * in with a pointer to our static area that has * the option filled in. This will be 32bit aligned. * * *lenp: This will be filled in with how long the option * pointed to by *cpp is. * * *protop: This will be filled in with appropriate protocol for * setsockopt, as socket protocol family. * * *optp: This will be filled in with appropriate option for * setsockopt, as socket protocol family. */ -int -sourceroute(ai, arg, cpp, lenp, protop, optp) - struct addrinfo *ai; - char *arg; - char **cpp; - int *lenp; - int *protop; - int *optp; +static int +sourceroute(struct addrinfo *ai, char *arg, char **cpp, int *lenp, int *protop, int *optp) { static char buf[1024 + ALIGNBYTES]; /*XXX*/ struct cmsghdr *cmsg; -#ifdef sysV88 - static IOPTN ipopt; -#endif char *cp, *cp2, *lsrp, *ep; - register int tmp; - struct sockaddr_in *sin; + struct sockaddr_in *_sin; struct sockaddr_in6 *sin6; struct addrinfo hints, *res; int error; - register char c; + char c; /* * Verify the arguments, and make sure we have * at least 7 bytes for the option. */ if (cpp == NULL || lenp == NULL) return -1; if (*cpp != NULL) { switch (res->ai_family) { case AF_INET: if (*lenp < 7) return -1; break; #ifdef INET6 case AF_INET6: - if (*lenp < CMSG_SPACE(sizeof(struct ip6_rthdr) + + if (*lenp < (int)CMSG_SPACE(sizeof(struct ip6_rthdr) + sizeof(struct in6_addr))) return -1; break; #endif } } /* * Decide whether we have a buffer passed to us, * or if we need to use our own static buffer. */ if (*cpp) { lsrp = *cpp; ep = lsrp + *lenp; } else { *cpp = lsrp = (char *)ALIGN(buf); ep = lsrp + 1024; } cp = arg; #ifdef INET6 if (ai->ai_family == AF_INET6) { cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0); if (*cp != '@') return -1; *protop = IPPROTO_IPV6; *optp = IPV6_PKTOPTIONS; } else #endif { /* * Next, decide whether we have a loose source * route or a strict source route, and fill in * the begining of the option. */ -#ifndef sysV88 if (*cp == '!') { cp++; *lsrp++ = IPOPT_SSRR; } else *lsrp++ = IPOPT_LSRR; -#else - if (*cp == '!') { - cp++; - ipopt.io_type = IPOPT_SSRR; - } else - ipopt.io_type = IPOPT_LSRR; -#endif if (*cp != '@') return -1; -#ifndef sysV88 lsrp++; /* skip over length, we'll fill it in later */ *lsrp++ = 4; -#endif *protop = IPPROTO_IP; *optp = IP_OPTIONS; } cp++; memset(&hints, 0, sizeof(hints)); hints.ai_family = ai->ai_family; hints.ai_socktype = SOCK_STREAM; for (c = 0;;) { if ( #ifdef INET6 ai->ai_family != AF_INET6 && #endif c == ':') cp2 = 0; else for (cp2 = cp; (c = *cp2); cp2++) { if (c == ',') { *cp2++ = '\0'; if (*cp2 == '@') cp2++; } else if (c == '@') { *cp2++ = '\0'; } else if ( #ifdef INET6 ai->ai_family != AF_INET6 && #endif c == ':') { *cp2++ = '\0'; } else continue; break; } if (!c) cp2 = 0; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(cp, NULL, &hints, &res); if (error == EAI_NODATA) { hints.ai_flags = 0; error = getaddrinfo(cp, NULL, &hints, &res); } if (error != 0) { fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "%s: %s\n", cp, strerror(errno)); *cpp = cp; return(0); } #ifdef INET6 if (res->ai_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)res->ai_addr; inet6_rthdr_add(cmsg, &sin6->sin6_addr, IPV6_RTHDR_LOOSE); } else #endif { - sin = (struct sockaddr_in *)res->ai_addr; - memcpy(lsrp, (char *)&sin->sin_addr, 4); + _sin = (struct sockaddr_in *)res->ai_addr; + memcpy(lsrp, (char *)&_sin->sin_addr, 4); lsrp += 4; } if (cp2) cp = cp2; else break; /* * Check to make sure there is space for next address */ #ifdef INET6 if (res->ai_family == AF_INET6) { if (((char *)CMSG_DATA(cmsg) + sizeof(struct ip6_rthdr) + ((inet6_rthdr_segments(cmsg) + 1) * sizeof(struct in6_addr))) > ep) return -1; } else #endif if (lsrp + 4 > ep) return -1; freeaddrinfo(res); } #ifdef INET6 if (res->ai_family == AF_INET6) { inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); *lenp = cmsg->cmsg_len; } else #endif { -#ifndef sysV88 if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { *cpp = 0; *lenp = 0; return -1; } *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ *lenp = lsrp - *cpp; -#else - ipopt.io_len = lsrp - *cpp; - if (ipopt.io_len <= 5) { /* Is 3 better ? */ - *cpp = 0; - *lenp = 0; - return -1; - } - *lenp = sizeof(ipopt); - *cpp = (char *) &ipopt; -#endif } freeaddrinfo(res); return 1; } Index: head/contrib/telnet/telnet/defines.h =================================================================== --- head/contrib/telnet/telnet/defines.h (revision 87138) +++ head/contrib/telnet/telnet/defines.h (revision 87139) @@ -1,61 +1,56 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)defines.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD$ */ #define settimer(x) clocks.x = clocks.system++ - -#if !defined(TN3270) - -#define SetIn3270() - -#endif /* !defined(TN3270) */ #define NETADD(c) { *netoring.supply = c; ring_supplied(&netoring, 1); } #define NET2ADD(c1,c2) { NETADD(c1); NETADD(c2); } #define NETBYTES() (ring_full_count(&netoring)) #define NETROOM() (ring_empty_count(&netoring)) #define TTYADD(c) if (!(SYNCHing||flushout)) { \ *ttyoring.supply = c; \ ring_supplied(&ttyoring, 1); \ } #define TTYBYTES() (ring_full_count(&ttyoring)) #define TTYROOM() (ring_empty_count(&ttyoring)) /* Various modes */ #define MODE_LOCAL_CHARS(m) ((m)&(MODE_EDIT|MODE_TRAPSIG)) #define MODE_LOCAL_ECHO(m) ((m)&MODE_ECHO) #define MODE_COMMAND_LINE(m) ((m)==-1) #define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */ Index: head/contrib/telnet/telnet/externs.h =================================================================== --- head/contrib/telnet/telnet/externs.h (revision 87138) +++ head/contrib/telnet/telnet/externs.h (revision 87139) @@ -1,493 +1,491 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)externs.h 8.3 (Berkeley) 5/30/95 * $FreeBSD$ */ #ifndef BSD # define BSD 43 #endif /* * ucb stdio.h defines BSD as something weird */ #if defined(sun) && defined(__svr4__) #define BSD 43 #endif #ifndef USE_TERMIO # if BSD > 43 || defined(SYSV_TERMIO) # define USE_TERMIO # endif #endif #include #include -#ifndef FILIO_H #include -#else -#include -#endif -# include +#include #ifdef USE_TERMIO # ifndef VINTR -# ifdef SYSV_TERMIO -# include -# else -# include -# define termio termios -# endif +# include # endif +# define termio termios #endif #if defined(NO_CC_T) || !defined(USE_TERMIO) # if !defined(USE_TERMIO) typedef char cc_t; # else typedef unsigned char cc_t; # endif #endif -#ifndef NO_STRING_H #include -#else -#include -#endif #if defined(IPSEC) #include #if defined(IPSEC_POLICY_IPSEC) extern char *ipsec_policy_in; extern char *ipsec_policy_out; #endif #endif #ifndef _POSIX_VDISABLE # ifdef sun # include /* pick up VDISABLE definition, mayby */ # endif # ifdef VDISABLE # define _POSIX_VDISABLE VDISABLE # else # define _POSIX_VDISABLE ((cc_t)'\377') # endif #endif #define SUBBUFSIZE 256 #if !defined(P) # ifdef __STDC__ # define P(x) x # else # define P(x) () # endif #endif extern int autologin, /* Autologin enabled */ skiprc, /* Don't process the ~/.telnetrc file */ eight, /* use eight bit mode (binary in and/or out */ family, /* address family of peer */ flushout, /* flush output */ connected, /* Are we connected to the other side? */ globalmode, /* Mode tty should be in */ - In3270, /* Are we in 3270 mode? */ telnetport, /* Are we connected to the telnet port? */ localflow, /* Flow control handled locally */ restartany, /* If flow control, restart output on any character */ localchars, /* we recognize interrupt/quit */ donelclchars, /* the user has set "localchars" */ showoptions, net, /* Network file descriptor */ tin, /* Terminal input file descriptor */ tout, /* Terminal output file descriptor */ crlf, /* Should '\r' be mapped to (or )? */ autoflush, /* flush output when interrupting? */ autosynch, /* send interrupt characters with SYNCH? */ SYNCHing, /* Is the stream in telnet SYNCH mode? */ donebinarytoggle, /* the user has put us in binary */ dontlecho, /* do we suppress local echoing right now? */ crmod, netdata, /* Print out network data flow */ prettydump, /* Print "netdata" output in user readable format */ -#if defined(unix) -#if defined(TN3270) - cursesdata, /* Print out curses data flow */ - apitrace, /* Trace API transactions */ -#endif /* defined(TN3270) */ termdata, /* Print out terminal data flow */ -#endif /* defined(unix) */ debug, /* Debug level */ doaddrlookup, /* do a reverse lookup? */ clienteof; /* Client received EOF */ extern cc_t escape; /* Escape to command mode */ extern cc_t rlogin; /* Rlogin mode escape character */ #ifdef KLUDGELINEMODE extern cc_t echoc; /* Toggle local echoing */ #endif extern char *prompt; /* Prompt for command. */ extern char doopt[], dont[], will[], wont[], options[], /* All the little options */ *hostname; /* Who are we connected to? */ #ifdef ENCRYPTION extern void (*encrypt_output) P((unsigned char *, int)); extern int (*decrypt_input) P((int)); #endif /* ENCRYPTION */ /* * We keep track of each side of the option negotiation. */ #define MY_STATE_WILL 0x01 #define MY_WANT_STATE_WILL 0x02 #define MY_STATE_DO 0x04 #define MY_WANT_STATE_DO 0x08 /* * Macros to check the current state of things */ #define my_state_is_do(opt) (options[opt]&MY_STATE_DO) #define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) #define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) #define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) #define my_state_is_dont(opt) (!my_state_is_do(opt)) #define my_state_is_wont(opt) (!my_state_is_will(opt)) #define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) #define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) #define set_my_state_do(opt) {options[opt] |= MY_STATE_DO;} #define set_my_state_will(opt) {options[opt] |= MY_STATE_WILL;} #define set_my_want_state_do(opt) {options[opt] |= MY_WANT_STATE_DO;} #define set_my_want_state_will(opt) {options[opt] |= MY_WANT_STATE_WILL;} #define set_my_state_dont(opt) {options[opt] &= ~MY_STATE_DO;} #define set_my_state_wont(opt) {options[opt] &= ~MY_STATE_WILL;} #define set_my_want_state_dont(opt) {options[opt] &= ~MY_WANT_STATE_DO;} #define set_my_want_state_wont(opt) {options[opt] &= ~MY_WANT_STATE_WILL;} /* * Make everything symetrical */ #define HIS_STATE_WILL MY_STATE_DO #define HIS_WANT_STATE_WILL MY_WANT_STATE_DO #define HIS_STATE_DO MY_STATE_WILL #define HIS_WANT_STATE_DO MY_WANT_STATE_WILL #define his_state_is_do my_state_is_will #define his_state_is_will my_state_is_do #define his_want_state_is_do my_want_state_is_will #define his_want_state_is_will my_want_state_is_do #define his_state_is_dont my_state_is_wont #define his_state_is_wont my_state_is_dont #define his_want_state_is_dont my_want_state_is_wont #define his_want_state_is_wont my_want_state_is_dont #define set_his_state_do set_my_state_will #define set_his_state_will set_my_state_do #define set_his_want_state_do set_my_want_state_will #define set_his_want_state_will set_my_want_state_do #define set_his_state_dont set_my_state_wont #define set_his_state_wont set_my_state_dont #define set_his_want_state_dont set_my_want_state_wont #define set_his_want_state_wont set_my_want_state_dont +#if defined(USE_TERMIO) +#define SIG_FUNC_RET void +#else +#define SIG_FUNC_RET int +#endif +#ifdef SIGINFO +extern SIG_FUNC_RET + ayt_status P((void)); +#endif + extern FILE *NetTrace; /* Where debugging output goes */ extern unsigned char NetTraceFile[]; /* Name of file where debugging output goes */ extern void SetNetTrace P((char *)); /* Function to change where debugging goes */ extern jmp_buf peerdied, toplevel; /* For error conditions. */ extern void - command P((int, char *, int)), - Dump P((int, unsigned char *, int)), - ExitString P((char *, int)), - init_3270 P((void)), - printoption P((char *, int, int)), - printsub P((int, unsigned char *, int)), + command P((int, const char *, int)), + Dump P((char, unsigned char *, int)), + env_init P((void)), + Exit P((int)), + ExitString P((const char *, int)), + init_network P((void)), + init_sys P((void)), + init_telnet P((void)), + init_terminal P((void)), + intp P((void)), + optionstatus P((void)), + printoption P((const char *, int, int)), + printsub P((char, unsigned char *, int)), + quit P((void)), + sendabort P((void)), + sendbrk P((void)), + sendeof P((void)), + sendsusp P((void)), sendnaws P((void)), + sendayt P((void)), setconnmode P((int)), setcommandmode P((void)), + set_escape_char P((char *s)), setneturg P((void)), sys_telnet_init P((void)), telnet P((char *)), tel_enter_binary P((int)), + tel_leave_binary P((int)), TerminalFlushOutput P((void)), TerminalNewMode P((int)), TerminalRestoreState P((void)), TerminalSaveState P((void)), + TerminalDefaultChars P((void)), + TerminalSpeeds P((long *, long *)), tninit P((void)), upcase P((char *)), willoption P((int)), wontoption P((int)); extern void send_do P((int, int)), send_dont P((int, int)), send_will P((int, int)), send_wont P((int, int)); extern void lm_will P((unsigned char *, int)), lm_wont P((unsigned char *, int)), lm_do P((unsigned char *, int)), lm_dont P((unsigned char *, int)), lm_mode P((unsigned char *, int, int)); extern void slc_init P((void)), slcstate P((void)), slc_mode_export P((void)), slc_mode_import P((int)), slc_import P((int)), slc_export P((void)), slc P((unsigned char *, int)), slc_check P((void)), slc_start_reply P((void)), - slc_add_reply P((int, int, int)), + slc_add_reply P((unsigned char, unsigned char, cc_t)), slc_end_reply P((void)); extern int + getconnmode P((void)), + opt_welldefined P((const char *)), NetClose P((int)), netflush P((void)), + process_rings P((int, int, int, int, int, int)), + rlogin_susp P((void)), SetSockOpt P((int, int, int, int)), slc_update P((void)), + stilloob P((void)), telrcv P((void)), + TerminalRead P((char *, int)), TerminalWrite P((char *, int)), TerminalAutoFlush P((void)), + TerminalWindowSize P((long *, long *)), + TerminalSpecialChars P((int)), + tn P((int, char **)), ttyflush P((int)); extern void env_opt P((unsigned char *, int)), env_opt_start P((void)), env_opt_start_info P((void)), env_opt_add P((unsigned char *)), env_opt_end P((int)); extern unsigned char *env_default P((int, int)), - *env_getvalue P((unsigned char *)); + *env_getvalue P((const unsigned char *)); extern int - get_status P((void)), - dosynch P((void)); + get_status P((char *)), + dosynch P((char *)); extern cc_t *tcval P((int)); #ifndef USE_TERMIO extern struct tchars ntc; extern struct ltchars nltc; extern struct sgttyb nttyb; # define termEofChar ntc.t_eofc # define termEraseChar nttyb.sg_erase # define termFlushChar nltc.t_flushc # define termIntChar ntc.t_intrc # define termKillChar nttyb.sg_kill # define termLiteralNextChar nltc.t_lnextc # define termQuitChar ntc.t_quitc # define termSuspChar nltc.t_suspc # define termRprntChar nltc.t_rprntc # define termWerasChar nltc.t_werasc # define termStartChar ntc.t_startc # define termStopChar ntc.t_stopc # define termForw1Char ntc.t_brkc extern cc_t termForw2Char; extern cc_t termAytChar; # define termEofCharp (cc_t *)&ntc.t_eofc # define termEraseCharp (cc_t *)&nttyb.sg_erase # define termFlushCharp (cc_t *)&nltc.t_flushc # define termIntCharp (cc_t *)&ntc.t_intrc # define termKillCharp (cc_t *)&nttyb.sg_kill # define termLiteralNextCharp (cc_t *)&nltc.t_lnextc # define termQuitCharp (cc_t *)&ntc.t_quitc # define termSuspCharp (cc_t *)&nltc.t_suspc # define termRprntCharp (cc_t *)&nltc.t_rprntc # define termWerasCharp (cc_t *)&nltc.t_werasc # define termStartCharp (cc_t *)&ntc.t_startc # define termStopCharp (cc_t *)&ntc.t_stopc # define termForw1Charp (cc_t *)&ntc.t_brkc # define termForw2Charp (cc_t *)&termForw2Char # define termAytCharp (cc_t *)&termAytChar # else extern struct termio new_tc; # define termEofChar new_tc.c_cc[VEOF] # define termEraseChar new_tc.c_cc[VERASE] # define termIntChar new_tc.c_cc[VINTR] # define termKillChar new_tc.c_cc[VKILL] # define termQuitChar new_tc.c_cc[VQUIT] # ifndef VSUSP extern cc_t termSuspChar; # else # define termSuspChar new_tc.c_cc[VSUSP] # endif # if defined(VFLUSHO) && !defined(VDISCARD) # define VDISCARD VFLUSHO # endif # ifndef VDISCARD extern cc_t termFlushChar; # else # define termFlushChar new_tc.c_cc[VDISCARD] # endif # ifndef VWERASE extern cc_t termWerasChar; # else # define termWerasChar new_tc.c_cc[VWERASE] # endif # ifndef VREPRINT extern cc_t termRprntChar; # else # define termRprntChar new_tc.c_cc[VREPRINT] # endif # ifndef VLNEXT extern cc_t termLiteralNextChar; # else # define termLiteralNextChar new_tc.c_cc[VLNEXT] # endif # ifndef VSTART extern cc_t termStartChar; # else # define termStartChar new_tc.c_cc[VSTART] # endif # ifndef VSTOP extern cc_t termStopChar; # else # define termStopChar new_tc.c_cc[VSTOP] # endif # ifndef VEOL extern cc_t termForw1Char; # else # define termForw1Char new_tc.c_cc[VEOL] # endif # ifndef VEOL2 extern cc_t termForw2Char; # else # define termForw2Char new_tc.c_cc[VEOL] # endif # ifndef VSTATUS extern cc_t termAytChar; #else # define termAytChar new_tc.c_cc[VSTATUS] #endif # if defined(__STDC__) # define termEofCharp &termEofChar # define termEraseCharp &termEraseChar # define termIntCharp &termIntChar # define termKillCharp &termKillChar # define termQuitCharp &termQuitChar # define termSuspCharp &termSuspChar # define termFlushCharp &termFlushChar # define termWerasCharp &termWerasChar # define termRprntCharp &termRprntChar # define termLiteralNextCharp &termLiteralNextChar # define termStartCharp &termStartChar # define termStopCharp &termStopChar # define termForw1Charp &termForw1Char # define termForw2Charp &termForw2Char # define termAytCharp &termAytChar # else /* Work around a compiler bug */ # define termEofCharp 0 # define termEraseCharp 0 # define termIntCharp 0 # define termKillCharp 0 # define termQuitCharp 0 # define termSuspCharp 0 # define termFlushCharp 0 # define termWerasCharp 0 # define termRprntCharp 0 # define termLiteralNextCharp 0 # define termStartCharp 0 # define termStopCharp 0 # define termForw1Charp 0 # define termForw2Charp 0 # define termAytCharp 0 # endif #endif /* Ring buffer structures which are shared */ extern Ring netoring, netiring, ttyoring, ttyiring; -/* Tn3270 section */ -#if defined(TN3270) - -extern int - HaveInput, /* Whether an asynchronous I/O indication came in */ - noasynchtty, /* Don't do signals on I/O (SIGURG, SIGIO) */ - noasynchnet, /* Don't do signals on I/O (SIGURG, SIGIO) */ - sigiocount, /* Count of SIGIO receptions */ - shell_active; /* Subshell is active */ - -extern char - *Ibackp, /* Oldest byte of 3270 data */ - Ibuf[], /* 3270 buffer */ - *Ifrontp, /* Where next 3270 byte goes */ - tline[], - *transcom; /* Transparent command */ - -extern int - settranscom P((int, char**)); - extern void - inputAvailable P((int)); -#endif /* defined(TN3270) */ + xmitAO P((void)), + xmitEC P((void)), + xmitEL P((void)); Index: head/contrib/telnet/telnet/main.c =================================================================== --- head/contrib/telnet/telnet/main.c (revision 87138) +++ head/contrib/telnet/telnet/main.c (revision 87139) @@ -1,410 +1,377 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1988, 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); + #ifndef lint static const char sccsid[] = "@(#)main.c 8.3 (Berkeley) 5/30/95"; -#endif /* not lint */ +#endif #include #include #include #include #include #include "ring.h" #include "externs.h" #include "defines.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif /* These values need to be the same as defined in libtelnet/kerberos5.c */ /* Either define them in both places, or put in some common header file. */ #define OPTS_FORWARD_CREDS 0x00000002 #define OPTS_FORWARDABLE_CREDS 0x00000001 #if 0 #define FORWARD #endif -void init_terminal(void); -void init_network(void); -void init_telnet(void); -void init_sys(void); -void init_3270(void); - #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) char *ipsec_policy_in = NULL; char *ipsec_policy_out = NULL; #endif int family = AF_UNSPEC; /* * Initialize variables. */ - void -tninit() +void +tninit(void) { init_terminal(); init_network(); init_telnet(); init_sys(); - -#if defined(TN3270) - init_3270(); -#endif } - void -usage() +static void +usage(void) { fprintf(stderr, "Usage: %s %s%s%s%s\n", prompt, #ifdef AUTHENTICATION "[-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-c] [-d]", "\n\t[-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ", #else "[-4] [-6] [-8] [-E] [-L] [-N] [-S tos] [-c] [-d]", "\n\t[-e char] [-l user] [-n tracefile] ", #endif -#if defined(TN3270) && defined(unix) - "[-noasynch] [-noasynctty] [-noasyncnet] [-r]\n\t" - "[-s src_addr] [-t transcom] ", -#else "[-r] [-s src_addr] [-u] ", -#endif #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) "[-P policy] " #endif #ifdef ENCRYPTION "[-y] [host-name [port]]" #else /* ENCRYPTION */ "[host-name [port]]" #endif /* ENCRYPTION */ ); exit(1); } /* * main. Parse arguments, invoke the protocol or command parser. */ - int -main(argc, argv) - int argc; - char *argv[]; +int +main(int argc, char *argv[]) { int ch; char *user; char *src_addr = NULL; #ifdef FORWARD extern int forward_flags; #endif /* FORWARD */ tninit(); /* Clear out things */ TerminalSaveState(); if ((prompt = strrchr(argv[0], '/'))) ++prompt; else prompt = argv[0]; user = NULL; rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE; #ifdef AUTHENTICATION autologin = 1; #else autologin = -1; #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION encrypt_auto(1); decrypt_auto(1); #endif #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) #define IPSECOPT "P:" #else #define IPSECOPT #endif while ((ch = getopt(argc, argv, "468EKLNS:X:acde:fFk:l:n:rs:t:uxy" IPSECOPT)) != -1) #undef IPSECOPT { switch(ch) { case '4': family = AF_INET; break; #ifdef INET6 case '6': family = AF_INET6; break; #endif case '8': eight = 3; /* binary output and input */ break; case 'E': rlogin = escape = _POSIX_VDISABLE; break; case 'K': #ifdef AUTHENTICATION autologin = 0; #endif break; case 'L': eight |= 2; /* binary output only */ break; case 'N': doaddrlookup = 0; break; case 'S': { #ifdef HAS_GETTOS extern int tos; if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s%s\n", prompt, ": Bad TOS argument '", optarg, "; will try to use default TOS"); #else fprintf(stderr, "%s: Warning: -S ignored, no parsetos() support.\n", prompt); #endif } break; case 'X': #ifdef AUTHENTICATION auth_disable_name(optarg); #endif break; case 'a': #ifdef AUTHENTICATION /* It's the default now, so ignore */ #else autologin = 1; #endif break; case 'c': skiprc = 1; break; case 'd': debug = 1; break; case 'e': set_escape_char(optarg); break; case 'f': -#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) +#ifdef AUTHENTICATION +#if defined(KRB5) && defined(FORWARD) if (forward_flags & OPTS_FORWARD_CREDS) { fprintf(stderr, "%s: Only one of -f and -F allowed.\n", prompt); usage(); } forward_flags |= OPTS_FORWARD_CREDS; #else fprintf(stderr, "%s: Warning: -f ignored, no Kerberos V5 support.\n", prompt); #endif +#else + fprintf(stderr, + "%s: Warning: -f ignored, no Kerberos V5 support.\n", + prompt); +#endif break; case 'F': -#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) +#ifdef AUTHENTICATION +#if defined(KRB5) && defined(FORWARD) if (forward_flags & OPTS_FORWARD_CREDS) { fprintf(stderr, "%s: Only one of -f and -F allowed.\n", prompt); usage(); } forward_flags |= OPTS_FORWARD_CREDS; forward_flags |= OPTS_FORWARDABLE_CREDS; #else fprintf(stderr, "%s: Warning: -F ignored, no Kerberos V5 support.\n", prompt); #endif +#else + fprintf(stderr, + "%s: Warning: -F ignored, no Kerberos V5 support.\n", + prompt); +#endif break; case 'k': -#if defined(AUTHENTICATION) && defined(KRB4) +#ifdef AUTHENTICATION +#if defined(KRB4) { extern char *dest_realm, dst_realm_buf[], dst_realm_sz; dest_realm = dst_realm_buf; (void)strncpy(dest_realm, optarg, dst_realm_sz); } #else fprintf(stderr, "%s: Warning: -k ignored, no Kerberos V4 support.\n", prompt); #endif +#else + fprintf(stderr, + "%s: Warning: -k ignored, no Kerberos V4 support.\n", + prompt); +#endif break; case 'l': #ifdef AUTHENTICATION /* This is the default now, so ignore it */ #else autologin = 1; #endif user = optarg; break; case 'n': -#if defined(TN3270) && defined(unix) - /* distinguish between "-n oasynch" and "-noasynch" */ - if (argv[optind - 1][0] == '-' && argv[optind - 1][1] - == 'n' && argv[optind - 1][2] == 'o') { - if (!strcmp(optarg, "oasynch")) { - noasynchtty = 1; - noasynchnet = 1; - } else if (!strcmp(optarg, "oasynchtty")) - noasynchtty = 1; - else if (!strcmp(optarg, "oasynchnet")) - noasynchnet = 1; - } else -#endif /* defined(TN3270) && defined(unix) */ SetNetTrace(optarg); break; case 'r': rlogin = '~'; break; case 's': src_addr = optarg; break; - case 't': -#if defined(TN3270) && defined(unix) - transcom = tline; - (void)strcpy(transcom, optarg); -#else - fprintf(stderr, - "%s: Warning: -t ignored, no TN3270 support.\n", - prompt); -#endif - break; case 'u': family = AF_UNIX; break; case 'x': -#ifdef ENCRYPTION - /* This is the default now, so ignore it */ -#else +#ifndef ENCRYPTION fprintf(stderr, "%s: Warning: -x ignored, no ENCRYPT support.\n", prompt); #endif /* ENCRYPTION */ break; case 'y': #ifdef ENCRYPTION encrypt_auto(0); decrypt_auto(0); #else fprintf(stderr, "%s: Warning: -y ignored, no ENCRYPT support.\n", prompt); #endif /* ENCRYPTION */ break; #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) case 'P': if (!strncmp("in", optarg, 2)) ipsec_policy_in = strdup(optarg); else if (!strncmp("out", optarg, 3)) ipsec_policy_out = strdup(optarg); else usage(); break; #endif case '?': default: usage(); /* NOTREACHED */ } } if (autologin == -1) autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1; argc -= optind; argv += optind; if (argc) { char *args[9], **argp = args; if (argc > 2) usage(); *argp++ = prompt; if (user) { - *argp++ = "-l"; + *argp++ = strdup("-l"); *argp++ = user; } if (src_addr) { - *argp++ = "-s"; + *argp++ = strdup("-s"); *argp++ = src_addr; } *argp++ = argv[0]; /* host */ if (argc > 1) *argp++ = argv[1]; /* port */ *argp = 0; if (setjmp(toplevel) != 0) Exit(0); if (tn(argp - args, args) == 1) return (0); else return (1); } (void)setjmp(toplevel); for (;;) { -#ifdef TN3270 - if (shell_active) - shell_continue(); - else -#endif command(1, 0, 0); } return 0; } Index: head/contrib/telnet/telnet/network.c =================================================================== --- head/contrib/telnet/telnet/network.c (revision 87138) +++ head/contrib/telnet/telnet/network.c (revision 87139) @@ -1,183 +1,181 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)network.c 8.2 (Berkeley) 12/15/93"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #include #include #include #include #include #include #include "ring.h" #include "defines.h" #include "externs.h" #include "fdset.h" Ring netoring, netiring; unsigned char netobuf[2*BUFSIZ], netibuf[BUFSIZ]; /* * Initialize internal network data structures. */ - void -init_network() +void +init_network(void) { if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) { exit(1); } if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) { exit(1); } NetTrace = stdout; } /* * Check to see if any out-of-band data exists on a socket (for * Telnet "synch" processing). */ - int -stilloob() +int +stilloob(void) { - static struct timeval timeout = { 0 }; + static struct timeval timeout = { 0, 0 }; fd_set excepts; int value; do { FD_ZERO(&excepts); FD_SET(net, &excepts); value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); } while ((value == -1) && (errno == EINTR)); if (value < 0) { perror("select"); (void) quit(); /* NOTREACHED */ } if (FD_ISSET(net, &excepts)) { return 1; } else { return 0; } } /* * setneturg() * * Sets "neturg" to the current location. */ - void -setneturg() +void +setneturg(void) { ring_mark(&netoring); } /* * netflush * Send as much data as possible to the network, * handling requests for urgent data. * * The return value indicates whether we did any * useful work. */ - - int -netflush() +int +netflush(void) { - register int n, n1; + int n, n1; #ifdef ENCRYPTION if (encrypt_output) ring_encrypt(&netoring, encrypt_output); #endif /* ENCRYPTION */ if ((n1 = n = ring_full_consecutive(&netoring)) > 0) { if (!ring_at_mark(&netoring)) { n = send(net, (char *)netoring.consume, n, 0); /* normal write */ } else { /* * In 4.2 (and 4.3) systems, there is some question about * what byte in a sendOOB operation is the "OOB" data. * To make ourselves compatible, we only send ONE byte * out of band, the one WE THINK should be OOB (though * we really have more the TCP philosophy of urgent data * rather than the Unix philosophy of OOB data). */ n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */ } } if (n < 0) { if (errno != ENOBUFS && errno != EWOULDBLOCK) { setcommandmode(); perror(hostname); (void)NetClose(net); ring_clear_mark(&netoring); longjmp(peerdied, -1); /*NOTREACHED*/ } n = 0; } if (netdata && n) { Dump('>', netoring.consume, n); } if (n) { ring_consumed(&netoring, n); /* * If we sent all, and more to send, then recurse to pick * up the other half. */ if ((n1 == n) && ring_full_consecutive(&netoring)) { (void) netflush(); } return 1; } else { return 0; } } Index: head/contrib/telnet/telnet/ring.c =================================================================== --- head/contrib/telnet/telnet/ring.c (revision 87138) +++ head/contrib/telnet/telnet/ring.c (revision 87139) @@ -1,369 +1,322 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)ring.c 8.2 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ /* * This defines a structure for a ring buffer. * * The circular buffer has two parts: *((( * full: [consume, supply) * empty: [supply, consume) *]]] * */ #include #include #include #ifdef size_t #undef size_t #endif #include #ifndef FILIO_H #include #endif #include #include "ring.h" #include "general.h" /* Internal macros */ #if !defined(MIN) #define MIN(a,b) (((a)<(b))? (a):(b)) #endif /* !defined(MIN) */ #define ring_subtract(d,a,b) (((a)-(b) >= 0)? \ (a)-(b): (((a)-(b))+(d)->size)) #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ (a)+(c) : (((a)+(c))-(d)->size)) #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \ (a)-(c) : (((a)-(c))-(d)->size)) /* * The following is a clock, used to determine full, empty, etc. * * There is some trickiness here. Since the ring buffers are initialized * to ZERO on allocation, we need to make sure, when interpreting the * clock, that when the times are EQUAL, then the buffer is FULL. */ static u_long ring_clock = 0; #define ring_empty(d) (((d)->consume == (d)->supply) && \ ((d)->consumetime >= (d)->supplytime)) #define ring_full(d) (((d)->supply == (d)->consume) && \ ((d)->supplytime > (d)->consumetime)) - - - - /* Buffer state transition routines */ - int -ring_init(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; +int +ring_init(Ring *ring, unsigned char *buffer, int count) { memset((char *)ring, 0, sizeof *ring); ring->size = count; ring->supply = ring->consume = ring->bottom = buffer; ring->top = ring->bottom+ring->size; #ifdef ENCRYPTION ring->clearto = 0; #endif /* ENCRYPTION */ return 1; } /* Mark routines */ /* * Mark the most recently supplied byte. */ - void -ring_mark(ring) - Ring *ring; +void +ring_mark(Ring *ring) { ring->mark = ring_decrement(ring, ring->supply, 1); } /* * Is the ring pointing to the mark? */ - int -ring_at_mark(ring) - Ring *ring; +int +ring_at_mark(Ring *ring) { if (ring->mark == ring->consume) { return 1; } else { return 0; } } /* * Clear any mark set on the ring. */ - void -ring_clear_mark(ring) - Ring *ring; +void +ring_clear_mark(Ring *ring) { ring->mark = 0; } /* * Add characters from current segment to ring buffer. */ - void -ring_supplied(ring, count) - Ring *ring; - int count; +void +ring_supplied(Ring *ring, int count) { ring->supply = ring_increment(ring, ring->supply, count); ring->supplytime = ++ring_clock; } /* * We have just consumed "c" bytes. */ - void -ring_consumed(ring, count) - Ring *ring; - int count; +void +ring_consumed(Ring *ring, int count) { if (count == 0) /* don't update anything */ return; if (ring->mark && (ring_subtract(ring, ring->mark, ring->consume) < count)) { ring->mark = 0; } #ifdef ENCRYPTION if (ring->consume < ring->clearto && ring->clearto <= ring->consume + count) ring->clearto = 0; else if (ring->consume + count > ring->top && ring->bottom <= ring->clearto && ring->bottom + ((ring->consume + count) - ring->top)) ring->clearto = 0; #endif /* ENCRYPTION */ ring->consume = ring_increment(ring, ring->consume, count); ring->consumetime = ++ring_clock; /* * Try to encourage "ring_empty_consecutive()" to be large. */ if (ring_empty(ring)) { ring->consume = ring->supply = ring->bottom; } } /* Buffer state query routines */ /* Number of bytes that may be supplied */ - int -ring_empty_count(ring) - Ring *ring; +int +ring_empty_count(Ring *ring) { if (ring_empty(ring)) { /* if empty */ return ring->size; } else { return ring_subtract(ring, ring->consume, ring->supply); } } /* number of CONSECUTIVE bytes that may be supplied */ - int -ring_empty_consecutive(ring) - Ring *ring; +int +ring_empty_consecutive(Ring *ring) { if ((ring->consume < ring->supply) || ring_empty(ring)) { /* * if consume is "below" supply, or empty, then * return distance to the top */ return ring_subtract(ring, ring->top, ring->supply); } else { /* * else, return what we may. */ return ring_subtract(ring, ring->consume, ring->supply); } } /* Return the number of bytes that are available for consuming * (but don't give more than enough to get to cross over set mark) */ - int -ring_full_count(ring) - Ring *ring; +int +ring_full_count(Ring *ring) { if ((ring->mark == 0) || (ring->mark == ring->consume)) { if (ring_full(ring)) { return ring->size; /* nothing consumed, but full */ } else { return ring_subtract(ring, ring->supply, ring->consume); } } else { return ring_subtract(ring, ring->mark, ring->consume); } } /* * Return the number of CONSECUTIVE bytes available for consuming. * However, don't return more than enough to cross over set mark. */ - int -ring_full_consecutive(ring) - Ring *ring; +int +ring_full_consecutive(Ring *ring) { if ((ring->mark == 0) || (ring->mark == ring->consume)) { if ((ring->supply < ring->consume) || ring_full(ring)) { return ring_subtract(ring, ring->top, ring->consume); } else { return ring_subtract(ring, ring->supply, ring->consume); } } else { if (ring->mark < ring->consume) { return ring_subtract(ring, ring->top, ring->consume); } else { /* Else, distance to mark */ return ring_subtract(ring, ring->mark, ring->consume); } } } /* * Move data into the "supply" portion of of the ring buffer. */ - void -ring_supply_data(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; +void +ring_supply_data(Ring *ring, unsigned char *buffer, int count) { int i; while (count) { i = MIN(count, ring_empty_consecutive(ring)); memcpy(ring->supply, buffer, i); ring_supplied(ring, i); count -= i; buffer += i; } } -#ifdef notdef - -/* - * Move data from the "consume" portion of the ring buffer - */ - void -ring_consume_data(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; -{ - int i; - - while (count) { - i = MIN(count, ring_full_consecutive(ring)); - memcpy(buffer, ring->consume, i); - ring_consumed(ring, i); - count -= i; - buffer += i; - } -} -#endif - #ifdef ENCRYPTION - void -ring_encrypt(ring, encryptor) - Ring *ring; - void (*encryptor)(); +void +ring_encrypt(Ring *ring, void (*encryptor)(unsigned char *, int)) { unsigned char *s, *c; if (ring_empty(ring) || ring->clearto == ring->supply) return; if (!(c = ring->clearto)) c = ring->consume; s = ring->supply; if (s <= c) { (*encryptor)(c, ring->top - c); (*encryptor)(ring->bottom, s - ring->bottom); } else (*encryptor)(c, s - c); ring->clearto = ring->supply; } void ring_clearto(ring) Ring *ring; { if (!ring_empty(ring)) ring->clearto = ring->supply; else ring->clearto = 0; } #endif /* ENCRYPTION */ Index: head/contrib/telnet/telnet/ring.h =================================================================== --- head/contrib/telnet/telnet/ring.h (revision 87138) +++ head/contrib/telnet/telnet/ring.h (revision 87139) @@ -1,106 +1,107 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ring.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #if defined(P) # undef P #endif #if defined(__STDC__) || defined(LINT_ARGS) # define P(x) x #else # define P(x) () #endif /* * This defines a structure for a ring buffer. * * The circular buffer has two parts: *((( * full: [consume, supply) * empty: [supply, consume) *]]] * */ typedef struct { unsigned char *consume, /* where data comes out of */ *supply, /* where data comes in to */ *bottom, /* lowest address in buffer */ *top, /* highest address+1 in buffer */ *mark; /* marker (user defined) */ #ifdef ENCRYPTION unsigned char *clearto; /* Data to this point is clear text */ unsigned char *encryyptedto; /* Data is encrypted to here */ #endif /* ENCRYPTION */ int size; /* size in bytes of buffer */ u_long consumetime, /* help us keep straight full, empty, etc. */ supplytime; } Ring; /* Here are some functions and macros to deal with the ring buffer */ /* Initialization routine */ extern int ring_init P((Ring *ring, unsigned char *buffer, int count)); /* Data movement routines */ extern void ring_supply_data P((Ring *ring, unsigned char *buffer, int count)); #ifdef notdef extern void ring_consume_data P((Ring *ring, unsigned char *buffer, int count)); #endif /* Buffer state transition routines */ extern void ring_supplied P((Ring *ring, int count)), ring_consumed P((Ring *ring, int count)); /* Buffer state query routines */ extern int + ring_at_mark P((Ring *)), ring_empty_count P((Ring *ring)), ring_empty_consecutive P((Ring *ring)), ring_full_count P((Ring *ring)), ring_full_consecutive P((Ring *ring)); #ifdef ENCRYPTION extern void - ring_encrypt P((Ring *ring, void (*func)())), + ring_encrypt P((Ring *ring, void (*func)(unsigned char *, int))), ring_clearto P((Ring *ring)); #endif /* ENCRYPTION */ extern void - ring_clear_mark P((Ring *)), - ring_mark P((Ring *)); + ring_clear_mark P((Ring *)), + ring_mark P((Ring *)); Index: head/contrib/telnet/telnet/sys_bsd.c =================================================================== --- head/contrib/telnet/telnet/sys_bsd.c (revision 87138) +++ head/contrib/telnet/telnet/sys_bsd.c (revision 87139) @@ -1,1244 +1,1121 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ /* * The following routines try to encapsulate what is system dependent * (at least between 4.x and dos) which is used in telnet.c. */ - -#include #include -#include #include -#include +#include #include -#include +#include +#include #include +#include #include "ring.h" - #include "fdset.h" - #include "defines.h" #include "externs.h" #include "types.h" -#if defined(USE_TERMIO) && !defined(SYSV_TERMIO) -#define SIG_FUNC_RET void -#else -#define SIG_FUNC_RET int -#endif - -#ifdef SIGINFO -extern SIG_FUNC_RET ayt_status(); -#endif - int tout, /* Output file descriptor */ tin, /* Input file descriptor */ net; #ifndef USE_TERMIO struct tchars otc = { 0 }, ntc = { 0 }; struct ltchars oltc = { 0 }, nltc = { 0 }; struct sgttyb ottyb = { 0 }, nttyb = { 0 }; int olmode = 0; # define cfgetispeed(ptr) (ptr)->sg_ispeed # define cfgetospeed(ptr) (ptr)->sg_ospeed # define old_tc ottyb #else /* USE_TERMIO */ -struct termio old_tc = { 0 }; -extern struct termio new_tc; +struct termio old_tc = { 0, 0, 0, 0, {}, 0, 0 }; # ifndef TCSANOW # ifdef TCSETS # define TCSANOW TCSETS # define TCSADRAIN TCSETSW # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) # else # ifdef TCSETA # define TCSANOW TCSETA # define TCSADRAIN TCSETAW # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) # else # define TCSANOW TIOCSETA # define TCSADRAIN TIOCSETAW # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) # endif # endif # define tcsetattr(f, a, t) ioctl(f, a, (char *)t) # define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) # ifdef CIBAUD # define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) # else # define cfgetispeed(ptr) cfgetospeed(ptr) # endif # endif /* TCSANOW */ # ifdef sysV88 # define TIOCFLUSH TC_PX_DRAIN # endif #endif /* USE_TERMIO */ static fd_set ibits, obits, xbits; +#ifdef SIGINT +static SIG_FUNC_RET intr(int); +#endif /* SIGINT */ +#ifdef SIGQUIT +static SIG_FUNC_RET intr2(int); +#endif /* SIGQUIT */ +#ifdef SIGTSTP +static SIG_FUNC_RET susp(int); +#endif /* SIGTSTP */ +#ifdef SIGINFO +static SIG_FUNC_RET ayt(int); +#endif - void -init_sys() +void +init_sys(void) { tout = fileno(stdout); tin = fileno(stdin); FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&xbits); errno = 0; } - - int -TerminalWrite(buf, n) - char *buf; - int n; +int +TerminalWrite(char *buf, int n) { return write(tout, buf, n); } - int -TerminalRead(buf, n) - char *buf; - int n; +int +TerminalRead(char *buf, int n) { return read(tin, buf, n); } /* * */ - int -TerminalAutoFlush() +int +TerminalAutoFlush(void) { #if defined(LNOFLSH) int flush; ioctl(0, TIOCLGET, (char *)&flush); return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ #else /* LNOFLSH */ return 1; #endif /* LNOFLSH */ } #ifdef KLUDGELINEMODE extern int kludgelinemode; #endif /* * TerminalSpecialChars() * * Look at an input character to see if it is a special character * and decide what to do. * * Output: * * 0 Don't add this character. * 1 Do add this character */ -extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); - - int -TerminalSpecialChars(c) - int c; +int +TerminalSpecialChars(int c) { if (c == termIntChar) { intp(); return 0; } else if (c == termQuitChar) { #ifdef KLUDGELINEMODE if (kludgelinemode) sendbrk(); else #endif sendabort(); return 0; } else if (c == termEofChar) { if (my_want_state_is_will(TELOPT_LINEMODE)) { sendeof(); return 0; } return 1; } else if (c == termSuspChar) { sendsusp(); return(0); } else if (c == termFlushChar) { xmitAO(); /* Transmit Abort Output */ return 0; } else if (!MODE_LOCAL_CHARS(globalmode)) { if (c == termKillChar) { xmitEL(); return 0; } else if (c == termEraseChar) { xmitEC(); /* Transmit Erase Character */ return 0; } } return 1; } /* * Flush output to the terminal */ - void -TerminalFlushOutput() +void +TerminalFlushOutput(void) { #ifdef TIOCFLUSH (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); #else (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); #endif } - void -TerminalSaveState() +void +TerminalSaveState(void) { #ifndef USE_TERMIO ioctl(0, TIOCGETP, (char *)&ottyb); ioctl(0, TIOCGETC, (char *)&otc); ioctl(0, TIOCGLTC, (char *)&oltc); ioctl(0, TIOCLGET, (char *)&olmode); ntc = otc; nltc = oltc; nttyb = ottyb; #else /* USE_TERMIO */ tcgetattr(0, &old_tc); new_tc = old_tc; #ifndef VDISCARD termFlushChar = CONTROL('O'); #endif #ifndef VWERASE termWerasChar = CONTROL('W'); #endif #ifndef VREPRINT termRprntChar = CONTROL('R'); #endif #ifndef VLNEXT termLiteralNextChar = CONTROL('V'); #endif #ifndef VSTART termStartChar = CONTROL('Q'); #endif #ifndef VSTOP termStopChar = CONTROL('S'); #endif #ifndef VSTATUS termAytChar = CONTROL('T'); #endif #endif /* USE_TERMIO */ } - cc_t * -tcval(func) - register int func; +cc_t * +tcval(int func) { switch(func) { case SLC_IP: return(&termIntChar); case SLC_ABORT: return(&termQuitChar); case SLC_EOF: return(&termEofChar); case SLC_EC: return(&termEraseChar); case SLC_EL: return(&termKillChar); case SLC_XON: return(&termStartChar); case SLC_XOFF: return(&termStopChar); case SLC_FORW1: return(&termForw1Char); #ifdef USE_TERMIO case SLC_FORW2: return(&termForw2Char); # ifdef VDISCARD case SLC_AO: return(&termFlushChar); # endif # ifdef VSUSP case SLC_SUSP: return(&termSuspChar); # endif # ifdef VWERASE case SLC_EW: return(&termWerasChar); # endif # ifdef VREPRINT case SLC_RP: return(&termRprntChar); # endif # ifdef VLNEXT case SLC_LNEXT: return(&termLiteralNextChar); # endif # ifdef VSTATUS case SLC_AYT: return(&termAytChar); # endif #endif case SLC_SYNCH: case SLC_BRK: case SLC_EOR: default: return((cc_t *)0); } } - void -TerminalDefaultChars() +void +TerminalDefaultChars(void) { #ifndef USE_TERMIO ntc = otc; nltc = oltc; nttyb.sg_kill = ottyb.sg_kill; nttyb.sg_erase = ottyb.sg_erase; #else /* USE_TERMIO */ memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); # ifndef VDISCARD termFlushChar = CONTROL('O'); # endif # ifndef VWERASE termWerasChar = CONTROL('W'); # endif # ifndef VREPRINT termRprntChar = CONTROL('R'); # endif # ifndef VLNEXT termLiteralNextChar = CONTROL('V'); # endif # ifndef VSTART termStartChar = CONTROL('Q'); # endif # ifndef VSTOP termStopChar = CONTROL('S'); # endif # ifndef VSTATUS termAytChar = CONTROL('T'); # endif #endif /* USE_TERMIO */ } -#ifdef notdef -void -TerminalRestoreState() -{ -} -#endif - /* * TerminalNewMode - set up terminal to a specific mode. * MODE_ECHO: do local terminal echo * MODE_FLOW: do local flow control * MODE_TRAPSIG: do local mapping to TELNET IAC sequences * MODE_EDIT: do local line editing * * Command mode: * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG * local echo * local editing * local xon/xoff * local signal mapping * * Linemode: * local/no editing * Both Linemode and Single Character mode: * local/remote echo * local/no xon/xoff * local/no signal mapping */ - - void -TerminalNewMode(f) - register int f; +void +TerminalNewMode(int f) { static int prevmode = 0; #ifndef USE_TERMIO struct tchars tc; struct ltchars ltc; struct sgttyb sb; int lmode; #else /* USE_TERMIO */ struct termio tmp_tc; #endif /* USE_TERMIO */ int onoff; int old; cc_t esc; globalmode = f&~MODE_FORCE; if (prevmode == f) return; /* * Write any outstanding data before switching modes * ttyflush() returns 0 only when there is no more data * left to write out, it returns -1 if it couldn't do * anything at all, otherwise it returns 1 + the number * of characters left to write. #ifndef USE_TERMIO * We would really like ask the kernel to wait for the output * to drain, like we can do with the TCSADRAIN, but we don't have * that option. The only ioctl that waits for the output to * drain, TIOCSETP, also flushes the input queue, which is NOT * what we want (TIOCSETP is like TCSADFLUSH). #endif */ old = ttyflush(SYNCHing|flushout); if (old < 0 || old > 1) { #ifdef USE_TERMIO tcgetattr(tin, &tmp_tc); #endif /* USE_TERMIO */ do { /* * Wait for data to drain, then flush again. */ #ifdef USE_TERMIO tcsetattr(tin, TCSADRAIN, &tmp_tc); #endif /* USE_TERMIO */ old = ttyflush(SYNCHing|flushout); } while (old < 0 || old > 1); } old = prevmode; prevmode = f&~MODE_FORCE; #ifndef USE_TERMIO sb = nttyb; tc = ntc; ltc = nltc; lmode = olmode; #else tmp_tc = new_tc; #endif if (f&MODE_ECHO) { #ifndef USE_TERMIO sb.sg_flags |= ECHO; #else tmp_tc.c_lflag |= ECHO; tmp_tc.c_oflag |= ONLCR; if (crlf) tmp_tc.c_iflag |= ICRNL; #endif } else { #ifndef USE_TERMIO sb.sg_flags &= ~ECHO; #else tmp_tc.c_lflag &= ~ECHO; tmp_tc.c_oflag &= ~ONLCR; -# ifdef notdef - if (crlf) - tmp_tc.c_iflag &= ~ICRNL; -# endif #endif } if ((f&MODE_FLOW) == 0) { #ifndef USE_TERMIO tc.t_startc = _POSIX_VDISABLE; tc.t_stopc = _POSIX_VDISABLE; #else tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ } else { if (restartany < 0) { tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ } else if (restartany > 0) { tmp_tc.c_iflag |= IXOFF|IXON|IXANY; } else { tmp_tc.c_iflag |= IXOFF|IXON; tmp_tc.c_iflag &= ~IXANY; } #endif } if ((f&MODE_TRAPSIG) == 0) { #ifndef USE_TERMIO tc.t_intrc = _POSIX_VDISABLE; tc.t_quitc = _POSIX_VDISABLE; tc.t_eofc = _POSIX_VDISABLE; ltc.t_suspc = _POSIX_VDISABLE; ltc.t_dsuspc = _POSIX_VDISABLE; #else tmp_tc.c_lflag &= ~ISIG; #endif localchars = 0; } else { #ifdef USE_TERMIO tmp_tc.c_lflag |= ISIG; #endif localchars = 1; } if (f&MODE_EDIT) { #ifndef USE_TERMIO sb.sg_flags &= ~CBREAK; sb.sg_flags |= CRMOD; #else tmp_tc.c_lflag |= ICANON; #endif } else { #ifndef USE_TERMIO sb.sg_flags |= CBREAK; if (f&MODE_ECHO) sb.sg_flags |= CRMOD; else sb.sg_flags &= ~CRMOD; #else tmp_tc.c_lflag &= ~ICANON; tmp_tc.c_iflag &= ~ICRNL; tmp_tc.c_cc[VMIN] = 1; tmp_tc.c_cc[VTIME] = 0; #endif } if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { #ifndef USE_TERMIO ltc.t_lnextc = _POSIX_VDISABLE; #else # ifdef VLNEXT tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); # endif #endif } if (f&MODE_SOFT_TAB) { #ifndef USE_TERMIO sb.sg_flags |= XTABS; #else # ifdef OXTABS tmp_tc.c_oflag |= OXTABS; # endif # ifdef TABDLY tmp_tc.c_oflag &= ~TABDLY; tmp_tc.c_oflag |= TAB3; # endif #endif } else { #ifndef USE_TERMIO sb.sg_flags &= ~XTABS; #else # ifdef OXTABS tmp_tc.c_oflag &= ~OXTABS; # endif # ifdef TABDLY tmp_tc.c_oflag &= ~TABDLY; # endif #endif } if (f&MODE_LIT_ECHO) { #ifndef USE_TERMIO lmode &= ~LCTLECH; #else # ifdef ECHOCTL tmp_tc.c_lflag &= ~ECHOCTL; # endif #endif } else { #ifndef USE_TERMIO lmode |= LCTLECH; #else # ifdef ECHOCTL tmp_tc.c_lflag |= ECHOCTL; # endif #endif } if (f == -1) { onoff = 0; } else { #ifndef USE_TERMIO if (f & MODE_OUTBIN) lmode |= LLITOUT; else lmode &= ~LLITOUT; if (f & MODE_INBIN) lmode |= LPASS8; else lmode &= ~LPASS8; #else if (f & MODE_INBIN) tmp_tc.c_iflag &= ~ISTRIP; else tmp_tc.c_iflag |= ISTRIP; if (f & MODE_OUTBIN) { tmp_tc.c_cflag &= ~(CSIZE|PARENB); tmp_tc.c_cflag |= CS8; tmp_tc.c_oflag &= ~OPOST; } else { tmp_tc.c_cflag &= ~(CSIZE|PARENB); tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); tmp_tc.c_oflag |= OPOST; } #endif onoff = 1; } if (f != -1) { -#ifdef SIGINT - SIG_FUNC_RET intr(); -#endif /* SIGINT */ -#ifdef SIGQUIT - SIG_FUNC_RET intr2(); -#endif /* SIGQUIT */ -#ifdef SIGTSTP - SIG_FUNC_RET susp(); -#endif /* SIGTSTP */ -#ifdef SIGINFO - SIG_FUNC_RET ayt(); -#endif - #ifdef SIGINT (void) signal(SIGINT, intr); #endif #ifdef SIGQUIT (void) signal(SIGQUIT, intr2); #endif #ifdef SIGTSTP (void) signal(SIGTSTP, susp); #endif /* SIGTSTP */ #ifdef SIGINFO (void) signal(SIGINFO, ayt); #endif #if defined(USE_TERMIO) && defined(NOKERNINFO) tmp_tc.c_lflag |= NOKERNINFO; #endif /* * We don't want to process ^Y here. It's just another * character that we'll pass on to the back end. It has * to process it because it will be processed when the * user attempts to read it, not when we send it. */ #ifndef USE_TERMIO ltc.t_dsuspc = _POSIX_VDISABLE; #else # ifdef VDSUSP tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); # endif #endif #ifdef USE_TERMIO /* * If the VEOL character is already set, then use VEOL2, * otherwise use VEOL. */ esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; if ((tmp_tc.c_cc[VEOL] != esc) # ifdef VEOL2 && (tmp_tc.c_cc[VEOL2] != esc) # endif ) { if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) tmp_tc.c_cc[VEOL] = esc; # ifdef VEOL2 else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) tmp_tc.c_cc[VEOL2] = esc; # endif } #else if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) tc.t_brkc = esc; #endif } else { #ifdef SIGINFO - SIG_FUNC_RET ayt_status(); - - (void) signal(SIGINFO, ayt_status); + (void) signal(SIGINFO, (void (*)(int))ayt_status); #endif #ifdef SIGINT (void) signal(SIGINT, SIG_DFL); #endif #ifdef SIGQUIT (void) signal(SIGQUIT, SIG_DFL); #endif #ifdef SIGTSTP (void) signal(SIGTSTP, SIG_DFL); # ifndef SOLARIS (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); # else SOLARIS (void) sigrelse(SIGTSTP); # endif SOLARIS #endif /* SIGTSTP */ #ifndef USE_TERMIO ltc = oltc; tc = otc; sb = ottyb; lmode = olmode; #else tmp_tc = old_tc; #endif } #ifndef USE_TERMIO ioctl(tin, TIOCLSET, (char *)&lmode); ioctl(tin, TIOCSLTC, (char *)<c); ioctl(tin, TIOCSETC, (char *)&tc); ioctl(tin, TIOCSETN, (char *)&sb); #else if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) tcsetattr(tin, TCSANOW, &tmp_tc); #endif -#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) -# if !defined(sysV88) ioctl(tin, FIONBIO, (char *)&onoff); ioctl(tout, FIONBIO, (char *)&onoff); -# endif -#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ -#if defined(TN3270) - if (noasynchtty == 0) { - ioctl(tin, FIOASYNC, (char *)&onoff); - } -#endif /* defined(TN3270) */ } /* * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). */ #if B4800 != 4800 #define DECODE_BAUD #endif #ifdef DECODE_BAUD #ifndef B7200 #define B7200 B4800 #endif #ifndef B14400 #define B14400 B9600 #endif #ifndef B19200 # define B19200 B14400 #endif #ifndef B28800 #define B28800 B19200 #endif #ifndef B38400 # define B38400 B28800 #endif #ifndef B57600 #define B57600 B38400 #endif #ifndef B76800 #define B76800 B57600 #endif #ifndef B115200 #define B115200 B76800 #endif #ifndef B230400 #define B230400 B115200 #endif /* * This code assumes that the values B0, B50, B75... * are in ascending order. They do not have to be * contiguous. */ struct termspeeds { long speed; long value; } termspeeds[] = { { 0, B0 }, { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, { 230400, B230400 }, { -1, B230400 } }; #endif /* DECODE_BAUD */ - void -TerminalSpeeds(ispeed, ospeed) - long *ispeed; - long *ospeed; +void +TerminalSpeeds(long *ispeed, long *ospeed) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; #endif /* DECODE_BAUD */ - register long in, out; + long in, out; out = cfgetospeed(&old_tc); in = cfgetispeed(&old_tc); if (in == 0) in = out; #ifdef DECODE_BAUD tp = termspeeds; while ((tp->speed != -1) && (tp->value < in)) tp++; *ispeed = tp->speed; tp = termspeeds; while ((tp->speed != -1) && (tp->value < out)) tp++; *ospeed = tp->speed; #else /* DECODE_BAUD */ *ispeed = in; *ospeed = out; #endif /* DECODE_BAUD */ } - int -TerminalWindowSize(rows, cols) - long *rows, *cols; +int +TerminalWindowSize(long *rows, long *cols) { #ifdef TIOCGWINSZ struct winsize ws; if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { *rows = ws.ws_row; *cols = ws.ws_col; return 1; } #endif /* TIOCGWINSZ */ return 0; } - int -NetClose(fd) - int fd; +int +NetClose(int fd) { return close(fd); } - - void -NetNonblockingIO(fd, onoff) - int fd; - int onoff; +static void +NetNonblockingIO(int fd, int onoff) { ioctl(fd, FIONBIO, (char *)&onoff); } -#if defined(TN3270) - void -NetSigIO(fd, onoff) - int fd; - int onoff; -{ - ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ -} - - void -NetSetPgrp(fd) - int fd; -{ - int myPid; - - myPid = getpid(); - fcntl(fd, F_SETOWN, myPid); -} -#endif /*defined(TN3270)*/ /* * Various signal handling routines. */ - /* ARGSUSED */ - SIG_FUNC_RET -deadpeer(sig) - int sig; +/* ARGSUSED */ +static SIG_FUNC_RET +deadpeer(int sig __unused) { setcommandmode(); longjmp(peerdied, -1); } - /* ARGSUSED */ - SIG_FUNC_RET -intr(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +intr(int sig __unused) { if (localchars) { intp(); return; } setcommandmode(); longjmp(toplevel, -1); } - /* ARGSUSED */ - SIG_FUNC_RET -intr2(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +intr2(int sig __unused) { if (localchars) { #ifdef KLUDGELINEMODE if (kludgelinemode) sendbrk(); else #endif sendabort(); return; } } #ifdef SIGTSTP - /* ARGSUSED */ - SIG_FUNC_RET -susp(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +susp(int sig __unused) { if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) return; if (localchars) sendsusp(); } #endif #ifdef SIGWINCH - /* ARGSUSED */ - SIG_FUNC_RET -sendwin(sig) - int sig; +/* ARGSUSED */ +static SIG_FUNC_RET +sendwin(int sig __unused) { if (connected) { sendnaws(); } } #endif #ifdef SIGINFO - /* ARGSUSED */ - SIG_FUNC_RET -ayt(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +ayt(int sig __unused) { if (connected) sendayt(); else ayt_status(); } #endif - void -sys_telnet_init() +void +sys_telnet_init(void) { (void) signal(SIGINT, intr); (void) signal(SIGQUIT, intr2); (void) signal(SIGPIPE, deadpeer); #ifdef SIGWINCH (void) signal(SIGWINCH, sendwin); #endif #ifdef SIGTSTP (void) signal(SIGTSTP, susp); #endif #ifdef SIGINFO (void) signal(SIGINFO, ayt); #endif setconnmode(0); NetNonblockingIO(net, 1); -#if defined(TN3270) - if (noasynchnet == 0) { /* DBX can't handle! */ - NetSigIO(net, 1); - NetSetPgrp(net); - } -#endif /* defined(TN3270) */ - #if defined(SO_OOBINLINE) if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { perror("SetSockOpt"); } #endif /* defined(SO_OOBINLINE) */ } /* * Process rings - * * This routine tries to fill up/empty our various rings. * * The parameter specifies whether this is a poll operation, * or a block-until-something-happens operation. * * The return value is 1 if something happened, 0 if not. */ - int -process_rings(netin, netout, netex, ttyin, ttyout, poll) - int poll; /* If 0, then block until something to do */ +int +process_rings(int netin, int netout, int netex, int ttyin, int ttyout, int poll) { - register int c; - /* One wants to be a bit careful about setting returnValue - * to one, since a one implies we did some useful work, - * and therefore probably won't be called to block next - * time (TN3270 mode only). - */ + int c; int returnValue = 0; - static struct timeval TimeValue = { 0 }; + static struct timeval TimeValue = { 0, 0 }; if (netout) { FD_SET(net, &obits); } if (ttyout) { FD_SET(tout, &obits); } -#if defined(TN3270) if (ttyin) { FD_SET(tin, &ibits); } -#else /* defined(TN3270) */ - if (ttyin) { - FD_SET(tin, &ibits); - } -#endif /* defined(TN3270) */ -#if defined(TN3270) if (netin) { FD_SET(net, &ibits); } -# else /* !defined(TN3270) */ - if (netin) { - FD_SET(net, &ibits); - } -# endif /* !defined(TN3270) */ if (netex) { FD_SET(net, &xbits); } if ((c = select(16, &ibits, &obits, &xbits, (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { if (c == -1) { /* * we can get EINTR if we are in line mode, * and the user does an escape (TSTP), or * some other signal generator. */ if (errno == EINTR) { return 0; } -# if defined(TN3270) - /* - * we can get EBADF if we were in transparent - * mode, and the transcom process died. - */ - if (errno == EBADF) { - /* - * zero the bits (even though kernel does it) - * to make sure we are selecting on the right - * ones. - */ - FD_ZERO(&ibits); - FD_ZERO(&obits); - FD_ZERO(&xbits); - return 0; - } -# endif /* defined(TN3270) */ /* I don't like this, does it ever happen? */ printf("sleep(5) from telnet, after select: %s\r\n", strerror(errno)); sleep(5); } return 0; } /* * Any urgent data? */ if (FD_ISSET(net, &xbits)) { FD_CLR(net, &xbits); SYNCHing = 1; (void) ttyflush(1); /* flush already enqueued data */ } /* * Something to read from the network... */ if (FD_ISSET(net, &ibits)) { int canread; FD_CLR(net, &ibits); canread = ring_empty_consecutive(&netiring); #if !defined(SO_OOBINLINE) /* * In 4.2 (and some early 4.3) systems, the * OOB indication and data handling in the kernel * is such that if two separate TCP Urgent requests * come in, one byte of TCP data will be overlaid. * This is fatal for Telnet, but we try to live * with it. * * In addition, in 4.2 (and...), a special protocol * is needed to pick up the TCP Urgent data in * the correct sequence. * * What we do is: if we think we are in urgent * mode, we look to see if we are "at the mark". * If we are, we do an OOB receive. If we run * this twice, we will do the OOB receive twice, * but the second will fail, since the second * time we were "at the mark", but there wasn't * any data there (the kernel doesn't reset * "at the mark" until we do a normal read). * Once we've read the OOB data, we go ahead * and do normal reads. * * There is also another problem, which is that * since the OOB byte we read doesn't put us * out of OOB state, and since that byte is most * likely the TELNET DM (data mark), we would * stay in the TELNET SYNCH (SYNCHing) state. * So, clocks to the rescue. If we've "just" * received a DM, then we test for the * presence of OOB data when the receive OOB * fails (and AFTER we did the normal mode read * to clear "at the mark"). */ if (SYNCHing) { int atmark; static int bogus_oob = 0, first = 1; ioctl(net, SIOCATMARK, (char *)&atmark); if (atmark) { c = recv(net, netiring.supply, canread, MSG_OOB); if ((c == -1) && (errno == EINVAL)) { c = recv(net, netiring.supply, canread, 0); if (clocks.didnetreceive < clocks.gotDM) { SYNCHing = stilloob(net); } } else if (first && c > 0) { /* * Bogosity check. Systems based on 4.2BSD * do not return an error if you do a second * recv(MSG_OOB). So, we do one. If it * succeeds and returns exactly the same * data, then assume that we are running * on a broken system and set the bogus_oob * flag. (If the data was different, then * we probably got some valid new data, so * increment the count...) */ int i; i = recv(net, netiring.supply + c, canread - c, MSG_OOB); if (i == c && memcmp(netiring.supply, netiring.supply + c, i) == 0) { bogus_oob = 1; first = 0; } else if (i < 0) { bogus_oob = 0; first = 0; } else c += i; } if (bogus_oob && c > 0) { int i; /* * Bogosity. We have to do the read * to clear the atmark to get out of * an infinate loop. */ i = read(net, netiring.supply + c, canread - c); if (i > 0) c += i; } } else { c = recv(net, netiring.supply, canread, 0); } } else { c = recv(net, netiring.supply, canread, 0); } settimer(didnetreceive); #else /* !defined(SO_OOBINLINE) */ c = recv(net, (char *)netiring.supply, canread, 0); #endif /* !defined(SO_OOBINLINE) */ if (c < 0 && errno == EWOULDBLOCK) { c = 0; } else if (c <= 0) { return -1; } if (netdata) { Dump('<', netiring.supply, c); } if (c) ring_supplied(&netiring, c); returnValue = 1; } /* * Something to read from the tty... */ if (FD_ISSET(tin, &ibits)) { FD_CLR(tin, &ibits); c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); if (c < 0 && errno == EIO) c = 0; if (c < 0 && errno == EWOULDBLOCK) { c = 0; } else { /* EOF detection for line mode!!!! */ if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { /* must be an EOF... */ *ttyiring.supply = termEofChar; c = 1; } if (c <= 0) { return -1; } if (termdata) { Dump('<', ttyiring.supply, c); } ring_supplied(&ttyiring, c); } returnValue = 1; /* did something useful */ } if (FD_ISSET(net, &obits)) { FD_CLR(net, &obits); returnValue |= netflush(); } if (FD_ISSET(tout, &obits)) { FD_CLR(tout, &obits); returnValue |= (ttyflush(SYNCHing|flushout) > 0); } return returnValue; } Index: head/contrib/telnet/telnet/telnet.c =================================================================== --- head/contrib/telnet/telnet/telnet.c (revision 87138) +++ head/contrib/telnet/telnet/telnet.c (revision 87139) @@ -1,2671 +1,2378 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #include -#if defined(unix) -#include /* By the way, we need to include curses.h before telnet.h since, * among other things, telnet.h #defines 'DO', which is a variable * declared in curses.h. */ -#endif /* defined(unix) */ -#include #include +#include +#include #include +#include #include +#include #include "ring.h" #include "defines.h" #include "externs.h" #include "types.h" #include "general.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif #include #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x)) static unsigned char subbuffer[SUBBUFSIZE], *subpointer, *subend; /* buffer for sub-options */ #define SB_CLEAR() subpointer = subbuffer; #define SB_TERM() { subend = subpointer; SB_CLEAR(); } #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ *subpointer++ = (c); \ } #define SB_GET() ((*subpointer++)&0xff) #define SB_PEEK() ((*subpointer)&0xff) #define SB_EOF() (subpointer >= subend) #define SB_LEN() (subend - subpointer) char options[256]; /* The combined options */ char do_dont_resp[256]; char will_wont_resp[256]; int eight = 0, autologin = 0, /* Autologin anyone? */ skiprc = 0, connected, showoptions, - In3270, /* Are we in 3270 mode? */ ISend, /* trying to send network data in */ debug = 0, crmod, netdata, /* Print out network data flow */ crlf, /* Should '\r' be mapped to (or )? */ -#if defined(TN3270) - noasynchtty = 0,/* User specified "-noasynch" on command line */ - noasynchnet = 0,/* User specified "-noasynch" on command line */ - askedSGA = 0, /* We have talked about suppress go ahead */ -#endif /* defined(TN3270) */ telnetport, SYNCHing, /* we are in TELNET SYNCH mode */ flushout, /* flush output */ autoflush = 0, /* flush output when interrupting? */ autosynch, /* send interrupt characters with SYNCH? */ localflow, /* we handle flow control locally */ restartany, /* if flow control enabled, restart on any character */ localchars, /* we recognize interrupt/quit */ donelclchars, /* the user has set "localchars" */ donebinarytoggle, /* the user has put us in binary */ dontlecho, /* do we suppress local echoing right now? */ globalmode, doaddrlookup = 1, /* do a reverse address lookup? */ clienteof = 0; char *prompt = 0; #ifdef ENCRYPTION char *line; /* hack around breakage in sra.c :-( !! */ #endif cc_t escape; cc_t rlogin; #ifdef KLUDGELINEMODE cc_t echoc; #endif /* * Telnet receiver states for fsm */ #define TS_DATA 0 #define TS_IAC 1 #define TS_WILL 2 #define TS_WONT 3 #define TS_DO 4 #define TS_DONT 5 #define TS_CR 6 #define TS_SB 7 /* sub-option collection */ #define TS_SE 8 /* looking for sub-option end */ static int telrcv_state; #ifdef OLD_ENVIRON unsigned char telopt_environ = TELOPT_NEW_ENVIRON; #else # define telopt_environ TELOPT_NEW_ENVIRON #endif -jmp_buf toplevel = { 0 }; +jmp_buf toplevel; jmp_buf peerdied; int flushline; int linemode; #ifdef KLUDGELINEMODE int kludgelinemode = 1; #endif +static int is_unique(char *, char **, char **); + /* * The following are some clocks used to decide how to interpret * the relationship between various variables. */ Clocks clocks; -#ifdef notdef -Modelist modelist[] = { - { "telnet command mode", COMMAND_LINE }, - { "character-at-a-time mode", 0 }, - { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, - { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, - { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, - { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, - { "3270 mode", 0 }, -}; -#endif - - /* * Initialize telnet environment. */ - void -init_telnet() +void +init_telnet(void) { env_init(); SB_CLEAR(); ClearArray(options); - connected = In3270 = ISend = localflow = donebinarytoggle = 0; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) + connected = ISend = localflow = donebinarytoggle = 0; +#ifdef AUTHENTICATION +#ifdef ENCRYPTION auth_encrypt_connect(connected); -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif +#endif restartany = -1; SYNCHing = 0; /* Don't change NetTrace */ escape = CONTROL(']'); rlogin = _POSIX_VDISABLE; #ifdef KLUDGELINEMODE echoc = CONTROL('E'); #endif flushline = 1; telrcv_state = TS_DATA; } -#ifdef notdef -#include - - /*VARARGS*/ - static void -printring(va_alist) - va_dcl -{ - va_list ap; - char buffer[100]; /* where things go */ - char *ptr; - char *format; - char *string; - Ring *ring; - int i; - - va_start(ap); - - ring = va_arg(ap, Ring *); - format = va_arg(ap, char *); - ptr = buffer; - - while ((i = *format++) != 0) { - if (i == '%') { - i = *format++; - switch (i) { - case 'c': - *ptr++ = va_arg(ap, int); - break; - case 's': - string = va_arg(ap, char *); - ring_supply_data(ring, buffer, ptr-buffer); - ring_supply_data(ring, string, strlen(string)); - ptr = buffer; - break; - case 0: - ExitString("printring: trailing %%.\n", 1); - /*NOTREACHED*/ - default: - ExitString("printring: unknown format character.\n", 1); - /*NOTREACHED*/ - } - } else { - *ptr++ = i; - } - } - ring_supply_data(ring, buffer, ptr-buffer); -} -#endif - /* * These routines are in charge of sending option negotiations * to the other side. * * The basic idea is that we send the negotiation if either side * is in disagreement as to what the current state should be. */ - void -send_do(c, init) - register int c, init; +void +send_do(int c, int init) { if (init) { if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || my_want_state_is_do(c)) return; set_my_want_state_do(c); do_dont_resp[c]++; } NET2ADD(IAC, DO); NETADD(c); printoption("SENT", DO, c); } - void -send_dont(c, init) - register int c, init; +void +send_dont(int c, int init) { if (init) { if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || my_want_state_is_dont(c)) return; set_my_want_state_dont(c); do_dont_resp[c]++; } NET2ADD(IAC, DONT); NETADD(c); printoption("SENT", DONT, c); } - void -send_will(c, init) - register int c, init; +void +send_will(int c, int init) { if (init) { if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || my_want_state_is_will(c)) return; set_my_want_state_will(c); will_wont_resp[c]++; } NET2ADD(IAC, WILL); NETADD(c); printoption("SENT", WILL, c); } - void -send_wont(c, init) - register int c, init; +void +send_wont(int c, int init) { if (init) { if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || my_want_state_is_wont(c)) return; set_my_want_state_wont(c); will_wont_resp[c]++; } NET2ADD(IAC, WONT); NETADD(c); printoption("SENT", WONT, c); } - - void -willoption(option) - int option; +void +willoption(int option) { int new_state_ok = 0; if (do_dont_resp[option]) { --do_dont_resp[option]; if (do_dont_resp[option] && my_state_is_do(option)) --do_dont_resp[option]; } if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { switch (option) { case TELOPT_ECHO: -# if defined(TN3270) - /* - * The following is a pain in the rear-end. - * Various IBM servers (some versions of Wiscnet, - * possibly Fibronics/Spartacus, and who knows who - * else) will NOT allow us to send "DO SGA" too early - * in the setup proceedings. On the other hand, - * 4.2 servers (telnetd) won't set SGA correctly. - * So, we are stuck. Empirically (but, based on - * a VERY small sample), the IBM servers don't send - * out anything about ECHO, so we postpone our sending - * "DO SGA" until we see "WILL ECHO" (which 4.2 servers - * DO send). - */ - { - if (askedSGA == 0) { - askedSGA = 1; - if (my_want_state_is_dont(TELOPT_SGA)) - send_do(TELOPT_SGA, 1); - } - } - /* Fall through */ - case TELOPT_EOR: -#endif /* defined(TN3270) */ case TELOPT_BINARY: case TELOPT_SGA: settimer(modenegotiated); /* FALL THROUGH */ case TELOPT_STATUS: -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: #endif /* ENCRYPTION */ new_state_ok = 1; break; case TELOPT_TM: if (flushout) flushout = 0; /* * Special case for TM. If we get back a WILL, * pretend we got back a WONT. */ set_my_want_state_dont(option); set_my_state_dont(option); return; /* Never reply to TM will's/wont's */ case TELOPT_LINEMODE: default: break; } if (new_state_ok) { set_my_want_state_do(option); send_do(option, 0); setconnmode(0); /* possibly set new tty mode */ } else { do_dont_resp[option]++; send_dont(option, 0); } } set_my_state_do(option); #ifdef ENCRYPTION if (option == TELOPT_ENCRYPT) encrypt_send_support(); #endif /* ENCRYPTION */ } - void -wontoption(option) - int option; +void +wontoption(int option) { if (do_dont_resp[option]) { --do_dont_resp[option]; if (do_dont_resp[option] && my_state_is_dont(option)) --do_dont_resp[option]; } if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { switch (option) { #ifdef KLUDGELINEMODE case TELOPT_SGA: if (!kludgelinemode) break; /* FALL THROUGH */ #endif case TELOPT_ECHO: settimer(modenegotiated); break; case TELOPT_TM: if (flushout) flushout = 0; set_my_want_state_dont(option); set_my_state_dont(option); return; /* Never reply to TM will's/wont's */ default: break; } set_my_want_state_dont(option); if (my_state_is_do(option)) send_dont(option, 0); setconnmode(0); /* Set new tty mode */ } else if (option == TELOPT_TM) { /* * Special case for TM. */ if (flushout) flushout = 0; set_my_want_state_dont(option); } set_my_state_dont(option); } - static void -dooption(option) - int option; +static void +dooption(int option) { int new_state_ok = 0; if (will_wont_resp[option]) { --will_wont_resp[option]; if (will_wont_resp[option] && my_state_is_will(option)) --will_wont_resp[option]; } if (will_wont_resp[option] == 0) { if (my_want_state_is_wont(option)) { switch (option) { case TELOPT_TM: /* * Special case for TM. We send a WILL, but pretend * we sent WONT. */ send_will(option, 0); set_my_want_state_wont(TELOPT_TM); set_my_state_wont(TELOPT_TM); return; -# if defined(TN3270) - case TELOPT_EOR: /* end of record */ -# endif /* defined(TN3270) */ case TELOPT_BINARY: /* binary mode */ case TELOPT_NAWS: /* window size */ case TELOPT_TSPEED: /* terminal speed */ case TELOPT_LFLOW: /* local flow control */ case TELOPT_TTYPE: /* terminal type option */ case TELOPT_SGA: /* no big deal */ #ifdef ENCRYPTION case TELOPT_ENCRYPT: /* encryption variable option */ #endif /* ENCRYPTION */ new_state_ok = 1; break; case TELOPT_NEW_ENVIRON: /* New environment variable option */ #ifdef OLD_ENVIRON if (my_state_is_will(TELOPT_OLD_ENVIRON)) send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */ goto env_common; case TELOPT_OLD_ENVIRON: /* Old environment variable option */ if (my_state_is_will(TELOPT_NEW_ENVIRON)) break; /* Don't enable if new one is in use! */ env_common: telopt_environ = option; #endif new_state_ok = 1; break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: if (autologin) new_state_ok = 1; break; #endif case TELOPT_XDISPLOC: /* X Display location */ - if (env_getvalue((unsigned char *)"DISPLAY")) + if (env_getvalue("DISPLAY")) new_state_ok = 1; break; case TELOPT_LINEMODE: #ifdef KLUDGELINEMODE kludgelinemode = 0; send_do(TELOPT_SGA, 1); #endif set_my_want_state_will(TELOPT_LINEMODE); send_will(option, 0); set_my_state_will(TELOPT_LINEMODE); slc_init(); return; case TELOPT_ECHO: /* We're never going to echo... */ default: break; } if (new_state_ok) { set_my_want_state_will(option); send_will(option, 0); setconnmode(0); /* Set new tty mode */ } else { will_wont_resp[option]++; send_wont(option, 0); } } else { /* * Handle options that need more things done after the * other side has acknowledged the option. */ switch (option) { case TELOPT_LINEMODE: #ifdef KLUDGELINEMODE kludgelinemode = 0; send_do(TELOPT_SGA, 1); #endif set_my_state_will(option); slc_init(); send_do(TELOPT_SGA, 0); return; } } } set_my_state_will(option); } - static void -dontoption(option) - int option; +static void +dontoption(int option) { if (will_wont_resp[option]) { --will_wont_resp[option]; if (will_wont_resp[option] && my_state_is_wont(option)) --will_wont_resp[option]; } if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { switch (option) { case TELOPT_LINEMODE: linemode = 0; /* put us back to the default state */ break; #ifdef OLD_ENVIRON case TELOPT_NEW_ENVIRON: /* * The new environ option wasn't recognized, try * the old one. */ send_will(TELOPT_OLD_ENVIRON, 1); telopt_environ = TELOPT_OLD_ENVIRON; break; #endif } /* we always accept a DONT */ set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); setconnmode(0); /* Set new tty mode */ } set_my_state_wont(option); } /* * Given a buffer returned by tgetent(), this routine will turn * the pipe separated list of names in the buffer into an array * of pointers to null terminated names. We toss out any bad, * duplicate, or verbose names (names with spaces). */ -static char *name_unknown = "UNKNOWN"; -static char *unknown[] = { 0, 0 }; +static const char *name_unknown = "UNKNOWN"; +static const char *unknown[] = { NULL, NULL }; - char ** -mklist(buf, name) - char *buf, *name; +static const char ** +mklist(char *buf, char *name) { - register int n; - register char c, *cp, **argvp, *cp2, **argv, **avt; + int n; + char c, *cp, **argvp, *cp2, **argv, **avt; if (name) { if (strlen(name) > 40) { name = 0; unknown[0] = name_unknown; } else { unknown[0] = name; upcase(name); } } else unknown[0] = name_unknown; /* * Count up the number of names. */ for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { if (*cp == '|') n++; } /* * Allocate an array to put the name pointers into */ argv = (char **)malloc((n+3)*sizeof(char *)); if (argv == 0) return(unknown); /* * Fill up the array of pointers to names. */ *argv = 0; argvp = argv+1; n = 0; for (cp = cp2 = buf; (c = *cp); cp++) { if (c == '|' || c == ':') { *cp++ = '\0'; /* * Skip entries that have spaces or are over 40 * characters long. If this is our environment * name, then put it up front. Otherwise, as * long as this is not a duplicate name (case * insensitive) add it to the list. */ if (n || (cp - cp2 > 41)) ; else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) *argv = cp2; else if (is_unique(cp2, argv+1, argvp)) *argvp++ = cp2; if (c == ':') break; /* * Skip multiple delimiters. Reset cp2 to * the beginning of the next name. Reset n, * the flag for names with spaces. */ while ((c = *cp) == '|') cp++; cp2 = cp; n = 0; } /* * Skip entries with spaces or non-ascii values. * Convert lower case letters to upper case. */ if ((c == ' ') || !isascii(c)) n = 1; else if (islower(c)) *cp = toupper(c); } /* * Check for an old V6 2 character name. If the second * name points to the beginning of the buffer, and is * only 2 characters long, move it to the end of the array. */ if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { --argvp; for (avt = &argv[1]; avt < argvp; avt++) *avt = *(avt+1); *argvp++ = buf; } /* * Duplicate last name, for TTYPE option, and null * terminate the array. If we didn't find a match on * our terminal name, put that name at the beginning. */ cp = *(argvp-1); *argvp++ = cp; *argvp = 0; if (*argv == 0) { if (name) *argv = name; else { --argvp; for (avt = argv; avt < argvp; avt++) *avt = *(avt+1); } } if (*argv) - return(argv); + return((const char **)argv); else return(unknown); } - int -is_unique(name, as, ae) - register char *name, **as, **ae; +static int +is_unique(char *name, char **as, char **ae) { - register char **ap; - register int n; + char **ap; + int n; n = strlen(name) + 1; for (ap = as; ap < ae; ap++) if (strncasecmp(*ap, name, n) == 0) return(0); return (1); } #ifdef TERMCAP char termbuf[1024]; - /*ARGSUSED*/ - int -setupterm(tname, fd, errp) - char *tname; - int fd, *errp; +/*ARGSUSED*/ +static int +setupterm(char *tname, int fd, int *errp) { if (tgetent(termbuf, tname) == 1) { termbuf[1023] = '\0'; if (errp) *errp = 1; return(0); } if (errp) *errp = 0; return(-1); } #else #define termbuf ttytype extern char ttytype[]; #endif int resettermname = 1; - char * -gettermname() +static const char * +gettermname(void) { char *tname; - static char **tnamep = 0; - static char **next; + static const char **tnamep = 0; + static const char **next; int err; if (resettermname) { resettermname = 0; if (tnamep && tnamep != unknown) free(tnamep); - if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && + if ((tname = env_getvalue("TERM")) && (setupterm(tname, 1, &err) == 0)) { tnamep = mklist(termbuf, tname); } else { if (tname && (strlen(tname) <= 40)) { unknown[0] = tname; upcase(tname); } else unknown[0] = name_unknown; tnamep = unknown; } next = tnamep; } if (*next == 0) next = tnamep; return(*next++); } /* * suboption() * * Look at the sub-option buffer, and try to be helpful to the other * side. * * Currently we recognize: * * Terminal type, send request. * Terminal speed (send request). * Local flow control (is request). * Linemode */ - static void -suboption() +static void +suboption(void) { unsigned char subchar; printsub('<', subbuffer, SB_LEN()+2); switch (subchar = SB_GET()) { case TELOPT_TTYPE: if (my_want_state_is_wont(TELOPT_TTYPE)) return; if (SB_EOF() || SB_GET() != TELQUAL_SEND) { return; } else { - char *name; + const char *name; unsigned char temp[50]; int len; -#if defined(TN3270) - if (tn3270_ttype()) { - return; - } -#endif /* defined(TN3270) */ name = gettermname(); len = strlen(name) + 4 + 2; if (len < NETROOM()) { - sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, + sprintf(temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE); ring_supply_data(&netoring, temp, len); printsub('>', &temp[2], len-2); } else { ExitString("No room in buffer for terminal type.\n", 1); /*NOTREACHED*/ } } break; case TELOPT_TSPEED: if (my_want_state_is_wont(TELOPT_TSPEED)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { long ospeed, ispeed; unsigned char temp[50]; int len; TerminalSpeeds(&ispeed, &ospeed); sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, TELQUAL_IS, ospeed, ispeed, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; case TELOPT_LFLOW: if (my_want_state_is_wont(TELOPT_LFLOW)) return; if (SB_EOF()) return; switch(SB_GET()) { case LFLOW_RESTART_ANY: restartany = 1; break; case LFLOW_RESTART_XON: restartany = 0; break; case LFLOW_ON: localflow = 1; break; case LFLOW_OFF: localflow = 0; break; default: return; } setcommandmode(); setconnmode(0); break; case TELOPT_LINEMODE: if (my_want_state_is_wont(TELOPT_LINEMODE)) return; if (SB_EOF()) return; switch (SB_GET()) { case WILL: lm_will(subpointer, SB_LEN()); break; case WONT: lm_wont(subpointer, SB_LEN()); break; case DO: lm_do(subpointer, SB_LEN()); break; case DONT: lm_dont(subpointer, SB_LEN()); break; case LM_SLC: slc(subpointer, SB_LEN()); break; case LM_MODE: lm_mode(subpointer, SB_LEN(), 0); break; default: break; } break; #ifdef OLD_ENVIRON case TELOPT_OLD_ENVIRON: #endif case TELOPT_NEW_ENVIRON: if (SB_EOF()) return; switch(SB_PEEK()) { case TELQUAL_IS: case TELQUAL_INFO: if (my_want_state_is_dont(subchar)) return; break; case TELQUAL_SEND: if (my_want_state_is_wont(subchar)) { return; } break; default: return; } env_opt(subpointer, SB_LEN()); break; case TELOPT_XDISPLOC: if (my_want_state_is_wont(TELOPT_XDISPLOC)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { unsigned char temp[50], *dp; int len; - if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL || + if ((dp = env_getvalue("DISPLAY")) == NULL || strlen(dp) > sizeof(temp) - 7) { /* * Something happened, we no longer have a DISPLAY * variable. Or it is too long. So, turn off the option. */ send_wont(TELOPT_XDISPLOC, 1); break; } - snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, + snprintf(temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: { if (!autologin) break; if (SB_EOF()) return; switch(SB_GET()) { case TELQUAL_IS: if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) return; auth_is(subpointer, SB_LEN()); break; case TELQUAL_SEND: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) return; auth_send(subpointer, SB_LEN()); break; case TELQUAL_REPLY: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) return; auth_reply(subpointer, SB_LEN()); break; case TELQUAL_NAME: if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) return; auth_name(subpointer, SB_LEN()); break; } } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: if (SB_EOF()) return; switch(SB_GET()) { case ENCRYPT_START: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_start(subpointer, SB_LEN()); break; case ENCRYPT_END: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_end(); break; case ENCRYPT_SUPPORT: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_support(subpointer, SB_LEN()); break; case ENCRYPT_REQSTART: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_request_start(subpointer, SB_LEN()); break; case ENCRYPT_REQEND: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; /* * We can always send an REQEND so that we cannot * get stuck encrypting. We should only get this * if we have been able to get in the correct mode * anyhow. */ encrypt_request_end(); break; case ENCRYPT_IS: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_is(subpointer, SB_LEN()); break; case ENCRYPT_REPLY: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_reply(subpointer, SB_LEN()); break; case ENCRYPT_ENC_KEYID: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_enc_keyid(subpointer, SB_LEN()); break; case ENCRYPT_DEC_KEYID: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_dec_keyid(subpointer, SB_LEN()); break; default: break; } break; #endif /* ENCRYPTION */ default: break; } } static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; - void -lm_will(cmd, len) - unsigned char *cmd; - int len; +void +lm_will(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: /* We shouldn't ever get this... */ default: str_lm[3] = DONT; str_lm[4] = cmd[0]; - if (NETROOM() > sizeof(str_lm)) { + if (NETROOM() > (int)sizeof(str_lm)) { ring_supply_data(&netoring, str_lm, sizeof(str_lm)); printsub('>', &str_lm[2], sizeof(str_lm)-2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); break; } } - void -lm_wont(cmd, len) - unsigned char *cmd; - int len; +void +lm_wont(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: /* We shouldn't ever get this... */ default: /* We are always DONT, so don't respond */ return; } } - void -lm_do(cmd, len) - unsigned char *cmd; - int len; +void +lm_do(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: default: str_lm[3] = WONT; str_lm[4] = cmd[0]; - if (NETROOM() > sizeof(str_lm)) { + if (NETROOM() > (int)sizeof(str_lm)) { ring_supply_data(&netoring, str_lm, sizeof(str_lm)); printsub('>', &str_lm[2], sizeof(str_lm)-2); } /*@*/ else printf("lm_do: not enough room in buffer\n"); break; } } - void -lm_dont(cmd, len) - unsigned char *cmd; - int len; +void +lm_dont(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: default: /* we are always WONT, so don't respond */ break; } } static unsigned char str_lm_mode[] = { IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE }; - void -lm_mode(cmd, len, init) - unsigned char *cmd; - int len, init; +void +lm_mode(unsigned char *cmd, int len, int init) { if (len != 1) return; if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) return; if (*cmd&MODE_ACK) return; linemode = *cmd&(MODE_MASK&~MODE_ACK); str_lm_mode[4] = linemode; if (!init) str_lm_mode[4] |= MODE_ACK; - if (NETROOM() > sizeof(str_lm_mode)) { + if (NETROOM() > (int)sizeof(str_lm_mode)) { ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); } /*@*/ else printf("lm_mode: not enough room in buffer\n"); setconnmode(0); /* set changed mode */ } /* * slc() * Handle special character suboption of LINEMODE. */ struct spc { cc_t val; cc_t *valp; char flags; /* Current flags & level */ char mylevel; /* Maximum level & flags */ } spc_data[NSLC+1]; #define SLC_IMPORT 0 #define SLC_EXPORT 1 #define SLC_RVALUE 2 static int slc_mode = SLC_EXPORT; - void -slc_init() +void +slc_init(void) { - register struct spc *spcp; + struct spc *spcp; localchars = 1; for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { spcp->val = 0; spcp->valp = 0; spcp->flags = spcp->mylevel = SLC_NOSUPPORT; } #define initfunc(func, flags) { \ spcp = &spc_data[func]; \ if ((spcp->valp = tcval(func))) { \ spcp->val = *spcp->valp; \ spcp->mylevel = SLC_VARIABLE|flags; \ } else { \ spcp->val = 0; \ spcp->mylevel = SLC_DEFAULT; \ } \ } initfunc(SLC_SYNCH, 0); /* No BRK */ initfunc(SLC_AO, 0); initfunc(SLC_AYT, 0); /* No EOR */ initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); initfunc(SLC_EOF, 0); #ifndef SYSV_TERMIO initfunc(SLC_SUSP, SLC_FLUSHIN); #endif initfunc(SLC_EC, 0); initfunc(SLC_EL, 0); #ifndef SYSV_TERMIO initfunc(SLC_EW, 0); initfunc(SLC_RP, 0); initfunc(SLC_LNEXT, 0); #endif initfunc(SLC_XON, 0); initfunc(SLC_XOFF, 0); #ifdef SYSV_TERMIO spc_data[SLC_XON].mylevel = SLC_CANTCHANGE; spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE; #endif initfunc(SLC_FORW1, 0); #ifdef USE_TERMIO initfunc(SLC_FORW2, 0); /* No FORW2 */ #endif initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); #undef initfunc if (slc_mode == SLC_EXPORT) slc_export(); else slc_import(1); } - void -slcstate() +void +slcstate(void) { printf("Special characters are %s values\n", slc_mode == SLC_IMPORT ? "remote default" : slc_mode == SLC_EXPORT ? "local" : "remote"); } - void -slc_mode_export() +void +slc_mode_export(void) { slc_mode = SLC_EXPORT; if (my_state_is_will(TELOPT_LINEMODE)) slc_export(); } - void -slc_mode_import(def) - int def; +void +slc_mode_import(int def) { slc_mode = def ? SLC_IMPORT : SLC_RVALUE; if (my_state_is_will(TELOPT_LINEMODE)) slc_import(def); } unsigned char slc_import_val[] = { IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE }; unsigned char slc_import_def[] = { IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE }; - void -slc_import(def) - int def; +void +slc_import(int def) { - if (NETROOM() > sizeof(slc_import_val)) { + if (NETROOM() > (int)sizeof(slc_import_val)) { if (def) { ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); } else { ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); } } /*@*/ else printf("slc_import: not enough room\n"); } - void -slc_export() +void +slc_export(void) { - register struct spc *spcp; + struct spc *spcp; TerminalDefaultChars(); slc_start_reply(); for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { if (spcp->mylevel != SLC_NOSUPPORT) { if (spcp->val == (cc_t)(_POSIX_VDISABLE)) spcp->flags = SLC_NOSUPPORT; else spcp->flags = spcp->mylevel; if (spcp->valp) spcp->val = *spcp->valp; slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); } } slc_end_reply(); (void)slc_update(); setconnmode(1); /* Make sure the character values are set */ } - void -slc(cp, len) - register unsigned char *cp; - int len; +void +slc(unsigned char *cp, int len) { - register struct spc *spcp; - register int func,level; + struct spc *spcp; + int func,level; slc_start_reply(); for (; len >= 3; len -=3, cp +=3) { func = cp[SLC_FUNC]; if (func == 0) { /* * Client side: always ignore 0 function. */ continue; } if (func > NSLC) { if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) slc_add_reply(func, SLC_NOSUPPORT, 0); continue; } spcp = &spc_data[func]; level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { continue; } if (level == (SLC_DEFAULT|SLC_ACK)) { /* * This is an error condition, the SLC_ACK * bit should never be set for the SLC_DEFAULT * level. Our best guess to recover is to * ignore the SLC_ACK bit. */ cp[SLC_FLAGS] &= ~SLC_ACK; } if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { spcp->val = (cc_t)cp[SLC_VALUE]; spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ continue; } level &= ~SLC_ACK; if (level <= (spcp->mylevel&SLC_LEVELBITS)) { spcp->flags = cp[SLC_FLAGS]|SLC_ACK; spcp->val = (cc_t)cp[SLC_VALUE]; } if (level == SLC_DEFAULT) { if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) spcp->flags = spcp->mylevel; else spcp->flags = SLC_NOSUPPORT; } slc_add_reply(func, spcp->flags, spcp->val); } slc_end_reply(); if (slc_update()) setconnmode(1); /* set the new character values */ } - void -slc_check() +void +slc_check(void) { - register struct spc *spcp; + struct spc *spcp; slc_start_reply(); for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { if (spcp->valp && spcp->val != *spcp->valp) { spcp->val = *spcp->valp; if (spcp->val == (cc_t)(_POSIX_VDISABLE)) spcp->flags = SLC_NOSUPPORT; else spcp->flags = spcp->mylevel; slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); } } slc_end_reply(); setconnmode(1); } - unsigned char slc_reply[128]; unsigned char *slc_replyp; - void -slc_start_reply() +void +slc_start_reply(void) { slc_replyp = slc_reply; *slc_replyp++ = IAC; *slc_replyp++ = SB; *slc_replyp++ = TELOPT_LINEMODE; *slc_replyp++ = LM_SLC; } - void -slc_add_reply(func, flags, value) - unsigned char func; - unsigned char flags; - cc_t value; +void +slc_add_reply(unsigned char func, unsigned char flags, cc_t value) { if ((*slc_replyp++ = func) == IAC) *slc_replyp++ = IAC; if ((*slc_replyp++ = flags) == IAC) *slc_replyp++ = IAC; if ((*slc_replyp++ = (unsigned char)value) == IAC) *slc_replyp++ = IAC; } - void -slc_end_reply() +void +slc_end_reply(void) { - register int len; + int len; *slc_replyp++ = IAC; *slc_replyp++ = SE; len = slc_replyp - slc_reply; if (len <= 6) return; if (NETROOM() > len) { ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); } /*@*/else printf("slc_end_reply: not enough room\n"); } - int -slc_update() +int +slc_update(void) { - register struct spc *spcp; + struct spc *spcp; int need_update = 0; for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { if (!(spcp->flags&SLC_ACK)) continue; spcp->flags &= ~SLC_ACK; if (spcp->valp && (*spcp->valp != spcp->val)) { *spcp->valp = spcp->val; need_update = 1; } } return(need_update); } #ifdef OLD_ENVIRON # ifdef ENV_HACK /* * Earlier version of telnet/telnetd from the BSD code had * the definitions of VALUE and VAR reversed. To ensure * maximum interoperability, we assume that the server is * an older BSD server, until proven otherwise. The newer * BSD servers should be able to handle either definition, * so it is better to use the wrong values if we don't * know what type of server it is. */ int env_auto = 1; int old_env_var = OLD_ENV_VAR; int old_env_value = OLD_ENV_VALUE; # else # define old_env_var OLD_ENV_VAR # define old_env_value OLD_ENV_VALUE # endif #endif - void -env_opt(buf, len) - register unsigned char *buf; - register int len; +void +env_opt(unsigned char *buf, int len) { - register unsigned char *ep = 0, *epc = 0; - register int i; + unsigned char *ep = 0, *epc = 0; + int i; switch(buf[0]&0xff) { case TELQUAL_SEND: env_opt_start(); if (len == 1) { env_opt_add(NULL); } else for (i = 1; i < len; i++) { switch (buf[i]&0xff) { #ifdef OLD_ENVIRON case OLD_ENV_VAR: # ifdef ENV_HACK if (telopt_environ == TELOPT_OLD_ENVIRON && env_auto) { /* Server has the same definitions */ old_env_var = OLD_ENV_VAR; old_env_value = OLD_ENV_VALUE; } /* FALL THROUGH */ # endif case OLD_ENV_VALUE: /* * Although OLD_ENV_VALUE is not legal, we will * still recognize it, just in case it is an * old server that has VAR & VALUE mixed up... */ /* FALL THROUGH */ #else case NEW_ENV_VAR: #endif case ENV_USERVAR: if (ep) { *epc = 0; env_opt_add(ep); } ep = epc = &buf[i+1]; break; case ENV_ESC: i++; /*FALL THROUGH*/ default: if (epc) *epc++ = buf[i]; break; } } if (ep) { *epc = 0; env_opt_add(ep); } env_opt_end(1); break; case TELQUAL_IS: case TELQUAL_INFO: /* Ignore for now. We shouldn't get it anyway. */ break; default: break; } } #define OPT_REPLY_SIZE 256 unsigned char *opt_reply; unsigned char *opt_replyp; unsigned char *opt_replyend; - void -env_opt_start() +void +env_opt_start(void) { if (opt_reply) opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); else opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE); if (opt_reply == NULL) { /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n"); opt_reply = opt_replyp = opt_replyend = NULL; return; } opt_replyp = opt_reply; opt_replyend = opt_reply + OPT_REPLY_SIZE; *opt_replyp++ = IAC; *opt_replyp++ = SB; *opt_replyp++ = telopt_environ; *opt_replyp++ = TELQUAL_IS; } - void -env_opt_start_info() +void +env_opt_start_info(void) { env_opt_start(); if (opt_replyp) opt_replyp[-1] = TELQUAL_INFO; } - void -env_opt_add(ep) - register unsigned char *ep; +void +env_opt_add(unsigned char *ep) { - register unsigned char *vp, c; + unsigned char *vp, c; if (opt_reply == NULL) /*XXX*/ return; /*XXX*/ if (ep == NULL || *ep == '\0') { /* Send user defined variables first. */ env_default(1, 0); while ((ep = env_default(0, 0))) env_opt_add(ep); /* Now add the list of well know variables. */ env_default(1, 1); while ((ep = env_default(0, 1))) env_opt_add(ep); return; } vp = env_getvalue(ep); if (opt_replyp + (vp ? strlen((char *)vp) : 0) + strlen((char *)ep) + 6 > opt_replyend) { - register int len; + int len; opt_replyend += OPT_REPLY_SIZE; len = opt_replyend - opt_reply; opt_reply = (unsigned char *)realloc(opt_reply, len); if (opt_reply == NULL) { /*@*/ printf("env_opt_add: realloc() failed!!!\n"); opt_reply = opt_replyp = opt_replyend = NULL; return; } opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); opt_replyend = opt_reply + len; } if (opt_welldefined(ep)) #ifdef OLD_ENVIRON if (telopt_environ == TELOPT_OLD_ENVIRON) *opt_replyp++ = old_env_var; else #endif *opt_replyp++ = NEW_ENV_VAR; else *opt_replyp++ = ENV_USERVAR; for (;;) { while ((c = *ep++)) { switch(c&0xff) { case IAC: *opt_replyp++ = IAC; break; case NEW_ENV_VAR: case NEW_ENV_VALUE: case ENV_ESC: case ENV_USERVAR: *opt_replyp++ = ENV_ESC; break; } *opt_replyp++ = c; } if ((ep = vp)) { #ifdef OLD_ENVIRON if (telopt_environ == TELOPT_OLD_ENVIRON) *opt_replyp++ = old_env_value; else #endif *opt_replyp++ = NEW_ENV_VALUE; vp = NULL; } else break; } } - int -opt_welldefined(ep) - char *ep; +int +opt_welldefined(const char *ep) { if ((strcmp(ep, "USER") == 0) || (strcmp(ep, "DISPLAY") == 0) || (strcmp(ep, "PRINTER") == 0) || (strcmp(ep, "SYSTEMTYPE") == 0) || (strcmp(ep, "JOB") == 0) || (strcmp(ep, "ACCT") == 0)) return(1); return(0); } - void -env_opt_end(emptyok) - register int emptyok; + +void +env_opt_end(int emptyok) { - register int len; + int len; len = opt_replyp - opt_reply + 2; if (emptyok || len > 6) { *opt_replyp++ = IAC; *opt_replyp++ = SE; if (NETROOM() > len) { ring_supply_data(&netoring, opt_reply, len); printsub('>', &opt_reply[2], len - 2); } /*@*/ else printf("slc_end_reply: not enough room\n"); } if (opt_reply) { free(opt_reply); opt_reply = opt_replyp = opt_replyend = NULL; } } - int -telrcv() +int +telrcv(void) { - register int c; - register int scc; - register unsigned char *sbp; + int c; + int scc; + unsigned char *sbp; int count; int returnValue = 0; scc = 0; count = 0; while (TTYROOM() > 2) { if (scc == 0) { if (count) { ring_consumed(&netiring, count); returnValue = 1; count = 0; } sbp = netiring.consume; scc = ring_full_consecutive(&netiring); if (scc == 0) { /* No more data coming in */ break; } } c = *sbp++ & 0xff, scc--; count++; #ifdef ENCRYPTION if (decrypt_input) c = (*decrypt_input)(c); #endif /* ENCRYPTION */ switch (telrcv_state) { case TS_CR: telrcv_state = TS_DATA; if (c == '\0') { break; /* Ignore \0 after CR */ } else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { TTYADD(c); break; } /* Else, fall through */ case TS_DATA: if (c == IAC) { telrcv_state = TS_IAC; break; } -# if defined(TN3270) - if (In3270) { - *Ifrontp++ = c; - while (scc > 0) { - c = *sbp++ & 0377, scc--; count++; -#ifdef ENCRYPTION - if (decrypt_input) - c = (*decrypt_input)(c); -#endif /* ENCRYPTION */ - if (c == IAC) { - telrcv_state = TS_IAC; - break; - } - *Ifrontp++ = c; - } - } else -# endif /* defined(TN3270) */ /* * The 'crmod' hack (see following) is needed * since we can't * set CRMOD on output only. * Machines like MULTICS like to send \r without * \n; since we must turn off CRMOD to get proper * input, the mapping is done here (sigh). */ if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { if (scc > 0) { c = *sbp&0xff; #ifdef ENCRYPTION if (decrypt_input) c = (*decrypt_input)(c); #endif /* ENCRYPTION */ if (c == 0) { sbp++, scc--; count++; /* a "true" CR */ TTYADD('\r'); } else if (my_want_state_is_dont(TELOPT_ECHO) && (c == '\n')) { sbp++, scc--; count++; TTYADD('\n'); } else { #ifdef ENCRYPTION if (decrypt_input) (*decrypt_input)(-1); #endif /* ENCRYPTION */ TTYADD('\r'); if (crmod) { TTYADD('\n'); } } } else { telrcv_state = TS_CR; TTYADD('\r'); if (crmod) { TTYADD('\n'); } } } else { TTYADD(c); } continue; case TS_IAC: process_iac: switch (c) { case WILL: telrcv_state = TS_WILL; continue; case WONT: telrcv_state = TS_WONT; continue; case DO: telrcv_state = TS_DO; continue; case DONT: telrcv_state = TS_DONT; continue; case DM: /* * We may have missed an urgent notification, * so make sure we flush whatever is in the * buffer currently. */ printoption("RCVD", IAC, DM); SYNCHing = 1; (void) ttyflush(1); SYNCHing = stilloob(); settimer(gotDM); break; case SB: SB_CLEAR(); telrcv_state = TS_SB; continue; -# if defined(TN3270) - case EOR: - if (In3270) { - if (Ibackp == Ifrontp) { - Ibackp = Ifrontp = Ibuf; - ISend = 0; /* should have been! */ - } else { - Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1); - ISend = 1; - } - } - printoption("RCVD", IAC, EOR); - break; -# endif /* defined(TN3270) */ - case IAC: -# if !defined(TN3270) TTYADD(IAC); -# else /* !defined(TN3270) */ - if (In3270) { - *Ifrontp++ = IAC; - } else { - TTYADD(IAC); - } -# endif /* !defined(TN3270) */ break; case NOP: case GA: default: printoption("RCVD", IAC, c); break; } telrcv_state = TS_DATA; continue; case TS_WILL: printoption("RCVD", WILL, c); willoption(c); - SetIn3270(); telrcv_state = TS_DATA; continue; case TS_WONT: printoption("RCVD", WONT, c); wontoption(c); - SetIn3270(); telrcv_state = TS_DATA; continue; case TS_DO: printoption("RCVD", DO, c); dooption(c); - SetIn3270(); if (c == TELOPT_NAWS) { sendnaws(); } else if (c == TELOPT_LFLOW) { localflow = 1; setcommandmode(); setconnmode(0); } telrcv_state = TS_DATA; continue; case TS_DONT: printoption("RCVD", DONT, c); dontoption(c); flushline = 1; setconnmode(0); /* set new tty mode (maybe) */ - SetIn3270(); telrcv_state = TS_DATA; continue; case TS_SB: if (c == IAC) { telrcv_state = TS_SE; } else { SB_ACCUM(c); } continue; case TS_SE: if (c != SE) { if (c != IAC) { /* * This is an error. We only expect to get * "IAC IAC" or "IAC SE". Several things may * have happend. An IAC was not doubled, the * IAC SE was left off, or another option got * inserted into the suboption are all possibilities. * If we assume that the IAC was not doubled, * and really the IAC SE was left off, we could * get into an infinate loop here. So, instead, * we terminate the suboption, and process the * partial suboption if we can. */ SB_ACCUM(IAC); SB_ACCUM(c); subpointer -= 2; SB_TERM(); printoption("In SUBOPTION processing, RCVD", IAC, c); suboption(); /* handle sub-option */ - SetIn3270(); telrcv_state = TS_IAC; goto process_iac; } SB_ACCUM(c); telrcv_state = TS_SB; } else { SB_ACCUM(IAC); SB_ACCUM(SE); subpointer -= 2; SB_TERM(); suboption(); /* handle sub-option */ - SetIn3270(); telrcv_state = TS_DATA; } } } if (count) ring_consumed(&netiring, count); return returnValue||count; } static int bol = 1, local = 0; - int -rlogin_susp() +int +rlogin_susp(void) { if (local) { local = 0; bol = 1; command(0, "z\n", 2); return(1); } return(0); } - static int -telsnd() +static int +telsnd(void) { int tcc; int count; int returnValue = 0; unsigned char *tbp; tcc = 0; count = 0; while (NETROOM() > 2) { - register int sc; - register int c; + int sc; + int c; if (tcc == 0) { if (count) { ring_consumed(&ttyiring, count); returnValue = 1; count = 0; } tbp = ttyiring.consume; tcc = ring_full_consecutive(&ttyiring); if (tcc == 0) { break; } } c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; if (rlogin != _POSIX_VDISABLE) { if (bol) { bol = 0; if (sc == rlogin) { local = 1; continue; } } else if (local) { local = 0; if (sc == '.' || c == termEofChar) { bol = 1; command(0, "close\n", 6); continue; } if (sc == termSuspChar) { bol = 1; command(0, "z\n", 2); continue; } if (sc == escape) { - command(0, (char *)tbp, tcc); + command(0, tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } if (sc != rlogin) { ++tcc; --tbp; --count; c = sc = rlogin; } } if ((sc == '\n') || (sc == '\r')) bol = 1; } else if (escape != _POSIX_VDISABLE && sc == escape) { /* * Double escape is a pass through of a single escape character. */ if (tcc && strip(*tbp) == escape) { tbp++; tcc--; count++; bol = 0; } else { command(0, (char *)tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } } else bol = 0; #ifdef KLUDGELINEMODE if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { if (tcc > 0 && strip(*tbp) == echoc) { tcc--; tbp++; count++; } else { dontlecho = !dontlecho; settimer(echotoggle); setconnmode(0); flushline = 1; break; } } #endif if (MODE_LOCAL_CHARS(globalmode)) { if (TerminalSpecialChars(sc) == 0) { bol = 1; break; } } if (my_want_state_is_wont(TELOPT_BINARY)) { switch (c) { case '\n': /* * If we are in CRMOD mode (\r ==> \n) * on our local machine, then probably * a newline (unix) is CRLF (TELNET). */ if (MODE_LOCAL_CHARS(globalmode)) { NETADD('\r'); } NETADD('\n'); bol = flushline = 1; break; case '\r': if (!crlf) { NET2ADD('\r', '\0'); } else { NET2ADD('\r', '\n'); } bol = flushline = 1; break; case IAC: NET2ADD(IAC, IAC); break; default: NETADD(c); break; } } else if (c == IAC) { NET2ADD(IAC, IAC); } else { NETADD(c); } } if (count) ring_consumed(&ttyiring, count); return returnValue||count; /* Non-zero if we did anything */ } /* * Scheduler() * * Try to do something. * * If we do something useful, return 1; else return 0. * */ - - int -Scheduler(block) - int block; /* should we block in the select ? */ +static int +Scheduler(int block) { /* One wants to be a bit careful about setting returnValue * to one, since a one implies we did some useful work, * and therefore probably won't be called to block next - * time (TN3270 mode only). */ int returnValue; int netin, netout, netex, ttyin, ttyout; /* Decide which rings should be processed */ netout = ring_full_count(&netoring) && (flushline || (my_want_state_is_wont(TELOPT_LINEMODE) #ifdef KLUDGELINEMODE && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)) #endif ) || my_want_state_is_will(TELOPT_BINARY)); ttyout = ring_full_count(&ttyoring); -#if defined(TN3270) - ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0); -#else /* defined(TN3270) */ ttyin = ring_empty_count(&ttyiring) && (clienteof == 0); -#endif /* defined(TN3270) */ -#if defined(TN3270) - netin = ring_empty_count(&netiring); -# else /* !defined(TN3270) */ netin = !ISend && ring_empty_count(&netiring); -# endif /* !defined(TN3270) */ netex = !SYNCHing; - /* If we have seen a signal recently, reset things */ -# if defined(TN3270) && defined(unix) - if (HaveInput) { - HaveInput = 0; - (void) signal(SIGIO, inputAvailable); - } -#endif /* defined(TN3270) && defined(unix) */ - /* Call to system code to process rings */ returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); /* Now, look at the input rings, looking for work to do. */ if (ring_full_count(&ttyiring)) { -# if defined(TN3270) - if (In3270) { - int c; - - c = DataFromTerminal(ttyiring.consume, - ring_full_consecutive(&ttyiring)); - if (c) { - returnValue = 1; - ring_consumed(&ttyiring, c); - } - } else { -# endif /* defined(TN3270) */ returnValue |= telsnd(); -# if defined(TN3270) - } -# endif /* defined(TN3270) */ } if (ring_full_count(&netiring)) { -# if !defined(TN3270) returnValue |= telrcv(); -# else /* !defined(TN3270) */ - returnValue = Push3270(); -# endif /* !defined(TN3270) */ } return returnValue; } +#ifdef AUTHENTICATION +#define __unusedhere +#else +#define __unusedhere __unused +#endif /* * Select from tty and network... */ - void -telnet(user) - char *user; +void +telnet(char *user __unusedhere) { sys_telnet_init(); -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION { static char local_host[256] = { 0 }; if (!local_host[0]) { gethostname(local_host, sizeof(local_host)); local_host[sizeof(local_host)-1] = 0; } auth_encrypt_init(local_host, hostname, "TELNET", 0); auth_encrypt_user(user); } -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ -# if !defined(TN3270) +#endif +#endif if (telnetport) { -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION if (autologin) send_will(TELOPT_AUTHENTICATION, 1); #endif #ifdef ENCRYPTION send_do(TELOPT_ENCRYPT, 1); send_will(TELOPT_ENCRYPT, 1); #endif /* ENCRYPTION */ send_do(TELOPT_SGA, 1); send_will(TELOPT_TTYPE, 1); send_will(TELOPT_NAWS, 1); send_will(TELOPT_TSPEED, 1); send_will(TELOPT_LFLOW, 1); send_will(TELOPT_LINEMODE, 1); send_will(TELOPT_NEW_ENVIRON, 1); send_do(TELOPT_STATUS, 1); - if (env_getvalue((unsigned char *)"DISPLAY")) + if (env_getvalue("DISPLAY")) send_will(TELOPT_XDISPLOC, 1); if (eight) tel_enter_binary(eight); } -# endif /* !defined(TN3270) */ -# if !defined(TN3270) for (;;) { int schedValue; while ((schedValue = Scheduler(0)) != 0) { if (schedValue == -1) { setcommandmode(); return; } } if (Scheduler(1) == -1) { setcommandmode(); return; } } -# else /* !defined(TN3270) */ - for (;;) { - int schedValue; - - while (!In3270 && !shell_active) { - if (Scheduler(1) == -1) { - setcommandmode(); - return; - } - } - - while ((schedValue = Scheduler(0)) != 0) { - if (schedValue == -1) { - setcommandmode(); - return; - } - } - /* If there is data waiting to go out to terminal, don't - * schedule any more data for the terminal. - */ - if (ring_full_count(&ttyoring)) { - schedValue = 1; - } else { - if (shell_active) { - if (shell_continue() == 0) { - ConnectScreen(); - } - } else if (In3270) { - schedValue = DoTerminalOutput(); - } - } - if (schedValue && (shell_active == 0)) { - if (Scheduler(1) == -1) { - setcommandmode(); - return; - } - } - } -# endif /* !defined(TN3270) */ } #if 0 /* XXX - this not being in is a bug */ /* * nextitem() * * Return the address of the next "item" in the TELNET data * stream. This will be the address of the next character if * the current address is a user data character, or it will * be the address of the character following the TELNET command * if the current address is a TELNET IAC ("I Am a Command") * character. */ - static char * -nextitem(current) - char *current; +static char * +nextitem(char *current) { if ((*current&0xff) != IAC) { return current+1; } switch (*(current+1)&0xff) { case DO: case DONT: case WILL: case WONT: return current+3; case SB: /* loop forever looking for the SE */ { - register char *look = current+2; + char *look = current+2; for (;;) { if ((*look++&0xff) == IAC) { if ((*look++&0xff) == SE) { return look; } } } } default: return current+2; } } #endif /* 0 */ /* * netclear() * * We are about to do a TELNET SYNCH operation. Clear * the path to the network. * * Things are a bit tricky since we may have sent the first * byte or so of a previous TELNET command into the network. * So, we have to scan the network buffer from the beginning * until we are up to where we want to be. * * A side effect of what we do, just to keep things * simple, is to clear the urgent data pointer. The principal * caller should be setting the urgent data pointer AFTER calling * us in any case. */ - static void -netclear() +static void +netclear(void) { -#if 0 /* XXX */ - register char *thisitem, *next; - char *good; -#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ - ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) - - thisitem = netobuf; - - while ((next = nextitem(thisitem)) <= netobuf.send) { - thisitem = next; - } - - /* Now, thisitem is first before/at boundary. */ - - good = netobuf; /* where the good bytes go */ - - while (netoring.add > thisitem) { - if (wewant(thisitem)) { - int length; - - next = thisitem; - do { - next = nextitem(next); - } while (wewant(next) && (nfrontp > next)); - length = next-thisitem; - memcpy(good, thisitem, length); - good += length; - thisitem = next; - } else { - thisitem = nextitem(thisitem); - } - } - -#endif /* 0 */ + /* Deleted */ } /* * These routines add various telnet commands to the data stream. */ - static void -doflush() +static void +doflush(void) { NET2ADD(IAC, DO); NETADD(TELOPT_TM); flushline = 1; flushout = 1; (void) ttyflush(1); /* Flush/drop output */ /* do printoption AFTER flush, otherwise the output gets tossed... */ printoption("SENT", DO, TELOPT_TM); } - void -xmitAO() +void +xmitAO(void) { NET2ADD(IAC, AO); printoption("SENT", IAC, AO); if (autoflush) { doflush(); } } - - void -xmitEL() +void +xmitEL(void) { NET2ADD(IAC, EL); printoption("SENT", IAC, EL); } - void -xmitEC() +void +xmitEC(void) { NET2ADD(IAC, EC); printoption("SENT", IAC, EC); } - - int -dosynch() +int +dosynch(char *ch __unused) { netclear(); /* clear the path to the network */ NETADD(IAC); setneturg(); NETADD(DM); printoption("SENT", IAC, DM); return 1; } int want_status_response = 0; - int -get_status() +int +get_status(char *ch __unused) { unsigned char tmp[16]; - register unsigned char *cp; + unsigned char *cp; if (my_want_state_is_dont(TELOPT_STATUS)) { printf("Remote side does not support STATUS option\n"); return 0; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_STATUS; *cp++ = TELQUAL_SEND; *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); } ++want_status_response; return 1; } - void -intp() +void +intp(void) { NET2ADD(IAC, IP); printoption("SENT", IAC, IP); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendbrk() +void +sendbrk(void) { NET2ADD(IAC, BREAK); printoption("SENT", IAC, BREAK); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendabort() +void +sendabort(void) { NET2ADD(IAC, ABORT); printoption("SENT", IAC, ABORT); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendsusp() +void +sendsusp(void) { NET2ADD(IAC, SUSP); printoption("SENT", IAC, SUSP); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendeof() +void +sendeof(void) { NET2ADD(IAC, xEOF); printoption("SENT", IAC, xEOF); } - void -sendayt() +void +sendayt(void) { NET2ADD(IAC, AYT); printoption("SENT", IAC, AYT); } /* * Send a window size update to the remote system. */ - void -sendnaws() +void +sendnaws(void) { long rows, cols; unsigned char tmp[16]; - register unsigned char *cp; + unsigned char *cp; if (my_state_is_wont(TELOPT_NAWS)) return; #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ return; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_NAWS; PUTSHORT(cp, cols); PUTSHORT(cp, rows); *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); } } - void -tel_enter_binary(rw) - int rw; +void +tel_enter_binary(int rw) { if (rw&1) send_do(TELOPT_BINARY, 1); if (rw&2) send_will(TELOPT_BINARY, 1); } - void -tel_leave_binary(rw) - int rw; +void +tel_leave_binary(int rw) { if (rw&1) send_dont(TELOPT_BINARY, 1); if (rw&2) send_wont(TELOPT_BINARY, 1); } Index: head/contrib/telnet/telnet/terminal.c =================================================================== --- head/contrib/telnet/telnet/terminal.c (revision 87138) +++ head/contrib/telnet/telnet/terminal.c (revision 87139) @@ -1,249 +1,240 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)terminal.c 8.2 (Berkeley) 2/16/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #include #include #include "ring.h" #include "externs.h" #include "types.h" -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif Ring ttyoring, ttyiring; unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ]; int termdata; /* Debugging flag */ #ifdef USE_TERMIO # ifndef VDISCARD cc_t termFlushChar; # endif # ifndef VLNEXT cc_t termLiteralNextChar; # endif # ifndef VSUSP cc_t termSuspChar; # endif # ifndef VWERASE cc_t termWerasChar; # endif # ifndef VREPRINT cc_t termRprntChar; # endif # ifndef VSTART cc_t termStartChar; # endif # ifndef VSTOP cc_t termStopChar; # endif # ifndef VEOL cc_t termForw1Char; # endif # ifndef VEOL2 cc_t termForw2Char; # endif # ifndef VSTATUS cc_t termAytChar; # endif #else cc_t termForw2Char; cc_t termAytChar; #endif /* * initialize the terminal data structures. */ - void -init_terminal() +void +init_terminal(void) { if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) { exit(1); } if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) { exit(1); } autoflush = TerminalAutoFlush(); } - /* * Send as much data as possible to the terminal. * * Return value: * -1: No useful work done, data waiting to go out. * 0: No data was waiting, so nothing was done. * 1: All waiting data was written out. * n: All data - n was written out. */ - - int -ttyflush(drop) - int drop; +int +ttyflush(int drop) { - register int n, n0, n1; + int n, n0, n1; n0 = ring_full_count(&ttyoring); if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) { if (drop) { TerminalFlushOutput(); /* we leave 'n' alone! */ } else { n = TerminalWrite(ttyoring.consume, n); } } if (n > 0) { if (termdata && n) { Dump('>', ttyoring.consume, n); } /* * If we wrote everything, and the full count is * larger than what we wrote, then write the * rest of the buffer. */ if (n1 == n && n0 > n) { n1 = n0 - n; if (!drop) n1 = TerminalWrite(ttyoring.bottom, n1); if (n1 > 0) n += n1; } ring_consumed(&ttyoring, n); } if (n < 0) return -1; if (n == n0) { if (n0) return -1; return 0; } return n0 - n + 1; } /* * These routines decides on what the mode should be (based on the values * of various global variables). */ - int -getconnmode() +int +getconnmode(void) { extern int linemode; int mode = 0; #ifdef KLUDGELINEMODE extern int kludgelinemode; #endif - if (In3270) - return(MODE_FLOW); - if (my_want_state_is_dont(TELOPT_ECHO)) mode |= MODE_ECHO; if (localflow) mode |= MODE_FLOW; if (my_want_state_is_will(TELOPT_BINARY)) mode |= MODE_INBIN; if (his_want_state_is_will(TELOPT_BINARY)) mode |= MODE_OUTBIN; #ifdef KLUDGELINEMODE if (kludgelinemode) { if (my_want_state_is_dont(TELOPT_SGA)) { mode |= (MODE_TRAPSIG|MODE_EDIT); if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) { mode &= ~MODE_ECHO; } } return(mode); } #endif if (my_want_state_is_will(TELOPT_LINEMODE)) mode |= linemode; return(mode); } - void -setconnmode(force) - int force; +void +setconnmode(int force) { #ifdef ENCRYPTION static int enc_passwd = 0; #endif /* ENCRYPTION */ - register int newmode; + int newmode; newmode = getconnmode()|(force?MODE_FORCE:0); TerminalNewMode(newmode); #ifdef ENCRYPTION if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) { if (my_want_state_is_will(TELOPT_ENCRYPT) && (enc_passwd == 0) && !encrypt_output) { encrypt_request_start(0, 0); enc_passwd = 1; } } else { if (enc_passwd) { encrypt_request_end(); enc_passwd = 0; } } #endif /* ENCRYPTION */ } - - void -setcommandmode() +void +setcommandmode(void) { TerminalNewMode(-1); } Index: head/contrib/telnet/telnet/utilities.c =================================================================== --- head/contrib/telnet/telnet/utilities.c (revision 87138) +++ head/contrib/telnet/telnet/utilities.c (revision 87139) @@ -1,950 +1,911 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #define TELOPTS #define TELCMDS #define SLC_NAMES #include #include #include #include #include #include #include "general.h" #include "fdset.h" #include "ring.h" #include "defines.h" #include "externs.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif FILE *NetTrace = 0; /* Not in bss, since needs to stay */ int prettydump; /* * upcase() * * Upcase (in place) the argument. */ - void -upcase(argument) - register char *argument; +void +upcase(char *argument) { - register int c; + int c; while ((c = *argument) != 0) { if (islower(c)) { *argument = toupper(c); } argument++; } } /* * SetSockOpt() * * Compensate for differences in 4.2 and 4.3 systems. */ - int -SetSockOpt(fd, level, option, yesno) - int fd, level, option, yesno; +int +SetSockOpt(int fd, int level, int option, int yesno) { -#ifndef NOT43 return setsockopt(fd, level, option, (char *)&yesno, sizeof yesno); -#else /* NOT43 */ - if (yesno == 0) { /* Can't do that in 4.2! */ - fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", - option); - return -1; - } - return setsockopt(fd, level, option, 0, 0); -#endif /* NOT43 */ } /* * The following are routines used to print out debugging information. */ unsigned char NetTraceFile[256] = "(standard output)"; - void -SetNetTrace(file) - register char *file; +void +SetNetTrace(char *file) { if (NetTrace && NetTrace != stdout) fclose(NetTrace); if (file && (strcmp(file, "-") != 0)) { NetTrace = fopen(file, "w"); if (NetTrace) { strcpy((char *)NetTraceFile, file); return; } fprintf(stderr, "Cannot open %s.\n", file); } NetTrace = stdout; strcpy((char *)NetTraceFile, "(standard output)"); } - void -Dump(direction, buffer, length) - char direction; - unsigned char *buffer; - int length; +void +Dump(char direction, unsigned char *buffer, int length) { # define BYTES_PER_LINE 32 # define min(x,y) ((x' */ - unsigned char *pointer; /* where suboption data sits */ - int length; /* length of suboption data */ +void +printsub(char direction, unsigned char *pointer, int length) { - register int i; + int i; +#ifdef AUTHENTICATION char buf[512]; +#endif extern int want_status_response; if (showoptions || direction == 0 || (want_status_response && (pointer[0] == TELOPT_STATUS))) { if (direction) { fprintf(NetTrace, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); if (length >= 3) { - register int j; + int j; i = pointer[length-2]; j = pointer[length-1]; if (i != IAC || j != SE) { fprintf(NetTrace, "(terminated by "); if (TELOPT_OK(i)) fprintf(NetTrace, "%s ", TELOPT(i)); else if (TELCMD_OK(i)) fprintf(NetTrace, "%s ", TELCMD(i)); else fprintf(NetTrace, "%d ", i); if (TELOPT_OK(j)) fprintf(NetTrace, "%s", TELOPT(j)); else if (TELCMD_OK(j)) fprintf(NetTrace, "%s", TELCMD(j)); else fprintf(NetTrace, "%d", j); fprintf(NetTrace, ", not IAC SE!) "); } } length -= 2; } if (length < 1) { fprintf(NetTrace, "(Empty suboption??\?)"); if (NetTrace == stdout) fflush(NetTrace); return; } switch (pointer[0]) { case TELOPT_TTYPE: fprintf(NetTrace, "TERMINAL-TYPE "); switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: fprintf(NetTrace, "SEND"); break; default: fprintf(NetTrace, "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_TSPEED: fprintf(NetTrace, "TERMINAL-SPEED"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, " IS "); fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); break; default: if (pointer[1] == 1) fprintf(NetTrace, " SEND"); else fprintf(NetTrace, " %d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; } break; case TELOPT_LFLOW: fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case LFLOW_OFF: fprintf(NetTrace, " OFF"); break; case LFLOW_ON: fprintf(NetTrace, " ON"); break; case LFLOW_RESTART_ANY: fprintf(NetTrace, " RESTART-ANY"); break; case LFLOW_RESTART_XON: fprintf(NetTrace, " RESTART-XON"); break; default: fprintf(NetTrace, " %d (unknown)", pointer[1]); } for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; case TELOPT_NAWS: fprintf(NetTrace, "NAWS"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } if (length == 2) { fprintf(NetTrace, " ?%d?", pointer[1]); break; } fprintf(NetTrace, " %d %d (%d)", pointer[1], pointer[2], (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); if (length == 4) { fprintf(NetTrace, " ?%d?", pointer[3]); break; } fprintf(NetTrace, " %d %d (%d)", pointer[3], pointer[4], (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); for (i = 5; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: fprintf(NetTrace, "AUTHENTICATION"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_REPLY: case TELQUAL_IS: fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? "IS" : "REPLY"); if (AUTHTYPE_NAME_OK(pointer[2])) fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); else fprintf(NetTrace, "%d ", pointer[2]); if (length < 3) { fprintf(NetTrace, "(partial suboption??\?)"); break; } fprintf(NetTrace, "%s|%s", ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); fprintf(NetTrace, "%s", buf); break; case TELQUAL_SEND: i = 2; fprintf(NetTrace, " SEND "); while (i < length) { if (AUTHTYPE_NAME_OK(pointer[i])) fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); else fprintf(NetTrace, "%d ", pointer[i]); if (++i >= length) { fprintf(NetTrace, "(partial suboption??\?)"); break; } fprintf(NetTrace, "%s|%s ", ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); ++i; } break; case TELQUAL_NAME: i = 2; fprintf(NetTrace, " NAME \""); while (i < length) putc(pointer[i++], NetTrace); putc('"', NetTrace); break; default: for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: fprintf(NetTrace, "ENCRYPT"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case ENCRYPT_START: fprintf(NetTrace, " START"); break; case ENCRYPT_END: fprintf(NetTrace, " END"); break; case ENCRYPT_REQSTART: fprintf(NetTrace, " REQUEST-START"); break; case ENCRYPT_REQEND: fprintf(NetTrace, " REQUEST-END"); break; case ENCRYPT_IS: case ENCRYPT_REPLY: fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? "IS" : "REPLY"); if (length < 3) { fprintf(NetTrace, " (partial suboption??\?)"); break; } if (ENCTYPE_NAME_OK(pointer[2])) fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); else fprintf(NetTrace, " %d (unknown)", pointer[2]); encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); fprintf(NetTrace, "%s", buf); break; case ENCRYPT_SUPPORT: i = 2; fprintf(NetTrace, " SUPPORT "); while (i < length) { if (ENCTYPE_NAME_OK(pointer[i])) fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); else fprintf(NetTrace, "%d ", pointer[i]); i++; } break; case ENCRYPT_ENC_KEYID: fprintf(NetTrace, " ENC_KEYID "); goto encommon; case ENCRYPT_DEC_KEYID: fprintf(NetTrace, " DEC_KEYID "); goto encommon; default: fprintf(NetTrace, " %d (unknown)", pointer[1]); encommon: for (i = 2; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); break; } break; #endif /* ENCRYPTION */ case TELOPT_LINEMODE: fprintf(NetTrace, "LINEMODE "); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case WILL: fprintf(NetTrace, "WILL "); goto common; case WONT: fprintf(NetTrace, "WONT "); goto common; case DO: fprintf(NetTrace, "DO "); goto common; case DONT: fprintf(NetTrace, "DONT "); common: if (length < 3) { fprintf(NetTrace, "(no option??\?)"); break; } switch (pointer[2]) { case LM_FORWARDMASK: fprintf(NetTrace, "Forward Mask"); for (i = 3; i < length; i++) fprintf(NetTrace, " %x", pointer[i]); break; default: fprintf(NetTrace, "%d (unknown)", pointer[2]); for (i = 3; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); break; } break; case LM_SLC: fprintf(NetTrace, "SLC"); for (i = 2; i < length - 2; i += 3) { if (SLC_NAME_OK(pointer[i+SLC_FUNC])) fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); else fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { case SLC_NOSUPPORT: fprintf(NetTrace, " NOSUPPORT"); break; case SLC_CANTCHANGE: fprintf(NetTrace, " CANTCHANGE"); break; case SLC_VARIABLE: fprintf(NetTrace, " VARIABLE"); break; case SLC_DEFAULT: fprintf(NetTrace, " DEFAULT"); break; } fprintf(NetTrace, "%s%s%s", pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| SLC_FLUSHOUT| SLC_LEVELBITS)) fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); if ((pointer[i+SLC_VALUE] == IAC) && (pointer[i+SLC_VALUE+1] == IAC)) i++; } for (; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; case LM_MODE: fprintf(NetTrace, "MODE "); if (length < 3) { fprintf(NetTrace, "(no mode??\?)"); break; } { char tbuf[64]; sprintf(tbuf, "%s%s%s%s%s", pointer[2]&MODE_EDIT ? "|EDIT" : "", pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", pointer[2]&MODE_ACK ? "|ACK" : ""); fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); } if (pointer[2]&~(MODE_MASK)) fprintf(NetTrace, " (0x%x)", pointer[2]); for (i = 3; i < length; i++) fprintf(NetTrace, " ?0x%x?", pointer[i]); break; default: fprintf(NetTrace, "%d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); } break; case TELOPT_STATUS: { - register char *cp; - register int j, k; + const char *cp; + int j, k; fprintf(NetTrace, "STATUS"); switch (pointer[1]) { default: if (pointer[1] == TELQUAL_SEND) fprintf(NetTrace, " SEND"); else fprintf(NetTrace, " %d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; case TELQUAL_IS: if (--want_status_response < 0) want_status_response = 0; if (NetTrace == stdout) fprintf(NetTrace, " IS\r\n"); else fprintf(NetTrace, " IS\n"); for (i = 2; i < length; i++) { switch(pointer[i]) { case DO: cp = "DO"; goto common2; case DONT: cp = "DONT"; goto common2; case WILL: cp = "WILL"; goto common2; case WONT: cp = "WONT"; goto common2; common2: i++; if (TELOPT_OK((int)pointer[i])) fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); else fprintf(NetTrace, " %s %d", cp, pointer[i]); if (NetTrace == stdout) fprintf(NetTrace, "\r\n"); else fprintf(NetTrace, "\n"); break; case SB: fprintf(NetTrace, " SB "); i++; j = k = i; while (j < length) { if (pointer[j] == SE) { if (j+1 == length) break; if (pointer[j+1] == SE) j++; else break; } pointer[k++] = pointer[j++]; } printsub(0, &pointer[i], k - i); if (i < length) { fprintf(NetTrace, " SE"); i = j; } else i = j - 1; if (NetTrace == stdout) fprintf(NetTrace, "\r\n"); else fprintf(NetTrace, "\n"); break; default: fprintf(NetTrace, " %d", pointer[i]); break; } } break; } break; } case TELOPT_XDISPLOC: fprintf(NetTrace, "X-DISPLAY-LOCATION "); switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: fprintf(NetTrace, "SEND"); break; default: fprintf(NetTrace, "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_NEW_ENVIRON: fprintf(NetTrace, "NEW-ENVIRON "); #ifdef OLD_ENVIRON goto env_common1; case TELOPT_OLD_ENVIRON: fprintf(NetTrace, "OLD-ENVIRON"); env_common1: #endif switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, "IS "); goto env_common; case TELQUAL_SEND: fprintf(NetTrace, "SEND "); goto env_common; case TELQUAL_INFO: fprintf(NetTrace, "INFO "); env_common: { - register int noquote = 2; + int noquote = 2; #if defined(ENV_HACK) && defined(OLD_ENVIRON) extern int old_env_var, old_env_value; #endif for (i = 2; i < length; i++ ) { switch (pointer[i]) { case NEW_ENV_VALUE: #ifdef OLD_ENVIRON /* case NEW_ENV_OVAR: */ if (pointer[0] == TELOPT_OLD_ENVIRON) { # ifdef ENV_HACK if (old_env_var == OLD_ENV_VALUE) fprintf(NetTrace, "\" (VALUE) " + noquote); else # endif fprintf(NetTrace, "\" VAR " + noquote); } else #endif /* OLD_ENVIRON */ fprintf(NetTrace, "\" VALUE " + noquote); noquote = 2; break; case NEW_ENV_VAR: #ifdef OLD_ENVIRON /* case OLD_ENV_VALUE: */ if (pointer[0] == TELOPT_OLD_ENVIRON) { # ifdef ENV_HACK if (old_env_value == OLD_ENV_VAR) fprintf(NetTrace, "\" (VAR) " + noquote); else # endif fprintf(NetTrace, "\" VALUE " + noquote); } else #endif /* OLD_ENVIRON */ fprintf(NetTrace, "\" VAR " + noquote); noquote = 2; break; case ENV_ESC: fprintf(NetTrace, "\" ESC " + noquote); noquote = 2; break; case ENV_USERVAR: fprintf(NetTrace, "\" USERVAR " + noquote); noquote = 2; break; default: if (isprint(pointer[i]) && pointer[i] != '"') { if (noquote) { putc('"', NetTrace); noquote = 0; } putc(pointer[i], NetTrace); } else { fprintf(NetTrace, "\" %03o " + noquote, pointer[i]); noquote = 2; } break; } } if (!noquote) putc('"', NetTrace); break; } } break; default: if (TELOPT_OK(pointer[0])) fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); else fprintf(NetTrace, "%d (unknown)", pointer[0]); for (i = 1; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); break; } if (direction) { if (NetTrace == stdout) fprintf(NetTrace, "\r\n"); else fprintf(NetTrace, "\n"); } if (NetTrace == stdout) fflush(NetTrace); } } /* EmptyTerminal - called to make sure that the terminal buffer is empty. * Note that we consider the buffer to run all the * way to the kernel (thus the select). */ - void -EmptyTerminal() +static void +EmptyTerminal(void) { -#if defined(unix) fd_set o; FD_ZERO(&o); -#endif /* defined(unix) */ if (TTYBYTES() == 0) { -#if defined(unix) FD_SET(tout, &o); (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, (struct timeval *) 0); /* wait for TTLOWAT */ -#endif /* defined(unix) */ } else { while (TTYBYTES()) { (void) ttyflush(0); -#if defined(unix) FD_SET(tout, &o); (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, (struct timeval *) 0); /* wait for TTLOWAT */ -#endif /* defined(unix) */ } } } - void -SetForExit() +static void +SetForExit(void) { setconnmode(0); -#if defined(TN3270) - if (In3270) { - Finish3270(); - } -#else /* defined(TN3270) */ do { (void)telrcv(); /* Process any incoming data */ EmptyTerminal(); } while (ring_full_count(&netiring)); /* While there is any */ -#endif /* defined(TN3270) */ setcommandmode(); fflush(stdout); fflush(stderr); -#if defined(TN3270) - if (In3270) { - StopScreen(1); - } -#endif /* defined(TN3270) */ setconnmode(0); EmptyTerminal(); /* Flush the path to the tty */ setcommandmode(); } - void -Exit(returnCode) - int returnCode; +void +Exit(int returnCode) { SetForExit(); exit(returnCode); } - void -ExitString(string, returnCode) - char *string; - int returnCode; +void +ExitString(const char *string, int returnCode) { SetForExit(); fwrite(string, 1, strlen(string), stderr); exit(returnCode); } Index: head/contrib/telnet/telnetd/authenc.c =================================================================== --- head/contrib/telnet/telnetd/authenc.c (revision 87138) +++ head/contrib/telnet/telnetd/authenc.c (revision 87139) @@ -1,93 +1,90 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)authenc.c 8.2 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION +/* Above "#ifdef"s actually "or"'ed together. XXX MarkM + */ #include "telnetd.h" #include - int -net_write(str, len) - unsigned char *str; - int len; +int +net_write(unsigned char *str, int len) { if (nfrontp + len < netobuf + BUFSIZ) { output_datalen(str, len); return(len); } return(0); } - void -net_encrypt() +void +net_encrypt(void) { #ifdef ENCRYPTION char *s = (nclearto > nbackp) ? nclearto : nbackp; if (s < nfrontp && encrypt_output) { (*encrypt_output)((unsigned char *)s, nfrontp - s); } nclearto = nfrontp; #endif /* ENCRYPTION */ } - int -telnet_spin() +int +telnet_spin(void) { ttloop(); return(0); } - char * -telnet_getenv(val) - char *val; +char * +telnet_getenv(char *val) { return(getenv(val)); } - char * -telnet_gets(prompt, result, length, echo) - char *prompt; - char *result; - int length; - int echo; +char * +telnet_gets(const char *prompt __unused, char *result __unused, int length __unused, int echo __unused) { - return((char *)0); + return(NULL); } -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif /* ENCRYPTION */ +#endif /* AUTHENTICATION */ Index: head/contrib/telnet/telnetd/ext.h =================================================================== --- head/contrib/telnet/telnetd/ext.h (revision 87138) +++ head/contrib/telnet/telnetd/ext.h (revision 87139) @@ -1,227 +1,226 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ext.h 8.2 (Berkeley) 12/15/93 * $FreeBSD$ */ /* * Telnet server variable declarations */ extern char options[256]; extern char do_dont_resp[256]; extern char will_wont_resp[256]; extern int linemode; /* linemode on/off */ #ifdef LINEMODE extern int uselinemode; /* what linemode to use (on/off) */ extern int editmode; /* edit modes in use */ extern int useeditmode; /* edit modes to use */ extern int alwayslinemode; /* command line option */ extern int lmodetype; /* Client support for linemode */ #endif /* LINEMODE */ extern int flowmode; /* current flow control state */ extern int restartany; /* restart output on any character state */ #ifdef DIAGNOSTICS extern int diagnostic; /* telnet diagnostic capabilities */ #endif /* DIAGNOSTICS */ #ifdef BFTPDAEMON extern int bftpd; /* behave as bftp daemon */ #endif /* BFTPDAEMON */ -#if defined(SecurID) -extern int require_SecurID; -#endif -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION extern int auth_level; #endif extern slcfun slctab[NSLC + 1]; /* slc mapping table */ char *terminaltype; /* * I/O data buffers, pointers, and counters. */ extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; extern char netibuf[BUFSIZ], *netip; extern char netobuf[BUFSIZ], *nfrontp, *nbackp; extern char *neturg; /* one past last bye of urgent data */ extern int pcc, ncc; extern int pty, net; extern char line[16]; extern int SYNCHing; /* we are in TELNET SYNCH mode */ #ifndef P # ifdef __STDC__ # define P(x) x # else # define P(x) () # endif #endif extern void _termstat P((void)), - add_slc P((int, int, int)), + add_slc P((char, char, cc_t)), check_slc P((void)), - change_slc P((int, int, int)), + change_slc P((char, char, cc_t)), cleanup P((int)), clientstat P((int, int, int)), - copy_termbuf P((char *, int)), + copy_termbuf P((char *, size_t)), deferslc P((void)), defer_terminit P((void)), do_opt_slc P((unsigned char *, int)), doeof P((void)), dooption P((int)), dontoption P((int)), edithost P((char *, char *)), - fatal P((int, char *)), - fatalperror P((int, char *)), + fatal P((int, const char *)), + fatalperror P((int, const char *)), get_slc_defaults P((void)), init_env P((void)), init_termbuf P((void)), interrupt P((void)), localstat P((void)), flowstat P((void)), netclear P((void)), netflush P((void)), #ifdef DIAGNOSTICS - printoption P((char *, int)), - printdata P((char *, char *, int)), - printsub P((int, unsigned char *, int)), + printoption P((const char *, int)), + printdata P((const char *, char *, int)), + printsub P((char, unsigned char *, int)), #endif + process_slc P((unsigned char, unsigned char, cc_t)), ptyflush P((void)), putchr P((int)), putf P((char *, char *)), recv_ayt P((void)), send_do P((int, int)), send_dont P((int, int)), send_slc P((void)), send_status P((void)), send_will P((int, int)), send_wont P((int, int)), sendbrk P((void)), sendsusp P((void)), set_termbuf P((void)), start_login P((char *, int, char *)), start_slc P((int)), -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION start_slave P((char *)), #else start_slave P((char *, int, char *)), #endif suboption P((void)), telrcv P((void)), ttloop P((void)), tty_binaryin P((int)), tty_binaryout P((int)); extern int end_slc P((unsigned char **)), getnpty P((void)), #ifndef convex getpty P((int *)), #endif login_tty P((int)), spcset P((int, cc_t *, cc_t **)), stilloob P((int)), terminit P((void)), termstat P((void)), tty_flowmode P((void)), tty_restartany P((void)), tty_isbinaryin P((void)), tty_isbinaryout P((void)), tty_iscrnl P((void)), tty_isecho P((void)), tty_isediting P((void)), tty_islitecho P((void)), tty_isnewmap P((void)), tty_israw P((void)), tty_issofttab P((void)), tty_istrapsig P((void)), tty_linemode P((void)); extern void tty_rspeed P((int)), tty_setecho P((int)), tty_setedit P((int)), tty_setlinemode P((int)), tty_setlitecho P((int)), tty_setsig P((int)), tty_setsofttab P((int)), tty_tspeed P((int)), willoption P((int)), wontoption P((int)); int output_data __P((const char *, ...)) __printflike(1, 2); void output_datalen __P((const char *, int)); +void startslave __P((char *, int, char *)); #ifdef ENCRYPTION extern void (*encrypt_output) P((unsigned char *, int)); extern int (*decrypt_input) P((int)); extern char *nclearto; #endif /* ENCRYPTION */ /* * The following are some clocks used to decide how to interpret * the relationship between various variables. */ extern struct { int system, /* what the current time is */ echotoggle, /* last time user entered echo character */ modenegotiated, /* last time operating mode negotiated */ didnetreceive, /* last time we read data from network */ ttypesubopt, /* ttype subopt is received */ tspeedsubopt, /* tspeed subopt is received */ environsubopt, /* environ subopt is received */ oenvironsubopt, /* old environ subopt is received */ xdisplocsubopt, /* xdisploc subopt is received */ baseline, /* time started to do timed action */ gotDM; /* when did we last see a data mark */ } clocks; #ifndef DEFAULT_IM # ifdef ultrix # define DEFAULT_IM "\r\n\r\nULTRIX (%h) (%t)\r\n\r\r\n\r" # else # ifdef __FreeBSD__ # define DEFAULT_IM "\r\n\r\nFreeBSD (%h) (%t)\r\n\r\r\n\r" # else # define DEFAULT_IM "\r\n\r\n4.4 BSD UNIX (%h) (%t)\r\n\r\r\n\r" # endif # endif #endif Index: head/contrib/telnet/telnetd/slc.c =================================================================== --- head/contrib/telnet/telnetd/slc.c (revision 87138) +++ head/contrib/telnet/telnetd/slc.c (revision 87139) @@ -1,494 +1,484 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)slc.c 8.2 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include "telnetd.h" #ifdef LINEMODE /* * local variables */ static unsigned char *def_slcbuf = (unsigned char *)0; static int def_slclen = 0; static int slcchange; /* change to slc is requested */ static unsigned char *slcptr; /* pointer into slc buffer */ static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */ /* * send_slc * * Write out the current special characters to the client. */ - void -send_slc() +void +send_slc(void) { - register int i; + int i; /* * Send out list of triplets of special characters * to client. We only send info on the characters * that are currently supported. */ for (i = 1; i <= NSLC; i++) { if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT) continue; add_slc((unsigned char)i, slctab[i].current.flag, slctab[i].current.val); } } /* end of send_slc */ /* * default_slc * * Set pty special characters to all the defaults. */ - void -default_slc() +static void +default_slc(void) { - register int i; + int i; for (i = 1; i <= NSLC; i++) { slctab[i].current.val = slctab[i].defset.val; if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE)) slctab[i].current.flag = SLC_NOSUPPORT; else slctab[i].current.flag = slctab[i].defset.flag; if (slctab[i].sptr) { *(slctab[i].sptr) = slctab[i].defset.val; } } slcchange = 1; } /* end of default_slc */ #endif /* LINEMODE */ /* * get_slc_defaults * * Initialize the slc mapping table. */ - void -get_slc_defaults() +void +get_slc_defaults(void) { - register int i; + int i; init_termbuf(); for (i = 1; i <= NSLC; i++) { slctab[i].defset.flag = spcset(i, &slctab[i].defset.val, &slctab[i].sptr); slctab[i].current.flag = SLC_NOSUPPORT; slctab[i].current.val = 0; } } /* end of get_slc_defaults */ #ifdef LINEMODE /* * add_slc * * Add an slc triplet to the slc buffer. */ - void -add_slc(func, flag, val) - register char func, flag; - register cc_t val; +void +add_slc(char func, char flag, cc_t val) { if ((*slcptr++ = (unsigned char)func) == 0xff) *slcptr++ = 0xff; if ((*slcptr++ = (unsigned char)flag) == 0xff) *slcptr++ = 0xff; if ((*slcptr++ = (unsigned char)val) == 0xff) *slcptr++ = 0xff; } /* end of add_slc */ /* * start_slc * * Get ready to process incoming slc's and respond to them. * * The parameter getit is non-zero if it is necessary to grab a copy * of the terminal control structures. */ - void -start_slc(getit) - register int getit; +void +start_slc(int getit) { slcchange = 0; if (getit) init_termbuf(); (void) sprintf((char *)slcbuf, "%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC); slcptr = slcbuf + 4; } /* end of start_slc */ /* * end_slc * * Finish up the slc negotiation. If something to send, then send it. */ - int -end_slc(bufp) - register unsigned char **bufp; +int +end_slc(unsigned char **bufp) { - register int len; + int len; /* * If a change has occured, store the new terminal control * structures back to the terminal driver. */ if (slcchange) { set_termbuf(); } /* * If the pty state has not yet been fully processed and there is a * deferred slc request from the client, then do not send any * sort of slc negotiation now. We will respond to the client's * request very soon. */ if (def_slcbuf && (terminit() == 0)) { return(0); } if (slcptr > (slcbuf + 4)) { if (bufp) { *bufp = &slcbuf[4]; return(slcptr - slcbuf - 4); } else { (void) sprintf((char *)slcptr, "%c%c", IAC, SE); slcptr += 2; len = slcptr - slcbuf; output_datalen(slcbuf, len); netflush(); /* force it out immediately */ DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2);); } } return (0); } /* end of end_slc */ /* * process_slc * * Figure out what to do about the client's slc */ - void -process_slc(func, flag, val) - register unsigned char func, flag; - register cc_t val; +void +process_slc(unsigned char func, unsigned char flag, cc_t val) { - register int hislevel, mylevel, ack; + int hislevel, mylevel, ack; /* * Ensure that we know something about this function */ if (func > NSLC) { add_slc(func, SLC_NOSUPPORT, 0); return; } /* * Process the special case requests of 0 SLC_DEFAULT 0 * and 0 SLC_VARIABLE 0. Be a little forgiving here, don't * worry about whether the value is actually 0 or not. */ if (func == 0) { if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) { default_slc(); send_slc(); } else if (flag == SLC_VARIABLE) { send_slc(); } return; } /* * Appears to be a function that we know something about. So * get on with it and see what we know. */ hislevel = flag & SLC_LEVELBITS; mylevel = slctab[func].current.flag & SLC_LEVELBITS; ack = flag & SLC_ACK; /* * ignore the command if: * the function value and level are the same as what we already have; * or the level is the same and the ack bit is set */ if (hislevel == mylevel && (val == slctab[func].current.val || ack)) { return; } else if (ack) { /* * If we get here, we got an ack, but the levels don't match. * This shouldn't happen. If it does, it is probably because * we have sent two requests to set a variable without getting * a response between them, and this is the first response. * So, ignore it, and wait for the next response. */ return; } else { change_slc(func, flag, val); } } /* end of process_slc */ /* * change_slc * * Process a request to change one of our special characters. * Compare client's request with what we are capable of supporting. */ - void -change_slc(func, flag, val) - register char func, flag; - register cc_t val; +void +change_slc(char func, char flag, cc_t val) { - register int hislevel, mylevel; + int hislevel, mylevel; hislevel = flag & SLC_LEVELBITS; mylevel = slctab[(int)func].defset.flag & SLC_LEVELBITS; /* * If client is setting a function to NOSUPPORT * or DEFAULT, then we can easily and directly * accomodate the request. */ if (hislevel == SLC_NOSUPPORT) { slctab[(int)func].current.flag = flag; slctab[(int)func].current.val = (cc_t)_POSIX_VDISABLE; flag |= SLC_ACK; add_slc(func, flag, val); return; } if (hislevel == SLC_DEFAULT) { /* * Special case here. If client tells us to use * the default on a function we don't support, then * return NOSUPPORT instead of what we may have as a * default level of DEFAULT. */ if (mylevel == SLC_DEFAULT) { slctab[(int)func].current.flag = SLC_NOSUPPORT; } else { slctab[(int)func].current.flag = slctab[(int)func].defset.flag; } slctab[(int)func].current.val = slctab[(int)func].defset.val; add_slc(func, slctab[(int)func].current.flag, slctab[(int)func].current.val); return; } /* * Client wants us to change to a new value or he * is telling us that he can't change to our value. * Some of the slc's we support and can change, * some we do support but can't change, * and others we don't support at all. * If we can change it then we have a pointer to * the place to put the new value, so change it, * otherwise, continue the negotiation. */ if (slctab[(int)func].sptr) { /* * We can change this one. */ slctab[(int)func].current.val = val; *(slctab[(int)func].sptr) = val; slctab[(int)func].current.flag = flag; flag |= SLC_ACK; slcchange = 1; add_slc(func, flag, val); } else { /* * It is not possible for us to support this * request as he asks. * * If our level is DEFAULT, then just ack whatever was * sent. * * If he can't change and we can't change, * then degenerate to NOSUPPORT. * * Otherwise we send our level back to him, (CANTCHANGE * or NOSUPPORT) and if CANTCHANGE, send * our value as well. */ if (mylevel == SLC_DEFAULT) { slctab[(int)func].current.flag = flag; slctab[(int)func].current.val = val; flag |= SLC_ACK; } else if (hislevel == SLC_CANTCHANGE && mylevel == SLC_CANTCHANGE) { flag &= ~SLC_LEVELBITS; flag |= SLC_NOSUPPORT; slctab[(int)func].current.flag = flag; } else { flag &= ~SLC_LEVELBITS; flag |= mylevel; slctab[(int)func].current.flag = flag; if (mylevel == SLC_CANTCHANGE) { slctab[(int)func].current.val = slctab[(int)func].defset.val; val = slctab[(int)func].current.val; } } add_slc(func, flag, val); } } /* end of change_slc */ #if defined(USE_TERMIO) && (VEOF == VMIN) cc_t oldeofc = '\004'; #endif /* * check_slc * * Check the special characters in use and notify the client if any have * changed. Only those characters that are capable of being changed are * likely to have changed. If a local change occurs, kick the support level * and flags up to the defaults. */ - void -check_slc() +void +check_slc(void) { - register int i; + int i; for (i = 1; i <= NSLC; i++) { #if defined(USE_TERMIO) && (VEOF == VMIN) /* * In a perfect world this would be a neat little * function. But in this world, we should not notify * client of changes to the VEOF char when * ICANON is off, because it is not representing * a special character. */ if (i == SLC_EOF) { if (!tty_isediting()) continue; else if (slctab[i].sptr) oldeofc = *(slctab[i].sptr); } #endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */ if (slctab[i].sptr && (*(slctab[i].sptr) != slctab[i].current.val)) { slctab[i].current.val = *(slctab[i].sptr); if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE) slctab[i].current.flag = SLC_NOSUPPORT; else slctab[i].current.flag = slctab[i].defset.flag; add_slc((unsigned char)i, slctab[i].current.flag, slctab[i].current.val); } } } /* check_slc */ /* * do_opt_slc * * Process an slc option buffer. Defer processing of incoming slc's * until after the terminal state has been processed. Save the first slc * request that comes along, but discard all others. * * ptr points to the beginning of the buffer, len is the length. */ - void -do_opt_slc(ptr, len) - register unsigned char *ptr; - register int len; +void +do_opt_slc(unsigned char *ptr, int len) { - register unsigned char func, flag; + unsigned char func, flag; cc_t val; - register unsigned char *end = ptr + len; + unsigned char *end = ptr + len; if (terminit()) { /* go ahead */ while (ptr < end) { func = *ptr++; if (ptr >= end) break; flag = *ptr++; if (ptr >= end) break; val = (cc_t)*ptr++; process_slc(func, flag, val); } } else { /* * save this slc buffer if it is the first, otherwise dump * it. */ if (def_slcbuf == (unsigned char *)0) { def_slclen = len; def_slcbuf = (unsigned char *)malloc((unsigned)len); if (def_slcbuf == (unsigned char *)0) return; /* too bad */ memmove(def_slcbuf, ptr, len); } } } /* end of do_opt_slc */ /* * deferslc * * Do slc stuff that was deferred. */ - void -deferslc() +void +deferslc(void) { if (def_slcbuf) { start_slc(1); do_opt_slc(def_slcbuf, def_slclen); (void) end_slc(0); free(def_slcbuf); def_slcbuf = (unsigned char *)0; def_slclen = 0; } } /* end of deferslc */ #endif /* LINEMODE */ Index: head/contrib/telnet/telnetd/state.c =================================================================== --- head/contrib/telnet/telnetd/state.c (revision 87138) +++ head/contrib/telnet/telnetd/state.c (revision 87139) @@ -1,1647 +1,1631 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)state.c 8.5 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include #include "telnetd.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; unsigned char will[] = { IAC, WILL, '%', 'c', 0 }; unsigned char wont[] = { IAC, WONT, '%', 'c', 0 }; int not42 = 1; /* * Buffer for sub-options, and macros * for suboptions buffer manipulations */ unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer; #define SB_CLEAR() subpointer = subbuffer #define SB_TERM() { subend = subpointer; SB_CLEAR(); } #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ *subpointer++ = (c); \ } #define SB_GET() ((*subpointer++)&0xff) #define SB_EOF() (subpointer >= subend) #define SB_LEN() (subend - subpointer) #ifdef ENV_HACK unsigned char *subsave; #define SB_SAVE() subsave = subpointer; #define SB_RESTORE() subpointer = subsave; #endif /* * State for recv fsm */ #define TS_DATA 0 /* base state */ #define TS_IAC 1 /* look for double IAC's */ #define TS_CR 2 /* CR-LF ->'s CR */ #define TS_SB 3 /* throw away begin's... */ #define TS_SE 4 /* ...end's (suboption negotiation) */ #define TS_WILL 5 /* will option negotiation */ #define TS_WONT 6 /* wont " */ #define TS_DO 7 /* do " */ #define TS_DONT 8 /* dont " */ - void -telrcv() +static void doclientstat(void); + +void +telrcv(void) { - register int c; + int c; static int state = TS_DATA; while (ncc > 0) { if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) break; c = *netip++ & 0377, ncc--; #ifdef ENCRYPTION if (decrypt_input) c = (*decrypt_input)(c); #endif /* ENCRYPTION */ switch (state) { case TS_CR: state = TS_DATA; /* Strip off \n or \0 after a \r */ if ((c == 0) || (c == '\n')) { break; } /* FALL THROUGH */ case TS_DATA: if (c == IAC) { state = TS_IAC; break; } /* * We now map \r\n ==> \r for pragmatic reasons. * Many client implementations send \r\n when * the user hits the CarriageReturn key. * * We USED to map \r\n ==> \n, since \r\n says * that we want to be in column 1 of the next * printable line, and \n is the standard * unix way of saying that (\r is only good * if CRMOD is set, which it normally is). */ if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { int nc = *netip; #ifdef ENCRYPTION if (decrypt_input) nc = (*decrypt_input)(nc & 0xff); #endif /* ENCRYPTION */ #ifdef LINEMODE /* * If we are operating in linemode, * convert to local end-of-line. */ if (linemode && (ncc > 0) && (('\n' == nc) || ((0 == nc) && tty_iscrnl())) ) { netip++; ncc--; c = '\n'; } else #endif { #ifdef ENCRYPTION if (decrypt_input) (void)(*decrypt_input)(-1); #endif /* ENCRYPTION */ state = TS_CR; } } *pfrontp++ = c; break; case TS_IAC: gotiac: switch (c) { /* * Send the process on the pty side an * interrupt. Do this with a NULL or * interrupt char; depending on the tty mode. */ case IP: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); interrupt(); break; case BREAK: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); sendbrk(); break; /* * Are You There? */ case AYT: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); recv_ayt(); break; /* * Abort Output */ case AO: { DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (slctab[SLC_AO].sptr && *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { *pfrontp++ = (unsigned char)*slctab[SLC_AO].sptr; } netclear(); /* clear buffer back */ output_data("%c%c", IAC, DM); neturg = nfrontp-1; /* off by one XXX */ DIAG(TD_OPTIONS, printoption("td: send IAC", DM)); break; } /* * Erase Character and * Erase Line */ case EC: case EL: { cc_t ch; DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (c == EC) ch = *slctab[SLC_EC].sptr; else ch = *slctab[SLC_EL].sptr; if (ch != (cc_t)(_POSIX_VDISABLE)) *pfrontp++ = (unsigned char)ch; break; } /* * Check for urgent data... */ case DM: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); SYNCHing = stilloob(net); settimer(gotDM); break; /* * Begin option subnegotiation... */ case SB: state = TS_SB; SB_CLEAR(); continue; case WILL: state = TS_WILL; continue; case WONT: state = TS_WONT; continue; case DO: state = TS_DO; continue; case DONT: state = TS_DONT; continue; case EOR: if (his_state_is_will(TELOPT_EOR)) doeof(); break; /* * Handle RFC 10xx Telnet linemode option additions * to command stream (EOF, SUSP, ABORT). */ case xEOF: doeof(); break; case SUSP: sendsusp(); break; case ABORT: sendbrk(); break; case IAC: *pfrontp++ = c; break; } state = TS_DATA; break; case TS_SB: if (c == IAC) { state = TS_SE; } else { SB_ACCUM(c); } break; case TS_SE: if (c != SE) { if (c != IAC) { /* * bad form of suboption negotiation. * handle it in such a way as to avoid * damage to local state. Parse * suboption buffer found so far, * then treat remaining stream as * another command sequence. */ /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(c); subpointer -= 2; SB_TERM(); suboption(); state = TS_IAC; goto gotiac; } SB_ACCUM(c); state = TS_SB; } else { /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(SE); subpointer -= 2; SB_TERM(); suboption(); /* handle sub-option */ state = TS_DATA; } break; case TS_WILL: willoption(c); state = TS_DATA; continue; case TS_WONT: wontoption(c); state = TS_DATA; continue; case TS_DO: dooption(c); state = TS_DATA; continue; case TS_DONT: dontoption(c); state = TS_DATA; continue; default: syslog(LOG_ERR, "panic state=%d", state); printf("telnetd: panic state=%d\n", state); exit(1); } } } /* end of telrcv */ /* * The will/wont/do/dont state machines are based on Dave Borman's * Telnet option processing state machine. * * These correspond to the following states: * my_state = the last negotiated state * want_state = what I want the state to go to * want_resp = how many requests I have sent * All state defaults are negative, and resp defaults to 0. * * When initiating a request to change state to new_state: * * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { * do nothing; * } else { * want_state = new_state; * send new_state; * want_resp++; * } * * When receiving new_state: * * if (want_resp) { * want_resp--; * if (want_resp && (new_state == my_state)) * want_resp--; * } * if ((want_resp == 0) && (new_state != want_state)) { * if (ok_to_switch_to new_state) * want_state = new_state; * else * want_resp++; * send want_state; * } * my_state = new_state; * * Note that new_state is implied in these functions by the function itself. * will and do imply positive new_state, wont and dont imply negative. * * Finally, there is one catch. If we send a negative response to a * positive request, my_state will be the positive while want_state will * remain negative. my_state will revert to negative when the negative * acknowlegment arrives from the peer. Thus, my_state generally tells * us not only the last negotiated state, but also tells us what the peer * wants to be doing as well. It is important to understand this difference * as we may wish to be processing data streams based on our desired state * (want_state) or based on what the peer thinks the state is (my_state). * * This all works fine because if the peer sends a positive request, the data * that we receive prior to negative acknowlegment will probably be affected * by the positive state, and we can process it as such (if we can; if we * can't then it really doesn't matter). If it is that important, then the * peer probably should be buffering until this option state negotiation * is complete. * */ - void -send_do(option, init) - int option, init; +void +send_do(int option, int init) { if (init) { if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || his_want_state_is_will(option)) return; /* * Special case for TELOPT_TM: We send a DO, but pretend * that we sent a DONT, so that we can send more DOs if * we want to. */ if (option == TELOPT_TM) set_his_want_state_wont(option); else set_his_want_state_will(option); do_dont_resp[option]++; } output_data((const char *)doopt, option); DIAG(TD_OPTIONS, printoption("td: send do", option)); } -#ifdef AUTHENTICATION -extern void auth_request(); -#endif -#ifdef LINEMODE -extern void doclientstat(); -#endif -#ifdef ENCRYPTION -extern void encrypt_send_support(); -#endif /* ENCRYPTION */ - - void -willoption(option) - int option; +void +willoption(int option) { int changeok = 0; - void (*func)() = 0; + void (*func)(void) = 0; /* * process input from peer. */ DIAG(TD_OPTIONS, printoption("td: recv will", option)); if (do_dont_resp[option]) { do_dont_resp[option]--; if (do_dont_resp[option] && his_state_is_will(option)) do_dont_resp[option]--; } if (do_dont_resp[option] == 0) { if (his_want_state_is_wont(option)) { switch (option) { case TELOPT_BINARY: init_termbuf(); tty_binaryin(1); set_termbuf(); changeok++; break; case TELOPT_ECHO: /* * See comments below for more info. */ not42 = 0; /* looks like a 4.2 system */ break; case TELOPT_TM: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * This telnetd implementation does not really * support timing marks, it just uses them to * support the kludge linemode stuff. If we * receive a will or wont TM in response to our * do TM request that may have been sent to * determine kludge linemode support, process * it, otherwise TM should get a negative * response back. */ /* * Handle the linemode kludge stuff. * If we are not currently supporting any * linemode at all, then we assume that this * is the client telling us to use kludge * linemode in response to our query. Set the * linemode type that is to be supported, note * that the client wishes to use linemode, and * eat the will TM as though it never arrived. */ if (lmodetype < KLUDGE_LINEMODE) { lmodetype = KLUDGE_LINEMODE; clientstat(TELOPT_LINEMODE, WILL, 0); send_wont(TELOPT_SGA, 1); } else if (lmodetype == NO_AUTOKLUDGE) { lmodetype = KLUDGE_OK; } #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ /* * We never respond to a WILL TM, and * we leave the state WONT. */ return; case TELOPT_LFLOW: /* * If we are going to support flow control * option, then don't worry peer that we can't * change the flow control characters. */ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XON].defset.flag |= SLC_DEFAULT; slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; case TELOPT_TTYPE: case TELOPT_SGA: case TELOPT_NAWS: case TELOPT_TSPEED: case TELOPT_XDISPLOC: case TELOPT_NEW_ENVIRON: case TELOPT_OLD_ENVIRON: changeok++; break; #ifdef LINEMODE case TELOPT_LINEMODE: # ifdef KLUDGELINEMODE /* * Note client's desire to use linemode. */ lmodetype = REAL_LINEMODE; # endif /* KLUDGELINEMODE */ func = doclientstat; changeok++; break; #endif /* LINEMODE */ #ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: func = auth_request; changeok++; break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: func = encrypt_send_support; changeok++; break; #endif /* ENCRYPTION */ default: break; } if (changeok) { set_his_want_state_will(option); send_do(option, 0); } else { do_dont_resp[option]++; send_dont(option, 0); } } else { /* * Option processing that should happen when * we receive conformation of a change in * state that we had requested. */ switch (option) { case TELOPT_ECHO: not42 = 0; /* looks like a 4.2 system */ /* * Egads, he responded "WILL ECHO". Turn * it off right now! */ send_dont(option, 1); /* * "WILL ECHO". Kludge upon kludge! * A 4.2 client is now echoing user input at * the tty. This is probably undesireable and * it should be stopped. The client will * respond WONT TM to the DO TM that we send to * check for kludge linemode. When the WONT TM * arrives, linemode will be turned off and a * change propogated to the pty. This change * will cause us to process the new pty state * in localstat(), which will notice that * linemode is off and send a WILL ECHO * so that we are properly in character mode and * all is well. */ break; #ifdef LINEMODE case TELOPT_LINEMODE: # ifdef KLUDGELINEMODE /* * Note client's desire to use linemode. */ lmodetype = REAL_LINEMODE; # endif /* KLUDGELINEMODE */ func = doclientstat; break; #endif /* LINEMODE */ #ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: func = auth_request; break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: func = encrypt_send_support; break; #endif /* ENCRYPTION */ case TELOPT_LFLOW: func = flowstat; break; } } } set_his_state_will(option); if (func) (*func)(); } /* end of willoption */ - void -send_dont(option, init) - int option, init; +void +send_dont(int option, int init) { if (init) { if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || his_want_state_is_wont(option)) return; set_his_want_state_wont(option); do_dont_resp[option]++; } output_data((const char *)dont, option); DIAG(TD_OPTIONS, printoption("td: send dont", option)); } - void -wontoption(option) - int option; +void +wontoption(int option) { /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv wont", option)); if (do_dont_resp[option]) { do_dont_resp[option]--; if (do_dont_resp[option] && his_state_is_wont(option)) do_dont_resp[option]--; } if (do_dont_resp[option] == 0) { if (his_want_state_is_will(option)) { /* it is always ok to change to negative state */ switch (option) { case TELOPT_ECHO: not42 = 1; /* doesn't seem to be a 4.2 system */ break; case TELOPT_BINARY: init_termbuf(); tty_binaryin(0); set_termbuf(); break; #ifdef LINEMODE case TELOPT_LINEMODE: # ifdef KLUDGELINEMODE /* * If real linemode is supported, then client is * asking to turn linemode off. */ if (lmodetype != REAL_LINEMODE) break; lmodetype = KLUDGE_LINEMODE; # endif /* KLUDGELINEMODE */ clientstat(TELOPT_LINEMODE, WONT, 0); break; #endif /* LINEMODE */ case TELOPT_TM: /* * If we get a WONT TM, and had sent a DO TM, * don't respond with a DONT TM, just leave it * as is. Short circut the state machine to * achive this. */ set_his_want_state_wont(TELOPT_TM); return; case TELOPT_LFLOW: /* * If we are not going to support flow control * option, then let peer know that we can't * change the flow control characters. */ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: auth_finished(0, AUTH_REJECT); break; #endif /* * For options that we might spin waiting for * sub-negotiation, if the client turns off the * option rather than responding to the request, * we have to treat it here as if we got a response * to the sub-negotiation, (by updating the timers) * so that we'll break out of the loop. */ case TELOPT_TTYPE: settimer(ttypesubopt); break; case TELOPT_TSPEED: settimer(tspeedsubopt); break; case TELOPT_XDISPLOC: settimer(xdisplocsubopt); break; case TELOPT_OLD_ENVIRON: settimer(oenvironsubopt); break; case TELOPT_NEW_ENVIRON: settimer(environsubopt); break; default: break; } set_his_want_state_wont(option); if (his_state_is_will(option)) send_dont(option, 0); } else { switch (option) { case TELOPT_TM: #if defined(LINEMODE) && defined(KLUDGELINEMODE) if (lmodetype < NO_AUTOKLUDGE) { lmodetype = NO_LINEMODE; clientstat(TELOPT_LINEMODE, WONT, 0); send_will(TELOPT_SGA, 1); send_will(TELOPT_ECHO, 1); } #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: auth_finished(0, AUTH_REJECT); break; #endif default: break; } } } set_his_state_wont(option); } /* end of wontoption */ - void -send_will(option, init) - int option, init; +void +send_will(int option, int init) { if (init) { if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| my_want_state_is_will(option)) return; set_my_want_state_will(option); will_wont_resp[option]++; } output_data((const char *)will, option); DIAG(TD_OPTIONS, printoption("td: send will", option)); } #if !defined(LINEMODE) || !defined(KLUDGELINEMODE) /* * When we get a DONT SGA, we will try once to turn it * back on. If the other side responds DONT SGA, we * leave it at that. This is so that when we talk to * clients that understand KLUDGELINEMODE but not LINEMODE, * we'll keep them in char-at-a-time mode. */ int turn_on_sga = 0; #endif - void -dooption(option) - int option; +void +dooption(int option) { int changeok = 0; /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv do", option)); if (will_wont_resp[option]) { will_wont_resp[option]--; if (will_wont_resp[option] && my_state_is_will(option)) will_wont_resp[option]--; } if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { switch (option) { case TELOPT_ECHO: #ifdef LINEMODE # ifdef KLUDGELINEMODE if (lmodetype == NO_LINEMODE) # else if (his_state_is_wont(TELOPT_LINEMODE)) # endif #endif { init_termbuf(); tty_setecho(1); set_termbuf(); } changeok++; break; case TELOPT_BINARY: init_termbuf(); tty_binaryout(1); set_termbuf(); changeok++; break; case TELOPT_SGA: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * If kludge linemode is in use, then we must * process an incoming do SGA for linemode * purposes. */ if (lmodetype == KLUDGE_LINEMODE) { /* * Receipt of "do SGA" in kludge * linemode is the peer asking us to * turn off linemode. Make note of * the request. */ clientstat(TELOPT_LINEMODE, WONT, 0); /* * If linemode did not get turned off * then don't tell peer that we did. * Breaking here forces a wont SGA to * be returned. */ if (linemode) break; } #else turn_on_sga = 0; #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ changeok++; break; case TELOPT_STATUS: changeok++; break; case TELOPT_TM: /* * Special case for TM. We send a WILL, but * pretend we sent a WONT. */ send_will(option, 0); set_my_want_state_wont(option); set_my_state_wont(option); return; case TELOPT_LOGOUT: /* * When we get a LOGOUT option, respond * with a WILL LOGOUT, make sure that * it gets written out to the network, * and then just go away... */ set_my_want_state_will(TELOPT_LOGOUT); send_will(TELOPT_LOGOUT, 0); set_my_state_will(TELOPT_LOGOUT); (void)netflush(); cleanup(0); /* NOT REACHED */ break; #ifdef ENCRYPTION case TELOPT_ENCRYPT: changeok++; break; #endif /* ENCRYPTION */ case TELOPT_LINEMODE: case TELOPT_TTYPE: case TELOPT_NAWS: case TELOPT_TSPEED: case TELOPT_LFLOW: case TELOPT_XDISPLOC: #ifdef TELOPT_ENVIRON case TELOPT_NEW_ENVIRON: #endif case TELOPT_OLD_ENVIRON: default: break; } if (changeok) { set_my_want_state_will(option); send_will(option, 0); } else { will_wont_resp[option]++; send_wont(option, 0); } } set_my_state_will(option); } /* end of dooption */ - void -send_wont(option, init) - int option, init; +void +send_wont(int option, int init) { if (init) { if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || my_want_state_is_wont(option)) return; set_my_want_state_wont(option); will_wont_resp[option]++; } output_data((const char *)wont, option); DIAG(TD_OPTIONS, printoption("td: send wont", option)); } - void -dontoption(option) - int option; +void +dontoption(int option) { /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv dont", option)); if (will_wont_resp[option]) { will_wont_resp[option]--; if (will_wont_resp[option] && my_state_is_wont(option)) will_wont_resp[option]--; } if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { switch (option) { case TELOPT_BINARY: init_termbuf(); tty_binaryout(0); set_termbuf(); break; case TELOPT_ECHO: /* we should stop echoing */ #ifdef LINEMODE # ifdef KLUDGELINEMODE if ((lmodetype != REAL_LINEMODE) && (lmodetype != KLUDGE_LINEMODE)) # else if (his_state_is_wont(TELOPT_LINEMODE)) # endif #endif { init_termbuf(); tty_setecho(0); set_termbuf(); } break; case TELOPT_SGA: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * If kludge linemode is in use, then we * must process an incoming do SGA for * linemode purposes. */ if ((lmodetype == KLUDGE_LINEMODE) || (lmodetype == KLUDGE_OK)) { /* * The client is asking us to turn * linemode on. */ lmodetype = KLUDGE_LINEMODE; clientstat(TELOPT_LINEMODE, WILL, 0); /* * If we did not turn line mode on, * then what do we say? Will SGA? * This violates design of telnet. * Gross. Very Gross. */ } break; #else set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); set_my_state_wont(option); if (turn_on_sga ^= 1) send_will(option, 1); return; #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ default: break; } set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); } set_my_state_wont(option); } /* end of dontoption */ #ifdef ENV_HACK int env_ovar = -1; int env_ovalue = -1; #else /* ENV_HACK */ # define env_ovar OLD_ENV_VAR # define env_ovalue OLD_ENV_VALUE #endif /* ENV_HACK */ /* * suboption() * * Look at the sub-option buffer, and try to be helpful to the other * side. * * Currently we recognize: * * Terminal type is * Linemode * Window size * Terminal speed */ - void -suboption() +void +suboption(void) { - register int subchar; + int subchar; DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); subchar = SB_GET(); switch (subchar) { case TELOPT_TSPEED: { - register int xspeed, rspeed; + int xspeed, rspeed; if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ break; settimer(tspeedsubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) return; xspeed = atoi((char *)subpointer); while (SB_GET() != ',' && !SB_EOF()); if (SB_EOF()) return; rspeed = atoi((char *)subpointer); clientstat(TELOPT_TSPEED, xspeed, rspeed); break; } /* end of case TELOPT_TSPEED */ case TELOPT_TTYPE: { /* Yaaaay! */ static char terminalname[41]; if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ break; settimer(ttypesubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) { return; /* ??? XXX but, this is the most robust */ } terminaltype = terminalname; while ((terminaltype < (terminalname + sizeof terminalname-1)) && !SB_EOF()) { - register int c; + int c; c = SB_GET(); if (isupper(c)) { c = tolower(c); } *terminaltype++ = c; /* accumulate name */ } *terminaltype = 0; terminaltype = terminalname; break; } /* end of case TELOPT_TTYPE */ case TELOPT_NAWS: { - register int xwinsize, ywinsize; + int xwinsize, ywinsize; if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ break; if (SB_EOF()) return; xwinsize = SB_GET() << 8; if (SB_EOF()) return; xwinsize |= SB_GET(); if (SB_EOF()) return; ywinsize = SB_GET() << 8; if (SB_EOF()) return; ywinsize |= SB_GET(); clientstat(TELOPT_NAWS, xwinsize, ywinsize); break; } /* end of case TELOPT_NAWS */ #ifdef LINEMODE case TELOPT_LINEMODE: { - register int request; + int request; if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ break; /* * Process linemode suboptions. */ if (SB_EOF()) break; /* garbage was sent */ request = SB_GET(); /* get will/wont */ if (SB_EOF()) break; /* another garbage check */ if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */ /* * Process suboption buffer of slc's */ start_slc(1); do_opt_slc(subpointer, subend - subpointer); (void) end_slc(0); break; } else if (request == LM_MODE) { if (SB_EOF()) return; useeditmode = SB_GET(); /* get mode flag */ clientstat(LM_MODE, 0, 0); break; } if (SB_EOF()) break; switch (SB_GET()) { /* what suboption? */ case LM_FORWARDMASK: /* * According to spec, only server can send request for * forwardmask, and client can only return a positive response. * So don't worry about it. */ default: break; } break; } /* end of case TELOPT_LINEMODE */ #endif case TELOPT_STATUS: { int mode; if (SB_EOF()) break; mode = SB_GET(); switch (mode) { case TELQUAL_SEND: if (my_state_is_will(TELOPT_STATUS)) send_status(); break; case TELQUAL_IS: break; default: break; } break; } /* end of case TELOPT_STATUS */ case TELOPT_XDISPLOC: { if (SB_EOF() || SB_GET() != TELQUAL_IS) return; settimer(xdisplocsubopt); subpointer[SB_LEN()] = '\0'; (void)setenv("DISPLAY", (char *)subpointer, 1); break; } /* end of case TELOPT_XDISPLOC */ #ifdef TELOPT_NEW_ENVIRON case TELOPT_NEW_ENVIRON: #endif case TELOPT_OLD_ENVIRON: { - register int c; - register char *cp, *varp, *valp; + int c; + char *cp, *varp, *valp; if (SB_EOF()) return; c = SB_GET(); if (c == TELQUAL_IS) { if (subchar == TELOPT_OLD_ENVIRON) settimer(oenvironsubopt); else settimer(environsubopt); } else if (c != TELQUAL_INFO) { return; } #ifdef TELOPT_NEW_ENVIRON if (subchar == TELOPT_NEW_ENVIRON) { while (!SB_EOF()) { c = SB_GET(); if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) break; } } else #endif { #ifdef ENV_HACK /* * We only want to do this if we haven't already decided * whether or not the other side has its VALUE and VAR * reversed. */ if (env_ovar < 0) { - register int last = -1; /* invalid value */ + int last = -1; /* invalid value */ int empty = 0; int got_var = 0, got_value = 0, got_uservar = 0; /* * The other side might have its VALUE and VAR values * reversed. To be interoperable, we need to determine * which way it is. If the first recognized character * is a VAR or VALUE, then that will tell us what * type of client it is. If the fist recognized * character is a USERVAR, then we continue scanning * the suboption looking for two consecutive * VAR or VALUE fields. We should not get two * consecutive VALUE fields, so finding two * consecutive VALUE or VAR fields will tell us * what the client is. */ SB_SAVE(); while (!SB_EOF()) { c = SB_GET(); switch(c) { case OLD_ENV_VAR: if (last < 0 || last == OLD_ENV_VAR || (empty && (last == OLD_ENV_VALUE))) goto env_ovar_ok; got_var++; last = OLD_ENV_VAR; break; case OLD_ENV_VALUE: if (last < 0 || last == OLD_ENV_VALUE || (empty && (last == OLD_ENV_VAR))) goto env_ovar_wrong; got_value++; last = OLD_ENV_VALUE; break; case ENV_USERVAR: /* count strings of USERVAR as one */ if (last != ENV_USERVAR) got_uservar++; if (empty) { if (last == OLD_ENV_VALUE) goto env_ovar_ok; if (last == OLD_ENV_VAR) goto env_ovar_wrong; } last = ENV_USERVAR; break; case ENV_ESC: if (!SB_EOF()) c = SB_GET(); /* FALL THROUGH */ default: empty = 0; continue; } empty = 1; } if (empty) { if (last == OLD_ENV_VALUE) goto env_ovar_ok; if (last == OLD_ENV_VAR) goto env_ovar_wrong; } /* * Ok, the first thing was a USERVAR, and there * are not two consecutive VAR or VALUE commands, * and none of the VAR or VALUE commands are empty. * If the client has sent us a well-formed option, * then the number of VALUEs received should always * be less than or equal to the number of VARs and * USERVARs received. * * If we got exactly as many VALUEs as VARs and * USERVARs, the client has the same definitions. * * If we got exactly as many VARs as VALUEs and * USERVARS, the client has reversed definitions. */ if (got_uservar + got_var == got_value) { env_ovar_ok: env_ovar = OLD_ENV_VAR; env_ovalue = OLD_ENV_VALUE; } else if (got_uservar + got_value == got_var) { env_ovar_wrong: env_ovar = OLD_ENV_VALUE; env_ovalue = OLD_ENV_VAR; DIAG(TD_OPTIONS, output_data("ENVIRON VALUE and VAR are reversed!\r\n")); } } SB_RESTORE(); #endif while (!SB_EOF()) { c = SB_GET(); if ((c == env_ovar) || (c == ENV_USERVAR)) break; } } if (SB_EOF()) return; cp = varp = (char *)subpointer; valp = 0; while (!SB_EOF()) { c = SB_GET(); if (subchar == TELOPT_OLD_ENVIRON) { if (c == env_ovar) c = NEW_ENV_VAR; else if (c == env_ovalue) c = NEW_ENV_VALUE; } switch (c) { case NEW_ENV_VALUE: *cp = '\0'; cp = valp = (char *)subpointer; break; case NEW_ENV_VAR: case ENV_USERVAR: *cp = '\0'; if (valp) (void)setenv(varp, valp, 1); else unsetenv(varp); cp = varp = (char *)subpointer; valp = 0; break; case ENV_ESC: if (SB_EOF()) break; c = SB_GET(); /* FALL THROUGH */ default: *cp++ = c; break; } } *cp = '\0'; if (valp) (void)setenv(varp, valp, 1); else unsetenv(varp); break; } /* end of case TELOPT_NEW_ENVIRON */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: if (SB_EOF()) break; switch(SB_GET()) { case TELQUAL_SEND: case TELQUAL_REPLY: /* * These are sent by us and cannot be sent by * the client. */ break; case TELQUAL_IS: auth_is(subpointer, SB_LEN()); break; case TELQUAL_NAME: auth_name(subpointer, SB_LEN()); break; } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: if (SB_EOF()) break; switch(SB_GET()) { case ENCRYPT_SUPPORT: encrypt_support(subpointer, SB_LEN()); break; case ENCRYPT_IS: encrypt_is(subpointer, SB_LEN()); break; case ENCRYPT_REPLY: encrypt_reply(subpointer, SB_LEN()); break; case ENCRYPT_START: encrypt_start(subpointer, SB_LEN()); break; case ENCRYPT_END: encrypt_end(); break; case ENCRYPT_REQSTART: encrypt_request_start(subpointer, SB_LEN()); break; case ENCRYPT_REQEND: /* * We can always send an REQEND so that we cannot * get stuck encrypting. We should only get this * if we have been able to get in the correct mode * anyhow. */ encrypt_request_end(); break; case ENCRYPT_ENC_KEYID: encrypt_enc_keyid(subpointer, SB_LEN()); break; case ENCRYPT_DEC_KEYID: encrypt_dec_keyid(subpointer, SB_LEN()); break; default: break; } break; #endif /* ENCRYPTION */ default: break; } /* end of switch */ } /* end of suboption */ - void -doclientstat() +static void +doclientstat(void) { clientstat(TELOPT_LINEMODE, WILL, 0); } #define ADD(c) *ncp++ = c #define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } - void -send_status() +void +send_status(void) { unsigned char statusbuf[256]; - register unsigned char *ncp; - register unsigned char i; + unsigned char *ncp; + unsigned char i; ncp = statusbuf; netflush(); /* get rid of anything waiting to go out */ ADD(IAC); ADD(SB); ADD(TELOPT_STATUS); ADD(TELQUAL_IS); /* * We check the want_state rather than the current state, * because if we received a DO/WILL for an option that we * don't support, and the other side didn't send a DONT/WONT * in response to our WONT/DONT, then the "state" will be * WILL/DO, and the "want_state" will be WONT/DONT. We * need to go by the latter. */ for (i = 0; i < (unsigned char)NTELOPTS; i++) { if (my_want_state_is_will(i)) { ADD(WILL); ADD_DATA(i); if (i == IAC) ADD(IAC); } if (his_want_state_is_will(i)) { ADD(DO); ADD_DATA(i); if (i == IAC) ADD(IAC); } } if (his_want_state_is_will(TELOPT_LFLOW)) { ADD(SB); ADD(TELOPT_LFLOW); if (flowmode) { ADD(LFLOW_ON); } else { ADD(LFLOW_OFF); } ADD(SE); if (restartany >= 0) { ADD(SB); ADD(TELOPT_LFLOW); if (restartany) { ADD(LFLOW_RESTART_ANY); } else { ADD(LFLOW_RESTART_XON); } ADD(SE); } } #ifdef LINEMODE if (his_want_state_is_will(TELOPT_LINEMODE)) { unsigned char *cp, *cpe; int len; ADD(SB); ADD(TELOPT_LINEMODE); ADD(LM_MODE); ADD_DATA(editmode); ADD(SE); ADD(SB); ADD(TELOPT_LINEMODE); ADD(LM_SLC); start_slc(0); send_slc(); len = end_slc(&cp); for (cpe = cp + len; cp < cpe; cp++) ADD_DATA(*cp); ADD(SE); } #endif /* LINEMODE */ ADD(IAC); ADD(SE); output_datalen(statusbuf, ncp - statusbuf); netflush(); /* Send it on its way */ DIAG(TD_OPTIONS, {printsub('>', statusbuf, ncp - statusbuf); netflush();}); } /* * This function appends data to nfrontp and advances nfrontp. * Returns the number of characters written altogether (the * buffer may have been flushed in the process). */ int output_data(const char *format, ...) { va_list args; int len; char *buf; va_start(args, format); if ((len = vasprintf(&buf, format, args)) == -1) return -1; output_datalen(buf, len); va_end(args); free(buf); return (len); } void output_datalen(const char *buf, int len) { int remaining, copied; remaining = BUFSIZ - (nfrontp - netobuf); while (len > 0) { /* Free up enough space if the room is too low*/ if ((len > BUFSIZ ? BUFSIZ : len) > remaining) { netflush(); remaining = BUFSIZ - (nfrontp - netobuf); } /* Copy out as much as will fit */ copied = remaining > len ? len : remaining; memmove(nfrontp, buf, copied); nfrontp += copied; len -= copied; remaining -= copied; buf += copied; } return; } Index: head/contrib/telnet/telnetd/sys_term.c =================================================================== --- head/contrib/telnet/telnetd/sys_term.c (revision 87138) +++ head/contrib/telnet/telnetd/sys_term.c (revision 87139) @@ -1,1855 +1,1331 @@ -/* + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ +#include +#include +#include +#include +#include + #include "telnetd.h" #include "pathnames.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -extern char *altlogin; -int cleanopen(char *line); +int cleanopen(char *); void scrub_env(void); -#ifdef NEWINIT -#include -#else /* NEWINIT*/ -# ifdef UTMPX -# include -struct utmpx wtmp; -# else -# include struct utmp wtmp; -# endif /* UTMPX */ -# ifndef PARENT_DOES_UTMP #ifdef _PATH_WTMP char wtmpf[] = _PATH_WTMP; #else -char wtmpf[] = "/usr/adm/wtmp"; +char wtmpf[] = "/var/log/wtmp"; #endif #ifdef _PATH_UTMP char utmpf[] = _PATH_UTMP; #else -char utmpf[] = "/etc/utmp"; +char utmpf[] = "/var/run/utmp"; #endif -# else /* PARENT_DOES_UTMP */ -char wtmpf[] = "/etc/wtmp"; -# endif /* PARENT_DOES_UTMP */ -#include +char *envinit[3]; +extern char **environ; -#endif /* NEWINIT */ - -#ifdef STREAMSPTY -#include -#include -#endif - #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) #define SCMPN(a, b) strncmp(a, b, sizeof(a)) -#ifdef STREAMS -#include -#endif -#include #ifdef t_erase #undef t_erase #undef t_kill #undef t_intrc #undef t_quitc #undef t_startc #undef t_stopc #undef t_eofc #undef t_brkc #undef t_suspc #undef t_dsuspc #undef t_rprntc #undef t_flushc #undef t_werasc #undef t_lnextc #endif #ifndef USE_TERMIO struct termbuf { struct sgttyb sg; struct tchars tc; struct ltchars ltc; int state; int lflags; } termbuf, termbuf2; # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) # define cfgetospeed(tp) (tp)->sg.sg_ospeed # define cfgetispeed(tp) (tp)->sg.sg_ispeed #else /* USE_TERMIO */ -# ifdef SYSV_TERMIO -# define termios termio -# endif # ifndef TCSANOW # ifdef TCSETS # define TCSANOW TCSETS # define TCSADRAIN TCSETSW # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) # else # ifdef TCSETA # define TCSANOW TCSETA # define TCSADRAIN TCSETAW # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) # else # define TCSANOW TIOCSETA # define TCSADRAIN TIOCSETAW # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) # endif # endif # define tcsetattr(f, a, t) ioctl(f, a, t) # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ (tp)->c_cflag |= (val) # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) # ifdef CIBAUD # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ (tp)->c_cflag |= ((val)<c_cflag & CIBAUD)>>IBSHIFT) # else # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ (tp)->c_cflag |= (val) # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) # endif # endif /* TCSANOW */ struct termios termbuf, termbuf2; /* pty control structure */ -# ifdef STREAMSPTY -int ttyfd = -1; -# endif #endif /* USE_TERMIO */ #include #include int cleanopen __P((char *)); void scrub_env __P((void)); +static char **addarg __P((char **, const char *)); /* * init_termbuf() * copy_termbuf(cp) * set_termbuf() * * These three routines are used to get and set the "termbuf" structure * to and from the kernel. init_termbuf() gets the current settings. * copy_termbuf() hands in a new "termbuf" to write to the kernel, and * set_termbuf() writes the structure into the kernel. */ - void -init_termbuf() +void +init_termbuf(void) { #ifndef USE_TERMIO (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); # ifdef TIOCGSTATE (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); # endif #else -# ifdef STREAMSPTY - (void) tcgetattr(ttyfd, &termbuf); -# else (void) tcgetattr(pty, &termbuf); -# endif #endif termbuf2 = termbuf; } #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) - void -copy_termbuf(cp, len) - char *cp; - int len; +void +copy_termbuf(char *cp, size_t len) { if (len > sizeof(termbuf)) len = sizeof(termbuf); memmove((char *)&termbuf, cp, len); termbuf2 = termbuf; } #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ - void -set_termbuf() +void +set_termbuf(void) { /* * Only make the necessary changes. */ #ifndef USE_TERMIO if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, sizeof(termbuf.ltc))) (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); if (termbuf.lflags != termbuf2.lflags) (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); #else /* USE_TERMIO */ if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) -# ifdef STREAMSPTY - (void) tcsetattr(ttyfd, TCSANOW, &termbuf); -# else (void) tcsetattr(pty, TCSANOW, &termbuf); -# endif #endif /* USE_TERMIO */ } /* * spcset(func, valp, valpp) * * This function takes various special characters (func), and * sets *valp to the current value of that character, and * *valpp to point to where in the "termbuf" structure that * value is kept. * * It returns the SLC_ level of support for this function. */ #ifndef USE_TERMIO - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; +int +spcset(int func, cc_t *valp, cc_t **valpp) { switch(func) { case SLC_EOF: *valp = termbuf.tc.t_eofc; *valpp = (cc_t *)&termbuf.tc.t_eofc; return(SLC_VARIABLE); case SLC_EC: *valp = termbuf.sg.sg_erase; *valpp = (cc_t *)&termbuf.sg.sg_erase; return(SLC_VARIABLE); case SLC_EL: *valp = termbuf.sg.sg_kill; *valpp = (cc_t *)&termbuf.sg.sg_kill; return(SLC_VARIABLE); case SLC_IP: *valp = termbuf.tc.t_intrc; *valpp = (cc_t *)&termbuf.tc.t_intrc; return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_ABORT: *valp = termbuf.tc.t_quitc; *valpp = (cc_t *)&termbuf.tc.t_quitc; return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_XON: *valp = termbuf.tc.t_startc; *valpp = (cc_t *)&termbuf.tc.t_startc; return(SLC_VARIABLE); case SLC_XOFF: *valp = termbuf.tc.t_stopc; *valpp = (cc_t *)&termbuf.tc.t_stopc; return(SLC_VARIABLE); case SLC_AO: *valp = termbuf.ltc.t_flushc; *valpp = (cc_t *)&termbuf.ltc.t_flushc; return(SLC_VARIABLE); case SLC_SUSP: *valp = termbuf.ltc.t_suspc; *valpp = (cc_t *)&termbuf.ltc.t_suspc; return(SLC_VARIABLE); case SLC_EW: *valp = termbuf.ltc.t_werasc; *valpp = (cc_t *)&termbuf.ltc.t_werasc; return(SLC_VARIABLE); case SLC_RP: *valp = termbuf.ltc.t_rprntc; *valpp = (cc_t *)&termbuf.ltc.t_rprntc; return(SLC_VARIABLE); case SLC_LNEXT: *valp = termbuf.ltc.t_lnextc; *valpp = (cc_t *)&termbuf.ltc.t_lnextc; return(SLC_VARIABLE); case SLC_FORW1: *valp = termbuf.tc.t_brkc; *valpp = (cc_t *)&termbuf.ltc.t_lnextc; return(SLC_VARIABLE); case SLC_BRK: case SLC_SYNCH: case SLC_AYT: case SLC_EOR: *valp = (cc_t)0; *valpp = (cc_t *)0; return(SLC_DEFAULT); default: *valp = (cc_t)0; *valpp = (cc_t *)0; return(SLC_NOSUPPORT); } } #else /* USE_TERMIO */ - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; -{ #define setval(a, b) *valp = termbuf.c_cc[a]; \ *valpp = &termbuf.c_cc[a]; \ return(b); #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); +int +spcset(int func, cc_t *valp, cc_t **valpp) +{ switch(func) { case SLC_EOF: setval(VEOF, SLC_VARIABLE); case SLC_EC: setval(VERASE, SLC_VARIABLE); case SLC_EL: setval(VKILL, SLC_VARIABLE); case SLC_IP: setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_ABORT: setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_XON: #ifdef VSTART setval(VSTART, SLC_VARIABLE); #else defval(0x13); #endif case SLC_XOFF: #ifdef VSTOP setval(VSTOP, SLC_VARIABLE); #else defval(0x11); #endif case SLC_EW: #ifdef VWERASE setval(VWERASE, SLC_VARIABLE); #else defval(0); #endif case SLC_RP: #ifdef VREPRINT setval(VREPRINT, SLC_VARIABLE); #else defval(0); #endif case SLC_LNEXT: #ifdef VLNEXT setval(VLNEXT, SLC_VARIABLE); #else defval(0); #endif case SLC_AO: #if !defined(VDISCARD) && defined(VFLUSHO) # define VDISCARD VFLUSHO #endif #ifdef VDISCARD setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); #else defval(0); #endif case SLC_SUSP: #ifdef VSUSP setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); #else defval(0); #endif #ifdef VEOL case SLC_FORW1: setval(VEOL, SLC_VARIABLE); #endif #ifdef VEOL2 case SLC_FORW2: setval(VEOL2, SLC_VARIABLE); #endif case SLC_AYT: #ifdef VSTATUS setval(VSTATUS, SLC_VARIABLE); #else defval(0); #endif case SLC_BRK: case SLC_SYNCH: case SLC_EOR: defval(0); default: *valp = 0; *valpp = 0; return(SLC_NOSUPPORT); } } #endif /* USE_TERMIO */ -#ifndef convex /* * getpty() * * Allocate a pty. As a side effect, the external character * array "line" contains the name of the slave side. * * Returns the file descriptor of the opened pty. */ +char alpha[] = "0123456789abcdefghijklmnopqrstuv"; char line[16]; - int -getpty(ptynum) -int *ptynum; +int +getpty(int *ptynum __unused) { - register int p; -#ifdef STREAMSPTY - int t; - char *ptsname(); + int p; + const char *cp; + char *p1, *p2; + int i; - p = open("/dev/ptmx", 2); - if (p > 0) { - grantpt(p); - unlockpt(p); - strcpy(line, ptsname(p)); - return(p); - } - -#else /* ! STREAMSPTY */ - register char *cp, *p1, *p2; - register int i; - (void) strcpy(line, _PATH_DEV); (void) strcat(line, "ptyXX"); p1 = &line[8]; p2 = &line[9]; for (cp = "pqrsPQRS"; *cp; cp++) { struct stat stb; *p1 = *cp; *p2 = '0'; /* * This stat() check is just to keep us from * looping through all 256 combinations if there * aren't that many ptys available. */ if (stat(line, &stb) < 0) break; for (i = 0; i < 32; i++) { - *p2 = "0123456789abcdefghijklmnopqrstuv"[i]; + *p2 = alpha[i]; p = open(line, 2); if (p > 0) { line[5] = 't'; chown(line, 0, 0); chmod(line, 0600); return(p); } } } -#endif /* STREAMSPTY */ return(-1); } -#endif /* convex */ #ifdef LINEMODE /* * tty_flowmode() Find out if flow control is enabled or disabled. * tty_linemode() Find out if linemode (external processing) is enabled. * tty_setlinemod(on) Turn on/off linemode. * tty_isecho() Find out if echoing is turned on. * tty_setecho(on) Enable/disable character echoing. * tty_israw() Find out if terminal is in RAW mode. * tty_binaryin(on) Turn on/off BINARY on input. * tty_binaryout(on) Turn on/off BINARY on output. * tty_isediting() Find out if line editing is enabled. * tty_istrapsig() Find out if signal trapping is enabled. * tty_setedit(on) Turn on/off line editing. * tty_setsig(on) Turn on/off signal trapping. * tty_issofttab() Find out if tab expansion is enabled. * tty_setsofttab(on) Turn on/off soft tab expansion. * tty_islitecho() Find out if typed control chars are echoed literally * tty_setlitecho() Turn on/off literal echo of control chars * tty_tspeed(val) Set transmit speed to val. * tty_rspeed(val) Set receive speed to val. */ -#ifdef convex -static int linestate; -#endif - int -tty_linemode() +int +tty_linemode(void) { -#ifndef convex #ifndef USE_TERMIO return(termbuf.state & TS_EXTPROC); #else return(termbuf.c_lflag & EXTPROC); #endif -#else - return(linestate); -#endif } - void -tty_setlinemode(on) - int on; +void +tty_setlinemode(int on) { #ifdef TIOCEXT -# ifndef convex set_termbuf(); -# else - linestate = on; -# endif (void) ioctl(pty, TIOCEXT, (char *)&on); -# ifndef convex init_termbuf(); -# endif #else /* !TIOCEXT */ # ifdef EXTPROC if (on) termbuf.c_lflag |= EXTPROC; else termbuf.c_lflag &= ~EXTPROC; # endif #endif /* TIOCEXT */ } #endif /* LINEMODE */ - int -tty_isecho() +int +tty_isecho(void) { #ifndef USE_TERMIO return (termbuf.sg.sg_flags & ECHO); #else return (termbuf.c_lflag & ECHO); #endif } - int -tty_flowmode() +int +tty_flowmode(void) { #ifndef USE_TERMIO return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); #else return((termbuf.c_iflag & IXON) ? 1 : 0); #endif } - int -tty_restartany() +int +tty_restartany(void) { #ifndef USE_TERMIO # ifdef DECCTQ return((termbuf.lflags & DECCTQ) ? 0 : 1); # else return(-1); # endif #else return((termbuf.c_iflag & IXANY) ? 1 : 0); #endif } - void -tty_setecho(on) - int on; +void +tty_setecho(int on) { #ifndef USE_TERMIO if (on) termbuf.sg.sg_flags |= ECHO|CRMOD; else termbuf.sg.sg_flags &= ~(ECHO|CRMOD); #else if (on) termbuf.c_lflag |= ECHO; else termbuf.c_lflag &= ~ECHO; #endif } - int -tty_israw() +int +tty_israw(void) { #ifndef USE_TERMIO return(termbuf.sg.sg_flags & RAW); #else return(!(termbuf.c_lflag & ICANON)); #endif } -#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - int -tty_setraw(on) +#ifdef AUTHENTICATION +#if defined(NO_LOGIN_F) && defined(LOGIN_R) +int +tty_setraw(int on) { # ifndef USE_TERMIO if (on) termbuf.sg.sg_flags |= RAW; else termbuf.sg.sg_flags &= ~RAW; # else if (on) termbuf.c_lflag &= ~ICANON; else termbuf.c_lflag |= ICANON; # endif } #endif +#endif /* AUTHENTICATION */ - void -tty_binaryin(on) - int on; +void +tty_binaryin(int on) { #ifndef USE_TERMIO if (on) termbuf.lflags |= LPASS8; else termbuf.lflags &= ~LPASS8; #else if (on) { termbuf.c_iflag &= ~ISTRIP; } else { termbuf.c_iflag |= ISTRIP; } #endif } - void -tty_binaryout(on) - int on; +void +tty_binaryout(int on) { #ifndef USE_TERMIO if (on) termbuf.lflags |= LLITOUT; else termbuf.lflags &= ~LLITOUT; #else if (on) { termbuf.c_cflag &= ~(CSIZE|PARENB); termbuf.c_cflag |= CS8; termbuf.c_oflag &= ~OPOST; } else { termbuf.c_cflag &= ~CSIZE; termbuf.c_cflag |= CS7|PARENB; termbuf.c_oflag |= OPOST; } #endif } - int -tty_isbinaryin() +int +tty_isbinaryin(void) { #ifndef USE_TERMIO return(termbuf.lflags & LPASS8); #else return(!(termbuf.c_iflag & ISTRIP)); #endif } - int -tty_isbinaryout() +int +tty_isbinaryout(void) { #ifndef USE_TERMIO return(termbuf.lflags & LLITOUT); #else return(!(termbuf.c_oflag&OPOST)); #endif } #ifdef LINEMODE - int -tty_isediting() +int +tty_isediting(void) { #ifndef USE_TERMIO return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); #else return(termbuf.c_lflag & ICANON); #endif } - int -tty_istrapsig() +int +tty_istrapsig(void) { #ifndef USE_TERMIO return(!(termbuf.sg.sg_flags&RAW)); #else return(termbuf.c_lflag & ISIG); #endif } - void -tty_setedit(on) - int on; +void +tty_setedit(int on) { #ifndef USE_TERMIO if (on) termbuf.sg.sg_flags &= ~CBREAK; else termbuf.sg.sg_flags |= CBREAK; #else if (on) termbuf.c_lflag |= ICANON; else termbuf.c_lflag &= ~ICANON; #endif } - void -tty_setsig(on) - int on; +void +tty_setsig(int on) { #ifndef USE_TERMIO if (on) ; #else if (on) termbuf.c_lflag |= ISIG; else termbuf.c_lflag &= ~ISIG; #endif } #endif /* LINEMODE */ - int -tty_issofttab() +int +tty_issofttab(void) { #ifndef USE_TERMIO return (termbuf.sg.sg_flags & XTABS); #else # ifdef OXTABS return (termbuf.c_oflag & OXTABS); # endif # ifdef TABDLY return ((termbuf.c_oflag & TABDLY) == TAB3); # endif #endif } - void -tty_setsofttab(on) - int on; +void +tty_setsofttab(int on) { #ifndef USE_TERMIO if (on) termbuf.sg.sg_flags |= XTABS; else termbuf.sg.sg_flags &= ~XTABS; #else if (on) { # ifdef OXTABS termbuf.c_oflag |= OXTABS; # endif # ifdef TABDLY termbuf.c_oflag &= ~TABDLY; termbuf.c_oflag |= TAB3; # endif } else { # ifdef OXTABS termbuf.c_oflag &= ~OXTABS; # endif # ifdef TABDLY termbuf.c_oflag &= ~TABDLY; termbuf.c_oflag |= TAB0; # endif } #endif } - int -tty_islitecho() +int +tty_islitecho(void) { #ifndef USE_TERMIO return (!(termbuf.lflags & LCTLECH)); #else # ifdef ECHOCTL return (!(termbuf.c_lflag & ECHOCTL)); # endif # ifdef TCTLECH return (!(termbuf.c_lflag & TCTLECH)); # endif # if !defined(ECHOCTL) && !defined(TCTLECH) return (0); /* assumes ctl chars are echoed '^x' */ # endif #endif } - void -tty_setlitecho(on) - int on; +void +tty_setlitecho(int on) { #ifndef USE_TERMIO if (on) termbuf.lflags &= ~LCTLECH; else termbuf.lflags |= LCTLECH; #else # ifdef ECHOCTL if (on) termbuf.c_lflag &= ~ECHOCTL; else termbuf.c_lflag |= ECHOCTL; # endif # ifdef TCTLECH if (on) termbuf.c_lflag &= ~TCTLECH; else termbuf.c_lflag |= TCTLECH; # endif #endif } - int -tty_iscrnl() +int +tty_iscrnl(void) { #ifndef USE_TERMIO return (termbuf.sg.sg_flags & CRMOD); #else return (termbuf.c_iflag & ICRNL); #endif } /* * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). */ #if B4800 != 4800 #define DECODE_BAUD #endif #ifdef DECODE_BAUD /* * A table of available terminal speeds */ struct termspeeds { int speed; int value; } termspeeds[] = { { 0, B0 }, { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, #ifdef B7200 { 7200, B7200 }, #endif { 9600, B9600 }, #ifdef B14400 { 14400, B14400 }, #endif #ifdef B19200 { 19200, B19200 }, #endif #ifdef B28800 { 28800, B28800 }, #endif #ifdef B38400 { 38400, B38400 }, #endif #ifdef B57600 { 57600, B57600 }, #endif #ifdef B115200 { 115200, B115200 }, #endif #ifdef B230400 { 230400, B230400 }, #endif { -1, 0 } }; #endif /* DECODE_BAUD */ - void -tty_tspeed(val) - int val; +void +tty_tspeed(int val) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ; if (tp->speed == -1) /* back up to last valid value */ --tp; cfsetospeed(&termbuf, tp->value); #else /* DECODE_BAUD */ cfsetospeed(&termbuf, val); #endif /* DECODE_BAUD */ } - void -tty_rspeed(val) - int val; +void +tty_rspeed(int val) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ; if (tp->speed == -1) /* back up to last valid value */ --tp; cfsetispeed(&termbuf, tp->value); #else /* DECODE_BAUD */ cfsetispeed(&termbuf, val); #endif /* DECODE_BAUD */ } -#ifdef PARENT_DOES_UTMP -# ifndef NEWINIT -extern struct utmp wtmp; -extern char wtmpf[]; -# else /* NEWINIT */ -int gotalarm; - - /* ARGSUSED */ - void -nologinproc(sig) - int sig; -{ - gotalarm++; -} -# endif /* NEWINIT */ -#endif /* PARENT_DOES_UTMP */ - -#ifndef NEWINIT -# ifdef PARENT_DOES_UTMP -extern void utmp_sig_init P((void)); -extern void utmp_sig_reset P((void)); -extern void utmp_sig_wait P((void)); -extern void utmp_sig_notify P((int)); -# endif /* PARENT_DOES_UTMP */ -#endif - /* * getptyslave() * * Open the slave side of the pty, and do any initialization * that is necessary. */ - void -getptyslave() +static void +getptyslave(void) { - register int t = -1; + int t = -1; char erase; # ifdef LINEMODE int waslm; # endif # ifdef TIOCGWINSZ struct winsize ws; extern int def_row, def_col; # endif extern int def_tspeed, def_rspeed; /* * Opening the slave side may cause initilization of the * kernel tty structure. We need remember the state of * if linemode was turned on * terminal window size * terminal speed * erase character * so that we can re-set them if we need to. */ # ifdef LINEMODE waslm = tty_linemode(); # endif erase = termbuf.c_cc[VERASE]; /* * Make sure that we don't have a controlling tty, and * that we are the session (process group) leader. */ # ifdef TIOCNOTTY t = open(_PATH_TTY, O_RDWR); if (t >= 0) { (void) ioctl(t, TIOCNOTTY, (char *)0); (void) close(t); } # endif - -# ifdef PARENT_DOES_UTMP - /* - * Wait for our parent to get the utmp stuff to get done. - */ - utmp_sig_wait(); -# endif - t = cleanopen(line); if (t < 0) fatalperror(net, line); -#ifdef STREAMSPTY -#ifdef USE_TERMIO - ttyfd = t; -#endif - if (ioctl(t, I_PUSH, "ptem") < 0) - fatal(net, "I_PUSH ptem"); - if (ioctl(t, I_PUSH, "ldterm") < 0) - fatal(net, "I_PUSH ldterm"); - if (ioctl(t, I_PUSH, "ttcompat") < 0) - fatal(net, "I_PUSH ttcompat"); - if (ioctl(pty, I_PUSH, "pckt") < 0) - fatal(net, "I_PUSH pckt"); -#endif /* * set up the tty modes as we like them to be. */ init_termbuf(); # ifdef TIOCGWINSZ if (def_row || def_col) { memset((char *)&ws, 0, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; (void)ioctl(t, TIOCSWINSZ, (char *)&ws); } # endif /* * Settings for sgtty based systems */ # ifndef USE_TERMIO termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; # endif /* USE_TERMIO */ /* * Settings for all other termios/termio based * systems, other than 4.4BSD. In 4.4BSD the * kernel does the initial terminal setup. */ -# if defined(USE_TERMIO) && (BSD <= 43) -# ifndef OXTABS -# define OXTABS 0 -# endif - termbuf.c_lflag |= ECHO; - termbuf.c_oflag |= ONLCR|OXTABS; - termbuf.c_iflag |= ICRNL; - termbuf.c_iflag &= ~IXOFF; -# endif /* defined(USE_TERMIO) && (BSD <= 43) */ tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); if (erase) termbuf.c_cc[VERASE] = erase; # ifdef LINEMODE if (waslm) tty_setlinemode(1); # endif /* LINEMODE */ /* * Set the tty modes, and make this our controlling tty. */ set_termbuf(); if (login_tty(t) == -1) fatalperror(net, "login_tty"); if (net > 2) (void) close(net); -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) +#ifdef AUTHENTICATION +#if defined(NO_LOGIN_F) && defined(LOGIN_R) /* * Leave the pty open so that we can write out the rlogin * protocol for /bin/login, if the authentication works. */ #else if (pty > 2) { (void) close(pty); pty = -1; } #endif +#endif /* AUTHENTICATION */ } #ifndef O_NOCTTY #define O_NOCTTY 0 #endif /* * Open the specified slave side of the pty, * making sure that we have a clean tty. */ - int -cleanopen(line) - char *line; +int +cleanopen(char *li) { - register int t; + int t; -#ifndef STREAMSPTY /* * Make sure that other people can't open the * slave side of the connection. */ - (void) chown(line, 0, 0); - (void) chmod(line, 0600); -#endif + (void) chown(li, 0, 0); + (void) chmod(li, 0600); - (void) revoke(line); + (void) revoke(li); t = open(line, O_RDWR|O_NOCTTY); if (t < 0) return(-1); - /* - * Hangup anybody else using this ttyp, then reopen it for - * ourselves. - */ -# if (BSD <= 43) && !defined(STREAMSPTY) - (void) signal(SIGHUP, SIG_IGN); - vhangup(); - (void) signal(SIGHUP, SIG_DFL); - t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); -# endif return(t); } -#if BSD <= 43 - - int -login_tty(t) - int t; -{ - if (setsid() < 0) { -#ifdef ultrix - /* - * The setsid() may have failed because we - * already have a pgrp == pid. Zero out - * our pgrp and try again... - */ - if ((setpgrp(0, 0) < 0) || (setsid() < 0)) -#endif - fatalperror(net, "setsid()"); - } -# ifdef TIOCSCTTY - if (ioctl(t, TIOCSCTTY, (char *)0) < 0) - fatalperror(net, "ioctl(sctty)"); -# else - /* - * We get our controlling tty assigned as a side-effect - * of opening up a tty device. But on BSD based systems, - * this only happens if our process group is zero. The - * setsid() call above may have set our pgrp, so clear - * it out before opening the tty... - */ - (void) setpgrp(0, 0); - close(open(line, O_RDWR)); -# endif - if (t != 0) - (void) dup2(t, 0); - if (t != 1) - (void) dup2(t, 1); - if (t != 2) - (void) dup2(t, 2); - if (t > 2) - close(t); - return(0); -} -#endif /* BSD <= 43 */ - -#ifdef NEWINIT -char *gen_id = "fe"; -#endif - /* * startslave(host) * * Given a hostname, do whatever * is necessary to startup the login process on the slave side of the pty. */ /* ARGSUSED */ - void -startslave(host, autologin, autoname) - char *host; - int autologin; - char *autoname; +void +startslave(char *host, int autologin, char *autoname) { - register int i; -#ifdef NEWINIT - extern char *ptyip; - struct init_request request; - void nologinproc(); - register int n; -#endif /* NEWINIT */ + int i; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION if (!autoname || !autoname[0]) autologin = 0; if (autologin < auth_level) { fatal(net, "Authorization failed"); exit(1); } #endif -#ifndef NEWINIT -# ifdef PARENT_DOES_UTMP - utmp_sig_init(); -# endif /* PARENT_DOES_UTMP */ if ((i = fork()) < 0) fatalperror(net, "fork"); if (i) { -# ifdef PARENT_DOES_UTMP - /* - * Cray parent will create utmp entry for child and send - * signal to child to tell when done. Child waits for signal - * before doing anything important. - */ - register int pid = i; - void sigjob P((int)); - - setpgrp(); - utmp_sig_reset(); /* reset handler to default */ - /* - * Create utmp entry for child - */ - (void) time(&wtmp.ut_time); - wtmp.ut_type = LOGIN_PROCESS; - wtmp.ut_pid = pid; - SCPYN(wtmp.ut_user, "LOGIN"); - SCPYN(wtmp.ut_host, host); - SCPYN(wtmp.ut_line, line + sizeof(_PATH_DEV) - 1); - SCPYN(wtmp.ut_id, wtmp.ut_line+3); - pututline(&wtmp); - endutent(); - if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { - (void) write(i, (char *)&wtmp, sizeof(struct utmp)); - (void) close(i); - } - utmp_sig_notify(pid); -# endif /* PARENT_DOES_UTMP */ } else { - getptyslave(autologin); + getptyslave(); start_login(host, autologin, autoname); /*NOTREACHED*/ } -#else /* NEWINIT */ - - /* - * Init will start up login process if we ask nicely. We only wait - * for it to start up and begin normal telnet operation. - */ - if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { - char tbuf[128]; - (void) snprintf(tbuf, sizeof(tbuf), "Can't open %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - memset((char *)&request, 0, sizeof(request)); - request.magic = INIT_MAGIC; - SCPYN(request.gen_id, gen_id); - SCPYN(request.tty_id, &line[8]); - SCPYN(request.host, host); - SCPYN(request.term_type, terminaltype ? terminaltype : "network"); - request.signal = SIGCLD; - request.pid = getpid(); -#ifdef BFTPDAEMON - /* - * Are we working as the bftp daemon? - */ - if (bftpd) { - SCPYN(request.exec_name, BFTPPATH); - } -#endif /* BFTPDAEMON */ - if (write(i, (char *)&request, sizeof(request)) < 0) { - char tbuf[128]; - (void) snprintf(tbuf, sizeof(tbuf), "Can't write to %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - (void) close(i); - (void) signal(SIGALRM, nologinproc); - for (i = 0; ; i++) { - char tbuf[128]; - alarm(15); - n = read(pty, ptyip, BUFSIZ); - if (i == 3 || n >= 0 || !gotalarm) - break; - gotalarm = 0; - snprintf(tbuf, sizeof(tbuf), "telnetd: waiting for /etc/init to start login process on %s\r\n", line); - (void) write(net, tbuf, strlen(tbuf)); - } - if (n < 0 && gotalarm) - fatal(net, "/etc/init didn't start login process"); - pcc += n; - alarm(0); - (void) signal(SIGALRM, SIG_DFL); - - return; -#endif /* NEWINIT */ } -char *envinit[3]; -extern char **environ; - - void -init_env() +void +init_env(void) { - extern char *getenv(); char **envp; envp = envinit; if ((*envp = getenv("TZ"))) *envp++ -= 3; *envp = 0; environ = envinit; } -#ifndef NEWINIT /* * start_login(host) * * Assuming that we are now running as a child processes, this * function will turn us into the login process. */ - void -start_login(host, autologin, name) - char *host; - int autologin; - char *name; -{ - register char **argv; - char **addarg(), *user; - extern char *getenv(); -#ifdef UTMPX - register int pid = getpid(); - struct utmpx utmpx; +#ifndef AUTHENTICATION +#define undef1 __unused +#else +#define undef1 #endif -#ifdef SOLARIS - char *term; - char termbuf[64]; -#endif -#ifdef UTMPX - /* - * Create utmp entry for child - */ +void +start_login(char *host undef1, int autologin undef1, char *name undef1) +{ + char **argv; - memset(&utmpx, 0, sizeof(utmpx)); - SCPYN(utmpx.ut_user, ".telnet"); - SCPYN(utmpx.ut_line, line + sizeof(_PATH_DEV) - 1); - utmpx.ut_pid = pid; - utmpx.ut_id[0] = 't'; - utmpx.ut_id[1] = 'n'; - utmpx.ut_id[2] = SC_WILDC; - utmpx.ut_id[3] = SC_WILDC; - utmpx.ut_type = LOGIN_PROCESS; - (void) time(&utmpx.ut_tv.tv_sec); - if (makeutx(&utmpx) == NULL) - fatal(net, "makeutx failed"); -#endif - scrub_env(); /* * -h : pass on name of host. * WARNING: -h is accepted by login if and only if * getuid() == 0. * -p : don't clobber the environment (so terminal type stays set). * * -f : force this login, he has already been authenticated */ argv = addarg(0, "login"); #if !defined(NO_LOGIN_H) - -# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) +#ifdef AUTHENTICATION +# if defined(NO_LOGIN_F) && defined(LOGIN_R) /* * Don't add the "-h host" option if we are going * to be adding the "-r host" option down below... */ if ((auth_level < 0) || (autologin != AUTH_VALID)) # endif { argv = addarg(argv, "-h"); argv = addarg(argv, host); -#ifdef SOLARIS - /* - * SVR4 version of -h takes TERM= as second arg, or - - */ - term = getenv("TERM"); - if (term == NULL || term[0] == 0) { - term = "-"; - } else { - strcpy(termbuf, "TERM="); - strncat(termbuf, term, sizeof(termbuf) - 6); - term = termbuf; - } - argv = addarg(argv, term); -#endif } +#endif /* AUTHENTICATION */ #endif #if !defined(NO_LOGIN_P) argv = addarg(argv, "-p"); #endif #ifdef LINEMODE /* * Set the environment variable "LINEMODE" to either * "real" or "kludge" if we are operating in either * real or kludge linemode. */ if (lmodetype == REAL_LINEMODE) setenv("LINEMODE", "real", 1); # ifdef KLUDGELINEMODE else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) setenv("LINEMODE", "kludge", 1); # endif #endif #ifdef BFTPDAEMON /* * Are we working as the bftp daemon? If so, then ask login * to start bftp instead of shell. */ if (bftpd) { argv = addarg(argv, "-e"); argv = addarg(argv, BFTPPATH); } else #endif -#if defined (SecurID) - /* - * don't worry about the -f that might get sent. - * A -s is supposed to override it anyhow. - */ - if (require_SecurID) - argv = addarg(argv, "-s"); -#endif -#if defined (AUTHENTICATION) +#ifdef AUTHENTICATION if (auth_level >= 0 && autologin == AUTH_VALID) { # if !defined(NO_LOGIN_F) argv = addarg(argv, "-f"); argv = addarg(argv, "--"); argv = addarg(argv, name); # else # if defined(LOGIN_R) /* * We don't have support for "login -f", but we * can fool /bin/login into thinking that we are * rlogind, and allow us to log in without a * password. The rlogin protocol expects * local-user\0remote-user\0term/speed\0 */ if (pty > 2) { - register char *cp; + char *cp; char speed[128]; int isecho, israw, xpty, len; extern int def_rspeed; # ifndef LOGIN_HOST /* * Tell login that we are coming from "localhost". * If we passed in the real host name, then the * user would have to allow .rhost access from * every machine that they want authenticated * access to work from, which sort of defeats * the purpose of an authenticated login... * So, we tell login that the session is coming * from "localhost", and the user will only have * to have "localhost" in their .rhost file. */ # define LOGIN_HOST "localhost" # endif argv = addarg(argv, "-r"); argv = addarg(argv, LOGIN_HOST); xpty = pty; -# ifndef STREAMSPTY pty = 0; -# else - ttyfd = 0; -# endif init_termbuf(); isecho = tty_isecho(); israw = tty_israw(); if (isecho || !israw) { tty_setecho(0); /* Turn off echo */ tty_setraw(1); /* Turn on raw */ set_termbuf(); } len = strlen(name)+1; write(xpty, name, len); write(xpty, name, len); snprintf(speed, sizeof(speed), "%s/%d", (cp = getenv("TERM")) ? cp : "", (def_rspeed > 0) ? def_rspeed : 9600); len = strlen(speed)+1; write(xpty, speed, len); if (isecho || !israw) { init_termbuf(); tty_setecho(isecho); tty_setraw(israw); set_termbuf(); if (!israw) { /* * Write a newline to ensure * that login will be able to * read the line... */ write(xpty, "\n", 1); } } pty = xpty; } # else argv = addarg(argv, "--"); argv = addarg(argv, name); # endif # endif } else #endif if (getenv("USER")) { argv = addarg(argv, "--"); argv = addarg(argv, getenv("USER")); #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) { - register char **cpp; + char **cpp; for (cpp = environ; *cpp; cpp++) argv = addarg(argv, *cpp); } #endif /* * Assume that login will set the USER variable * correctly. For SysV systems, this means that * USER will no longer be set, just LOGNAME by * login. (The problem is that if the auto-login * fails, and the user then specifies a different * account name, he can get logged in with both * LOGNAME and USER in his environment, but the * USER value will be wrong. */ unsetenv("USER"); } -#ifdef SOLARIS - else { - char **p; - - argv = addarg(argv, ""); /* no login name */ - for (p = environ; *p; p++) { - argv = addarg(argv, *p); - } - } -#endif /* SOLARIS */ -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) +#ifdef AUTHENTICATION +#if defined(NO_LOGIN_F) && defined(LOGIN_R) if (pty > 2) close(pty); #endif +#endif /* AUTHENTICATION */ closelog(); if (altlogin == NULL) { altlogin = _PATH_LOGIN; } execv(altlogin, argv); syslog(LOG_ERR, "%s: %m", altlogin); fatalperror(net, altlogin); /*NOTREACHED*/ } - char ** -addarg(argv, val) - register char **argv; - register char *val; +static char ** +addarg(char **argv, const char *val) { - register char **cpp; + char **cpp; if (argv == NULL) { /* * 10 entries, a leading length, and a null */ argv = (char **)malloc(sizeof(*argv) * 12); if (argv == NULL) return(NULL); *argv++ = (char *)10; *argv = (char *)0; } for (cpp = argv; *cpp; cpp++) ; if (cpp == &argv[(int)argv[-1]]) { --argv; *argv = (char *)((int)(*argv) + 10); argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2)); if (argv == NULL) return(NULL); argv++; cpp = &argv[(int)argv[-1] - 10]; } - *cpp++ = val; + *cpp++ = strdup(val); *cpp = 0; return(argv); } -#endif /* NEWINIT */ /* * scrub_env() * * We only accept the environment variables listed below. */ - void -scrub_env() +void +scrub_env(void) { - static const char *reject[] = { + static const char *rej[] = { "TERMCAP=/", NULL }; - static const char *accept[] = { + static const char *acc[] = { "XAUTH=", "XAUTHORITY=", "DISPLAY=", "TERM=", "EDITOR=", "PAGER=", "LOGNAME=", "POSIXLY_CORRECT=", "PRINTER=", NULL }; char **cpp, **cpp2; const char **p; for (cpp2 = cpp = environ; *cpp; cpp++) { int reject_it = 0; - for(p = reject; *p; p++) + for(p = rej; *p; p++) if(strncmp(*cpp, *p, strlen(*p)) == 0) { reject_it = 1; break; } if (reject_it) continue; - for(p = accept; *p; p++) + for(p = acc; *p; p++) if(strncmp(*cpp, *p, strlen(*p)) == 0) break; if(*p != NULL) *cpp2++ = *cpp; } *cpp2 = NULL; } /* * cleanup() * * This is the routine to call when we are all through, to * clean up anything that needs to be cleaned up. */ - /* ARGSUSED */ - void -cleanup(sig) - int sig; +/* ARGSUSED */ +void +cleanup(int sig __unused) { -#ifndef PARENT_DOES_UTMP -# if (BSD > 43) || defined(convex) char *p; p = line + sizeof(_PATH_DEV) - 1; if (logout(p)) logwtmp(p, "", ""); (void)chmod(line, 0666); (void)chown(line, 0, 0); *p = 'p'; (void)chmod(line, 0666); (void)chown(line, 0, 0); (void) shutdown(net, 2); exit(1); -# else - void rmut(); - - rmut(); - vhangup(); /* XXX */ - (void) shutdown(net, 2); - exit(1); -# endif -#else /* PARENT_DOES_UTMP */ -# ifdef NEWINIT - (void) shutdown(net, 2); - exit(1); -# else /* NEWINIT */ - rmut(line); - close(pty); - (void) shutdown(net, 2); - exit(1); -# endif /* NEWINT */ -#endif /* PARENT_DOES_UTMP */ } - -#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) -/* - * _utmp_sig_rcv - * utmp_sig_init - * utmp_sig_wait - * These three functions are used to coordinate the handling of - * the utmp file between the server and the soon-to-be-login shell. - * The server actually creates the utmp structure, the child calls - * utmp_sig_wait(), until the server calls utmp_sig_notify() and - * signals the future-login shell to proceed. - */ -static int caught=0; /* NZ when signal intercepted */ -static void (*func)(); /* address of previous handler */ - - void -_utmp_sig_rcv(sig) - int sig; -{ - caught = 1; - (void) signal(SIGUSR1, func); -} - - void -utmp_sig_init() -{ - /* - * register signal handler for UTMP creation - */ - if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) - fatalperror(net, "telnetd/signal"); -} - - void -utmp_sig_reset() -{ - (void) signal(SIGUSR1, func); /* reset handler to default */ -} - - void -utmp_sig_wait() -{ - /* - * Wait for parent to write our utmp entry. - */ - sigoff(); - while (caught == 0) { - pause(); /* wait until we get a signal (sigon) */ - sigoff(); /* turn off signals while we check caught */ - } - sigon(); /* turn on signals again */ -} - - void -utmp_sig_notify(pid) -{ - kill(pid, SIGUSR1); -} - -#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ - -/* - * rmut() - * - * This is the function called by cleanup() to - * remove the utmp entry for this person. - */ - -#ifdef UTMPX - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - struct utmpx *utxp, utmpx; - - /* - * This updates the utmpx and utmp entries and make a wtmp/x entry - */ - - SCPYN(utmpx.ut_line, line + sizeof(_PATH_DEV) - 1); - utxp = getutxline(&utmpx); - if (utxp) { - utxp->ut_type = DEAD_PROCESS; - utxp->ut_exit.e_termination = 0; - utxp->ut_exit.e_exit = 0; - (void) time(&utmpx.ut_tv.tv_sec); - utmpx.ut_tv.tv_usec = 0; - modutx(utxp); - } - endutxent(); -} /* end of rmut */ -#endif - -#if !defined(UTMPX) && BSD <= 43 - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - f = open(utmpf, O_RDWR); - if (f >= 0) { - (void) fstat(f, &statbf); - utmp = (struct utmp *)malloc((unsigned)statbf.st_size); - if (!utmp) - syslog(LOG_ERR, "utmp malloc failed"); - if (statbf.st_size && utmp) { - nutmp = read(f, (char *)utmp, (int)statbf.st_size); - nutmp /= sizeof(struct utmp); - - for (u = utmp ; u < &utmp[nutmp] ; u++) { - if (SCMPN(u->ut_line, line+5) || - u->ut_name[0]==0) - continue; - (void) lseek(f, ((long)u)-((long)utmp), L_SET); - SCPYN(u->ut_name, ""); - SCPYN(u->ut_host, ""); - (void) time(&u->ut_time); - (void) write(f, (char *)u, sizeof(wtmp)); - found++; - } - } - (void) close(f); - } - if (found) { - f = open(wtmpf, O_WRONLY|O_APPEND); - if (f >= 0) { - SCPYN(wtmp.ut_line, line+5); - SCPYN(wtmp.ut_name, ""); - SCPYN(wtmp.ut_host, ""); - (void) time(&wtmp.ut_time); - (void) write(f, (char *)&wtmp, sizeof(wtmp)); - (void) close(f); - } - } - (void) chmod(line, 0666); - (void) chown(line, 0, 0); - line[strlen(_PATH_DEV)] = 'p'; - (void) chmod(line, 0666); - (void) chown(line, 0, 0); -} /* end of rmut */ -#endif Index: head/contrib/telnet/telnetd/telnetd.8 =================================================================== --- head/contrib/telnet/telnetd/telnetd.8 (revision 87138) +++ head/contrib/telnet/telnetd/telnetd.8 (revision 87139) @@ -1,607 +1,587 @@ .\" Copyright (c) 1983, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)telnetd.8 8.4 (Berkeley) 6/1/94 .\" $FreeBSD$ .\" .Dd January 27, 2000 .Dt TELNETD 8 .Os .Sh NAME .Nm telnetd .Nd DARPA .Tn TELNET protocol server .Sh SYNOPSIS .Nm /usr/libexec/telnetd .Op Fl BUhlkns .Op Fl D Ar debugmode .Op Fl S Ar tos .Op Fl X Ar authtype .Op Fl a Ar authmode .Op Fl edebug .Op Fl p Ar loginprog .Op Fl r Ns Ar lowpty-highpty .Op Fl u Ar len .Op Fl debug Op Ar port .Sh DESCRIPTION The .Nm command is a server which supports the .Tn DARPA standard .Tn TELNET virtual terminal protocol. .Nm Telnetd is normally invoked by the internet server (see .Xr inetd 8 ) for requests to connect to the .Tn TELNET port as indicated by the .Pa /etc/services file (see .Xr services 5 ) . The .Fl debug option may be used to start up .Nm manually, instead of through .Xr inetd 8 . If started up this way, .Ar port may be specified to run .Nm on an alternate .Tn TCP port number. .Pp The .Nm command accepts the following options: .Bl -tag -width indent .It Fl a Ar authmode This option may be used for specifying what mode should be used for authentication. Note that this option is only useful if .Nm has been compiled with support for the .Dv AUTHENTICATION option. There are several valid values for .Ar authmode : .Bl -tag -width debug .It Cm debug Turn on authentication debugging code. .It Cm user Only allow connections when the remote user can provide valid authentication information to identify the remote user, and is allowed access to the specified account without providing a password. .It Cm valid Only allow connections when the remote user can provide valid authentication information to identify the remote user. The .Xr login 1 command will provide any additional user verification needed if the remote user is not allowed automatic access to the specified account. .It Cm other Only allow connections that supply some authentication information. This option is currently not supported by any of the existing authentication mechanisms, and is thus the same as specifying .Fl a .Cm valid . .It Cm none This is the default state. Authentication information is not required. If no or insufficient authentication information is provided, then the .Xr login 1 program will provide the necessary user verification. .It Cm off Disable the authentication code. All user verification will happen through the .Xr login 1 program. .El .It Fl B Specify bftp server mode. In this mode, .Nm causes login to start a .Xr bftp 1 session rather than the user's normal shell. In bftp daemon mode normal logins are not supported, and it must be used on a port other than the normal .Tn TELNET port. .It Fl D Ar debugmode This option may be used for debugging purposes. This allows .Nm to print out debugging information to the connection, allowing the user to see what .Nm is doing. There are several possible values for .Ar debugmode : .Bl -tag -width exercise .It Cm options Print information about the negotiation of .Tn TELNET options. .It Cm report Print the .Cm options information, plus some additional information about what processing is going on. .It Cm netdata Display the data stream received by .Nm . .It Cm ptydata Display data written to the pty. .It Cm exercise Has not been implemented yet. .El .It Fl debug Enable debugging on each socket created by .Nm (see .Dv SO_DEBUG in .Xr socket 2 ) . .It Fl edebug If .Nm has been compiled with support for data encryption, then the .Fl edebug option may be used to enable encryption debugging code. .It Fl p Ar loginprog Specify an alternate .Xr login 1 command to run to complete the login. The alternate command must understand the same command arguments as the standard login. .It Fl h Disable the printing of host-specific information before login has been completed. .It Fl k This option is only useful if .Nm has been compiled with both linemode and kludge linemode support. If the .Fl k option is specified, then if the remote client does not support the .Dv LINEMODE option, then .Nm will operate in character at a time mode. It will still support kludge linemode, but will only go into kludge linemode if the remote client requests it. (This is done by the client sending .Dv DONT SUPPRESS-GO-AHEAD and .Dv DONT ECHO . ) The .Fl k option is most useful when there are remote clients that do not support kludge linemode, but pass the heuristic (if they respond with .Dv WILL TIMING-MARK in response to a .Dv DO TIMING-MARK ) for kludge linemode support. .It Fl l Specify line mode. Try to force clients to use line- at-a-time mode. If the .Dv LINEMODE option is not supported, it will go into kludge linemode. .It Fl n Disable .Dv TCP keep-alives. Normally .Nm enables the .Tn TCP keep-alive mechanism to probe connections that have been idle for some period of time to determine if the client is still there, so that idle connections from machines that have crashed or can no longer be reached may be cleaned up. -.It Fl s -This option is only enabled if -.Nm -is compiled with support for -.Tn SecurID -cards. -It causes the -.Fl s -option to be passed on to -.Xr login 1 , -and thus is only useful if -.Xr login 1 -supports the -.Fl s -flag to indicate that only -.Tn SecurID -validated logins are allowed, and is -usually useful for controlling remote logins -from outside of a firewall. -.It Fl S Ar tos .It Fl u Ar len This option is used to specify the size of the field in the .Dv utmp structure that holds the remote host name. If the resolved host name is longer than .Ar len , the dotted decimal value will be used instead. This allows hosts with very long host names that overflow this field to still be uniquely identified. Specifying .Fl u0 indicates that only dotted decimal addresses should be put into the .Pa utmp file. .It Fl U This option causes .Nm to refuse connections from addresses that cannot be mapped back into a symbolic name via the .Xr gethostbyaddr 3 routine. .It Fl X Ar authtype This option is only valid if .Nm has been built with support for the authentication option. It disables the use of .Ar authtype authentication, and can be used to temporarily disable a specific authentication type without having to recompile .Nm . .El .Pp .Nm Telnetd operates by allocating a pseudo-terminal device (see .Xr pty 4 ) for a client, then creating a login process which has the slave side of the pseudo-terminal as .Dv stdin , .Dv stdout and .Dv stderr . .Nm Telnetd manipulates the master side of the pseudo-terminal, implementing the .Tn TELNET protocol and passing characters between the remote client and the login process. .Pp When a .Tn TELNET session is started up, .Nm sends .Tn TELNET options to the client side indicating a willingness to do the following .Tn TELNET options, which are described in more detail below: .Bd -literal -offset indent DO AUTHENTICATION WILL ENCRYPT DO TERMINAL TYPE DO TSPEED DO XDISPLOC DO NEW-ENVIRON DO ENVIRON WILL SUPPRESS GO AHEAD DO ECHO DO LINEMODE DO NAWS WILL STATUS DO LFLOW DO TIMING-MARK .Ed .Pp The pseudo-terminal allocated to the client is configured to operate in .Dq cooked mode, and with .Dv XTABS and .Dv CRMOD enabled (see .Xr tty 4 ) . .Pp .Nm Telnetd has support for enabling locally the following .Tn TELNET options: .Bl -tag -width "DO AUTHENTICATION" .It "WILL ECHO" When the .Dv LINEMODE option is enabled, a .Dv WILL ECHO or .Dv WONT ECHO will be sent to the client to indicate the current state of terminal echoing. When terminal echo is not desired, a .Dv WILL ECHO is sent to indicate that .Nm will take care of echoing any data that needs to be echoed to the terminal, and then nothing is echoed. When terminal echo is desired, a .Dv WONT ECHO is sent to indicate that .Nm will not be doing any terminal echoing, so the client should do any terminal echoing that is needed. .It "WILL BINARY" Indicate that the client is willing to send a 8 bits of data, rather than the normal 7 bits of the Network Virtual Terminal. .It "WILL SGA" Indicate that it will not be sending .Dv IAC GA , go ahead, commands. .It "WILL STATUS" Indicate a willingness to send the client, upon request, of the current status of all .Tn TELNET options. .It "WILL TIMING-MARK" Whenever a .Dv DO TIMING-MARK command is received, it is always responded to with a .Dv WILL TIMING-MARK . .It "WILL LOGOUT" When a .Dv DO LOGOUT is received, a .Dv WILL LOGOUT is sent in response, and the .Tn TELNET session is shut down. .It "WILL ENCRYPT" Only sent if .Nm is compiled with support for data encryption, and indicates a willingness to decrypt the data stream. .El .Pp .Nm Telnetd has support for enabling remotely the following .Tn TELNET options: .Bl -tag -width "DO AUTHENTICATION" .It "DO BINARY" Sent to indicate that .Nm is willing to receive an 8 bit data stream. .It "DO LFLOW" Requests that the client handle flow control characters remotely. .It "DO ECHO" This is not really supported, but is sent to identify a .Bx 4.2 .Xr telnet 1 client, which will improperly respond with .Dv WILL ECHO . If a .Dv WILL ECHO is received, a .Dv DONT ECHO will be sent in response. .It "DO TERMINAL-TYPE" Indicate a desire to be able to request the name of the type of terminal that is attached to the client side of the connection. .It "DO SGA" Indicate that it does not need to receive .Dv IAC GA , the go ahead command. .It "DO NAWS" Requests that the client inform the server when the window (display) size changes. .It "DO TERMINAL-SPEED" Indicate a desire to be able to request information about the speed of the serial line to which the client is attached. .It "DO XDISPLOC" Indicate a desire to be able to request the name of the X Window System display that is associated with the telnet client. .It "DO NEW-ENVIRON" Indicate a desire to be able to request environment variable information, as described in RFC 1572. .It "DO ENVIRON" Indicate a desire to be able to request environment variable information, as described in RFC 1408. .It "DO LINEMODE" Only sent if .Nm is compiled with support for linemode, and requests that the client do line by line processing. .It "DO TIMING-MARK" Only sent if .Nm is compiled with support for both linemode and kludge linemode, and the client responded with .Dv WONT LINEMODE . If the client responds with .Dv WILL TM , the it is assumed that the client supports kludge linemode. Note that the .Op Fl k option can be used to disable this. .It "DO AUTHENTICATION" Only sent if .Nm is compiled with support for authentication, and indicates a willingness to receive authentication information for automatic login. .It "DO ENCRYPT" Only sent if .Nm is compiled with support for data encryption, and indicates a willingness to decrypt the data stream. .El .Sh NOTES By default .Nm will read the .Em \&he , .Em \&hn , and .Em \&im capabilities from .Pa /etc/gettytab and use that information (if present) to determine what to display before the login: prompt. You can also use a System V style .Pa /etc/issue file by using the .Em \&if capability, which will override .Em \&im . The information specified in either .Em \&im or .Em \&if will be displayed to both console and remote logins. .\" .Sh ENVIRONMENT .Sh FILES .Bl -tag -width /usr/ucb/bftp -compact .It Pa /etc/services .It Pa /etc/gettytab .It Pa /etc/iptos (if supported) .It Pa /usr/ucb/bftp (if supported) .El .Sh "SEE ALSO" .Xr bftp 1 , .Xr login 1 , .Xr gettytab 5 , .Xr telnet 1 (if supported) .Sh STANDARDS .Bl -tag -compact -width RFC-1572 .It Cm RFC-854 .Tn TELNET PROTOCOL SPECIFICATION .It Cm RFC-855 TELNET OPTION SPECIFICATIONS .It Cm RFC-856 TELNET BINARY TRANSMISSION .It Cm RFC-857 TELNET ECHO OPTION .It Cm RFC-858 TELNET SUPPRESS GO AHEAD OPTION .It Cm RFC-859 TELNET STATUS OPTION .It Cm RFC-860 TELNET TIMING MARK OPTION .It Cm RFC-861 TELNET EXTENDED OPTIONS - LIST OPTION .It Cm RFC-885 TELNET END OF RECORD OPTION .It Cm RFC-1073 Telnet Window Size Option .It Cm RFC-1079 Telnet Terminal Speed Option .It Cm RFC-1091 Telnet Terminal-Type Option .It Cm RFC-1096 Telnet X Display Location Option .It Cm RFC-1123 Requirements for Internet Hosts -- Application and Support .It Cm RFC-1184 Telnet Linemode Option .It Cm RFC-1372 Telnet Remote Flow Control Option .It Cm RFC-1416 Telnet Authentication Option .It Cm RFC-1411 Telnet Authentication: Kerberos Version 4 .It Cm RFC-1412 Telnet Authentication: SPX .It Cm RFC-1571 Telnet Environment Option Interoperability Issues .It Cm RFC-1572 Telnet Environment Option .El .Sh BUGS Some .Tn TELNET commands are only partially implemented. .Pp Because of bugs in the original .Bx 4.2 .Xr telnet 1 , .Nm performs some dubious protocol exchanges to try to discover if the remote client is, in fact, a .Bx 4.2 .Xr telnet 1 . .Pp Binary mode has no common interpretation except between similar operating systems (Unix in this case). .Pp The terminal type name received from the remote client is converted to lower case. .Pp .Nm Telnetd never sends .Tn TELNET .Dv IAC GA (go ahead) commands. .Sh HISTORY IPv6 support was added by WIDE/KAME project. Index: head/contrib/telnet/telnetd/telnetd.c =================================================================== --- head/contrib/telnet/telnetd/telnetd.c (revision 87138) +++ head/contrib/telnet/telnetd/telnetd.c (revision 87139) @@ -1,1371 +1,1226 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include "telnetd.h" #include "pathnames.h" -#include -#include - #include +#include #include #include +#include #include -#if defined(AUTHENTICATION) +#include + +#ifdef AUTHENTICATION #include int auth_level = 0; #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif #include -#if defined(SecurID) -int require_SecurID = 0; -#endif char remote_hostname[MAXHOSTNAMELEN]; -int utmp_len = sizeof(remote_hostname) - 1; +size_t utmp_len = sizeof(remote_hostname) - 1; int registerd_host_only = 0; -#ifdef STREAMSPTY -# include -# include -/* make sure we don't get the bsd version */ -# include "/usr/include/sys/tty.h" -# include /* - * Because of the way ptyibuf is used with streams messages, we need - * ptyibuf+1 to be on a full-word boundary. The following weirdness - * is simply to make that happen. - */ -long ptyibufbuf[BUFSIZ/sizeof(long)+1]; -char *ptyibuf = ((char *)&ptyibufbuf[1])-1; -char *ptyip = ((char *)&ptyibufbuf[1])-1; -char ptyibuf2[BUFSIZ]; -unsigned char ctlbuf[BUFSIZ]; -struct strbuf strbufc, strbufd; - -#else /* ! STREAMPTY */ - -/* * I/O data buffers, * pointers, and counters. */ char ptyibuf[BUFSIZ], *ptyip = ptyibuf; char ptyibuf2[BUFSIZ]; -# include +int readstream(int, char *, int); +void doit(struct sockaddr *); +int terminaltypeok(char *); -int readstream(int p, char *ibuf, int bufsize); -void doit(struct sockaddr *who); -int terminaltypeok(char *s); -void startslave(char *host, int autologin, char *autoname); - -#endif /* ! STREAMPTY */ - int hostinfo = 1; /* do we print login banner? */ int debug = 0; int keepalive = 1; -char *altlogin; +const char *altlogin; void doit __P((struct sockaddr *)); int terminaltypeok __P((char *)); void startslave __P((char *, int, char *)); extern void usage P((void)); +static void _gettermname __P((void)); /* * The string to pass to getopt(). We do it this way so * that only the actual options that we support will be * passed off to getopt(). */ char valid_opts[] = { 'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U', '4', '6', #ifdef AUTHENTICATION 'a', ':', 'X', ':', #endif #ifdef BFTPDAEMON 'B', #endif #ifdef DIAGNOSTICS 'D', ':', #endif #ifdef ENCRYPTION 'e', ':', #endif #ifdef LINEMODE 'l', #endif -#ifdef SecurID - 's', -#endif '\0' }; int family = AF_INET; +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif /* MAXHOSTNAMELEN */ + +char *hostname; +char host_name[MAXHOSTNAMELEN]; + +extern void telnet P((int, int, char *)); + +int level; +char user_name[256]; + int -main(argc, argv) - char *argv[]; +main(int argc, char *argv[]) { struct sockaddr_storage from; int on = 1, fromlen; - register int ch; + int ch; #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; #ifdef ENCRYPTION nclearto = 0; #endif /* ENCRYPTION */ /* * This initialization causes linemode to default to a configuration * that works on all telnet clients, including the FreeBSD client. * This is not quite the same as the telnet client issuing a "mode * character" command, but has most of the same benefits, and is * preferable since some clients (like usofts) don't have the * mode character command anyway and linemode breaks things. * The most notable symptom of fix is that csh "set filec" operations * like (filename completion) and ^D (choices) keys now work * in telnet sessions and can be used more than once on the same line. * CR/LF handling is also corrected in some termio modes. This * change resolves problem reports bin/771 and bin/1037. */ linemode=1; /*Default to mode that works on bulk of clients*/ while ((ch = getopt(argc, argv, valid_opts)) != -1) { switch(ch) { #ifdef AUTHENTICATION case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { warnx("unknown authorization level for -a"); } break; #endif /* AUTHENTICATION */ #ifdef BFTPDAEMON case 'B': bftpd++; break; #endif /* BFTPDAEMON */ case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ #ifdef ENCRYPTION case 'e': if (strcmp(optarg, "debug") == 0) { extern int encrypt_debug_mode; encrypt_debug_mode = 1; break; } usage(); /* NOTREACHED */ break; #endif /* ENCRYPTION */ case 'h': hostinfo = 0; break; #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'k': #if defined(LINEMODE) && defined(KLUDGELINEMODE) lmodetype = NO_AUTOKLUDGE; #else /* ignore -k option if built without kludge linemode */ #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ break; case 'n': keepalive = 0; break; case 'p': altlogin = optarg; break; -#ifdef SecurID - case 's': - /* SecurID required */ - require_SecurID = 1; - break; -#endif /* SecurID */ case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) warnx("%s%s%s", "bad TOS argument '", optarg, "'; will try to use default TOS"); #else warnx("TOS option unavailable; -S flag not supported"); #endif break; case 'u': - utmp_len = atoi(optarg); - if (utmp_len < 0) - utmp_len = -utmp_len; + utmp_len = (size_t)atoi(optarg); if (utmp_len >= sizeof(remote_hostname)) utmp_len = sizeof(remote_hostname) - 1; break; case 'U': registerd_host_only = 1; break; #ifdef AUTHENTICATION case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif /* AUTHENTICATION */ case '4': family = AF_INET; break; #ifdef INET6 case '6': family = AF_INET6; break; #endif default: warnx("%c: unknown option", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debug) { int s, ns, foo, error; - char *service = "telnet"; + const char *service = "telnet"; struct addrinfo hints, *res; if (argc > 1) { usage(); /* NOT REACHED */ } else if (argc == 1) service = *argv; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; error = getaddrinfo(NULL, service, &hints, &res); if (error) { errx(1, "tcp/%s: %s\n", service, gai_strerror(error)); if (error == EAI_SYSTEM) errx(1, "tcp/%s: %s\n", service, strerror(errno)); usage(); } s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) err(1, "socket"); (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); if (bind(s, res->ai_addr, res->ai_addrlen) < 0) err(1, "bind"); if (listen(s, 1) < 0) err(1, "listen"); foo = res->ai_addrlen; ns = accept(s, res->ai_addr, &foo); if (ns < 0) err(1, "accept"); (void) dup2(ns, 0); (void) close(ns); (void) close(s); #ifdef convex } else if (argc == 1) { ; /* VOID*/ /* Just ignore the host/port name */ #endif } else if (argc > 0) { usage(); /* NOT REACHED */ } openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { warn("getpeername"); _exit(1); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof (on)) < 0) { syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } #if defined(IPPROTO_IP) && defined(IP_TOS) if (from.ss_family == AF_INET) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = 0; doit((struct sockaddr *)&from); /* NOTREACHED */ return(0); } /* end of main */ void usage() { fprintf(stderr, "usage: telnetd"); #ifdef AUTHENTICATION fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); #endif #ifdef BFTPDAEMON fprintf(stderr, " [-B]"); #endif fprintf(stderr, " [-debug]"); #ifdef DIAGNOSTICS fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); #endif #ifdef AUTHENTICATION fprintf(stderr, " [-edebug]"); #endif fprintf(stderr, " [-h]"); #if defined(LINEMODE) && defined(KLUDGELINEMODE) fprintf(stderr, " [-k]"); #endif #ifdef LINEMODE fprintf(stderr, " [-l]"); #endif fprintf(stderr, " [-n]"); fprintf(stderr, "\n\t"); -#ifdef SecurID - fprintf(stderr, " [-s]"); -#endif #ifdef HAS_GETTOS fprintf(stderr, " [-S tos]"); #endif #ifdef AUTHENTICATION fprintf(stderr, " [-X auth-type]"); #endif fprintf(stderr, " [-u utmp_hostname_length] [-U]"); fprintf(stderr, " [port]\n"); exit(1); } /* * getterminaltype * * Ask the other end to send along its terminal type and speed. * Output is the variable terminaltype filled in. */ static unsigned char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE }; - int -getterminaltype(name) - char *name; + +#ifndef AUTHENTICATION +#define undef2 __unused +#else +#define undef2 +#endif + +static int +getterminaltype(char *name undef2) { int retval = -1; - void _gettermname(); settimer(baseline); -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION /* * Handle the Authentication option before we do anything else. */ send_do(TELOPT_AUTHENTICATION, 1); while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) ttloop(); if (his_state_is_will(TELOPT_AUTHENTICATION)) { retval = auth_wait(name); } #endif #ifdef ENCRYPTION send_will(TELOPT_ENCRYPT, 1); #endif /* ENCRYPTION */ send_do(TELOPT_TTYPE, 1); send_do(TELOPT_TSPEED, 1); send_do(TELOPT_XDISPLOC, 1); send_do(TELOPT_NEW_ENVIRON, 1); send_do(TELOPT_OLD_ENVIRON, 1); while ( #ifdef ENCRYPTION his_do_dont_is_changing(TELOPT_ENCRYPT) || #endif /* ENCRYPTION */ his_will_wont_is_changing(TELOPT_TTYPE) || his_will_wont_is_changing(TELOPT_TSPEED) || his_will_wont_is_changing(TELOPT_XDISPLOC) || his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { ttloop(); } #ifdef ENCRYPTION /* * Wait for the negotiation of what type of encryption we can * send with. If autoencrypt is not set, this will just return. */ if (his_state_is_will(TELOPT_ENCRYPT)) { encrypt_wait(); } #endif /* ENCRYPTION */ if (his_state_is_will(TELOPT_TSPEED)) { static unsigned char sb[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_XDISPLOC)) { static unsigned char sb[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_NEW_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_TTYPE)) { output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, sizeof ttytype_sbbuf - 2);); } if (his_state_is_will(TELOPT_TSPEED)) { while (sequenceIs(tspeedsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_XDISPLOC)) { while (sequenceIs(xdisplocsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_NEW_ENVIRON)) { while (sequenceIs(environsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_OLD_ENVIRON)) { while (sequenceIs(oenvironsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_TTYPE)) { char first[256], last[256]; while (sequenceIs(ttypesubopt, baseline)) ttloop(); /* * If the other side has already disabled the option, then * we have to just go with what we (might) have already gotten. */ if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { (void) strncpy(first, terminaltype, sizeof(first)-1); first[sizeof(first)-1] = '\0'; for(;;) { /* * Save the unknown name, and request the next name. */ (void) strncpy(last, terminaltype, sizeof(last)-1); last[sizeof(last)-1] = '\0'; _gettermname(); if (terminaltypeok(terminaltype)) break; if ((strncmp(last, terminaltype, sizeof(last)) == 0) || his_state_is_wont(TELOPT_TTYPE)) { /* * We've hit the end. If this is the same as * the first name, just go with it. */ if (strncmp(first, terminaltype, sizeof(first)) == 0) break; /* * Get the terminal name one more time, so that * RFC1091 compliant telnets will cycle back to * the start of the list. */ _gettermname(); if (strncmp(first, terminaltype, sizeof(first)) != 0) { (void) strncpy(terminaltype, first, sizeof(terminaltype)-1); terminaltype[sizeof(terminaltype)-1] = '\0'; } break; } } } } return(retval); } /* end of getterminaltype */ - void -_gettermname() +static void +_gettermname(void) { /* * If the client turned off the option, * we can't send another request, so we * just return. */ if (his_state_is_wont(TELOPT_TTYPE)) return; settimer(baseline); output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, sizeof ttytype_sbbuf - 2);); while (sequenceIs(ttypesubopt, baseline)) ttloop(); } - int -terminaltypeok(s) - char *s; +int +terminaltypeok(char *s) { char buf[1024]; if (terminaltype == NULL) return(1); /* * tgetent() will return 1 if the type is known, and * 0 if it is not known. If it returns -1, it couldn't * open the database. But if we can't open the database, * it won't help to say we failed, because we won't be * able to verify anything else. So, we treat -1 like 1. */ if (tgetent(buf, s) == 0) return(0); return(1); } -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 256 -#endif /* MAXHOSTNAMELEN */ - -char *hostname; -char host_name[MAXHOSTNAMELEN]; - -extern void telnet P((int, int, char *)); - -int level; -char user_name[256]; /* * Get a pty, scan input lines. */ - void -doit(who) - struct sockaddr *who; +void +doit(struct sockaddr *who) { - int err; + int err_; /* XXX */ int ptynum; /* * Find an available pty to use. */ #ifndef convex pty = getpty(&ptynum); if (pty < 0) fatal(net, "All network ports in use"); #else for (;;) { char *lp; if ((lp = getpty()) == NULL) fatal(net, "Out of ptys"); if ((pty = open(lp, 2)) >= 0) { strlcpy(line,lp,sizeof(line)); line[5] = 't'; break; } } #endif /* get name of connected client */ if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1, who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only) fatal(net, "Couldn't resolve your address into a host name.\r\n\ Please contact your net administrator"); remote_hostname[sizeof(remote_hostname) - 1] = '\0'; trimdomain(remote_hostname, UT_HOSTSIZE); if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len) - err = getnameinfo(who, who->sa_len, remote_hostname, + err_ = getnameinfo(who, who->sa_len, remote_hostname, sizeof(remote_hostname), NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID); - /* XXX: do 'err' check */ + /* XXX: do 'err_' check */ (void) gethostname(host_name, sizeof(host_name) - 1); host_name[sizeof(host_name) - 1] = '\0'; hostname = host_name; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION +/* The above #ifdefs should actually be "or"'ed, not "and"'ed. + * This is a byproduct of needing "#ifdef" and not "#if defined()" + * for unifdef. XXX MarkM + */ auth_encrypt_init(hostname, remote_hostname, "TELNETD", 1); #endif +#endif init_env(); /* * get terminal type. */ *user_name = 0; level = getterminaltype(user_name); setenv("TERM", terminaltype ? terminaltype : "network", 1); telnet(net, pty, remote_hostname); /* begin server process */ /*NOTREACHED*/ } /* end of doit */ /* * Main loop. Select from pty and network, and * hand data to telnet receiver finite state machine. */ - void -telnet(f, p, host) - int f, p; - char *host; +void +telnet(int f, int p, char *host) { int on = 1; #define TABBUFSIZ 512 char defent[TABBUFSIZ]; char defstrs[TABBUFSIZ]; #undef TABBUFSIZ char *HE; char *HN; char *IM; int nfd; /* * Initialize the slc mapping table. */ get_slc_defaults(); /* * Do some tests where it is desireable to wait for a response. * Rather than doing them slowly, one at a time, do them all * at once. */ if (my_state_is_wont(TELOPT_SGA)) send_will(TELOPT_SGA, 1); /* * Is the client side a 4.2 (NOT 4.3) system? We need to know this * because 4.2 clients are unable to deal with TCP urgent data. * * To find out, we send out a "DO ECHO". If the remote system * answers "WILL ECHO" it is probably a 4.2 client, and we note * that fact ("WILL ECHO" ==> that the client will echo what * WE, the server, sends it; it does NOT mean that the client will * echo the terminal input). */ send_do(TELOPT_ECHO, 1); #ifdef LINEMODE if (his_state_is_wont(TELOPT_LINEMODE)) { /* Query the peer for linemode support by trying to negotiate * the linemode option. */ linemode = 0; editmode = 0; send_do(TELOPT_LINEMODE, 1); /* send do linemode */ } #endif /* LINEMODE */ /* * Send along a couple of other options that we wish to negotiate. */ send_do(TELOPT_NAWS, 1); send_will(TELOPT_STATUS, 1); flowmode = 1; /* default flow control state */ restartany = -1; /* uninitialized... */ send_do(TELOPT_LFLOW, 1); /* * Spin, waiting for a response from the DO ECHO. However, * some REALLY DUMB telnets out there might not respond * to the DO ECHO. So, we spin looking for NAWS, (most dumb * telnets so far seem to respond with WONT for a DO that * they don't understand...) because by the time we get the * response, it will already have processed the DO ECHO. * Kludge upon kludge. */ while (his_will_wont_is_changing(TELOPT_NAWS)) ttloop(); /* * But... * The client might have sent a WILL NAWS as part of its * startup code; if so, we'll be here before we get the * response to the DO ECHO. We'll make the assumption * that any implementation that understands about NAWS * is a modern enough implementation that it will respond * to our DO ECHO request; hence we'll do another spin * waiting for the ECHO option to settle down, which is * what we wanted to do in the first place... */ if (his_want_state_is_will(TELOPT_ECHO) && his_state_is_will(TELOPT_NAWS)) { while (his_will_wont_is_changing(TELOPT_ECHO)) ttloop(); } /* * On the off chance that the telnet client is broken and does not * respond to the DO ECHO we sent, (after all, we did send the * DO NAWS negotiation after the DO ECHO, and we won't get here * until a response to the DO NAWS comes back) simulate the * receipt of a will echo. This will also send a WONT ECHO * to the client, since we assume that the client failed to * respond because it believes that it is already in DO ECHO * mode, which we do not want. */ if (his_want_state_is_will(TELOPT_ECHO)) { DIAG(TD_OPTIONS, output_data("td: simulating recv\r\n")); willoption(TELOPT_ECHO); } /* * Finally, to clean things up, we turn on our echo. This * will break stupid 4.2 telnets out of local terminal echo. */ if (my_state_is_wont(TELOPT_ECHO)) send_will(TELOPT_ECHO, 1); -#ifndef STREAMSPTY /* * Turn on packet mode */ (void) ioctl(p, TIOCPKT, (char *)&on); -#endif #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * Continuing line mode support. If client does not support * real linemode, attempt to negotiate kludge linemode by sending * the do timing mark sequence. */ if (lmodetype < REAL_LINEMODE) send_do(TELOPT_TM, 1); #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ /* * Call telrcv() once to pick up anything received during * terminal type negotiation, 4.2/4.3 determination, and * linemode negotiation. */ telrcv(); (void) ioctl(f, FIONBIO, (char *)&on); (void) ioctl(p, FIONBIO, (char *)&on); #if defined(SO_OOBINLINE) (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof on); #endif /* defined(SO_OOBINLINE) */ #ifdef SIGTSTP (void) signal(SIGTSTP, SIG_IGN); #endif #ifdef SIGTTOU /* * Ignoring SIGTTOU keeps the kernel from blocking us * in ttioct() in /sys/tty.c. */ (void) signal(SIGTTOU, SIG_IGN); #endif (void) signal(SIGCHLD, cleanup); #ifdef TIOCNOTTY { - register int t; + int t; t = open(_PATH_TTY, O_RDWR); if (t >= 0) { (void) ioctl(t, TIOCNOTTY, (char *)0); (void) close(t); } } #endif /* * Show banner that getty never gave. * * We put the banner in the pty input buffer. This way, it * gets carriage return null processing, etc., just like all * other pty --> client data. */ if (getent(defent, "default") == 1) { - char *Getstr(); char *cp=defstrs; HE = Getstr("he", &cp); HN = Getstr("hn", &cp); IM = Getstr("im", &cp); if (HN && *HN) (void) strlcpy(host_name, HN, sizeof(host_name)); if (IM == 0) - IM = ""; + IM = strdup(""); } else { - IM = DEFAULT_IM; + IM = strdup(DEFAULT_IM); HE = 0; } edithost(HE, host_name); if (hostinfo && *IM) putf(IM, ptyibuf2); if (pcc) (void) strncat(ptyibuf2, ptyip, pcc+1); ptyip = ptyibuf2; pcc = strlen(ptyip); #ifdef LINEMODE /* * Last check to make sure all our states are correct. */ init_termbuf(); localstat(); #endif /* LINEMODE */ DIAG(TD_REPORT, output_data("td: Entering processing loop\r\n")); /* * Startup the login process on the slave side of the terminal * now. We delay this until here to insure option negotiation * is complete. */ startslave(host, level, user_name); nfd = ((f > p) ? f : p) + 1; for (;;) { fd_set ibits, obits, xbits; - register int c; + int c; if (ncc < 0 && pcc < 0) break; FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&xbits); /* * Never look for input if there's still * stuff in the corresponding output buffer */ if (nfrontp - nbackp || pcc > 0) { FD_SET(f, &obits); } else { FD_SET(p, &ibits); } if (pfrontp - pbackp || ncc > 0) { FD_SET(p, &obits); } else { FD_SET(f, &ibits); } if (!SYNCHing) { FD_SET(f, &xbits); } if ((c = select(nfd, &ibits, &obits, &xbits, (struct timeval *)0)) < 1) { if (c == -1) { if (errno == EINTR) { continue; } } sleep(5); continue; } /* * Any urgent data? */ if (FD_ISSET(net, &xbits)) { SYNCHing = 1; } /* * Something to read from the network... */ if (FD_ISSET(net, &ibits)) { #if !defined(SO_OOBINLINE) /* * In 4.2 (and 4.3 beta) systems, the * OOB indication and data handling in the kernel * is such that if two separate TCP Urgent requests * come in, one byte of TCP data will be overlaid. * This is fatal for Telnet, but we try to live * with it. * * In addition, in 4.2 (and...), a special protocol * is needed to pick up the TCP Urgent data in * the correct sequence. * * What we do is: if we think we are in urgent * mode, we look to see if we are "at the mark". * If we are, we do an OOB receive. If we run * this twice, we will do the OOB receive twice, * but the second will fail, since the second * time we were "at the mark", but there wasn't * any data there (the kernel doesn't reset * "at the mark" until we do a normal read). * Once we've read the OOB data, we go ahead * and do normal reads. * * There is also another problem, which is that * since the OOB byte we read doesn't put us * out of OOB state, and since that byte is most * likely the TELNET DM (data mark), we would * stay in the TELNET SYNCH (SYNCHing) state. * So, clocks to the rescue. If we've "just" * received a DM, then we test for the * presence of OOB data when the receive OOB * fails (and AFTER we did the normal mode read * to clear "at the mark"). */ if (SYNCHing) { int atmark; (void) ioctl(net, SIOCATMARK, (char *)&atmark); if (atmark) { ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); if ((ncc == -1) && (errno == EINVAL)) { ncc = read(net, netibuf, sizeof (netibuf)); if (sequenceIs(didnetreceive, gotDM)) { SYNCHing = stilloob(net); } } } else { ncc = read(net, netibuf, sizeof (netibuf)); } } else { ncc = read(net, netibuf, sizeof (netibuf)); } settimer(didnetreceive); #else /* !defined(SO_OOBINLINE)) */ ncc = read(net, netibuf, sizeof (netibuf)); #endif /* !defined(SO_OOBINLINE)) */ if (ncc < 0 && errno == EWOULDBLOCK) ncc = 0; else { if (ncc <= 0) { break; } netip = netibuf; } DIAG((TD_REPORT | TD_NETDATA), output_data("td: netread %d chars\r\n", ncc)); DIAG(TD_NETDATA, printdata("nd", netip, ncc)); } /* * Something to read from the pty... */ if (FD_ISSET(p, &ibits)) { -#ifndef STREAMSPTY pcc = read(p, ptyibuf, BUFSIZ); -#else - pcc = readstream(p, ptyibuf, BUFSIZ); -#endif /* * On some systems, if we try to read something * off the master side before the slave side is * opened, we get EIO. */ if (pcc < 0 && (errno == EWOULDBLOCK || #ifdef EAGAIN errno == EAGAIN || #endif errno == EIO)) { pcc = 0; } else { if (pcc <= 0) break; #ifdef LINEMODE /* * If ioctl from pty, pass it through net */ if (ptyibuf[0] & TIOCPKT_IOCTL) { copy_termbuf(ptyibuf+1, pcc-1); localstat(); pcc = 1; } #endif /* LINEMODE */ if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { netclear(); /* clear buffer back */ #ifndef NO_URGENT /* * There are client telnets on some * operating systems get screwed up * royally if we send them urgent * mode data. */ output_data("%c%c", IAC, DM); neturg = nfrontp-1; /* off by one XXX */ DIAG(TD_OPTIONS, printoption("td: send IAC", DM)); #endif } if (his_state_is_will(TELOPT_LFLOW) && (ptyibuf[0] & (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { int newflow = ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; if (newflow != flowmode) { flowmode = newflow; output_data("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, flowmode ? LFLOW_ON : LFLOW_OFF, IAC, SE); DIAG(TD_OPTIONS, printsub('>', (unsigned char *)nfrontp-4, 4);); } } pcc--; ptyip = ptyibuf+1; } } while (pcc > 0) { if ((&netobuf[BUFSIZ] - nfrontp) < 2) break; c = *ptyip++ & 0377, pcc--; if (c == IAC) output_data("%c", c); output_data("%c", c); if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { if (pcc > 0 && ((*ptyip & 0377) == '\n')) { output_data("%c", *ptyip++ & 0377); pcc--; } else output_data("%c", '\0'); } } if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) netflush(); if (ncc > 0) telrcv(); if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) ptyflush(); } cleanup(0); } /* end of telnet */ #ifndef TCSIG # ifdef TIOCSIG # define TCSIG TIOCSIG # endif #endif -#ifdef STREAMSPTY - -int flowison = -1; /* current state of flow: -1 is unknown */ - -int readstream(p, ibuf, bufsize) - int p; - char *ibuf; - int bufsize; -{ - int flags = 0; - int ret = 0; - struct termios *tsp; - struct termio *tp; - struct iocblk *ip; - char vstop, vstart; - int ixon; - int newflow; - - strbufc.maxlen = BUFSIZ; - strbufc.buf = (char *)ctlbuf; - strbufd.maxlen = bufsize-1; - strbufd.len = 0; - strbufd.buf = ibuf+1; - ibuf[0] = 0; - - ret = getmsg(p, &strbufc, &strbufd, &flags); - if (ret < 0) /* error of some sort -- probably EAGAIN */ - return(-1); - - if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { - /* data message */ - if (strbufd.len > 0) { /* real data */ - return(strbufd.len + 1); /* count header char */ - } else { - /* nothing there */ - errno = EAGAIN; - return(-1); - } - } - - /* - * It's a control message. Return 1, to look at the flag we set - */ - - switch (ctlbuf[0]) { - case M_FLUSH: - if (ibuf[1] & FLUSHW) - ibuf[0] = TIOCPKT_FLUSHWRITE; - return(1); - - case M_IOCTL: - ip = (struct iocblk *) (ibuf+1); - - switch (ip->ioc_cmd) { - case TCSETS: - case TCSETSW: - case TCSETSF: - tsp = (struct termios *) - (ibuf+1 + sizeof(struct iocblk)); - vstop = tsp->c_cc[VSTOP]; - vstart = tsp->c_cc[VSTART]; - ixon = tsp->c_iflag & IXON; - break; - case TCSETA: - case TCSETAW: - case TCSETAF: - tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); - vstop = tp->c_cc[VSTOP]; - vstart = tp->c_cc[VSTART]; - ixon = tp->c_iflag & IXON; - break; - default: - errno = EAGAIN; - return(-1); - } - - newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; - if (newflow != flowison) { /* it's a change */ - flowison = newflow; - ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; - return(1); - } - } - - /* nothing worth doing anything about */ - errno = EAGAIN; - return(-1); -} -#endif /* STREAMSPTY */ - /* * Send interrupt to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write intr char. */ - void -interrupt() +void +interrupt(void) { ptyflush(); /* half-hearted */ -#if defined(STREAMSPTY) && defined(TIOCSIGNAL) - /* Streams PTY style ioctl to post a signal */ - { - int sig = SIGINT; - (void) ioctl(pty, TIOCSIGNAL, &sig); - (void) ioctl(pty, I_FLUSH, FLUSHR); - } -#else #ifdef TCSIG (void) ioctl(pty, TCSIG, (char *)SIGINT); #else /* TCSIG */ init_termbuf(); *pfrontp++ = slctab[SLC_IP].sptr ? (unsigned char)*slctab[SLC_IP].sptr : '\177'; #endif /* TCSIG */ -#endif } /* * Send quit to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write quit char. */ - void -sendbrk() +void +sendbrk(void) { ptyflush(); /* half-hearted */ #ifdef TCSIG (void) ioctl(pty, TCSIG, (char *)SIGQUIT); #else /* TCSIG */ init_termbuf(); *pfrontp++ = slctab[SLC_ABORT].sptr ? (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; #endif /* TCSIG */ } - void -sendsusp() +void +sendsusp(void) { #ifdef SIGTSTP ptyflush(); /* half-hearted */ # ifdef TCSIG (void) ioctl(pty, TCSIG, (char *)SIGTSTP); # else /* TCSIG */ *pfrontp++ = slctab[SLC_SUSP].sptr ? (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; # endif /* TCSIG */ #endif /* SIGTSTP */ } /* * When we get an AYT, if ^T is enabled, use that. Otherwise, * just send back "[Yes]". */ - void -recv_ayt() +void +recv_ayt(void) { #if defined(SIGINFO) && defined(TCSIG) if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { (void) ioctl(pty, TCSIG, (char *)SIGINFO); return; } #endif output_data("\r\n[Yes]\r\n"); } - void -doeof() +void +doeof(void) { init_termbuf(); #if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) if (!tty_isediting()) { extern char oldeofc; *pfrontp++ = oldeofc; return; } #endif *pfrontp++ = slctab[SLC_EOF].sptr ? (unsigned char)*slctab[SLC_EOF].sptr : '\004'; } Index: head/contrib/telnet/telnetd/telnetd.h =================================================================== --- head/contrib/telnet/telnetd/telnetd.h (revision 87138) +++ head/contrib/telnet/telnetd/telnetd.h (revision 87139) @@ -1,49 +1,49 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)telnetd.h 8.1 (Berkeley) 6/4/93 + * $FreeBSD$ */ #include "defs.h" #include "ext.h" #ifdef DIAGNOSTICS #define DIAG(a,b) if (diagnostic & (a)) b #else #define DIAG(a,b) #endif /* other external variables */ extern char **environ; -extern int errno; - +extern const char *altlogin; Index: head/contrib/telnet/telnetd/termstat.c =================================================================== --- head/contrib/telnet/telnetd/termstat.c (revision 87138) +++ head/contrib/telnet/telnetd/termstat.c (revision 87139) @@ -1,633 +1,632 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include "telnetd.h" -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif /* * local variables */ int def_tspeed = -1, def_rspeed = -1; #ifdef TIOCSWINSZ int def_row = 0, def_col = 0; #endif #ifdef LINEMODE static int _terminit = 0; #endif /* LINEMODE */ #ifdef LINEMODE /* * localstat * * This function handles all management of linemode. * * Linemode allows the client to do the local editing of data * and send only complete lines to the server. Linemode state is * based on the state of the pty driver. If the pty is set for * external processing, then we can use linemode. Further, if we * can use real linemode, then we can look at the edit control bits * in the pty to determine what editing the client should do. * * Linemode support uses the following state flags to keep track of * current and desired linemode state. * alwayslinemode : true if -l was specified on the telnetd * command line. It means to have linemode on as much as * possible. * * lmodetype: signifies whether the client can * handle real linemode, or if use of kludgeomatic linemode * is preferred. It will be set to one of the following: * REAL_LINEMODE : use linemode option * NO_KLUDGE : don't initiate kludge linemode. * KLUDGE_LINEMODE : use kludge linemode * NO_LINEMODE : client is ignorant of linemode * * linemode, uselinemode : linemode is true if linemode * is currently on, uselinemode is the state that we wish * to be in. If another function wishes to turn linemode * on or off, it sets or clears uselinemode. * * editmode, useeditmode : like linemode/uselinemode, but * these contain the edit mode states (edit and trapsig). * * The state variables correspond to some of the state information * in the pty. * linemode: * In real linemode, this corresponds to whether the pty * expects external processing of incoming data. * In kludge linemode, this more closely corresponds to the * whether normal processing is on or not. (ICANON in * system V, or COOKED mode in BSD.) * If the -l option was specified (alwayslinemode), then * an attempt is made to force external processing on at * all times. * * The following heuristics are applied to determine linemode * handling within the server. * 1) Early on in starting up the server, an attempt is made * to negotiate the linemode option. If this succeeds * then lmodetype is set to REAL_LINEMODE and all linemode * processing occurs in the context of the linemode option. * 2) If the attempt to negotiate the linemode option failed, * and the "-k" (don't initiate kludge linemode) isn't set, * then we try to use kludge linemode. We test for this * capability by sending "do Timing Mark". If a positive * response comes back, then we assume that the client * understands kludge linemode (ech!) and the * lmodetype flag is set to KLUDGE_LINEMODE. * 3) Otherwise, linemode is not supported at all and * lmodetype remains set to NO_LINEMODE (which happens * to be 0 for convenience). * 4) At any time a command arrives that implies a higher * state of linemode support in the client, we move to that * linemode support. * * A short explanation of kludge linemode is in order here. * 1) The heuristic to determine support for kludge linemode * is to send a do timing mark. We assume that a client * that supports timing marks also supports kludge linemode. * A risky proposition at best. * 2) Further negotiation of linemode is done by changing the * the server's state regarding SGA. If server will SGA, * then linemode is off, if server won't SGA, then linemode * is on. */ - void -localstat() +void +localstat(void) { int need_will_echo = 0; /* * Check for changes to flow control if client supports it. */ flowstat(); /* * Check linemode on/off state */ uselinemode = tty_linemode(); /* * If alwayslinemode is on, and pty is changing to turn it off, then * force linemode back on. */ if (alwayslinemode && linemode && !uselinemode) { uselinemode = 1; tty_setlinemode(uselinemode); } if (uselinemode) { /* * Check for state of BINARY options. * * We only need to do the binary dance if we are actually going * to use linemode. As this confuses some telnet clients * that don't support linemode, and doesn't gain us * anything, we don't do it unless we're doing linemode. * -Crh (henrich@msu.edu) */ if (tty_isbinaryin()) { if (his_want_state_is_wont(TELOPT_BINARY)) send_do(TELOPT_BINARY, 1); } else { if (his_want_state_is_will(TELOPT_BINARY)) send_dont(TELOPT_BINARY, 1); } if (tty_isbinaryout()) { if (my_want_state_is_wont(TELOPT_BINARY)) send_will(TELOPT_BINARY, 1); } else { if (my_want_state_is_will(TELOPT_BINARY)) send_wont(TELOPT_BINARY, 1); } } #ifdef ENCRYPTION /* * If the terminal is not echoing, but editing is enabled, * something like password input is going to happen, so * if we the other side is not currently sending encrypted * data, ask the other side to start encrypting. */ if (his_state_is_will(TELOPT_ENCRYPT)) { static int enc_passwd = 0; if (uselinemode && !tty_isecho() && tty_isediting() && (enc_passwd == 0) && !decrypt_input) { encrypt_send_request_start(); enc_passwd = 1; } else if (enc_passwd) { encrypt_send_request_end(); enc_passwd = 0; } } #endif /* ENCRYPTION */ /* * Do echo mode handling as soon as we know what the * linemode is going to be. * If the pty has echo turned off, then tell the client that * the server will echo. If echo is on, then the server * will echo if in character mode, but in linemode the * client should do local echoing. The state machine will * not send anything if it is unnecessary, so don't worry * about that here. * * If we need to send the WILL ECHO (because echo is off), * then delay that until after we have changed the MODE. * This way, when the user is turning off both editing * and echo, the client will get editing turned off first. * This keeps the client from going into encryption mode * and then right back out if it is doing auto-encryption * when passwords are being typed. */ if (uselinemode) { if (tty_isecho()) send_wont(TELOPT_ECHO, 1); else need_will_echo = 1; #ifdef KLUDGELINEMODE if (lmodetype == KLUDGE_OK) lmodetype = KLUDGE_LINEMODE; #endif } /* * If linemode is being turned off, send appropriate * command and then we're all done. */ if (!uselinemode && linemode) { # ifdef KLUDGELINEMODE if (lmodetype == REAL_LINEMODE) { # endif /* KLUDGELINEMODE */ send_dont(TELOPT_LINEMODE, 1); # ifdef KLUDGELINEMODE } else if (lmodetype == KLUDGE_LINEMODE) send_will(TELOPT_SGA, 1); # endif /* KLUDGELINEMODE */ send_will(TELOPT_ECHO, 1); linemode = uselinemode; goto done; } # ifdef KLUDGELINEMODE /* * If using real linemode check edit modes for possible later use. * If we are in kludge linemode, do the SGA negotiation. */ if (lmodetype == REAL_LINEMODE) { # endif /* KLUDGELINEMODE */ useeditmode = 0; if (tty_isediting()) useeditmode |= MODE_EDIT; if (tty_istrapsig()) useeditmode |= MODE_TRAPSIG; if (tty_issofttab()) useeditmode |= MODE_SOFT_TAB; if (tty_islitecho()) useeditmode |= MODE_LIT_ECHO; # ifdef KLUDGELINEMODE } else if (lmodetype == KLUDGE_LINEMODE) { if (tty_isediting() && uselinemode) send_wont(TELOPT_SGA, 1); else send_will(TELOPT_SGA, 1); } # endif /* KLUDGELINEMODE */ /* * Negotiate linemode on if pty state has changed to turn it on. * Send appropriate command and send along edit mode, then all done. */ if (uselinemode && !linemode) { # ifdef KLUDGELINEMODE if (lmodetype == KLUDGE_LINEMODE) { send_wont(TELOPT_SGA, 1); } else if (lmodetype == REAL_LINEMODE) { # endif /* KLUDGELINEMODE */ send_do(TELOPT_LINEMODE, 1); /* send along edit modes */ output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode, IAC, SE); editmode = useeditmode; # ifdef KLUDGELINEMODE } # endif /* KLUDGELINEMODE */ linemode = uselinemode; goto done; } # ifdef KLUDGELINEMODE /* * None of what follows is of any value if not using * real linemode. */ if (lmodetype < REAL_LINEMODE) goto done; # endif /* KLUDGELINEMODE */ if (linemode && his_state_is_will(TELOPT_LINEMODE)) { /* * If edit mode changed, send edit mode. */ if (useeditmode != editmode) { /* * Send along appropriate edit mode mask. */ output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode, IAC, SE); editmode = useeditmode; } /* * Check for changes to special characters in use. */ start_slc(0); check_slc(); (void) end_slc(0); } done: if (need_will_echo) send_will(TELOPT_ECHO, 1); /* * Some things should be deferred until after the pty state has * been set by the local process. Do those things that have been * deferred now. This only happens once. */ if (_terminit == 0) { _terminit = 1; defer_terminit(); } netflush(); set_termbuf(); return; } /* end of localstat */ #endif /* LINEMODE */ /* * flowstat * * Check for changes to flow control */ - void -flowstat() +void +flowstat(void) { if (his_state_is_will(TELOPT_LFLOW)) { if (tty_flowmode() != flowmode) { flowmode = tty_flowmode(); output_data("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, flowmode ? LFLOW_ON : LFLOW_OFF, IAC, SE); } if (tty_restartany() != restartany) { restartany = tty_restartany(); output_data("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, restartany ? LFLOW_RESTART_ANY : LFLOW_RESTART_XON, IAC, SE); } } } /* * clientstat * * Process linemode related requests from the client. * Client can request a change to only one of linemode, editmode or slc's * at a time, and if using kludge linemode, then only linemode may be * affected. */ - void -clientstat(code, parm1, parm2) - register int code, parm1, parm2; +void +clientstat(int code, int parm1, int parm2) { /* * Get a copy of terminal characteristics. */ init_termbuf(); /* * Process request from client. code tells what it is. */ switch (code) { #ifdef LINEMODE case TELOPT_LINEMODE: /* * Don't do anything unless client is asking us to change * modes. */ uselinemode = (parm1 == WILL); if (uselinemode != linemode) { # ifdef KLUDGELINEMODE /* * If using kludge linemode, make sure that * we can do what the client asks. * We can not turn off linemode if alwayslinemode * and the ICANON bit is set. */ if (lmodetype == KLUDGE_LINEMODE) { if (alwayslinemode && tty_isediting()) { uselinemode = 1; } } /* * Quit now if we can't do it. */ if (uselinemode == linemode) return; /* * If using real linemode and linemode is being * turned on, send along the edit mode mask. */ if (lmodetype == REAL_LINEMODE && uselinemode) # else /* KLUDGELINEMODE */ if (uselinemode) # endif /* KLUDGELINEMODE */ { useeditmode = 0; if (tty_isediting()) useeditmode |= MODE_EDIT; if (tty_istrapsig) useeditmode |= MODE_TRAPSIG; if (tty_issofttab()) useeditmode |= MODE_SOFT_TAB; if (tty_islitecho()) useeditmode |= MODE_LIT_ECHO; output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode, IAC, SE); editmode = useeditmode; } tty_setlinemode(uselinemode); linemode = uselinemode; if (!linemode) send_will(TELOPT_ECHO, 1); } break; case LM_MODE: { - register int ack, changed; + int ack, changed; /* * Client has sent along a mode mask. If it agrees with * what we are currently doing, ignore it; if not, it could * be viewed as a request to change. Note that the server * will change to the modes in an ack if it is different from * what we currently have, but we will not ack the ack. */ useeditmode &= MODE_MASK; ack = (useeditmode & MODE_ACK); useeditmode &= ~MODE_ACK; if ((changed = (useeditmode ^ editmode))) { /* * This check is for a timing problem. If the * state of the tty has changed (due to the user * application) we need to process that info * before we write in the state contained in the * ack!!! This gets out the new MODE request, * and when the ack to that command comes back * we'll set it and be in the right mode. */ if (ack) localstat(); if (changed & MODE_EDIT) tty_setedit(useeditmode & MODE_EDIT); if (changed & MODE_TRAPSIG) tty_setsig(useeditmode & MODE_TRAPSIG); if (changed & MODE_SOFT_TAB) tty_setsofttab(useeditmode & MODE_SOFT_TAB); if (changed & MODE_LIT_ECHO) tty_setlitecho(useeditmode & MODE_LIT_ECHO); set_termbuf(); if (!ack) { output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode|MODE_ACK, IAC, SE); } editmode = useeditmode; } break; } /* end of case LM_MODE */ #endif /* LINEMODE */ case TELOPT_NAWS: #ifdef TIOCSWINSZ { struct winsize ws; def_col = parm1; def_row = parm2; #ifdef LINEMODE /* * Defer changing window size until after terminal is * initialized. */ if (terminit() == 0) return; #endif /* LINEMODE */ /* * Change window size as requested by client. */ ws.ws_col = parm1; ws.ws_row = parm2; (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); } #endif /* TIOCSWINSZ */ break; case TELOPT_TSPEED: { def_tspeed = parm1; def_rspeed = parm2; #ifdef LINEMODE /* * Defer changing the terminal speed. */ if (terminit() == 0) return; #endif /* LINEMODE */ /* * Change terminal speed as requested by client. * We set the receive speed first, so that if we can't * store separate receive and transmit speeds, the transmit * speed will take precedence. */ tty_rspeed(parm2); tty_tspeed(parm1); set_termbuf(); break; } /* end of case TELOPT_TSPEED */ default: /* What? */ break; } /* end of switch */ netflush(); } /* end of clientstat */ #ifdef LINEMODE /* * defer_terminit * * Some things should not be done until after the login process has started * and all the pty modes are set to what they are supposed to be. This * function is called when the pty state has been processed for the first time. * It calls other functions that do things that were deferred in each module. */ - void -defer_terminit() +void +defer_terminit(void) { /* * local stuff that got deferred. */ if (def_tspeed != -1) { clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed); def_tspeed = def_rspeed = 0; } #ifdef TIOCSWINSZ if (def_col || def_row) { struct winsize ws; memset((char *)&ws, 0, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); } #endif /* * The only other module that currently defers anything. */ deferslc(); } /* end of defer_terminit */ /* * terminit * * Returns true if the pty state has been processed yet. */ - int -terminit() +int +terminit(void) { return(_terminit); } /* end of terminit */ #endif /* LINEMODE */ Index: head/contrib/telnet/telnetd/utility.c =================================================================== --- head/contrib/telnet/telnetd/utility.c (revision 87138) +++ head/contrib/telnet/telnetd/utility.c (revision 87139) @@ -1,1107 +1,1081 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static const char sccsid[] = "@(#)utility.c 8.4 (Berkeley) 5/30/95"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #ifdef __FreeBSD__ #include #include #endif #include #define PRINTOPTIONS #include "telnetd.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif /* * utility functions performing io related tasks */ /* * ttloop * * A small subroutine to flush the network output buffer, get some data * from the network, and pass it through the telnet state machine. We * also flush the pty input buffer (by dropping its data) if it becomes * too full. */ void ttloop() { DIAG(TD_REPORT, output_data("td: ttloop\r\n")); if (nfrontp - nbackp > 0) { netflush(); } ncc = read(net, netibuf, sizeof netibuf); if (ncc < 0) { syslog(LOG_INFO, "ttloop: read: %m"); exit(1); } else if (ncc == 0) { syslog(LOG_INFO, "ttloop: peer died: %m"); exit(1); } DIAG(TD_REPORT, output_data("td: ttloop read %d chars\r\n", ncc)); netip = netibuf; telrcv(); /* state machine */ if (ncc > 0) { pfrontp = pbackp = ptyobuf; telrcv(); } } /* end of ttloop */ /* * Check a descriptor to see if out of band data exists on it. */ - int -stilloob(s) - int s; /* socket number */ +int +stilloob(int s) { - static struct timeval timeout = { 0 }; + static struct timeval timeout = { 0, 0 }; fd_set excepts; int value; do { FD_ZERO(&excepts); FD_SET(s, &excepts); memset((char *)&timeout, 0, sizeof timeout); value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); } while ((value == -1) && (errno == EINTR)); if (value < 0) { fatalperror(pty, "select"); } if (FD_ISSET(s, &excepts)) { return 1; } else { return 0; } } - void -ptyflush() +void +ptyflush(void) { int n; if ((n = pfrontp - pbackp) > 0) { DIAG(TD_REPORT | TD_PTYDATA, output_data("td: ptyflush %d chars\r\n", n)); DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); n = write(pty, pbackp, n); } if (n < 0) { if (errno == EWOULDBLOCK || errno == EINTR) return; cleanup(0); } pbackp += n; if (pbackp == pfrontp) pbackp = pfrontp = ptyobuf; } /* * nextitem() * * Return the address of the next "item" in the TELNET data * stream. This will be the address of the next character if * the current address is a user data character, or it will * be the address of the character following the TELNET command * if the current address is a TELNET IAC ("I Am a Command") * character. */ - char * -nextitem(current) - char *current; +static char * +nextitem(char *current) { if ((*current&0xff) != IAC) { return current+1; } switch (*(current+1)&0xff) { case DO: case DONT: case WILL: case WONT: return current+3; case SB: /* loop forever looking for the SE */ { - register char *look = current+2; + char *look = current+2; for (;;) { if ((*look++&0xff) == IAC) { if ((*look++&0xff) == SE) { return look; } } } } default: return current+2; } } /* end of nextitem */ - /* * netclear() * * We are about to do a TELNET SYNCH operation. Clear * the path to the network. * * Things are a bit tricky since we may have sent the first * byte or so of a previous TELNET command into the network. * So, we have to scan the network buffer from the beginning * until we are up to where we want to be. * * A side effect of what we do, just to keep things * simple, is to clear the urgent data pointer. The principal * caller should be setting the urgent data pointer AFTER calling * us in any case. */ - void -netclear() +void +netclear(void) { - register char *thisitem, *next; + char *thisitem, *next; char *good; #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) #ifdef ENCRYPTION thisitem = nclearto > netobuf ? nclearto : netobuf; #else /* ENCRYPTION */ thisitem = netobuf; #endif /* ENCRYPTION */ while ((next = nextitem(thisitem)) <= nbackp) { thisitem = next; } /* Now, thisitem is first before/at boundary. */ #ifdef ENCRYPTION good = nclearto > netobuf ? nclearto : netobuf; #else /* ENCRYPTION */ good = netobuf; /* where the good bytes go */ #endif /* ENCRYPTION */ while (nfrontp > thisitem) { if (wewant(thisitem)) { int length; next = thisitem; do { next = nextitem(next); } while (wewant(next) && (nfrontp > next)); length = next-thisitem; memmove(good, thisitem, length); good += length; thisitem = next; } else { thisitem = nextitem(thisitem); } } nbackp = netobuf; nfrontp = good; /* next byte to be sent */ neturg = 0; } /* end of netclear */ /* * netflush * Send as much data as possible to the network, * handling requests for urgent data. */ - void -netflush() +void +netflush(void) { int n; extern int not42; while ((n = nfrontp - nbackp) > 0) { #if 0 /* XXX This causes output_data() to recurse and die */ DIAG(TD_REPORT, { n += output_data("td: netflush %d chars\r\n", n); }); #endif #ifdef ENCRYPTION if (encrypt_output) { char *s = nclearto ? nclearto : nbackp; if (nfrontp - s > 0) { (*encrypt_output)((unsigned char *)s, nfrontp-s); nclearto = nfrontp; } } #endif /* ENCRYPTION */ /* * if no urgent data, or if the other side appears to be an * old 4.2 client (and thus unable to survive TCP urgent data), * write the entire buffer in non-OOB mode. */ if ((neturg == 0) || (not42 == 0)) { n = write(net, nbackp, n); /* normal write */ } else { n = neturg - nbackp; /* * In 4.2 (and 4.3) systems, there is some question about * what byte in a sendOOB operation is the "OOB" data. * To make ourselves compatible, we only send ONE byte * out of band, the one WE THINK should be OOB (though * we really have more the TCP philosophy of urgent data * rather than the Unix philosophy of OOB data). */ if (n > 1) { n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ } else { n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ } } if (n == -1) { if (errno == EWOULDBLOCK || errno == EINTR) continue; cleanup(0); /* NOTREACHED */ } nbackp += n; #ifdef ENCRYPTION if (nbackp > nclearto) nclearto = 0; #endif /* ENCRYPTION */ if (nbackp >= neturg) { neturg = 0; } if (nbackp == nfrontp) { nbackp = nfrontp = netobuf; #ifdef ENCRYPTION nclearto = 0; #endif /* ENCRYPTION */ } } return; } /* end of netflush */ /* * miscellaneous functions doing a variety of little jobs follow ... */ - void -fatal(f, msg) - int f; - char *msg; +void +fatal(int f, const char *msg) { char buf[BUFSIZ]; (void) snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg); #ifdef ENCRYPTION if (encrypt_output) { /* * Better turn off encryption first.... * Hope it flushes... */ encrypt_send_end(); netflush(); } #endif /* ENCRYPTION */ (void) write(f, buf, (int)strlen(buf)); sleep(1); /*XXX*/ exit(1); } - void -fatalperror(f, msg) - int f; - char *msg; +void +fatalperror(int f, const char *msg) { - char buf[BUFSIZ], *strerror(); + char buf[BUFSIZ]; (void) snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno)); fatal(f, buf); } char editedhost[32]; - void -edithost(pat, host) - register char *pat; - register char *host; +void +edithost(char *pat, char *host) { - register char *res = editedhost; + char *res = editedhost; if (!pat) - pat = ""; + pat = strdup(""); while (*pat) { switch (*pat) { case '#': if (*host) host++; break; case '@': if (*host) *res++ = *host++; break; default: *res++ = *pat; break; } if (res == &editedhost[sizeof editedhost - 1]) { *res = '\0'; return; } pat++; } if (*host) (void) strncpy(res, host, sizeof editedhost - (res - editedhost) -1); else *res = '\0'; editedhost[sizeof editedhost - 1] = '\0'; } static char *putlocation; - void -putstr(s) - register char *s; +static void +putstr(const char *s) { while (*s) putchr(*s++); } - void -putchr(cc) - int cc; +void +putchr(int cc) { *putlocation++ = cc; } #ifdef __FreeBSD__ static char fmtstr[] = { "%+" }; #else -/* - * This is split on two lines so that SCCS will not see the M - * between two % signs and expand it... - */ -static char fmtstr[] = { "%l:%M\ -%P on %A, %d %B %Y" }; +static char fmtstr[] = { "%l:%M%P on %A, %d %B %Y" }; #endif - void -putf(cp, where) - register char *cp; - char *where; +void +putf(char *cp, char *where) { char *slash; time_t t; char db[100]; #ifdef __FreeBSD__ static struct utsname kerninfo; if (!*kerninfo.sysname) uname(&kerninfo); #endif putlocation = where; while (*cp) { if (*cp =='\n') { putstr("\r\n"); cp++; continue; } else if (*cp != '%') { putchr(*cp++); continue; } switch (*++cp) { case 't': #ifdef STREAMSPTY /* names are like /dev/pts/2 -- we want pts/2 */ slash = strchr(line+1, '/'); #else slash = strrchr(line, '/'); #endif if (slash == (char *) 0) putstr(line); else putstr(&slash[1]); break; case 'h': putstr(editedhost); break; case 'd': #ifdef __FreeBSD__ setlocale(LC_TIME, ""); #endif (void)time(&t); (void)strftime(db, sizeof(db), fmtstr, localtime(&t)); putstr(db); break; #ifdef __FreeBSD__ case 's': putstr(kerninfo.sysname); break; case 'm': putstr(kerninfo.machine); break; case 'r': putstr(kerninfo.release); break; case 'v': putstr(kerninfo.version); break; #endif case '%': putchr('%'); break; } cp++; } } #ifdef DIAGNOSTICS /* * Print telnet options and commands in plain text, if possible. */ - void -printoption(fmt, option) - register char *fmt; - register int option; +void +printoption(const char *fmt, int option) { if (TELOPT_OK(option)) output_data("%s %s\r\n", fmt, TELOPT(option)); else if (TELCMD_OK(option)) output_data("%s %s\r\n", fmt, TELCMD(option)); else output_data("%s %d\r\n", fmt, option); return; } - void -printsub(direction, pointer, length) - char direction; /* '<' or '>' */ - unsigned char *pointer; /* where suboption data sits */ - int length; /* length of suboption data */ +void +printsub(char direction, unsigned char *pointer, int length) { - register int i = 0; + int i = 0; if (!(diagnostic & TD_OPTIONS)) return; if (direction) { output_data("td: %s suboption ", direction == '<' ? "recv" : "send"); if (length >= 3) { - register int j; + int j; i = pointer[length-2]; j = pointer[length-1]; if (i != IAC || j != SE) { output_data("(terminated by "); if (TELOPT_OK(i)) output_data("%s ", TELOPT(i)); else if (TELCMD_OK(i)) output_data("%s ", TELCMD(i)); else output_data("%d ", i); if (TELOPT_OK(j)) output_data("%s", TELOPT(j)); else if (TELCMD_OK(j)) output_data("%s", TELCMD(j)); else output_data("%d", j); output_data(", not IAC SE!) "); } } length -= 2; } if (length < 1) { output_data("(Empty suboption??\?)"); return; } switch (pointer[0]) { case TELOPT_TTYPE: output_data("TERMINAL-TYPE "); switch (pointer[1]) { case TELQUAL_IS: output_data("IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: output_data("SEND"); break; default: output_data( "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_TSPEED: output_data("TERMINAL-SPEED"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_IS: output_data(" IS %.*s", length-2, (char *)pointer+2); break; default: if (pointer[1] == 1) output_data(" SEND"); else output_data(" %d (unknown)", pointer[1]); for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; } break; case TELOPT_LFLOW: output_data("TOGGLE-FLOW-CONTROL"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case LFLOW_OFF: output_data(" OFF"); break; case LFLOW_ON: output_data(" ON"); break; case LFLOW_RESTART_ANY: output_data(" RESTART-ANY"); break; case LFLOW_RESTART_XON: output_data(" RESTART-XON"); break; default: output_data(" %d (unknown)", pointer[1]); } for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case TELOPT_NAWS: output_data("NAWS"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } if (length == 2) { output_data(" ?%d?", pointer[1]); break; } output_data(" %d %d (%d)", pointer[1], pointer[2], (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); if (length == 4) { output_data(" ?%d?", pointer[3]); break; } output_data(" %d %d (%d)", pointer[3], pointer[4], (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); for (i = 5; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case TELOPT_LINEMODE: output_data("LINEMODE "); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case WILL: output_data("WILL "); goto common; case WONT: output_data("WONT "); goto common; case DO: output_data("DO "); goto common; case DONT: output_data("DONT "); common: if (length < 3) { output_data("(no option??\?)"); break; } switch (pointer[2]) { case LM_FORWARDMASK: output_data("Forward Mask"); for (i = 3; i < length; i++) { output_data(" %x", pointer[i]); } break; default: output_data("%d (unknown)", pointer[2]); for (i = 3; i < length; i++) { output_data(" %d", pointer[i]); } break; } break; case LM_SLC: output_data("SLC"); for (i = 2; i < length - 2; i += 3) { if (SLC_NAME_OK(pointer[i+SLC_FUNC])) output_data(" %s", SLC_NAME(pointer[i+SLC_FUNC])); else output_data(" %d", pointer[i+SLC_FUNC]); switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { case SLC_NOSUPPORT: output_data(" NOSUPPORT"); break; case SLC_CANTCHANGE: output_data(" CANTCHANGE"); break; case SLC_VARIABLE: output_data(" VARIABLE"); break; case SLC_DEFAULT: output_data(" DEFAULT"); break; } output_data("%s%s%s", pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| SLC_FLUSHOUT| SLC_LEVELBITS)) { output_data("(0x%x)", pointer[i+SLC_FLAGS]); } output_data(" %d;", pointer[i+SLC_VALUE]); if ((pointer[i+SLC_VALUE] == IAC) && (pointer[i+SLC_VALUE+1] == IAC)) i++; } for (; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case LM_MODE: output_data("MODE "); if (length < 3) { output_data("(no mode??\?)"); break; } { char tbuf[32]; sprintf(tbuf, "%s%s%s%s%s", pointer[2]&MODE_EDIT ? "|EDIT" : "", pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", pointer[2]&MODE_ACK ? "|ACK" : ""); output_data("%s", tbuf[1] ? &tbuf[1] : "0"); } if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { output_data(" (0x%x)", pointer[2]); } for (i = 3; i < length; i++) { output_data(" ?0x%x?", pointer[i]); } break; default: output_data("%d (unknown)", pointer[1]); for (i = 2; i < length; i++) { output_data(" %d", pointer[i]); } } break; case TELOPT_STATUS: { - register char *cp; - register int j, k; + const char *cp; + int j, k; output_data("STATUS"); switch (pointer[1]) { default: if (pointer[1] == TELQUAL_SEND) output_data(" SEND"); else output_data(" %d (unknown)", pointer[1]); for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case TELQUAL_IS: output_data(" IS\r\n"); for (i = 2; i < length; i++) { switch(pointer[i]) { case DO: cp = "DO"; goto common2; case DONT: cp = "DONT"; goto common2; case WILL: cp = "WILL"; goto common2; case WONT: cp = "WONT"; goto common2; common2: i++; if (TELOPT_OK(pointer[i])) output_data(" %s %s", cp, TELOPT(pointer[i])); else output_data(" %s %d", cp, pointer[i]); output_data("\r\n"); break; case SB: output_data(" SB "); i++; j = k = i; while (j < length) { if (pointer[j] == SE) { if (j+1 == length) break; if (pointer[j+1] == SE) j++; else break; } pointer[k++] = pointer[j++]; } printsub(0, &pointer[i], k - i); if (i < length) { output_data(" SE"); i = j; } else i = j - 1; output_data("\r\n"); break; default: output_data(" %d", pointer[i]); break; } } break; } break; } case TELOPT_XDISPLOC: output_data("X-DISPLAY-LOCATION "); switch (pointer[1]) { case TELQUAL_IS: output_data("IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: output_data("SEND"); break; default: output_data("- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_NEW_ENVIRON: output_data("NEW-ENVIRON "); goto env_common1; case TELOPT_OLD_ENVIRON: output_data("OLD-ENVIRON"); env_common1: switch (pointer[1]) { case TELQUAL_IS: output_data("IS "); goto env_common; case TELQUAL_SEND: output_data("SEND "); goto env_common; case TELQUAL_INFO: output_data("INFO "); env_common: { - register int noquote = 2; + int noquote = 2; for (i = 2; i < length; i++ ) { switch (pointer[i]) { case NEW_ENV_VAR: output_data("\" VAR " + noquote); noquote = 2; break; case NEW_ENV_VALUE: output_data("\" VALUE " + noquote); noquote = 2; break; case ENV_ESC: output_data("\" ESC " + noquote); noquote = 2; break; case ENV_USERVAR: output_data("\" USERVAR " + noquote); noquote = 2; break; default: if (isprint(pointer[i]) && pointer[i] != '"') { if (noquote) { output_data("\""); noquote = 0; } output_data("%c", pointer[i]); } else { output_data("\" %03o " + noquote, pointer[i]); noquote = 2; } break; } } if (!noquote) output_data("\""); break; } } break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: output_data("AUTHENTICATION"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_REPLY: case TELQUAL_IS: output_data(" %s ", (pointer[1] == TELQUAL_IS) ? "IS" : "REPLY"); if (AUTHTYPE_NAME_OK(pointer[2])) output_data("%s ", AUTHTYPE_NAME(pointer[2])); else output_data("%d ", pointer[2]); if (length < 3) { output_data("(partial suboption??\?)"); break; } output_data("%s|%s", ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); { char buf[512]; auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); output_data("%s", buf); } break; case TELQUAL_SEND: i = 2; output_data(" SEND "); while (i < length) { if (AUTHTYPE_NAME_OK(pointer[i])) output_data("%s ", AUTHTYPE_NAME(pointer[i])); else output_data("%d ", pointer[i]); if (++i >= length) { output_data("(partial suboption??\?)"); break; } output_data("%s|%s ", ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); ++i; } break; case TELQUAL_NAME: output_data(" NAME \"%.*s\"", length - 2, pointer + 2); break; default: for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: output_data("ENCRYPT"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case ENCRYPT_START: output_data(" START"); break; case ENCRYPT_END: output_data(" END"); break; case ENCRYPT_REQSTART: output_data(" REQUEST-START"); break; case ENCRYPT_REQEND: output_data(" REQUEST-END"); break; case ENCRYPT_IS: case ENCRYPT_REPLY: output_data(" %s ", (pointer[1] == ENCRYPT_IS) ? "IS" : "REPLY"); if (length < 3) { output_data(" (partial suboption??\?)"); break; } if (ENCTYPE_NAME_OK(pointer[2])) output_data("%s ", ENCTYPE_NAME(pointer[2])); else output_data(" %d (unknown)", pointer[2]); { char buf[512]; encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); output_data("%s", buf); } break; case ENCRYPT_SUPPORT: i = 2; output_data(" SUPPORT "); while (i < length) { if (ENCTYPE_NAME_OK(pointer[i])) output_data("%s ", ENCTYPE_NAME(pointer[i])); else output_data("%d ", pointer[i]); i++; } break; case ENCRYPT_ENC_KEYID: output_data(" ENC_KEYID"); goto encommon; case ENCRYPT_DEC_KEYID: output_data(" DEC_KEYID"); goto encommon; default: output_data(" %d (unknown)", pointer[1]); encommon: for (i = 2; i < length; i++) { output_data(" %d", pointer[i]); } break; } break; #endif /* ENCRYPTION */ default: if (TELOPT_OK(pointer[0])) output_data("%s (unknown)", TELOPT(pointer[0])); else output_data("%d (unknown)", pointer[i]); for (i = 1; i < length; i++) { output_data(" %d", pointer[i]); } break; } output_data("\r\n"); } /* * Dump a data buffer in hex and ascii to the output data stream. */ - void -printdata(tag, ptr, cnt) - register char *tag; - register char *ptr; - register int cnt; +void +printdata(const char *tag, char *ptr, int cnt) { - register int i; + int i; char xbuf[30]; while (cnt) { /* flush net output buffer if no room for new data) */ if ((&netobuf[BUFSIZ] - nfrontp) < 80) { netflush(); } /* add a line of output */ output_data("%s: ", tag); for (i = 0; i < 20 && cnt; i++) { output_data("%02x", *ptr); if (isprint(*ptr)) { xbuf[i] = *ptr; } else { xbuf[i] = '.'; } if (i % 2) { output_data(" "); } cnt--; ptr++; } xbuf[i] = '\0'; output_data(" %s\r\n", xbuf ); } } #endif /* DIAGNOSTICS */ Index: head/crypto/telnet/arpa/telnet.h =================================================================== --- head/crypto/telnet/arpa/telnet.h (revision 87138) +++ head/crypto/telnet/arpa/telnet.h (revision 87139) @@ -1,342 +1,342 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)telnet.h 8.2 (Berkeley) 12/15/93 * $FreeBSD$ */ #ifndef _ARPA_TELNET_H_ #define _ARPA_TELNET_H_ /* * Definitions for the TELNET protocol. */ #define IAC 255 /* interpret as command: */ #define DONT 254 /* you are not to use option */ #define DO 253 /* please, you use option */ #define WONT 252 /* I won't use option */ #define WILL 251 /* I will use option */ #define SB 250 /* interpret as subnegotiation */ #define GA 249 /* you may reverse the line */ #define EL 248 /* erase the current line */ #define EC 247 /* erase the current character */ #define AYT 246 /* are you there */ #define AO 245 /* abort output--but let prog finish */ #define IP 244 /* interrupt process--permanently */ #define BREAK 243 /* break */ #define DM 242 /* data mark--for connect. cleaning */ #define NOP 241 /* nop */ #define SE 240 /* end sub negotiation */ #define EOR 239 /* end of record (transparent mode) */ #define ABORT 238 /* Abort process */ #define SUSP 237 /* Suspend process */ #define xEOF 236 /* End of file: EOF is already used... */ #define SYNCH 242 /* for telfunc calls */ #ifdef TELCMDS -char *telcmds[] = { +const char *telcmds[] = { "EOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0 }; #else extern char *telcmds[]; #endif #define TELCMD_FIRST xEOF #define TELCMD_LAST IAC #define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ (unsigned int)(x) >= TELCMD_FIRST) #define TELCMD(x) telcmds[(x)-TELCMD_FIRST] /* telnet options */ #define TELOPT_BINARY 0 /* 8-bit data path */ #define TELOPT_ECHO 1 /* echo */ #define TELOPT_RCP 2 /* prepare to reconnect */ #define TELOPT_SGA 3 /* suppress go ahead */ #define TELOPT_NAMS 4 /* approximate message size */ #define TELOPT_STATUS 5 /* give status */ #define TELOPT_TM 6 /* timing mark */ #define TELOPT_RCTE 7 /* remote controlled transmission and echo */ #define TELOPT_NAOL 8 /* negotiate about output line width */ #define TELOPT_NAOP 9 /* negotiate about output page size */ #define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ #define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ #define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ #define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ #define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ #define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ #define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ #define TELOPT_XASCII 17 /* extended ascic character set */ #define TELOPT_LOGOUT 18 /* force logout */ #define TELOPT_BM 19 /* byte macro */ #define TELOPT_DET 20 /* data entry terminal */ #define TELOPT_SUPDUP 21 /* supdup protocol */ #define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ #define TELOPT_SNDLOC 23 /* send location */ #define TELOPT_TTYPE 24 /* terminal type */ #define TELOPT_EOR 25 /* end or record */ #define TELOPT_TUID 26 /* TACACS user identification */ #define TELOPT_OUTMRK 27 /* output marking */ #define TELOPT_TTYLOC 28 /* terminal location number */ #define TELOPT_3270REGIME 29 /* 3270 regime */ #define TELOPT_X3PAD 30 /* X.3 PAD */ #define TELOPT_NAWS 31 /* window size */ #define TELOPT_TSPEED 32 /* terminal speed */ #define TELOPT_LFLOW 33 /* remote flow control */ #define TELOPT_LINEMODE 34 /* Linemode option */ #define TELOPT_XDISPLOC 35 /* X Display Location */ #define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ #define TELOPT_AUTHENTICATION 37/* Authenticate */ #define TELOPT_ENCRYPT 38 /* Encryption option */ #define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ #define TELOPT_EXOPL 255 /* extended-options-list */ #define NTELOPTS (1+TELOPT_NEW_ENVIRON) #ifdef TELOPTS -char *telopts[NTELOPTS+1] = { +const char *telopts[NTELOPTS+1] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON", 0 }; #define TELOPT_FIRST TELOPT_BINARY #define TELOPT_LAST TELOPT_NEW_ENVIRON #define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) #define TELOPT(x) telopts[(x)-TELOPT_FIRST] #endif /* sub-option qualifiers */ #define TELQUAL_IS 0 /* option is... */ #define TELQUAL_SEND 1 /* send option */ #define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ #define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ #define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ #define LFLOW_OFF 0 /* Disable remote flow control */ #define LFLOW_ON 1 /* Enable remote flow control */ #define LFLOW_RESTART_ANY 2 /* Restart output on any char */ #define LFLOW_RESTART_XON 3 /* Restart output only on XON */ /* * LINEMODE suboptions */ #define LM_MODE 1 #define LM_FORWARDMASK 2 #define LM_SLC 3 #define MODE_EDIT 0x01 #define MODE_TRAPSIG 0x02 #define MODE_ACK 0x04 #define MODE_SOFT_TAB 0x08 #define MODE_LIT_ECHO 0x10 #define MODE_MASK 0x1f /* Not part of protocol, but needed to simplify things... */ #define MODE_FLOW 0x0100 #define MODE_ECHO 0x0200 #define MODE_INBIN 0x0400 #define MODE_OUTBIN 0x0800 #define MODE_FORCE 0x1000 #define SLC_SYNCH 1 #define SLC_BRK 2 #define SLC_IP 3 #define SLC_AO 4 #define SLC_AYT 5 #define SLC_EOR 6 #define SLC_ABORT 7 #define SLC_EOF 8 #define SLC_SUSP 9 #define SLC_EC 10 #define SLC_EL 11 #define SLC_EW 12 #define SLC_RP 13 #define SLC_LNEXT 14 #define SLC_XON 15 #define SLC_XOFF 16 #define SLC_FORW1 17 #define SLC_FORW2 18 #define SLC_MCL 19 #define SLC_MCR 20 #define SLC_MCWL 21 #define SLC_MCWR 22 #define SLC_MCBOL 23 #define SLC_MCEOL 24 #define SLC_INSRT 25 #define SLC_OVER 26 #define SLC_ECR 27 #define SLC_EWR 28 #define SLC_EBOL 29 #define SLC_EEOL 30 #define NSLC 30 /* * For backwards compatibility, we define SLC_NAMES to be the * list of names if SLC_NAMES is not defined. */ #define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ "LNEXT", "XON", "XOFF", "FORW1", "FORW2", \ "MCL", "MCR", "MCWL", "MCWR", "MCBOL", \ "MCEOL", "INSRT", "OVER", "ECR", "EWR", \ "EBOL", "EEOL", \ 0 #ifdef SLC_NAMES -char *slc_names[] = { +const char *slc_names[] = { SLC_NAMELIST }; #else extern char *slc_names[]; #define SLC_NAMES SLC_NAMELIST #endif #define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) #define SLC_NAME(x) slc_names[x] #define SLC_NOSUPPORT 0 #define SLC_CANTCHANGE 1 #define SLC_VARIABLE 2 #define SLC_DEFAULT 3 #define SLC_LEVELBITS 0x03 #define SLC_FUNC 0 #define SLC_FLAGS 1 #define SLC_VALUE 2 #define SLC_ACK 0x80 #define SLC_FLUSHIN 0x40 #define SLC_FLUSHOUT 0x20 #define OLD_ENV_VAR 1 #define OLD_ENV_VALUE 0 #define NEW_ENV_VAR 0 #define NEW_ENV_VALUE 1 #define ENV_ESC 2 #define ENV_USERVAR 3 /* * AUTHENTICATION suboptions */ /* * Who is authenticating who ... */ #define AUTH_WHO_CLIENT 0 /* Client authenticating server */ #define AUTH_WHO_SERVER 1 /* Server authenticating client */ #define AUTH_WHO_MASK 1 /* * amount of authentication done */ #define AUTH_HOW_ONE_WAY 0 #define AUTH_HOW_MUTUAL 2 #define AUTH_HOW_MASK 2 #define AUTHTYPE_NULL 0 #define AUTHTYPE_KERBEROS_V4 1 #define AUTHTYPE_KERBEROS_V5 2 #define AUTHTYPE_SPX 3 #define AUTHTYPE_MINK 4 #define AUTHTYPE_SRA 6 #define AUTHTYPE_CNT 7 #define AUTHTYPE_TEST 99 #ifdef AUTH_NAMES -char *authtype_names[] = { +const char *authtype_names[] = { "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", NULL, "SRA", 0 }; #else extern char *authtype_names[]; #endif #define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) #define AUTHTYPE_NAME(x) authtype_names[x] /* * ENCRYPTion suboptions */ #define ENCRYPT_IS 0 /* I pick encryption type ... */ #define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ #define ENCRYPT_REPLY 2 /* Initial setup response */ #define ENCRYPT_START 3 /* Am starting to send encrypted */ #define ENCRYPT_END 4 /* Am ending encrypted */ #define ENCRYPT_REQSTART 5 /* Request you start encrypting */ #define ENCRYPT_REQEND 6 /* Request you end encrypting */ #define ENCRYPT_ENC_KEYID 7 #define ENCRYPT_DEC_KEYID 8 #define ENCRYPT_CNT 9 #define ENCTYPE_ANY 0 #define ENCTYPE_DES_CFB64 1 #define ENCTYPE_DES_OFB64 2 #define ENCTYPE_CNT 3 #ifdef ENCRYPT_NAMES -char *encrypt_names[] = { +const char *encrypt_names[] = { "IS", "SUPPORT", "REPLY", "START", "END", "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", 0 }; -char *enctype_names[] = { +const char *enctype_names[] = { "ANY", "DES_CFB64", "DES_OFB64", 0 }; #else extern char *encrypt_names[]; extern char *enctype_names[]; #endif #define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) #define ENCRYPT_NAME(x) encrypt_names[x] #define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) #define ENCTYPE_NAME(x) enctype_names[x] #endif /* !_TELNET_H_ */ Index: head/crypto/telnet/libtelnet/spx.c =================================================================== --- head/crypto/telnet/libtelnet/spx.c (revision 87138) +++ head/crypto/telnet/libtelnet/spx.c (nonexistent) @@ -1,592 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)spx.c 8.2 (Berkeley) 5/30/95"; -#endif -#endif /* not lint */ - -#ifdef SPX -/* - * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION - * ALL RIGHTS RESERVED - * - * "Digital Equipment Corporation authorizes the reproduction, - * distribution and modification of this software subject to the following - * restrictions: - * - * 1. Any partial or whole copy of this software, or any modification - * thereof, must include this copyright notice in its entirety. - * - * 2. This software is supplied "as is" with no warranty of any kind, - * expressed or implied, for any purpose, including any warranty of fitness - * or merchantibility. DIGITAL assumes no responsibility for the use or - * reliability of this software, nor promises to provide any form of - * support for it on any basis. - * - * 3. Distribution of this software is authorized only if no profit or - * remuneration of any kind is received in exchange for such distribution. - * - * 4. This software produces public key authentication certificates - * bearing an expiration date established by DIGITAL and RSA Data - * Security, Inc. It may cease to generate certificates after the expiration - * date. Any modification of this software that changes or defeats - * the expiration date or its effect is unauthorized. - * - * 5. Software that will renew or extend the expiration date of - * authentication certificates produced by this software may be obtained - * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA - * 94065, (415)595-8782, or from DIGITAL" - * - */ - -#include -#include -#include -#include "gssapi_defs.h" -#ifdef __STDC__ -#include -#endif -#ifdef NO_STRING_H -#include -#else -#include -#endif - -#include -#include "encrypt.h" -#include "auth.h" -#include "misc.h" - -extern auth_debug_mode; - -static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, - AUTHTYPE_SPX, }; -static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, - TELQUAL_NAME, }; - -#define SPX_AUTH 0 /* Authentication data follows */ -#define SPX_REJECT 1 /* Rejected (reason might follow) */ -#define SPX_ACCEPT 2 /* Accepted */ - -#ifdef ENCRYPTION -static Block session_key = { 0 }; -#endif /* ENCRYPTION */ -static Block challenge = { 0 }; - - -/*******************************************************************/ - -gss_OID_set actual_mechs; -gss_OID actual_mech_type, output_name_type; -int major_status, status, msg_ctx = 0, new_status; -int req_flags = 0, ret_flags, lifetime_rec; -gss_cred_id_t gss_cred_handle; -gss_ctx_id_t actual_ctxhandle, context_handle; -gss_buffer_desc output_token, input_token, input_name_buffer; -gss_buffer_desc status_string; -gss_name_t desired_targname, src_name; -gss_channel_bindings input_chan_bindings; -char lhostname[GSS_C_MAX_PRINTABLE_NAME]; -char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; -int to_addr=0, from_addr=0; -char *address; -gss_buffer_desc fullname_buffer; -gss_OID fullname_type; -gss_cred_id_t gss_delegated_cred_handle; - -/*******************************************************************/ - - - - static int -Data(ap, type, d, c) - Authenticator *ap; - int type; - void *d; - int c; -{ - unsigned char *p = str_data + 4; - unsigned char *cd = (unsigned char *)d; - - if (c == -1) - c = strlen((char *)cd); - - if (0) { - printf("%s:%d: [%d] (%d)", - str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", - str_data[3], - type, c); - printd(d, c); - printf("\r\n"); - } - *p++ = ap->type; - *p++ = ap->way; - *p++ = type; - while (c-- > 0) { - if ((*p++ = *cd++) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - if (str_data[3] == TELQUAL_IS) - printsub('>', &str_data[2], p - (&str_data[2])); - return(net_write(str_data, p - str_data)); -} - - int -spx_init(ap, server) - Authenticator *ap; - int server; -{ - gss_cred_id_t tmp_cred_handle; - - if (server) { - str_data[3] = TELQUAL_REPLY; - gethostname(lhostname, sizeof(lhostname)); - strcpy(targ_printable, "SERVICE:rcmd@"); - strcat(targ_printable, lhostname); - input_name_buffer.length = strlen(targ_printable); - input_name_buffer.value = targ_printable; - major_status = gss_import_name(&status, - &input_name_buffer, - GSS_C_NULL_OID, - &desired_targname); - major_status = gss_acquire_cred(&status, - desired_targname, - 0, - GSS_C_NULL_OID_SET, - GSS_C_ACCEPT, - &tmp_cred_handle, - &actual_mechs, - &lifetime_rec); - if (major_status != GSS_S_COMPLETE) return(0); - } else { - str_data[3] = TELQUAL_IS; - } - return(1); -} - - int -spx_send(ap) - Authenticator *ap; -{ - Block enckey; - int r; - - gss_OID actual_mech_type, output_name_type; - int msg_ctx = 0, new_status, status; - int req_flags = 0, ret_flags, lifetime_rec, major_status; - gss_buffer_desc output_token, input_token, input_name_buffer; - gss_buffer_desc output_name_buffer, status_string; - gss_name_t desired_targname; - gss_channel_bindings input_chan_bindings; - char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; - int from_addr=0, to_addr=0, myhostlen, j; - int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0; - char *address; - - printf("[ Trying SPX ... ]\n"); - strcpy(targ_printable, "SERVICE:rcmd@"); - strcat(targ_printable, RemoteHostName); - - input_name_buffer.length = strlen(targ_printable); - input_name_buffer.value = targ_printable; - - if (!UserNameRequested) { - return(0); - } - - major_status = gss_import_name(&status, - &input_name_buffer, - GSS_C_NULL_OID, - &desired_targname); - - - major_status = gss_display_name(&status, - desired_targname, - &output_name_buffer, - &output_name_type); - - printf("target is '%s'\n", output_name_buffer.value); fflush(stdout); - - major_status = gss_release_buffer(&status, &output_name_buffer); - - input_chan_bindings = (gss_channel_bindings) - malloc(sizeof(gss_channel_bindings_desc)); - - input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; - input_chan_bindings->initiator_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->initiator_address.value = (char *) address; - address[0] = ((from_addr & 0xff000000) >> 24); - address[1] = ((from_addr & 0xff0000) >> 16); - address[2] = ((from_addr & 0xff00) >> 8); - address[3] = (from_addr & 0xff); - input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; - input_chan_bindings->acceptor_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->acceptor_address.value = (char *) address; - address[0] = ((to_addr & 0xff000000) >> 24); - address[1] = ((to_addr & 0xff0000) >> 16); - address[2] = ((to_addr & 0xff00) >> 8); - address[3] = (to_addr & 0xff); - input_chan_bindings->application_data.length = 0; - - req_flags = 0; - if (deleg_flag) req_flags = req_flags | 1; - if (mutual_flag) req_flags = req_flags | 2; - if (replay_flag) req_flags = req_flags | 4; - if (seq_flag) req_flags = req_flags | 8; - - major_status = gss_init_sec_context(&status, /* minor status */ - GSS_C_NO_CREDENTIAL, /* cred handle */ - &actual_ctxhandle, /* ctx handle */ - desired_targname, /* target name */ - GSS_C_NULL_OID, /* mech type */ - req_flags, /* req flags */ - 0, /* time req */ - input_chan_bindings, /* chan binding */ - GSS_C_NO_BUFFER, /* input token */ - &actual_mech_type, /* actual mech */ - &output_token, /* output token */ - &ret_flags, /* ret flags */ - &lifetime_rec); /* time rec */ - - if ((major_status != GSS_S_COMPLETE) && - (major_status != GSS_S_CONTINUE_NEEDED)) { - gss_display_status(&new_status, - status, - GSS_C_MECH_CODE, - GSS_C_NULL_OID, - &msg_ctx, - &status_string); - printf("%s\n", status_string.value); - return(0); - } - - if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { - return(0); - } - - if (!Data(ap, SPX_AUTH, (void *)output_token.value, output_token.length)) { - return(0); - } - - return(1); -} - - void -spx_is(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; -{ - Session_Key skey; - Block datablock; - int r; - - if (cnt-- < 1) - return; - switch (*data++) { - case SPX_AUTH: - input_token.length = cnt; - input_token.value = (char *) data; - - gethostname(lhostname, sizeof(lhostname)); - - strcpy(targ_printable, "SERVICE:rcmd@"); - strcat(targ_printable, lhostname); - - input_name_buffer.length = strlen(targ_printable); - input_name_buffer.value = targ_printable; - - major_status = gss_import_name(&status, - &input_name_buffer, - GSS_C_NULL_OID, - &desired_targname); - - major_status = gss_acquire_cred(&status, - desired_targname, - 0, - GSS_C_NULL_OID_SET, - GSS_C_ACCEPT, - &gss_cred_handle, - &actual_mechs, - &lifetime_rec); - - major_status = gss_release_name(&status, desired_targname); - - input_chan_bindings = (gss_channel_bindings) - malloc(sizeof(gss_channel_bindings_desc)); - - input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; - input_chan_bindings->initiator_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->initiator_address.value = (char *) address; - address[0] = ((from_addr & 0xff000000) >> 24); - address[1] = ((from_addr & 0xff0000) >> 16); - address[2] = ((from_addr & 0xff00) >> 8); - address[3] = (from_addr & 0xff); - input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; - input_chan_bindings->acceptor_address.length = 4; - address = (char *) malloc(4); - input_chan_bindings->acceptor_address.value = (char *) address; - address[0] = ((to_addr & 0xff000000) >> 24); - address[1] = ((to_addr & 0xff0000) >> 16); - address[2] = ((to_addr & 0xff00) >> 8); - address[3] = (to_addr & 0xff); - input_chan_bindings->application_data.length = 0; - - major_status = gss_accept_sec_context(&status, - &context_handle, - gss_cred_handle, - &input_token, - input_chan_bindings, - &src_name, - &actual_mech_type, - &output_token, - &ret_flags, - &lifetime_rec, - &gss_delegated_cred_handle); - - - if (major_status != GSS_S_COMPLETE) { - - major_status = gss_display_name(&status, - src_name, - &fullname_buffer, - &fullname_type); - Data(ap, SPX_REJECT, (void *)"auth failed", -1); - auth_finished(ap, AUTH_REJECT); - return; - } - - major_status = gss_display_name(&status, - src_name, - &fullname_buffer, - &fullname_type); - - - Data(ap, SPX_ACCEPT, (void *)output_token.value, output_token.length); - auth_finished(ap, AUTH_USER); - break; - - default: - Data(ap, SPX_REJECT, 0, 0); - break; - } -} - - - void -spx_reply(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; -{ - Session_Key skey; - - if (cnt-- < 1) - return; - switch (*data++) { - case SPX_REJECT: - if (cnt > 0) { - printf("[ SPX refuses authentication because %.*s ]\r\n", - cnt, data); - } else - printf("[ SPX refuses authentication ]\r\n"); - auth_send_retry(); - return; - case SPX_ACCEPT: - printf("[ SPX accepts you ]\n"); - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* - * Send over the encrypted challenge. - */ - input_token.value = (char *) data; - input_token.length = cnt; - - major_status = gss_init_sec_context(&status, /* minor stat */ - GSS_C_NO_CREDENTIAL, /* cred handle */ - &actual_ctxhandle, /* ctx handle */ - desired_targname, /* target name */ - GSS_C_NULL_OID, /* mech type */ - req_flags, /* req flags */ - 0, /* time req */ - input_chan_bindings, /* chan binding */ - &input_token, /* input token */ - &actual_mech_type, /* actual mech */ - &output_token, /* output token */ - &ret_flags, /* ret flags */ - &lifetime_rec); /* time rec */ - - if (major_status != GSS_S_COMPLETE) { - gss_display_status(&new_status, - status, - GSS_C_MECH_CODE, - GSS_C_NULL_OID, - &msg_ctx, - &status_string); - printf("[ SPX mutual response fails ... '%s' ]\r\n", - status_string.value); - auth_send_retry(); - return; - } - } - auth_finished(ap, AUTH_USER); - return; - - default: - return; - } -} - - int -spx_status(ap, name, level) - Authenticator *ap; - char *name; - int level; -{ - - gss_buffer_desc fullname_buffer, acl_file_buffer; - gss_OID fullname_type; - char acl_file[160], fullname[160]; - int major_status, status = 0; - struct passwd *pwd; - - /* - * hard code fullname to - * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan" - * and acl_file to "~kannan/.sphinx" - */ - - pwd = getpwnam(UserNameRequested); - if (pwd == NULL) { - return(AUTH_USER); /* not authenticated */ - } - - strcpy(acl_file, pwd->pw_dir); - strcat(acl_file, "/.sphinx"); - acl_file_buffer.value = acl_file; - acl_file_buffer.length = strlen(acl_file); - - major_status = gss_display_name(&status, - src_name, - &fullname_buffer, - &fullname_type); - - if (level < AUTH_USER) - return(level); - - major_status = gss__check_acl(&status, &fullname_buffer, - &acl_file_buffer); - - if (major_status == GSS_S_COMPLETE) { - strcpy(name, UserNameRequested); - return(AUTH_VALID); - } else { - return(AUTH_USER); - } - -} - -#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} -#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - - void -spx_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; -{ - char lbuf[32]; - register int i; - - buf[buflen-1] = '\0'; /* make sure its NULL terminated */ - buflen -= 1; - - switch(data[3]) { - case SPX_REJECT: /* Rejected (reason might follow) */ - strncpy((char *)buf, " REJECT ", buflen); - goto common; - - case SPX_ACCEPT: /* Accepted (name might follow) */ - strncpy((char *)buf, " ACCEPT ", buflen); - common: - BUMP(buf, buflen); - if (cnt <= 4) - break; - ADDC(buf, buflen, '"'); - for (i = 4; i < cnt; i++) - ADDC(buf, buflen, data[i]); - ADDC(buf, buflen, '"'); - ADDC(buf, buflen, '\0'); - break; - - case SPX_AUTH: /* Authentication data follows */ - strncpy((char *)buf, " AUTH", buflen); - goto common2; - - default: - sprintf(lbuf, " %d (unknown)", data[3]); - strncpy((char *)buf, lbuf, buflen); - common2: - BUMP(buf, buflen); - for (i = 4; i < cnt; i++) { - sprintf(lbuf, " %d", data[i]); - strncpy((char *)buf, lbuf, buflen); - BUMP(buf, buflen); - } - break; - } -} - -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); -} -#endif Property changes on: head/crypto/telnet/libtelnet/spx.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/crypto/telnet/libtelnet/auth-proto.h =================================================================== --- head/crypto/telnet/libtelnet/auth-proto.h (revision 87138) +++ head/crypto/telnet/libtelnet/auth-proto.h (revision 87139) @@ -1,109 +1,119 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)auth-proto.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #if !defined(P) #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #endif -#if defined(AUTHENTICATION) -Authenticator *findauthenticator P((int, int)); +#ifdef AUTHENTICATION -void auth_init P((char *, int)); -int auth_cmd P((int, char **)); -void auth_request P((void)); -void auth_send P((unsigned char *, int)); -void auth_send_retry P((void)); -void auth_is P((unsigned char *, int)); -void auth_reply P((unsigned char *, int)); -void auth_finished P((Authenticator *, int)); -int auth_wait P((char *)); -void auth_disable_name P((char *)); -void auth_gen_printsub P((unsigned char *, int, unsigned char *, int)); -void auth_name P((unsigned char *, int)); -void auth_printsub P((unsigned char *, int, unsigned char *, int)); -int auth_sendname P((unsigned char *, int)); -void auth_encrypt_user P((char *)); +Authenticator *findauthenticator(int, int); +void auth_init(const char *, int); +int auth_cmd(int, char **); +void auth_request(void); +void auth_send(unsigned char *, int); +void auth_send_retry(void); +void auth_is(unsigned char *, int); +void auth_reply(unsigned char *, int); +void auth_finished(Authenticator *, int); +int auth_wait(char *); +void auth_disable_name(char *); +void auth_gen_printsub(unsigned char *, int, unsigned char *, int); +void auth_name(unsigned char *, int); +void auth_printsub(unsigned char *, int, unsigned char *, int); +int auth_sendname(unsigned char *, int); +void auth_encrypt_user(char *); +int auth_disable(char *); +int auth_enable(char *); +int auth_togdebug(int); +int auth_status(void); + +int getauthmask(char *, int *); + #ifdef KRB4 -int kerberos4_init P((Authenticator *, int)); -int kerberos4_send P((Authenticator *)); -void kerberos4_is P((Authenticator *, unsigned char *, int)); -void kerberos4_reply P((Authenticator *, unsigned char *, int)); -int kerberos4_status P((Authenticator *, char *, int)); -void kerberos4_printsub P((unsigned char *, int, unsigned char *, int)); +int kerberos4_init(Authenticator *, int); +int kerberos4_send(Authenticator *); +void kerberos4_is(Authenticator *, unsigned char *, int); +void kerberos4_reply(Authenticator *, unsigned char *, int); +int kerberos4_status(Authenticator *, char *, int); +void kerberos4_printsub(unsigned char *, int, unsigned char *, int); #endif #ifdef KRB5 -int kerberos5_init P((Authenticator *, int)); -int kerberos5_send P((Authenticator *)); -void kerberos5_is P((Authenticator *, unsigned char *, int)); -void kerberos5_reply P((Authenticator *, unsigned char *, int)); -int kerberos5_status P((Authenticator *, char *, int)); -void kerberos5_printsub P((unsigned char *, int, unsigned char *, int)); +int kerberos5_init(Authenticator *, int); +int kerberos5_send_mutual(Authenticator *); +int kerberos5_send_oneway(Authenticator *); +void kerberos5_is(Authenticator *, unsigned char *, int); +void kerberos5_reply(Authenticator *, unsigned char *, int); +int kerberos5_status(Authenticator *, char *, int level); +void kerberos5_printsub(unsigned char *, int, unsigned char *, int); #endif + #ifdef SRA -int sra_init P((Authenticator *, int)); -int sra_send P((Authenticator *)); -void sra_is P((Authenticator *, unsigned char *, int)); -void sra_reply P((Authenticator *, unsigned char *, int)); -int sra_status P((Authenticator *, char *, int)); -void sra_printsub P((unsigned char *, int, unsigned char *, int)); +int sra_init(Authenticator *, int); +int sra_send(Authenticator *); +void sra_is(Authenticator *, unsigned char *, int); +void sra_reply(Authenticator *, unsigned char *, int); +int sra_status(Authenticator *, char *, int); +void sra_printsub(unsigned char *, int, unsigned char *, int); #endif + #endif Index: head/crypto/telnet/libtelnet/auth.c =================================================================== --- head/crypto/telnet/libtelnet/auth.c (revision 87138) +++ head/crypto/telnet/libtelnet/auth.c (revision 87139) @@ -1,689 +1,623 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)auth.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ -#if defined(AUTHENTICATION) -#include +#ifdef AUTHENTICATION +#define AUTH_NAMES #include #include -#define AUTH_NAMES -#include -#ifdef __STDC__ +#include #include -#include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif +#include +#include #include "encrypt.h" #include "auth.h" #include "misc-proto.h" #include "auth-proto.h" -#define typemask(x) (1<<((x)-1)) +#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) #ifdef KRB4_ENCPWD extern krb4encpwd_init(); extern krb4encpwd_send(); extern krb4encpwd_is(); extern krb4encpwd_reply(); extern krb4encpwd_status(); extern krb4encpwd_printsub(); #endif #ifdef RSA_ENCPWD extern rsaencpwd_init(); extern rsaencpwd_send(); extern rsaencpwd_is(); extern rsaencpwd_reply(); extern rsaencpwd_status(); extern rsaencpwd_printsub(); #endif int auth_debug_mode = 0; -static char *Name = "Noname"; +static const char *Name = "Noname"; static int Server = 0; static Authenticator *authenticated = 0; static int authenticating = 0; static int validuser = 0; static unsigned char _auth_send_data[256]; static unsigned char *auth_send_data; static int auth_send_cnt = 0; int auth_onoff(char *type, int on); void auth_encrypt_user(char *name); /* * Authentication types supported. Plese note that these are stored * in priority order, i.e. try the first one first. */ Authenticator authenticators[] = { -#ifdef SPX - { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, - spx_init, - spx_send, - spx_is, - spx_reply, - spx_status, - spx_printsub }, - { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - spx_init, - spx_send, - spx_is, - spx_reply, - spx_status, - spx_printsub }, -#endif #ifdef KRB5 # ifdef ENCRYPTION { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, kerberos5_init, - kerberos5_send, + kerberos5_send_mutual, kerberos5_is, kerberos5_reply, kerberos5_status, kerberos5_printsub }, # endif /* ENCRYPTION */ { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, kerberos5_init, - kerberos5_send, + kerberos5_send_oneway, kerberos5_is, kerberos5_reply, kerberos5_status, kerberos5_printsub }, #endif #ifdef KRB4 # ifdef ENCRYPTION { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, kerberos4_init, kerberos4_send, kerberos4_is, kerberos4_reply, kerberos4_status, kerberos4_printsub }, # endif /* ENCRYPTION */ { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, kerberos4_init, kerberos4_send, kerberos4_is, kerberos4_reply, kerberos4_status, kerberos4_printsub }, #endif #ifdef KRB4_ENCPWD { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, krb4encpwd_init, krb4encpwd_send, krb4encpwd_is, krb4encpwd_reply, krb4encpwd_status, krb4encpwd_printsub }, #endif #ifdef RSA_ENCPWD { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, rsaencpwd_init, rsaencpwd_send, rsaencpwd_is, rsaencpwd_reply, rsaencpwd_status, rsaencpwd_printsub }, #endif #ifdef SRA { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, sra_init, sra_send, sra_is, sra_reply, sra_status, sra_printsub }, #endif - { 0, }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, }; -static Authenticator NoAuth = { 0 }; +static Authenticator NoAuth = { 0, 0, 0, 0, 0, 0, 0, 0 }; static int i_support = 0; static int i_wont_support = 0; - Authenticator * -findauthenticator(type, way) - int type; - int way; +Authenticator * +findauthenticator(int type, int way) { Authenticator *ap = authenticators; while (ap->type && (ap->type != type || ap->way != way)) ++ap; return(ap->type ? ap : 0); } - void -auth_init(name, server) - char *name; - int server; +void +auth_init(const char *name, int server) { Authenticator *ap = authenticators; Server = server; Name = name; i_support = 0; authenticated = 0; authenticating = 0; while (ap->type) { if (!ap->init || (*ap->init)(ap, server)) { i_support |= typemask(ap->type); if (auth_debug_mode) printf(">>>%s: I support auth type %d %d\r\n", Name, ap->type, ap->way); } else if (auth_debug_mode) printf(">>>%s: Init failed: auth type %d %d\r\n", Name, ap->type, ap->way); ++ap; } } - void -auth_disable_name(name) - char *name; +void +auth_disable_name(char *name) { int x; for (x = 0; x < AUTHTYPE_CNT; ++x) { if (AUTHTYPE_NAME(x) && !strcasecmp(name, AUTHTYPE_NAME(x))) { i_wont_support |= typemask(x); break; } } } - int -getauthmask(type, maskp) - char *type; - int *maskp; +int +getauthmask(char *type, int *maskp) { - register int x; + int x; if (AUTHTYPE_NAME(0) && !strcasecmp(type, AUTHTYPE_NAME(0))) { *maskp = -1; return(1); } for (x = 1; x < AUTHTYPE_CNT; ++x) { if (AUTHTYPE_NAME(x) && !strcasecmp(type, AUTHTYPE_NAME(x))) { *maskp = typemask(x); return(1); } } return(0); } - int -auth_enable(type) - char *type; +int +auth_enable(char *type) { return(auth_onoff(type, 1)); } - int -auth_disable(type) - char *type; +int +auth_disable(char *type) { return(auth_onoff(type, 0)); } - int -auth_onoff(type, on) - char *type; - int on; +int +auth_onoff(char *type, int on) { int i, mask = -1; Authenticator *ap; if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) { printf("auth %s 'type'\n", on ? "enable" : "disable"); printf("Where 'type' is one of:\n"); printf("\t%s\n", AUTHTYPE_NAME(0)); mask = 0; for (ap = authenticators; ap->type; ap++) { if ((mask & (i = typemask(ap->type))) != 0) continue; mask |= i; printf("\t%s\n", AUTHTYPE_NAME(ap->type)); } return(0); } if (!getauthmask(type, &mask)) { printf("%s: invalid authentication type\n", type); return(0); } if (on) i_wont_support &= ~mask; else i_wont_support |= mask; return(1); } - int -auth_togdebug(on) - int on; +int +auth_togdebug(int on) { if (on < 0) auth_debug_mode ^= 1; else auth_debug_mode = on; printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled"); return(1); } - int -auth_status() +int +auth_status(void) { Authenticator *ap; int i, mask; if (i_wont_support == -1) printf("Authentication disabled\n"); else printf("Authentication enabled\n"); mask = 0; for (ap = authenticators; ap->type; ap++) { if ((mask & (i = typemask(ap->type))) != 0) continue; mask |= i; printf("%s: %s\n", AUTHTYPE_NAME(ap->type), (i_wont_support & typemask(ap->type)) ? "disabled" : "enabled"); } return(1); } /* * This routine is called by the server to start authentication * negotiation. */ - void -auth_request() +void +auth_request(void) { static unsigned char str_request[64] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_SEND, }; Authenticator *ap = authenticators; unsigned char *e = str_request + 4; if (!authenticating) { authenticating = 1; while (ap->type) { if (i_support & ~i_wont_support & typemask(ap->type)) { if (auth_debug_mode) { printf(">>>%s: Sending type %d %d\r\n", Name, ap->type, ap->way); } *e++ = ap->type; *e++ = ap->way; } ++ap; } *e++ = IAC; *e++ = SE; net_write(str_request, e - str_request); printsub('>', &str_request[2], e - str_request - 2); } } /* * This is called when an AUTH SEND is received. * It should never arrive on the server side (as only the server can * send an AUTH SEND). * You should probably respond to it if you can... * * If you want to respond to the types out of order (i.e. even * if he sends LOGIN KERBEROS and you support both, you respond * with KERBEROS instead of LOGIN (which is against what the * protocol says)) you will have to hack this code... */ - void -auth_send(data, cnt) - unsigned char *data; - int cnt; +void +auth_send(unsigned char *data, int cnt) { Authenticator *ap; static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_IS, AUTHTYPE_NULL, 0, IAC, SE }; if (Server) { if (auth_debug_mode) { printf(">>>%s: auth_send called!\r\n", Name); } return; } if (auth_debug_mode) { printf(">>>%s: auth_send got:", Name); printd(data, cnt); printf("\r\n"); } /* * Save the data, if it is new, so that we can continue looking * at it if the authorization we try doesn't work */ if (data < _auth_send_data || data > _auth_send_data + sizeof(_auth_send_data)) { - auth_send_cnt = cnt > sizeof(_auth_send_data) + auth_send_cnt = (size_t)cnt > sizeof(_auth_send_data) ? sizeof(_auth_send_data) : cnt; memmove((void *)_auth_send_data, (void *)data, auth_send_cnt); auth_send_data = _auth_send_data; } else { /* * This is probably a no-op, but we just make sure */ auth_send_data = data; auth_send_cnt = cnt; } while ((auth_send_cnt -= 2) >= 0) { if (auth_debug_mode) printf(">>>%s: He supports %d\r\n", Name, *auth_send_data); if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) { ap = findauthenticator(auth_send_data[0], auth_send_data[1]); if (ap && ap->send) { if (auth_debug_mode) printf(">>>%s: Trying %d %d\r\n", Name, auth_send_data[0], auth_send_data[1]); if ((*ap->send)(ap)) { /* * Okay, we found one we like * and did it. * we can go home now. */ if (auth_debug_mode) printf(">>>%s: Using type %d\r\n", Name, *auth_send_data); auth_send_data += 2; return; } } /* else * just continue on and look for the * next one if we didn't do anything. */ } auth_send_data += 2; } net_write(str_none, sizeof(str_none)); printsub('>', &str_none[2], sizeof(str_none) - 2); if (auth_debug_mode) printf(">>>%s: Sent failure message\r\n", Name); auth_finished(0, AUTH_REJECT); -#ifdef KANNAN - /* - * We requested strong authentication, however no mechanisms worked. - * Therefore, exit on client end. - */ - printf("Unable to securely authenticate user ... exit\n"); - exit(0); -#endif /* KANNAN */ } - void -auth_send_retry() +void +auth_send_retry(void) { /* * if auth_send_cnt <= 0 then auth_send will end up rejecting * the authentication and informing the other side of this. */ auth_send(auth_send_data, auth_send_cnt); } - void -auth_is(data, cnt) - unsigned char *data; - int cnt; +void +auth_is(unsigned char *data, int cnt) { Authenticator *ap; if (cnt < 2) return; if (data[0] == AUTHTYPE_NULL) { auth_finished(0, AUTH_REJECT); return; } if ((ap = findauthenticator(data[0], data[1]))) { if (ap->is) (*ap->is)(ap, data+2, cnt-2); } else if (auth_debug_mode) printf(">>>%s: Invalid authentication in IS: %d\r\n", Name, *data); } - void -auth_reply(data, cnt) - unsigned char *data; - int cnt; +void +auth_reply(unsigned char *data, int cnt) { Authenticator *ap; if (cnt < 2) return; if ((ap = findauthenticator(data[0], data[1]))) { if (ap->reply) (*ap->reply)(ap, data+2, cnt-2); } else if (auth_debug_mode) printf(">>>%s: Invalid authentication in SEND: %d\r\n", Name, *data); } - void -auth_name(data, cnt) - unsigned char *data; - int cnt; +void +auth_name(unsigned char *data, int cnt) { unsigned char savename[256]; if (cnt < 1) { if (auth_debug_mode) printf(">>>%s: Empty name in NAME\r\n", Name); return; } - if (cnt > sizeof(savename) - 1) { + if ((size_t)cnt > sizeof(savename) - 1) { if (auth_debug_mode) printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n", Name, cnt, sizeof(savename)-1); return; } memmove((void *)savename, (void *)data, cnt); savename[cnt] = '\0'; /* Null terminate */ if (auth_debug_mode) printf(">>>%s: Got NAME [%s]\r\n", Name, savename); auth_encrypt_user(savename); } - int -auth_sendname(cp, len) - unsigned char *cp; - int len; +int +auth_sendname(unsigned char *cp, int len) { static unsigned char str_request[256+6] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; - register unsigned char *e = str_request + 4; - register unsigned char *ee = &str_request[sizeof(str_request)-2]; + unsigned char *e = str_request + 4; + unsigned char *ee = &str_request[sizeof(str_request)-2]; while (--len >= 0) { if ((*e++ = *cp++) == IAC) *e++ = IAC; if (e >= ee) return(0); } *e++ = IAC; *e++ = SE; net_write(str_request, e - str_request); printsub('>', &str_request[2], e - &str_request[2]); return(1); } - void -auth_finished(ap, result) - Authenticator *ap; - int result; +void +auth_finished(Authenticator *ap, int result) { if (!(authenticated = ap)) authenticated = &NoAuth; validuser = result; } - /* ARGSUSED */ - static void -auth_intr(sig) - int sig; +/* ARGSUSED */ +static void +auth_intr(int sig __unused) { auth_finished(0, AUTH_REJECT); } - int -auth_wait(name) - char *name; +int +auth_wait(char *name) { if (auth_debug_mode) printf(">>>%s: in auth_wait.\r\n", Name); if (Server && !authenticating) return(0); (void) signal(SIGALRM, auth_intr); alarm(30); while (!authenticated) if (telnet_spin()) break; alarm(0); (void) signal(SIGALRM, SIG_DFL); /* * Now check to see if the user is valid or not */ if (!authenticated || authenticated == &NoAuth) return(AUTH_REJECT); if (validuser == AUTH_VALID) validuser = AUTH_USER; if (authenticated->status) validuser = (*authenticated->status)(authenticated, name, validuser); return(validuser); } - void -auth_debug(mode) - int mode; +void +auth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - auth_debug_mode = mode; -} - - void -auth_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; -{ Authenticator *ap; if ((ap = findauthenticator(data[1], data[2])) && ap->printsub) (*ap->printsub)(data, cnt, buf, buflen); else auth_gen_printsub(data, cnt, buf, buflen); } - void -auth_gen_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - register unsigned char *cp; + unsigned char *cp; unsigned char tbuf[16]; cnt -= 3; data += 3; buf[buflen-1] = '\0'; buf[buflen-2] = '*'; buflen -= 2; for (; cnt > 0; cnt--, data++) { sprintf((char *)tbuf, " %d", *data); for (cp = tbuf; *cp && buflen > 0; --buflen) *buf++ = *cp++; if (buflen <= 0) return; } *buf = '\0'; } #endif Index: head/crypto/telnet/libtelnet/auth.h =================================================================== --- head/crypto/telnet/libtelnet/auth.h (revision 87138) +++ head/crypto/telnet/libtelnet/auth.h (revision 87139) @@ -1,88 +1,80 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)auth.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifndef __AUTH__ #define __AUTH__ #define AUTH_REJECT 0 /* Rejected */ #define AUTH_UNKNOWN 1 /* We don't know who he is, but he's okay */ #define AUTH_OTHER 2 /* We know him, but not his name */ #define AUTH_USER 3 /* We know he name */ #define AUTH_VALID 4 /* We know him, and he needs no password */ -#if !defined(P) -#ifdef __STDC__ -#define P(x) x -#else -#define P(x) () -#endif -#endif - typedef struct XauthP { int type; int way; - int (*init) P((struct XauthP *, int)); - int (*send) P((struct XauthP *)); - void (*is) P((struct XauthP *, unsigned char *, int)); - void (*reply) P((struct XauthP *, unsigned char *, int)); - int (*status) P((struct XauthP *, char *, int)); - void (*printsub) P((unsigned char *, int, unsigned char *, int)); + int (*init)(struct XauthP *, int); + int (*send)(struct XauthP *); + void (*is)(struct XauthP *, unsigned char *, int); + void (*reply)(struct XauthP *, unsigned char *, int); + int (*status)(struct XauthP *, char *, int); + void (*printsub)(unsigned char *, int, unsigned char *, int); } Authenticator; #include "auth-proto.h" extern int auth_debug_mode; #endif Index: head/crypto/telnet/libtelnet/enc-proto.h =================================================================== --- head/crypto/telnet/libtelnet/enc-proto.h (revision 87138) +++ head/crypto/telnet/libtelnet/enc-proto.h (revision 87139) @@ -1,129 +1,133 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)enc-proto.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #if !defined(P) #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #endif #ifdef ENCRYPTION -void encrypt_init P((char *, int)); -Encryptions *findencryption P((int)); -void encrypt_send_supprt P((void)); -void encrypt_auto P((int)); -void decrypt_auto P((int)); -void encrypt_is P((unsigned char *, int)); -void encrypt_reply P((unsigned char *, int)); -void encrypt_start_input P((int)); -void encrypt_session_key P((Session_Key *, int)); -void encrypt_end_input P((void)); -void encrypt_start_output P((int)); -void encrypt_end_output P((void)); -void encrypt_send_request_start P((void)); -void encrypt_send_request_end P((void)); -void encrypt_send_end P((void)); -void encrypt_wait P((void)); -void encrypt_send_support P((void)); -void encrypt_send_keyid P((int, unsigned char *, int, int)); -void encrypt_start P((unsigned char *, int)); -void encrypt_end P((void)); -void encrypt_support P((unsigned char *, int)); -void encrypt_request_start P((unsigned char *, int)); -void encrypt_request_end P((void)); -void encrypt_enc_keyid P((unsigned char *, int)); -void encrypt_dec_keyid P((unsigned char *, int)); -void encrypt_printsub P((unsigned char *, int, unsigned char *, int)); -int net_write P((unsigned char *, int)); +void encrypt_init(const char *, int); +Encryptions *findencryption(int); +void encrypt_send_supprt(void); +void encrypt_auto(int); +void decrypt_auto(int); +void encrypt_is(unsigned char *, int); +void encrypt_reply(unsigned char *, int); +void encrypt_start_input(int); +void encrypt_session_key(Session_Key *, int); +void encrypt_end_input(void); +void encrypt_start_output(int); +void encrypt_end_output(void); +void encrypt_send_request_start(void); +void encrypt_send_request_end(void); +void encrypt_send_end(void); +void encrypt_wait(void); +void encrypt_send_support(void); +void encrypt_send_keyid(int, const char *, int, int); +void encrypt_start(unsigned char *, int); +void encrypt_end(void); +void encrypt_support(unsigned char *, int); +void encrypt_request_start(unsigned char *, int); +void encrypt_request_end(void); +void encrypt_enc_keyid(unsigned char *, int); +void encrypt_dec_keyid(unsigned char *, int); +void encrypt_printsub(unsigned char *, int, unsigned char *, int); +void encrypt_gen_printsub(unsigned char *, int, unsigned char *, int); +void encrypt_display(void); -#ifndef TELENTD -int encrypt_cmd P((int, char **)); -void encrypt_display P((void)); -#endif +void fb64_printsub(unsigned char *, int, unsigned char *, int, const char *); -#ifdef DES_ENCRYPTION -void krbdes_encrypt P((unsigned char *, int)); -int krbdes_decrypt P((int)); -int krbdes_is P((unsigned char *, int)); -int krbdes_reply P((unsigned char *, int)); -void krbdes_init P((int)); -int krbdes_start P((int, int)); -void krbdes_session P((Session_Key *, int)); -void krbdes_printsub P((unsigned char *, int, unsigned char *, int)); +int EncryptEnable(char *, char *); +int EncryptDisable(char *, char *); +int EncryptStatus(void); +int EncryptDebug(int); +int EncryptVerbose(int); +int EncryptAutoEnc(int); +int EncryptAutoDec(int); -void cfb64_encrypt P((unsigned char *, int)); -int cfb64_decrypt P((int)); -void cfb64_init P((int)); -int cfb64_start P((int, int)); -int cfb64_is P((unsigned char *, int)); -int cfb64_reply P((unsigned char *, int)); -void cfb64_session P((Session_Key *, int)); -int cfb64_keyid P((int, unsigned char *, int *)); -void cfb64_printsub P((unsigned char *, int, unsigned char *, int)); +void krbdes_encrypt(unsigned char *, int); +int krbdes_decrypt(int); +int krbdes_is(unsigned char *, int); +int krbdes_reply(unsigned char *, int); +void krbdes_init(int); +int krbdes_start(int, int); +void krbdes_session(Session_Key *, int); +void krbdes_printsub(unsigned char *, int, unsigned char *, int); -void ofb64_encrypt P((unsigned char *, int)); -int ofb64_decrypt P((int)); -void ofb64_init P((int)); -int ofb64_start P((int, int)); -int ofb64_is P((unsigned char *, int)); -int ofb64_reply P((unsigned char *, int)); -void ofb64_session P((Session_Key *, int)); -int ofb64_keyid P((int, unsigned char *, int *)); -void ofb64_printsub P((unsigned char *, int, unsigned char *, int)); -#endif /* DES_ENCRYPTION */ +void cfb64_encrypt(unsigned char *, int); +int cfb64_decrypt(int); +void cfb64_init(int); +int cfb64_start(int, int); +int cfb64_is(unsigned char *, int); +int cfb64_reply(unsigned char *, int); +void cfb64_session(Session_Key *, int); +int cfb64_keyid(int, unsigned char *, int *); +void cfb64_printsub(unsigned char *, int, unsigned char *, int); + +void ofb64_encrypt(unsigned char *, int); +int ofb64_decrypt(int); +void ofb64_init(int); +int ofb64_start(int, int); +int ofb64_is(unsigned char *, int); +int ofb64_reply(unsigned char *, int); +void ofb64_session(Session_Key *, int); +int ofb64_keyid(int, unsigned char *, int *); +void ofb64_printsub(unsigned char *, int, unsigned char *, int); #endif /* ENCRYPTION */ Index: head/crypto/telnet/libtelnet/enc_des.c =================================================================== --- head/crypto/telnet/libtelnet/enc_des.c (revision 87138) +++ head/crypto/telnet/libtelnet/enc_des.c (revision 87139) @@ -1,726 +1,670 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ #ifdef ENCRYPTION # ifdef AUTHENTICATION -# ifdef DES_ENCRYPTION #include +#include #include -#ifdef __STDC__ #include -#endif - -#include #include + #include "encrypt.h" #include "key-proto.h" #include "misc-proto.h" extern int encrypt_debug_mode; void des_set_random_generator_seed(des_cblock *); /* XXX */ #define CFB 0 #define OFB 1 #define NO_SEND_IV 1 #define NO_RECV_IV 2 #define NO_KEYID 4 #define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) #define SUCCESS 0 #define FAILED -1 struct fb { Block krbdes_key; Schedule krbdes_sched; Block temp_feed; unsigned char fb_feed[64]; int need_start; int state[2]; int keyid[2]; int once; struct stinfo { Block str_output; Block str_feed; Block str_iv; Block str_ikey; Schedule str_sched; int str_index; int str_flagshift; } streams[2]; }; static struct fb fb[2]; struct keyidlist { - char *keyid; + const char *keyid; int keyidlen; char *key; int keylen; int flags; } keyidlist [] = { { "\0", 1, 0, 0, 0 }, /* default key of zero */ { 0, 0, 0, 0, 0 } }; #define KEYFLAG_MASK 03 #define KEYFLAG_NOINIT 00 #define KEYFLAG_INIT 01 #define KEYFLAG_OK 02 #define KEYFLAG_BAD 03 #define KEYFLAG_SHIFT 2 #define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) #define FB64_IV 1 #define FB64_IV_OK 2 #define FB64_IV_BAD 3 void fb64_stream_iv P((Block, struct stinfo *)); void fb64_init P((struct fb *)); static int fb64_start P((struct fb *, int, int)); int fb64_is P((unsigned char *, int, struct fb *)); int fb64_reply P((unsigned char *, int, struct fb *)); static void fb64_session P((Session_Key *, int, struct fb *)); void fb64_stream_key P((Block, struct stinfo *)); int fb64_keyid P((int, unsigned char *, int *, struct fb *)); - void -cfb64_init(server) - int server; +void +cfb64_init(int server __unused) { fb64_init(&fb[CFB]); fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); } - void -ofb64_init(server) - int server; +void +ofb64_init(int server __unused) { fb64_init(&fb[OFB]); fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); } - void -fb64_init(fbp) - register struct fb *fbp; +void +fb64_init(struct fb *fbp) { memset((void *)fbp, 0, sizeof(*fbp)); fbp->state[0] = fbp->state[1] = FAILED; fbp->fb_feed[0] = IAC; fbp->fb_feed[1] = SB; fbp->fb_feed[2] = TELOPT_ENCRYPT; fbp->fb_feed[3] = ENCRYPT_IS; } /* * Returns: * -1: some error. Negotiation is done, encryption not ready. * 0: Successful, initial negotiation all done. * 1: successful, negotiation not done yet. * 2: Not yet. Other things (like getting the key from * Kerberos) have to happen before we can continue. */ - int -cfb64_start(dir, server) - int dir; - int server; +int +cfb64_start(int dir, int server) { return(fb64_start(&fb[CFB], dir, server)); } - int -ofb64_start(dir, server) - int dir; - int server; + +int +ofb64_start(int dir, int server) { return(fb64_start(&fb[OFB], dir, server)); } - static int -fb64_start(fbp, dir, server) - struct fb *fbp; - int dir; - int server; +static int +fb64_start(struct fb *fbp, int dir, int server __unused) { - int x; + size_t x; unsigned char *p; - register int state; + int state; switch (dir) { case DIR_DECRYPT: /* * This is simply a request to have the other side * start output (our input). He will negotiate an * IV so we need not look for it. */ state = fbp->state[dir-1]; if (state == FAILED) state = IN_PROGRESS; break; case DIR_ENCRYPT: state = fbp->state[dir-1]; if (state == FAILED) state = IN_PROGRESS; else if ((state & NO_SEND_IV) == 0) break; if (!VALIDKEY(fbp->krbdes_key)) { fbp->need_start = 1; break; } state &= ~NO_SEND_IV; state |= NO_RECV_IV; if (encrypt_debug_mode) printf("Creating new feed\r\n"); /* * Create a random feed and send it over. */ des_new_random_key((Block *)fbp->temp_feed); des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed, fbp->krbdes_sched, 1); p = fbp->fb_feed + 3; *p++ = ENCRYPT_IS; p++; *p++ = FB64_IV; for (x = 0; x < sizeof(Block); ++x) { if ((*p++ = fbp->temp_feed[x]) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); net_write(fbp->fb_feed, p - fbp->fb_feed); break; default: return(FAILED); } return(fbp->state[dir-1] = state); } /* * Returns: * -1: some error. Negotiation is done, encryption not ready. * 0: Successful, initial negotiation all done. * 1: successful, negotiation not done yet. */ - int -cfb64_is(data, cnt) - unsigned char *data; - int cnt; +int +cfb64_is(unsigned char *data, int cnt) { return(fb64_is(data, cnt, &fb[CFB])); } - int -ofb64_is(data, cnt) - unsigned char *data; - int cnt; + +int +ofb64_is(unsigned char *data, int cnt) { return(fb64_is(data, cnt, &fb[OFB])); } - int -fb64_is(data, cnt, fbp) - unsigned char *data; - int cnt; - struct fb *fbp; +int +fb64_is(unsigned char *data, int cnt, struct fb *fbp) { unsigned char *p; - register int state = fbp->state[DIR_DECRYPT-1]; + int state = fbp->state[DIR_DECRYPT-1]; if (cnt-- < 1) goto failure; switch (*data++) { case FB64_IV: if (cnt != sizeof(Block)) { if (encrypt_debug_mode) printf("CFB64: initial vector failed on size\r\n"); state = FAILED; goto failure; } if (encrypt_debug_mode) printf("CFB64: initial vector received\r\n"); if (encrypt_debug_mode) printf("Initializing Decrypt stream\r\n"); fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); p = fbp->fb_feed + 3; *p++ = ENCRYPT_REPLY; p++; *p++ = FB64_IV_OK; *p++ = IAC; *p++ = SE; printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); net_write(fbp->fb_feed, p - fbp->fb_feed); state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; break; default: if (encrypt_debug_mode) { printf("Unknown option type: %d\r\n", *(data-1)); printd(data, cnt); printf("\r\n"); } /* FALL THROUGH */ failure: /* * We failed. Send an FB64_IV_BAD option * to the other side so it will know that * things failed. */ p = fbp->fb_feed + 3; *p++ = ENCRYPT_REPLY; p++; *p++ = FB64_IV_BAD; *p++ = IAC; *p++ = SE; printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); net_write(fbp->fb_feed, p - fbp->fb_feed); break; } return(fbp->state[DIR_DECRYPT-1] = state); } /* * Returns: * -1: some error. Negotiation is done, encryption not ready. * 0: Successful, initial negotiation all done. * 1: successful, negotiation not done yet. */ - int -cfb64_reply(data, cnt) - unsigned char *data; - int cnt; +int +cfb64_reply(unsigned char *data, int cnt) { return(fb64_reply(data, cnt, &fb[CFB])); } - int -ofb64_reply(data, cnt) - unsigned char *data; - int cnt; + +int +ofb64_reply(unsigned char *data, int cnt) { return(fb64_reply(data, cnt, &fb[OFB])); } - - int -fb64_reply(data, cnt, fbp) - unsigned char *data; - int cnt; - struct fb *fbp; +int +fb64_reply(unsigned char *data, int cnt, struct fb *fbp) { - register int state = fbp->state[DIR_ENCRYPT-1]; + int state = fbp->state[DIR_ENCRYPT-1]; if (cnt-- < 1) goto failure; switch (*data++) { case FB64_IV_OK: fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); if (state == FAILED) state = IN_PROGRESS; state &= ~NO_RECV_IV; - encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); + encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1); break; case FB64_IV_BAD: memset(fbp->temp_feed, 0, sizeof(Block)); fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); state = FAILED; break; default: if (encrypt_debug_mode) { printf("Unknown option type: %d\r\n", data[-1]); printd(data, cnt); printf("\r\n"); } /* FALL THROUGH */ failure: state = FAILED; break; } return(fbp->state[DIR_ENCRYPT-1] = state); } - void -cfb64_session(key, server) - Session_Key *key; - int server; +void +cfb64_session(Session_Key *key, int server) { fb64_session(key, server, &fb[CFB]); } - void -ofb64_session(key, server) - Session_Key *key; - int server; +void +ofb64_session(Session_Key *key, int server) { fb64_session(key, server, &fb[OFB]); } - static void -fb64_session(key, server, fbp) - Session_Key *key; - int server; - struct fb *fbp; +static void +fb64_session(Session_Key *key, int server, struct fb *fbp) { - if (!key || key->type != SK_DES) { if (encrypt_debug_mode) printf("Can't set krbdes's session key (%d != %d)\r\n", key ? key->type : -1, SK_DES); return; } memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block)); fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); if (fbp->once == 0) { des_set_random_generator_seed((Block *)fbp->krbdes_key); fbp->once = 1; } des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched); /* * Now look to see if krbdes_start() was was waiting for * the key to show up. If so, go ahead an call it now * that we have the key. */ if (fbp->need_start) { fbp->need_start = 0; fb64_start(fbp, DIR_ENCRYPT, server); } } /* * We only accept a keyid of 0. If we get a keyid of * 0, then mark the state as SUCCESS. */ - int -cfb64_keyid(dir, kp, lenp) - int dir, *lenp; - unsigned char *kp; +int +cfb64_keyid(int dir, unsigned char *kp, int *lenp) { return(fb64_keyid(dir, kp, lenp, &fb[CFB])); } - int -ofb64_keyid(dir, kp, lenp) - int dir, *lenp; - unsigned char *kp; +int +ofb64_keyid(int dir, unsigned char *kp, int *lenp) { return(fb64_keyid(dir, kp, lenp, &fb[OFB])); } - int -fb64_keyid(dir, kp, lenp, fbp) - int dir, *lenp; - unsigned char *kp; - struct fb *fbp; +int +fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp) { - register int state = fbp->state[dir-1]; + int state = fbp->state[dir-1]; if (*lenp != 1 || (*kp != '\0')) { *lenp = 0; return(state); } if (state == FAILED) state = IN_PROGRESS; state &= ~NO_KEYID; return(fbp->state[dir-1] = state); } - void -fb64_printsub(data, cnt, buf, buflen, type) - unsigned char *data, *buf, *type; - int cnt, buflen; +void +fb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type) { char lbuf[32]; - register int i; + int i; char *cp; buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ buflen -= 1; switch(data[2]) { case FB64_IV: sprintf(lbuf, "%s_IV", type); cp = lbuf; goto common; case FB64_IV_OK: sprintf(lbuf, "%s_IV_OK", type); cp = lbuf; goto common; case FB64_IV_BAD: sprintf(lbuf, "%s_IV_BAD", type); cp = lbuf; goto common; default: sprintf(lbuf, " %d (unknown)", data[2]); cp = lbuf; common: for (; (buflen > 0) && (*buf = *cp++); buf++) buflen--; for (i = 3; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) buflen--; } break; } } - void -cfb64_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +cfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { fb64_printsub(data, cnt, buf, buflen, "CFB64"); } - void -ofb64_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +ofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { fb64_printsub(data, cnt, buf, buflen, "OFB64"); } - void -fb64_stream_iv(seed, stp) - Block seed; - register struct stinfo *stp; +void +fb64_stream_iv(Block seed, struct stinfo *stp) { memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); des_key_sched((Block *)stp->str_ikey, stp->str_sched); stp->str_index = sizeof(Block); } - void -fb64_stream_key(key, stp) - Block key; - register struct stinfo *stp; +void +fb64_stream_key(Block key, struct stinfo *stp) { memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); des_key_sched((Block *)key, stp->str_sched); memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); stp->str_index = sizeof(Block); } /* * DES 64 bit Cipher Feedback * * key --->+-----+ * +->| DES |--+ * | +-----+ | * | v * INPUT --(--------->(+)+---> DATA * | | * +-------------+ * * * Given: * iV: Initial vector, 64 bits (8 bytes) long. * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. * * V0 = DES(iV, key) * On = Dn ^ Vn * V(n+1) = DES(On, key) */ - void -cfb64_encrypt(s, c) - register unsigned char *s; - int c; +void +cfb64_encrypt(unsigned char *s, int c) { - register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; - register int index; + struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; + int idx; - index = stp->str_index; + idx = stp->str_index; while (c-- > 0) { - if (index == sizeof(Block)) { + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); - index = 0; + idx = 0; } /* On encryption, we store (feed ^ data) which is cypher */ - *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); + *s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s); s++; - index++; + idx++; } - stp->str_index = index; + stp->str_index = idx; } - int -cfb64_decrypt(data) - int data; +int +cfb64_decrypt(int data) { - register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; - int index; + struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; + int idx; if (data == -1) { /* * Back up one byte. It is assumed that we will * never back up more than one byte. If we do, this * may or may not work. */ if (stp->str_index) --stp->str_index; return(0); } - index = stp->str_index++; - if (index == sizeof(Block)) { + idx = stp->str_index++; + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); stp->str_index = 1; /* Next time will be 1 */ - index = 0; /* But now use 0 */ + idx = 0; /* But now use 0 */ } /* On decryption we store (data) which is cypher. */ - stp->str_output[index] = data; - return(data ^ stp->str_feed[index]); + stp->str_output[idx] = data; + return(data ^ stp->str_feed[idx]); } /* * DES 64 bit Output Feedback * * key --->+-----+ * +->| DES |--+ * | +-----+ | * +-----------+ * v * INPUT -------->(+) ----> DATA * * Given: * iV: Initial vector, 64 bits (8 bytes) long. * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. * * V0 = DES(iV, key) * V(n+1) = DES(Vn, key) * On = Dn ^ Vn */ - void -ofb64_encrypt(s, c) - register unsigned char *s; - int c; +void +ofb64_encrypt(unsigned char *s, int c) { - register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; - register int index; + struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; + int idx; - index = stp->str_index; + idx = stp->str_index; while (c-- > 0) { - if (index == sizeof(Block)) { + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); - index = 0; + idx = 0; } - *s++ ^= stp->str_feed[index]; - index++; + *s++ ^= stp->str_feed[idx]; + idx++; } - stp->str_index = index; + stp->str_index = idx; } - int -ofb64_decrypt(data) - int data; +int +ofb64_decrypt(int data) { - register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; - int index; + struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; + int idx; if (data == -1) { /* * Back up one byte. It is assumed that we will * never back up more than one byte. If we do, this * may or may not work. */ if (stp->str_index) --stp->str_index; return(0); } - index = stp->str_index++; - if (index == sizeof(Block)) { + idx = stp->str_index++; + if (idx == sizeof(Block)) { Block b; des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); stp->str_index = 1; /* Next time will be 1 */ - index = 0; /* But now use 0 */ + idx = 0; /* But now use 0 */ } - return(data ^ stp->str_feed[index]); + return(data ^ stp->str_feed[idx]); } -# endif /* DES_ENCRYPTION */ # endif /* AUTHENTICATION */ #endif /* ENCRYPTION */ Index: head/crypto/telnet/libtelnet/encrypt.c =================================================================== --- head/crypto/telnet/libtelnet/encrypt.c (revision 87138) +++ head/crypto/telnet/libtelnet/encrypt.c (revision 87139) @@ -1,1028 +1,952 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static const char sccsid[] = "@(#)encrypt.c 8.2 (Berkeley) 5/30/95"; #endif #endif /* not lint */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifdef ENCRYPTION #define ENCRYPT_NAMES -#include #include +#include +#include +#include #include "encrypt.h" #include "misc.h" -#ifdef __STDC__ -#include -#endif -#ifdef NO_STRING_H -#include -#else -#include -#endif - /* * These functions pointers point to the current routines * for encrypting and decrypting data. */ void (*encrypt_output) P((unsigned char *, int)); int (*decrypt_input) P((int)); int EncryptType(char *type, char *mode); int EncryptStart(char *mode); int EncryptStop(char *mode); int EncryptStartInput(void); int EncryptStartOutput(void); int EncryptStopInput(void); int EncryptStopOutput(void); -int Ambiguous(char **s); -int isprefix(char *s1, char *s2); -char **genget(char *name, char **table, int stlen); - int encrypt_debug_mode = 0; static int decrypt_mode = 0; static int encrypt_mode = 0; static int encrypt_verbose = 0; static int autoencrypt = 0; static int autodecrypt = 0; static int havesessionkey = 0; static int Server = 0; -static char *Name = "Noname"; +static const char *Name = "Noname"; #define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) static long i_support_encrypt = 0 -#ifdef DES_ENCRYPTION | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) -#endif |0; static long i_support_decrypt = 0 -#ifdef DES_ENCRYPTION | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) -#endif |0; static long i_wont_support_encrypt = 0; static long i_wont_support_decrypt = 0; #define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) #define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) static long remote_supports_encrypt = 0; static long remote_supports_decrypt = 0; static Encryptions encryptions[] = { -#ifdef DES_ENCRYPTION { "DES_CFB64", ENCTYPE_DES_CFB64, cfb64_encrypt, cfb64_decrypt, cfb64_init, cfb64_start, cfb64_is, cfb64_reply, cfb64_session, cfb64_keyid, cfb64_printsub }, { "DES_OFB64", ENCTYPE_DES_OFB64, ofb64_encrypt, ofb64_decrypt, ofb64_init, ofb64_start, ofb64_is, ofb64_reply, ofb64_session, ofb64_keyid, ofb64_printsub }, -#endif /* DES_ENCRYPTION */ - { 0, }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, ENCRYPT_SUPPORT }; static unsigned char str_suplen = 0; static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; - Encryptions * -findencryption(type) - int type; +Encryptions * +findencryption(int type) { Encryptions *ep = encryptions; - if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) + if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & (unsigned)typemask(type))) return(0); while (ep->type && ep->type != type) ++ep; return(ep->type ? ep : 0); } - Encryptions * -finddecryption(type) - int type; +static Encryptions * +finddecryption(int type) { Encryptions *ep = encryptions; - if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) + if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)typemask(type))) return(0); while (ep->type && ep->type != type) ++ep; return(ep->type ? ep : 0); } #define MAXKEYLEN 64 static struct key_info { unsigned char keyid[MAXKEYLEN]; int keylen; int dir; int *modep; - Encryptions *(*getcrypt)(); + Encryptions *(*getcrypt)(int); } ki[2] = { { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, }; static void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len); - void -encrypt_init(name, server) - char *name; - int server; +void +encrypt_init(const char *name, int server) { Encryptions *ep = encryptions; Name = name; Server = server; i_support_encrypt = i_support_decrypt = 0; remote_supports_encrypt = remote_supports_decrypt = 0; encrypt_mode = 0; decrypt_mode = 0; encrypt_output = 0; decrypt_input = 0; -#ifdef notdef - encrypt_verbose = !server; -#endif str_suplen = 4; while (ep->type) { if (encrypt_debug_mode) printf(">>>%s: I will support %s\r\n", Name, ENCTYPE_NAME(ep->type)); i_support_encrypt |= typemask(ep->type); i_support_decrypt |= typemask(ep->type); if ((i_wont_support_decrypt & typemask(ep->type)) == 0) if ((str_send[str_suplen++] = ep->type) == IAC) str_send[str_suplen++] = IAC; if (ep->init) (*ep->init)(Server); ++ep; } str_send[str_suplen++] = IAC; str_send[str_suplen++] = SE; } - void -encrypt_list_types() +static void +encrypt_list_types(void) { Encryptions *ep = encryptions; printf("Valid encryption types:\n"); while (ep->type) { printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type); ++ep; } } - int -EncryptEnable(type, mode) - char *type, *mode; +int +EncryptEnable(char *type, char *mode) { if (isprefix(type, "help") || isprefix(type, "?")) { printf("Usage: encrypt enable [input|output]\n"); encrypt_list_types(); return(0); } if (EncryptType(type, mode)) return(EncryptStart(mode)); return(0); } - int -EncryptDisable(type, mode) - char *type, *mode; +int +EncryptDisable(char *type, char *mode) { - register Encryptions *ep; + Encryptions *ep; int ret = 0; if (isprefix(type, "help") || isprefix(type, "?")) { printf("Usage: encrypt disable [input|output]\n"); encrypt_list_types(); } else if ((ep = (Encryptions *)genget(type, (char **)encryptions, sizeof(Encryptions))) == 0) { printf("%s: invalid encryption type\n", type); } else if (Ambiguous((char **)ep)) { printf("Ambiguous type '%s'\n", type); } else { if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { if (decrypt_mode == ep->type) EncryptStopInput(); i_wont_support_decrypt |= typemask(ep->type); ret = 1; } if ((mode == 0) || (isprefix(mode, "output"))) { if (encrypt_mode == ep->type) EncryptStopOutput(); i_wont_support_encrypt |= typemask(ep->type); ret = 1; } if (ret == 0) printf("%s: invalid encryption mode\n", mode); } return(ret); } - int -EncryptType(type, mode) - char *type; - char *mode; +int +EncryptType(char *type, char *mode) { - register Encryptions *ep; + Encryptions *ep; int ret = 0; if (isprefix(type, "help") || isprefix(type, "?")) { printf("Usage: encrypt type [input|output]\n"); encrypt_list_types(); } else if ((ep = (Encryptions *)genget(type, (char **)encryptions, sizeof(Encryptions))) == 0) { printf("%s: invalid encryption type\n", type); } else if (Ambiguous((char **)ep)) { printf("Ambiguous type '%s'\n", type); } else { if ((mode == 0) || isprefix(mode, "input")) { decrypt_mode = ep->type; i_wont_support_decrypt &= ~typemask(ep->type); ret = 1; } if ((mode == 0) || isprefix(mode, "output")) { encrypt_mode = ep->type; i_wont_support_encrypt &= ~typemask(ep->type); ret = 1; } if (ret == 0) printf("%s: invalid encryption mode\n", mode); } return(ret); } - int -EncryptStart(mode) - char *mode; +int +EncryptStart(char *mode) { - register int ret = 0; + int ret = 0; if (mode) { if (isprefix(mode, "input")) return(EncryptStartInput()); if (isprefix(mode, "output")) return(EncryptStartOutput()); if (isprefix(mode, "help") || isprefix(mode, "?")) { printf("Usage: encrypt start [input|output]\n"); return(0); } printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode); return(0); } ret += EncryptStartInput(); ret += EncryptStartOutput(); return(ret); } - int -EncryptStartInput() +int +EncryptStartInput(void) { if (decrypt_mode) { encrypt_send_request_start(); return(1); } printf("No previous decryption mode, decryption not enabled\r\n"); return(0); } - int -EncryptStartOutput() +int +EncryptStartOutput(void) { if (encrypt_mode) { encrypt_start_output(encrypt_mode); return(1); } printf("No previous encryption mode, encryption not enabled\r\n"); return(0); } - int -EncryptStop(mode) - char *mode; +int +EncryptStop(char *mode) { int ret = 0; if (mode) { if (isprefix(mode, "input")) return(EncryptStopInput()); if (isprefix(mode, "output")) return(EncryptStopOutput()); if (isprefix(mode, "help") || isprefix(mode, "?")) { printf("Usage: encrypt stop [input|output]\n"); return(0); } printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode); return(0); } ret += EncryptStopInput(); ret += EncryptStopOutput(); return(ret); } - int -EncryptStopInput() +int +EncryptStopInput(void) { encrypt_send_request_end(); return(1); } - int -EncryptStopOutput() +int +EncryptStopOutput(void) { encrypt_send_end(); return(1); } - void -encrypt_display() +void +encrypt_display(void) { if (encrypt_output) printf("Currently encrypting output with %s\r\n", ENCTYPE_NAME(encrypt_mode)); if (decrypt_input) printf("Currently decrypting input with %s\r\n", ENCTYPE_NAME(decrypt_mode)); } - int -EncryptStatus() +int +EncryptStatus(void) { if (encrypt_output) printf("Currently encrypting output with %s\r\n", ENCTYPE_NAME(encrypt_mode)); else if (encrypt_mode) { printf("Currently output is clear text.\r\n"); printf("Last encryption mode was %s\r\n", ENCTYPE_NAME(encrypt_mode)); } if (decrypt_input) { printf("Currently decrypting input with %s\r\n", ENCTYPE_NAME(decrypt_mode)); } else if (decrypt_mode) { printf("Currently input is clear text.\r\n"); printf("Last decryption mode was %s\r\n", ENCTYPE_NAME(decrypt_mode)); } return 1; } - void -encrypt_send_support() +void +encrypt_send_support(void) { if (str_suplen) { /* * If the user has requested that decryption start * immediatly, then send a "REQUEST START" before * we negotiate the type. */ if (!Server && autodecrypt) encrypt_send_request_start(); net_write(str_send, str_suplen); printsub('>', &str_send[2], str_suplen - 2); str_suplen = 0; } } - int -EncryptDebug(on) - int on; +int +EncryptDebug(int on) { if (on < 0) encrypt_debug_mode ^= 1; else encrypt_debug_mode = on; printf("Encryption debugging %s\r\n", encrypt_debug_mode ? "enabled" : "disabled"); return(1); } - int -EncryptVerbose(on) - int on; +int +EncryptVerbose(int on) { if (on < 0) encrypt_verbose ^= 1; else encrypt_verbose = on; printf("Encryption %s verbose\r\n", encrypt_verbose ? "is" : "is not"); return(1); } - int -EncryptAutoEnc(on) - int on; +int +EncryptAutoEnc(int on) { encrypt_auto(on); printf("Automatic encryption of output is %s\r\n", autoencrypt ? "enabled" : "disabled"); return(1); } - int -EncryptAutoDec(on) - int on; +int +EncryptAutoDec(int on) { decrypt_auto(on); printf("Automatic decryption of input is %s\r\n", autodecrypt ? "enabled" : "disabled"); return(1); } /* * Called when ENCRYPT SUPPORT is received. */ - void -encrypt_support(typelist, cnt) - unsigned char *typelist; - int cnt; +void +encrypt_support(unsigned char *typelist, int cnt) { - register int type, use_type = 0; + int type, use_type = 0; Encryptions *ep; /* * Forget anything the other side has previously told us. */ remote_supports_decrypt = 0; while (cnt-- > 0) { type = *typelist++; if (encrypt_debug_mode) printf(">>>%s: He is supporting %s (%d)\r\n", Name, ENCTYPE_NAME(type), type); if ((type < ENCTYPE_CNT) && (I_SUPPORT_ENCRYPT & typemask(type))) { remote_supports_decrypt |= typemask(type); if (use_type == 0) use_type = type; } } if (use_type) { ep = findencryption(use_type); if (!ep) return; type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0; if (encrypt_debug_mode) printf(">>>%s: (*ep->start)() returned %d\r\n", Name, type); if (type < 0) return; encrypt_mode = use_type; if (type == 0) encrypt_start_output(use_type); } } - void -encrypt_is(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_is(unsigned char *data, int cnt) { Encryptions *ep; - register int type, ret; + int type, ret; if (--cnt < 0) return; type = *data++; if (type < ENCTYPE_CNT) remote_supports_encrypt |= typemask(type); if (!(ep = finddecryption(type))) { if (encrypt_debug_mode) printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); return; } if (!ep->is) { if (encrypt_debug_mode) printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); ret = 0; } else { ret = (*ep->is)(data, cnt); if (encrypt_debug_mode) printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt, (ret < 0) ? "FAIL " : (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); } if (ret < 0) { autodecrypt = 0; } else { decrypt_mode = type; if (ret == 0 && autodecrypt) encrypt_send_request_start(); } } - void -encrypt_reply(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_reply(unsigned char *data, int cnt) { Encryptions *ep; - register int ret, type; + int ret, type; if (--cnt < 0) return; type = *data++; if (!(ep = findencryption(type))) { if (encrypt_debug_mode) printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); return; } if (!ep->reply) { if (encrypt_debug_mode) printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); ret = 0; } else { ret = (*ep->reply)(data, cnt); if (encrypt_debug_mode) printf("(*ep->reply)(%p, %d) returned %s(%d)\n", data, cnt, (ret < 0) ? "FAIL " : (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); } if (encrypt_debug_mode) printf(">>>%s: encrypt_reply returned %d\n", Name, ret); if (ret < 0) { autoencrypt = 0; } else { encrypt_mode = type; if (ret == 0 && autoencrypt) encrypt_start_output(type); } } /* * Called when a ENCRYPT START command is received. */ - void -encrypt_start(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_start(unsigned char *data __unused, int cnt __unused) { Encryptions *ep; if (!decrypt_mode) { /* * Something is wrong. We should not get a START * command without having already picked our * decryption scheme. Send a REQUEST-END to * attempt to clear the channel... */ printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); encrypt_send_request_end(); return; } if ((ep = finddecryption(decrypt_mode))) { decrypt_input = ep->input; if (encrypt_verbose) printf("[ Input is now decrypted with type %s ]\r\n", ENCTYPE_NAME(decrypt_mode)); if (encrypt_debug_mode) printf(">>>%s: Start to decrypt input with type %s\r\n", Name, ENCTYPE_NAME(decrypt_mode)); } else { printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", Name, ENCTYPE_NAME_OK(decrypt_mode) ? ENCTYPE_NAME(decrypt_mode) : "(unknown)", decrypt_mode); encrypt_send_request_end(); } } - void -encrypt_session_key(key, server) - Session_Key *key; - int server; +void +encrypt_session_key( Session_Key *key, int server) { Encryptions *ep = encryptions; havesessionkey = 1; while (ep->type) { if (ep->session) (*ep->session)(key, server); -#ifdef notdef - if (!encrypt_output && autoencrypt && !server) - encrypt_start_output(ep->type); - if (!decrypt_input && autodecrypt && !server) - encrypt_send_request_start(); -#endif ++ep; } } /* * Called when ENCRYPT END is received. */ - void -encrypt_end() +void +encrypt_end(void) { decrypt_input = 0; if (encrypt_debug_mode) printf(">>>%s: Input is back to clear text\r\n", Name); if (encrypt_verbose) printf("[ Input is now clear text ]\r\n"); } /* * Called when ENCRYPT REQUEST-END is received. */ - void -encrypt_request_end() +void +encrypt_request_end(void) { encrypt_send_end(); } /* * Called when ENCRYPT REQUEST-START is received. If we receive * this before a type is picked, then that indicates that the * other side wants us to start encrypting data as soon as we * can. */ - void -encrypt_request_start(data, cnt) - unsigned char *data; - int cnt; +void +encrypt_request_start(unsigned char *data __unused, int cnt __unused) { if (encrypt_mode == 0) { if (Server) autoencrypt = 1; return; } encrypt_start_output(encrypt_mode); } static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; - void -encrypt_enc_keyid(keyid, len) - unsigned char *keyid; - int len; +void +encrypt_enc_keyid(unsigned char *keyid, int len) { encrypt_keyid(&ki[1], keyid, len); } - void -encrypt_dec_keyid(keyid, len) - unsigned char *keyid; - int len; +void +encrypt_dec_keyid(unsigned char *keyid, int len) { encrypt_keyid(&ki[0], keyid, len); } - void -encrypt_keyid(kp, keyid, len) - struct key_info *kp; - unsigned char *keyid; - int len; +void +encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len) { Encryptions *ep; int dir = kp->dir; - register int ret = 0; + int ret = 0; if (!(ep = (*kp->getcrypt)(*kp->modep))) { if (len == 0) return; kp->keylen = 0; } else if (len == 0) { /* * Empty option, indicates a failure. */ if (kp->keylen == 0) return; kp->keylen = 0; if (ep->keyid) (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); } else if ((len != kp->keylen) || (memcmp(keyid, kp->keyid, len) != 0)) { /* * Length or contents are different */ kp->keylen = len; memmove(kp->keyid, keyid, len); if (ep->keyid) (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); } else { if (ep->keyid) ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) encrypt_start_output(*kp->modep); return; } encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); } - void -encrypt_send_keyid(dir, keyid, keylen, saveit) - int dir; - unsigned char *keyid; - int keylen; - int saveit; +void +encrypt_send_keyid(int dir, const char *keyid, int keylen, int saveit) { unsigned char *strp; str_keyid[3] = (dir == DIR_ENCRYPT) ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; if (saveit) { struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; memmove(kp->keyid, keyid, keylen); kp->keylen = keylen; } for (strp = &str_keyid[4]; keylen > 0; --keylen) { if ((*strp++ = *keyid++) == IAC) *strp++ = IAC; } *strp++ = IAC; *strp++ = SE; net_write(str_keyid, strp - str_keyid); printsub('>', &str_keyid[2], strp - str_keyid - 2); } - void -encrypt_auto(on) - int on; +void +encrypt_auto(int on) { if (on < 0) autoencrypt ^= 1; else autoencrypt = on ? 1 : 0; } - void -decrypt_auto(on) - int on; +void +decrypt_auto(int on) { if (on < 0) autodecrypt ^= 1; else autodecrypt = on ? 1 : 0; } - void -encrypt_start_output(type) - int type; +void +encrypt_start_output(int type) { Encryptions *ep; - register unsigned char *p; - register int i; + unsigned char *p; + int i; if (!(ep = findencryption(type))) { if (encrypt_debug_mode) { printf(">>>%s: Can't encrypt with type %s (%d)\r\n", Name, ENCTYPE_NAME_OK(type) ? ENCTYPE_NAME(type) : "(unknown)", type); } return; } if (ep->start) { i = (*ep->start)(DIR_ENCRYPT, Server); if (encrypt_debug_mode) { printf(">>>%s: Encrypt start: %s (%d) %s\r\n", Name, (i < 0) ? "failed" : "initial negotiation in progress", i, ENCTYPE_NAME(type)); } if (i) return; } p = str_start + 3; *p++ = ENCRYPT_START; for (i = 0; i < ki[0].keylen; ++i) { if ((*p++ = ki[0].keyid[i]) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; net_write(str_start, p - str_start); net_encrypt(); printsub('>', &str_start[2], p - &str_start[2]); /* * If we are already encrypting in some mode, then * encrypt the ring (which includes our request) in * the old mode, mark it all as "clear text" and then * switch to the new mode. */ encrypt_output = ep->output; encrypt_mode = type; if (encrypt_debug_mode) printf(">>>%s: Started to encrypt output with type %s\r\n", Name, ENCTYPE_NAME(type)); if (encrypt_verbose) printf("[ Output is now encrypted with type %s ]\r\n", ENCTYPE_NAME(type)); } - void -encrypt_send_end() +void +encrypt_send_end(void) { if (!encrypt_output) return; str_end[3] = ENCRYPT_END; net_write(str_end, sizeof(str_end)); net_encrypt(); printsub('>', &str_end[2], sizeof(str_end) - 2); /* * Encrypt the output buffer now because it will not be done by * netflush... */ encrypt_output = 0; if (encrypt_debug_mode) printf(">>>%s: Output is back to clear text\r\n", Name); if (encrypt_verbose) printf("[ Output is now clear text ]\r\n"); } - void -encrypt_send_request_start() +void +encrypt_send_request_start(void) { - register unsigned char *p; - register int i; + unsigned char *p; + int i; p = &str_start[3]; *p++ = ENCRYPT_REQSTART; for (i = 0; i < ki[1].keylen; ++i) { if ((*p++ = ki[1].keyid[i]) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; net_write(str_start, p - str_start); printsub('>', &str_start[2], p - &str_start[2]); if (encrypt_debug_mode) printf(">>>%s: Request input to be encrypted\r\n", Name); } - void -encrypt_send_request_end() +void +encrypt_send_request_end(void) { str_end[3] = ENCRYPT_REQEND; net_write(str_end, sizeof(str_end)); printsub('>', &str_end[2], sizeof(str_end) - 2); if (encrypt_debug_mode) printf(">>>%s: Request input to be clear text\r\n", Name); } - void -encrypt_wait() +void +encrypt_wait(void) { if (encrypt_debug_mode) printf(">>>%s: in encrypt_wait\r\n", Name); if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt)) return; while (autoencrypt && !encrypt_output) if (telnet_spin()) return; } - void -encrypt_debug(mode) - int mode; +void +encrypt_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - encrypt_debug_mode = mode; -} - - void -encrypt_gen_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; -{ char tbuf[16], *cp; cnt -= 2; data += 2; buf[buflen-1] = '\0'; buf[buflen-2] = '*'; buflen -= 2;; for (; cnt > 0; cnt--, data++) { sprintf(tbuf, " %d", *data); for (cp = tbuf; *cp && buflen > 0; --buflen) *buf++ = *cp++; if (buflen <= 0) return; } *buf = '\0'; } - void -encrypt_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { Encryptions *ep; - register int type = data[1]; + int type = data[1]; for (ep = encryptions; ep->type && ep->type != type; ep++) ; if (ep->printsub) (*ep->printsub)(data, cnt, buf, buflen); else encrypt_gen_printsub(data, cnt, buf, buflen); } #endif /* ENCRYPTION */ Index: head/crypto/telnet/libtelnet/encrypt.h =================================================================== --- head/crypto/telnet/libtelnet/encrypt.h (revision 87138) +++ head/crypto/telnet/libtelnet/encrypt.h (revision 87139) @@ -1,114 +1,106 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)encrypt.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifdef ENCRYPTION # ifndef __ENCRYPTION__ # define __ENCRYPTION__ #define DIR_DECRYPT 1 #define DIR_ENCRYPT 2 #include typedef unsigned char Block[8]; typedef unsigned char *BlockT; #if 0 typedef struct { Block __; } Schedule[16]; #else #define Schedule des_key_schedule #endif #define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \ key[4] | key[5] | key[6] | key[7]) #define SAMEKEY(k1, k2) (!bcmp((void *)k1, (void *)k2, sizeof(Block))) typedef struct { short type; int length; unsigned char *data; } Session_Key; -# if !defined(P) -# ifdef __STDC__ -# define P(x) x -# else -# define P(x) () -# endif -# endif - typedef struct { - char *name; + const char *name; int type; - void (*output) P((unsigned char *, int)); - int (*input) P((int)); - void (*init) P((int)); - int (*start) P((int, int)); - int (*is) P((unsigned char *, int)); - int (*reply) P((unsigned char *, int)); - void (*session) P((Session_Key *, int)); - int (*keyid) P((int, unsigned char *, int *)); - void (*printsub) P((unsigned char *, int, unsigned char *, int)); + void (*output)(unsigned char *, int); + int (*input)(int); + void (*init)(int); + int (*start)(int, int); + int (*is)(unsigned char *, int); + int (*reply)(unsigned char *, int); + void (*session)(Session_Key *, int); + int (*keyid)(int, unsigned char *, int *); + void (*printsub)(unsigned char *, int, unsigned char *, int); } Encryptions; #define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */ #include "enc-proto.h" extern int encrypt_debug_mode; -extern int (*decrypt_input) P((int)); -extern void (*encrypt_output) P((unsigned char *, int)); +extern int (*decrypt_input)(int); +extern void (*encrypt_output)(unsigned char *, int); # endif /* __ENCRYPTION__ */ #endif /* ENCRYPTION */ Index: head/crypto/telnet/libtelnet/genget.c =================================================================== --- head/crypto/telnet/libtelnet/genget.c (revision 87138) +++ head/crypto/telnet/libtelnet/genget.c (revision 87139) @@ -1,104 +1,107 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static const char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95"; #endif #endif /* not lint */ #include +#include "misc-proto.h" + #define LOWER(x) (isupper(x) ? tolower(x) : (x)) /* * The prefix function returns 0 if *s1 is not a prefix * of *s2. If *s1 exactly matches *s2, the negative of * the length is returned. If *s1 is a prefix of *s2, * the length of *s1 is returned. */ int -isprefix(char *s1, char *s2) +isprefix(char *s1, const char *s2) { char *os1; char c1, c2; if (*s1 == '\0') return(-1); os1 = s1; c1 = *s1; c2 = *s2; while (LOWER(c1) == LOWER(c2)) { if (c1 == '\0') break; c1 = *++s1; c2 = *++s2; } return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); } static char *ambiguous; /* special return value for command routines */ char ** genget(char *name, char **table, int stlen) { char **c, **found; int n; if (name == 0) return 0; found = 0; for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { if ((n = isprefix(name, *c)) == 0) continue; if (n < 0) /* exact match */ return(c); if (found) return(&ambiguous); found = c; } return(found); } /* * Function call version of Ambiguous() */ int -Ambiguous(char *s) +Ambiguous(char **s) { - return((char **)s == &ambiguous); + return(s == &ambiguous); } Index: head/crypto/telnet/libtelnet/getent.c =================================================================== --- head/crypto/telnet/libtelnet/getent.c (revision 87138) +++ head/crypto/telnet/libtelnet/getent.c (revision 87139) @@ -1,76 +1,76 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static char sccsid[] = "@(#)getent.c 8.2 (Berkeley) 12/15/93"; #endif #endif /* not lint */ -#ifdef HAS_CGETENT #include -#endif +#include +#include "misc-proto.h" + static char *area; +static char gettytab[] = "/etc/gettytab"; /*ARGSUSED*/ int -getent(char *cp, char *name) +getent(char *cp __unused, const char *name) { -#ifdef HAS_CGETENT - char *dba[2]; + int retval; + char *tempnam, *dba[2] = { gettytab, NULL }; - dba[0] = "/etc/gettytab"; - dba[1] = 0; - return((cgetent(&area, dba, name) == 0) ? 1 : 0); -#else - return(0); -#endif + tempnam = strdup(name); + retval = cgetent(&area, dba, tempnam) == 0 ? 1 : 0; + free(tempnam); + return(retval); } -#ifndef SOLARIS /*ARGSUSED*/ char * -Getstr(char *id, char **cpp) +Getstr(const char *id, char **cpp __unused) { -# ifdef HAS_CGETENT - char *answer; - return((cgetstr(area, id, &answer) > 0) ? answer : 0); -# else - return(0); -# endif + int retval; + char *answer, *tempid; + + tempid = strdup(id); + retval = cgetstr(area, tempid, &answer); + free(tempid); + return((retval > 0) ? answer : NULL); } -#endif Index: head/crypto/telnet/libtelnet/kerberos.c =================================================================== --- head/crypto/telnet/libtelnet/kerberos.c (revision 87138) +++ head/crypto/telnet/libtelnet/kerberos.c (revision 87139) @@ -1,555 +1,512 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)kerberos.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifdef KRB4 #include #include -#include #include /* BSD wont include this in krb.h, so we do it here */ #include -#ifdef __STDC__ +#include #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif #include "encrypt.h" #include "auth.h" #include "misc.h" int kerberos4_cksum P((unsigned char *, int)); int kuserok P((AUTH_DAT *, char *)); -extern auth_debug_mode; +extern int auth_debug_mode; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KERBEROS_V4, }; #define KRB_AUTH 0 /* Authentication data follows */ #define KRB_REJECT 1 /* Rejected (reason might follow) */ #define KRB_ACCEPT 2 /* Accepted */ #define KRB_CHALLENGE 3 /* Challenge for mutual auth. */ #define KRB_RESPONSE 4 /* Response for mutual auth. */ -#define KRB_SERVICE_NAME "rcmd" - static KTEXT_ST auth; static char name[ANAME_SZ]; -static AUTH_DAT adat = { 0 }; +static AUTH_DAT adat = { 0, "", "", "", 0, {}, 0, 0, 0, { 0, "", 0 } }; #ifdef ENCRYPTION static Block session_key = { 0 }; static des_key_schedule sched; static Block challenge = { 0 }; #endif /* ENCRYPTION */ - static int -Data(ap, type, d, c) - Authenticator *ap; - int type; - void *d; - int c; +static char krb_service_name[] = "rcmd"; +static char empty[] = ""; + +static int +Data(Authenticator *ap, int type, const unsigned char *d, int c) { unsigned char *p = str_data + 4; - unsigned char *cd = (unsigned char *)d; + const unsigned char *cd = d; if (c == -1) - c = strlen((char *)cd); + c = strlen(cd); if (auth_debug_mode) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } - int -kerberos4_init(ap, server) - Authenticator *ap; - int server; +int +kerberos4_init(Authenticator *ap __unused, int server) { FILE *fp; if (server) { str_data[3] = TELQUAL_REPLY; if ((fp = fopen(KEYFILE, "r")) == NULL) return(0); fclose(fp); } else { str_data[3] = TELQUAL_IS; } return(1); } char dst_realm_buf[REALM_SZ], *dest_realm = NULL; int dst_realm_sz = REALM_SZ; - int -kerberos4_send(ap) - Authenticator *ap; +int +kerberos4_send(Authenticator *ap) { - KTEXT_ST auth; + KTEXT_ST lauth; char instance[INST_SZ]; char *realm; - char *krb_realmofhost(); - char *krb_get_phost(); CREDENTIALS cred; int r; printf("[ Trying KERBEROS4 ... ]\n"); if (!UserNameRequested) { if (auth_debug_mode) { printf("Kerberos V4: no user name supplied\r\n"); } return(0); } memset(instance, 0, sizeof(instance)); if ((realm = krb_get_phost(RemoteHostName))) strncpy(instance, realm, sizeof(instance)); instance[sizeof(instance)-1] = '\0'; realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName); if (!realm) { printf("Kerberos V4: no realm for %s\r\n", RemoteHostName); return(0); } - if ((r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L))) { + if ((r = krb_mk_req(&lauth, krb_service_name, instance, realm, 0L))) { printf("mk_req failed: %s\r\n", krb_err_txt[r]); return(0); } - if ((r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred))) { + if ((r = krb_get_cred(krb_service_name, instance, realm, &cred))) { printf("get_cred failed: %s\r\n", krb_err_txt[r]); return(0); } if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { if (auth_debug_mode) printf("Not enough room for user name\r\n"); return(0); } if (auth_debug_mode) - printf("Sent %d bytes of authentication data\r\n", auth.length); - if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) { + printf("Sent %d bytes of authentication data\r\n", lauth.length); + if (!Data(ap, KRB_AUTH, (void *)lauth.dat, lauth.length)) { if (auth_debug_mode) printf("Not enough room for authentication data\r\n"); return(0); } #ifdef ENCRYPTION /* * If we are doing mutual authentication, get set up to send * the challenge, and verify it when the response comes back. */ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { register int i; des_key_sched(&cred.session, sched); des_init_random_number_generator(&cred.session); des_new_random_key(&session_key); des_ecb_encrypt(&session_key, &session_key, sched, 0); des_ecb_encrypt(&session_key, &challenge, sched, 0); /* * Increment the challenge by 1, and encrypt it for * later comparison. */ for (i = 7; i >= 0; --i) { register int x; x = (unsigned int)challenge[i] + 1; challenge[i] = x; /* ignore overflow */ if (x < 256) /* if no overflow, all done */ break; } des_ecb_encrypt(&challenge, &challenge, sched, 1); } #endif /* ENCRYPTION */ if (auth_debug_mode) { - printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); - printd(auth.dat, auth.length); + printf("CK: %d:", kerberos4_cksum(lauth.dat, lauth.length)); + printd(lauth.dat, lauth.length); printf("\r\n"); printf("Sent Kerberos V4 credentials to server\r\n"); } return(1); } - void -kerberos4_is(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; +void +kerberos4_is(Authenticator *ap, unsigned char *data, int cnt) { #ifdef ENCRYPTION Session_Key skey; Block datablock; #endif /* ENCRYPTION */ char realm[REALM_SZ]; char instance[INST_SZ]; int r; if (cnt-- < 1) return; switch (*data++) { case KRB_AUTH: if (krb_get_lrealm(realm, 1) != KSUCCESS) { - Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1); + Data(ap, KRB_REJECT, "No local V4 Realm.", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("No local realm\r\n"); return; } memmove((void *)auth.dat, (void *)data, auth.length = cnt); if (auth_debug_mode) { printf("Got %d bytes of authentication data\r\n", cnt); printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); printd(auth.dat, auth.length); printf("\r\n"); } instance[0] = '*'; instance[1] = 0; - if ((r = krb_rd_req(&auth, KRB_SERVICE_NAME, - instance, 0, &adat, ""))) { + if ((r = krb_rd_req(&auth, krb_service_name, + instance, 0, &adat, empty))) { if (auth_debug_mode) printf("Kerberos failed him as %s\r\n", name); - Data(ap, KRB_REJECT, (void *)krb_err_txt[r], -1); + Data(ap, KRB_REJECT, krb_err_txt[r], -1); auth_finished(ap, AUTH_REJECT); return; } #ifdef ENCRYPTION memmove((void *)session_key, (void *)adat.session, sizeof(Block)); #endif /* ENCRYPTION */ krb_kntoln(&adat, name); if (UserNameRequested && !kuserok(&adat, UserNameRequested)) - Data(ap, KRB_ACCEPT, (void *)0, 0); + Data(ap, KRB_ACCEPT, NULL, 0); else - Data(ap, KRB_REJECT, - (void *)"user is not authorized", -1); + Data(ap, KRB_REJECT, "user is not authorized", -1); auth_finished(ap, AUTH_USER); break; case KRB_CHALLENGE: #ifndef ENCRYPTION - Data(ap, KRB_RESPONSE, (void *)0, 0); + Data(ap, KRB_RESPONSE, NULL, 0); #else /* ENCRYPTION */ if (!VALIDKEY(session_key)) { /* * We don't have a valid session key, so just * send back a response with an empty session * key. */ - Data(ap, KRB_RESPONSE, (void *)0, 0); + Data(ap, KRB_RESPONSE, NULL, 0); break; } /* * Initialize the random number generator since it's * used later on by the encryption routine. */ des_init_random_number_generator(&session_key); des_key_sched(&session_key, sched); memmove((void *)datablock, (void *)data, sizeof(Block)); /* * Take the received encrypted challenge, and encrypt * it again to get a unique session_key for the * ENCRYPT option. */ des_ecb_encrypt(&datablock, &session_key, sched, 1); skey.type = SK_DES; skey.length = 8; skey.data = session_key; encrypt_session_key(&skey, 1); /* * Now decrypt the received encrypted challenge, * increment by one, re-encrypt it and send it back. */ des_ecb_encrypt(&datablock, &challenge, sched, 0); for (r = 7; r >= 0; r--) { register int t; t = (unsigned int)challenge[r] + 1; challenge[r] = t; /* ignore overflow */ if (t < 256) /* if no overflow, all done */ break; } des_ecb_encrypt(&challenge, &challenge, sched, 1); - Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge)); + Data(ap, KRB_RESPONSE, challenge, sizeof(challenge)); #endif /* ENCRYPTION */ break; default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); - Data(ap, KRB_REJECT, 0, 0); + Data(ap, KRB_REJECT, NULL, 0); break; } } - void -kerberos4_reply(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; +void +kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt) { #ifdef ENCRYPTION Session_Key skey; #endif /* ENCRYPTION */ if (cnt-- < 1) return; switch (*data++) { case KRB_REJECT: if (cnt > 0) { printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n", cnt, data); } else printf("[ Kerberos V4 refuses authentication ]\r\n"); auth_send_retry(); return; case KRB_ACCEPT: printf("[ Kerberos V4 accepts you ]\n"); if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { /* * Send over the encrypted challenge. */ #ifndef ENCRYPTION - Data(ap, KRB_CHALLENGE, (void *)0, 0); + Data(ap, KRB_CHALLENGE, NULL, 0); #else /* ENCRYPTION */ - Data(ap, KRB_CHALLENGE, (void *)session_key, + Data(ap, KRB_CHALLENGE, session_key, sizeof(session_key)); des_ecb_encrypt(&session_key, &session_key, sched, 1); skey.type = SK_DES; skey.length = 8; skey.data = session_key; encrypt_session_key(&skey, 0); #endif /* ENCRYPTION */ return; } auth_finished(ap, AUTH_USER); return; case KRB_RESPONSE: #ifdef ENCRYPTION /* * Verify that the response to the challenge is correct. */ if ((cnt != sizeof(Block)) || (0 != memcmp((void *)data, (void *)challenge, sizeof(challenge)))) { #endif /* ENCRYPTION */ printf("[ Kerberos V4 challenge failed!!! ]\r\n"); auth_send_retry(); return; #ifdef ENCRYPTION } printf("[ Kerberos V4 challenge successful ]\r\n"); auth_finished(ap, AUTH_USER); #endif /* ENCRYPTION */ break; default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); return; } } - int -kerberos4_status(ap, name, level) - Authenticator *ap; - char *name; - int level; +int +kerberos4_status(Authenticator *ap __unused, char *nam, int level) { if (level < AUTH_USER) return(level); if (UserNameRequested && !kuserok(&adat, UserNameRequested)) { - strcpy(name, UserNameRequested); + strcpy(nam, UserNameRequested); return(AUTH_VALID); } else return(AUTH_USER); } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - void -kerberos4_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +kerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { char lbuf[32]; register int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case KRB_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case KRB_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case KRB_AUTH: /* Authentication data follows */ strncpy((char *)buf, " AUTH", buflen); goto common2; case KRB_CHALLENGE: strncpy((char *)buf, " CHALLENGE", buflen); goto common2; case KRB_RESPONSE: strncpy((char *)buf, " RESPONSE", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } - int -kerberos4_cksum(d, n) - unsigned char *d; - int n; +int +kerberos4_cksum(unsigned char *d, int n) { int ck = 0; /* * A comment is probably needed here for those not * well versed in the "C" language. Yes, this is * supposed to be a "switch" with the body of the * "switch" being a "while" statement. The whole * purpose of the switch is to allow us to jump into * the middle of the while() loop, and then not have * to do any more switch()s. * * Some compilers will spit out a warning message * about the loop not being entered at the top. */ switch (n&03) while (n > 0) { case 0: ck ^= (int)*d++ << 24; --n; case 3: ck ^= (int)*d++ << 16; --n; case 2: ck ^= (int)*d++ << 8; --n; case 1: ck ^= (int)*d++; --n; } return(ck); -} -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); } #endif Index: head/crypto/telnet/libtelnet/kerberos5.c =================================================================== --- head/crypto/telnet/libtelnet/kerberos5.c (revision 87138) +++ head/crypto/telnet/libtelnet/kerberos5.c (revision 87139) @@ -1,758 +1,801 @@ -/* - * $Source: /mit/krb5/.cvsroot/src/appl/telnet/libtelnet/kerberos5.c,v $ - * $Author: tytso $ - * $Id: kerberos5.c,v 1.1 1997/09/04 06:11:15 markm Exp $ - */ - -#include -__FBSDID("$FreeBSD$"); - /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#ifndef lint -static const char sccsid[] = "@(#)kerberos5.c 8.3 (Berkeley) 5/30/95"; -#endif /* not lint */ - /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ +#include +__FBSDID("$FreeBSD$"); + #ifdef KRB5 + #include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#define Authenticator k5_Authenticator +#include +#undef Authenticator -/* kerberos 5 include files (ext-proto.h) will get an appropriate stdlib.h - and string.h/strings.h */ - #include "encrypt.h" #include "auth.h" #include "misc.h" -extern int auth_debug_mode; - -#ifdef FORWARD int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ /* These values need to be the same as those defined in telnet/main.c. */ /* Either define them in both places, or put in some common header file. */ #define OPTS_FORWARD_CREDS 0x00000002 #define OPTS_FORWARDABLE_CREDS 0x00000001 -void kerberos5_forward(); +void kerberos5_forward (Authenticator *); -#endif /* FORWARD */ - static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KERBEROS_V5, }; -/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, - TELQUAL_NAME, };*/ #define KRB_AUTH 0 /* Authentication data follows */ #define KRB_REJECT 1 /* Rejected (reason might follow) */ #define KRB_ACCEPT 2 /* Accepted */ #define KRB_RESPONSE 3 /* Response for mutual auth. */ -#ifdef FORWARD #define KRB_FORWARD 4 /* Forwarded credentials follow */ #define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ #define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ -#endif /* FORWARD */ static krb5_data auth; - /* telnetd gets session key from here */ -static krb5_tkt_authent *authdat = NULL; -/* telnet matches the AP_REQ and AP_REP with this */ -static krb5_authenticator authenticator; +static krb5_ticket *ticket; -/* some compilers can't hack void *, so we use the Kerberos krb5_pointer, - which is either void * or char *, depending on the compiler. */ +static krb5_context context; +static krb5_auth_context auth_context; -#define Voidptr krb5_pointer +static int +Data(Authenticator *ap, int type, const char *d, int c) +{ + unsigned char *p = str_data + 4; + const unsigned char *cd = d; -Block session_key; + if (c == -1) + c = strlen(cd); - static int -Data(ap, type, d, c) - Authenticator *ap; - int type; - Voidptr d; - int c; + if (auth_debug_mode) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - &str_data[2]); + return(net_write(str_data, p - str_data)); +} + +int +kerberos5_init(Authenticator *ap __unused, int server) { - unsigned char *p = str_data + 4; - unsigned char *cd = (unsigned char *)d; + krb5_error_code ret; - if (c == -1) - c = strlen((char *)cd); + ret = krb5_init_context(&context); + if (ret) + return 0; + if (server) { + krb5_keytab kt; + krb5_kt_cursor cursor; - if (auth_debug_mode) { - printf("%s:%d: [%d] (%d)", - str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", - str_data[3], - type, c); - printd(d, c); - printf("\r\n"); + ret = krb5_kt_default(context, &kt); + if (ret) + return 0; + + ret = krb5_kt_start_seq_get (context, kt, &cursor); + if (ret) { + krb5_kt_close (context, kt); + return 0; } - *p++ = ap->type; - *p++ = ap->way; - *p++ = type; - while (c-- > 0) { - if ((*p++ = *cd++) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - if (str_data[3] == TELQUAL_IS) - printsub('>', &str_data[2], p - &str_data[2]); - return(net_write(str_data, p - str_data)); -} + krb5_kt_end_seq_get (context, kt, &cursor); + krb5_kt_close (context, kt); - int -kerberos5_init(ap, server) - Authenticator *ap; - int server; -{ - if (server) - str_data[3] = TELQUAL_REPLY; - else - str_data[3] = TELQUAL_IS; - krb5_init_ets(); - return(1); + str_data[3] = TELQUAL_REPLY; + } else + str_data[3] = TELQUAL_IS; + return(1); } - int -kerberos5_send(ap) - Authenticator *ap; +extern int net; + +static int +kerberos5_send(const char *name, Authenticator *ap) { - char **realms; - char *name; - char *p1, *p2; - krb5_checksum ksum; - krb5_octet sum[CRC32_CKSUM_LENGTH]; - krb5_principal server; - krb5_error_code r; - krb5_ccache ccache; - krb5_creds creds; /* telnet gets session key from here */ - extern krb5_flags krb5_kdc_default_options; - int ap_opts; + krb5_error_code ret; + krb5_ccache ccache; + int ap_opts; + krb5_data cksum_data; + char foo[2]; + + if (!UserNameRequested) { + if (auth_debug_mode) { + printf("Kerberos V5: no user name supplied\r\n"); + } + return(0); + } + + ret = krb5_cc_default(context, &ccache); + if (ret) { + if (auth_debug_mode) { + printf("Kerberos V5: could not get default ccache: %s\r\n", + krb5_get_err_text (context, ret)); + } + return 0; + } + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) + ap_opts = AP_OPTS_MUTUAL_REQUIRED; + else + ap_opts = 0; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) { + if (auth_debug_mode) { + printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } -#ifdef ENCRYPTION - krb5_keyblock *newkey = 0; -#endif /* ENCRYPTION */ + ret = krb5_auth_con_setaddrs_from_fd (context, + auth_context, + &net); + if (ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } - ksum.checksum_type = CKSUMTYPE_CRC32; - ksum.contents = sum; - ksum.length = sizeof(sum); - memset((Voidptr )sum, 0, sizeof(sum)); + krb5_auth_setkeytype (context, auth_context, KEYTYPE_DES); - if (!UserNameRequested) { - if (auth_debug_mode) { - printf("Kerberos V5: no user name supplied\r\n"); - } - return(0); - } + foo[0] = ap->type; + foo[1] = ap->way; - if (r = krb5_cc_default(&ccache)) { - if (auth_debug_mode) { - printf("Kerberos V5: could not get default ccache\r\n"); - } - return(0); - } + cksum_data.length = sizeof(foo); + cksum_data.data = foo; - if ((name = malloc(strlen(RemoteHostName)+1)) == NULL) { - if (auth_debug_mode) - printf("Out of memory for hostname in Kerberos V5\r\n"); - return(0); - } - if (r = krb5_get_host_realm(RemoteHostName, &realms)) { - if (auth_debug_mode) - printf("Kerberos V5: no realm for %s\r\n", RemoteHostName); - free(name); - return(0); - } + { + krb5_principal service; + char sname[128]; - p1 = RemoteHostName; - p2 = name; - while (*p2 = *p1++) { - if (isupper(*p2)) - *p2 |= 040; - ++p2; + ret = krb5_sname_to_principal (context, + RemoteHostName, + NULL, + KRB5_NT_SRV_HST, + &service); + if(ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_sname_to_principal(%s) failed (%s)\r\n", + RemoteHostName, krb5_get_err_text(context, ret)); + } + return 0; } + ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname)); + if(ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_unparse_name_fixed failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return 0; + } + printf("[ Trying %s (%s)... ]\r\n", name, sname); + ret = krb5_mk_req_exact(context, &auth_context, ap_opts, + service, + &cksum_data, ccache, &auth); + krb5_free_principal (context, service); - if (r = krb5_build_principal_ext(&server, - strlen(realms[0]), realms[0], - 4, "host", - p2 - name, name, - 0)) { - if (auth_debug_mode) { - printf("Kerberos V5: failure setting up principal (%s)\r\n", - error_message(r)); - } - free(name); - krb5_free_host_realm(realms); - return(0); + } + if (ret) { + if (1 || auth_debug_mode) { + printf("Kerberos V5: mk_req failed (%s)\r\n", + krb5_get_err_text(context, ret)); } + return(0); + } + if (!auth_sendname((unsigned char *)UserNameRequested, + strlen(UserNameRequested))) { + if (auth_debug_mode) + printf("Not enough room for user name\r\n"); + return(0); + } + if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + return(0); + } + if (auth_debug_mode) { + printf("Sent Kerberos V5 credentials to server\r\n"); + } + return(1); +} - memset((char *)&creds, 0, sizeof(creds)); - creds.server = server; +int +kerberos5_send_mutual(Authenticator *ap) +{ + return kerberos5_send("mutual KERBEROS5", ap); +} - if (r = krb5_cc_get_principal(ccache, &creds.client)) { - if (auth_debug_mode) { - printf("Kerberos V5: failure on principal (%s)\r\n", - error_message(r)); - } - free(name); - krb5_free_principal(server); - krb5_free_host_realm(realms); - return(0); +int +kerberos5_send_oneway(Authenticator *ap) +{ + return kerberos5_send("KERBEROS5", ap); +} + +void +kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) +{ + krb5_error_code ret; + krb5_data outbuf; + krb5_keyblock *key_block; + char *name; + krb5_principal server; + int zero = 0; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_AUTH: + auth.data = (char *)data; + auth.length = cnt; + + auth_context = NULL; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; } - if (r = krb5_get_credentials(krb5_kdc_default_options, ccache, &creds)) { - if (auth_debug_mode) { - printf("Kerberos V5: failure on credentials(%d)\r\n",r); - } - free(name); - krb5_free_host_realm(realms); - krb5_free_principal(server); - return(0); + ret = krb5_auth_con_setaddrs_from_fd (context, + auth_context, + &zero); + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; } - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) - ap_opts = AP_OPTS_MUTUAL_REQUIRED; - else - ap_opts = 0; + ret = krb5_sock_to_principal (context, + 0, + "host", + KRB5_NT_SRV_HST, + &server); + if (ret) { + Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_sock_to_principal failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; + } - r = krb5_mk_req_extended(ap_opts, &ksum, krb5_kdc_default_options, 0, -#ifdef ENCRYPTION - &newkey, -#else /* ENCRYPTION */ - 0, -#endif /* ENCRYPTION */ - ccache, &creds, &authenticator, &auth); - /* don't let the key get freed if we clean up the authenticator */ - authenticator.subkey = 0; + ret = krb5_rd_req(context, + &auth_context, + &auth, + server, + NULL, + NULL, + &ticket); - free(name); - krb5_free_host_realm(realms); - krb5_free_principal(server); -#ifdef ENCRYPTION - if (newkey) { - /* keep the key in our private storage, but don't use it - yet---see kerberos5_reply() below */ - if (newkey->keytype != KEYTYPE_DES) { - if (creds.keyblock.keytype == KEYTYPE_DES) - /* use the session key in credentials instead */ - memmove((char *)session_key, - (char *)creds.keyblock.contents, sizeof(Block)); - else - /* XXX ? */; - } else { - memmove((char *)session_key, (char *)newkey->contents, - sizeof(Block)); - } - krb5_free_keyblock(newkey); + krb5_free_principal (context, server); + if (ret) { + char *errbuf; + + asprintf(&errbuf, + "Read req failed: %s", + krb5_get_err_text(context, ret)); + Data(ap, KRB_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("%s\r\n", errbuf); + free (errbuf); + return; } -#endif /* ENCRYPTION */ - if (r) { - if (auth_debug_mode) { - printf("Kerberos V5: mk_req failed (%s)\r\n", - error_message(r)); - } - return(0); - } + + { + char foo[2]; + + foo[0] = ap->type; + foo[1] = ap->way; + + ret = krb5_verify_authenticator_checksum(context, + auth_context, + foo, + sizeof(foo)); - if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + if (ret) { + char *errbuf; + asprintf(&errbuf, "Bad checksum: %s", + krb5_get_err_text(context, ret)); + Data(ap, KRB_REJECT, errbuf, -1); if (auth_debug_mode) - printf("Not enough room for user name\r\n"); - return(0); + printf ("%s\r\n", errbuf); + free(errbuf); + return; + } } - if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { - if (auth_debug_mode) - printf("Not enough room for authentication data\r\n"); - return(0); + ret = krb5_auth_con_getremotesubkey (context, + auth_context, + &key_block); + + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_auth_con_getremotesubkey failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; } - if (auth_debug_mode) { - printf("Sent Kerberos V5 credentials to server\r\n"); - } - return(1); -} - void -kerberos5_is(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; -{ - int r; - struct hostent *hp; - char *p1, *p2; - static char *realm = NULL; - krb5_principal server; - krb5_ap_rep_enc_part reply; - krb5_data outbuf; -#ifdef ENCRYPTION - Session_Key skey; -#endif /* ENCRYPTION */ - char *name; - char *getenv(); - krb5_data inbuf; - - if (cnt-- < 1) + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + ret = krb5_mk_rep(context, auth_context, &outbuf); + if (ret) { + Data(ap, KRB_REJECT, + "krb5_mk_rep failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_mk_rep failed (%s)\r\n", + krb5_get_err_text(context, ret)); return; - switch (*data++) { - case KRB_AUTH: - auth.data = (char *)data; - auth.length = cnt; + } + Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); + } + if (krb5_unparse_name(context, ticket->client, &name)) + name = 0; - if (!(hp = gethostbyname(LocalHostName))) { - if (auth_debug_mode) - printf("Cannot resolve local host name\r\n"); - Data(ap, KRB_REJECT, "Unknown local hostname.", -1); - auth_finished(ap, AUTH_REJECT); - return; - } + if(UserNameRequested && krb5_kuserok(context, + ticket->client, + UserNameRequested)) { + Data(ap, KRB_ACCEPT, name, name ? -1 : 0); + if (auth_debug_mode) { + printf("Kerberos5 identifies him as ``%s''\r\n", + name ? name : ""); + } - if (!realm && (krb5_get_default_realm(&realm))) { - if (auth_debug_mode) - printf("Could not get default realm\r\n"); - Data(ap, KRB_REJECT, "Could not get default realm.", -1); - auth_finished(ap, AUTH_REJECT); - return; - } + if(key_block->keytype == ETYPE_DES_CBC_MD5 || + key_block->keytype == ETYPE_DES_CBC_MD4 || + key_block->keytype == ETYPE_DES_CBC_CRC) { + Session_Key skey; - if ((name = malloc(strlen(hp->h_name)+1)) == NULL) { - if (auth_debug_mode) - printf("Out of memory for hostname in Kerberos V5\r\n"); - Data(ap, KRB_REJECT, "Out of memory.", -1); - auth_finished(ap, AUTH_REJECT); - return; - } + skey.type = SK_DES; + skey.length = 8; + skey.data = key_block->keyvalue.data; + encrypt_session_key(&skey, 0); + } - p1 = hp->h_name; - p2 = name; + } else { + char *msg; - while (*p2 = *p1++) { - if (isupper(*p2)) - *p2 |= 040; - ++p2; - } + asprintf (&msg, "user `%s' is not authorized to " + "login as `%s'", + name ? name : "", + UserNameRequested ? UserNameRequested : ""); + if (msg == NULL) + Data(ap, KRB_REJECT, NULL, 0); + else { + Data(ap, KRB_REJECT, (void *)msg, -1); + free(msg); + } + auth_finished (ap, AUTH_REJECT); + krb5_free_keyblock_contents(context, key_block); + break; + } + auth_finished(ap, AUTH_USER); + krb5_free_keyblock_contents(context, key_block); + + break; + case KRB_FORWARD: { + struct passwd *pwd; + char ccname[1024]; /* XXX */ + krb5_data inbuf; + krb5_ccache ccache; + inbuf.data = (char *)data; + inbuf.length = cnt; - if (authdat) - krb5_free_tkt_authent(authdat); + pwd = getpwnam (UserNameRequested); + if (pwd == NULL) + break; - r = krb5_build_principal_ext(&server, - strlen(realm), realm, - 4, "host", - p2 - name, name, - 0); - if (!r) { - r = krb5_rd_req_simple(&auth, server, 0, &authdat); - krb5_free_principal(server); - } - if (r) { - char errbuf[128]; + snprintf (ccname, sizeof(ccname), + "FILE:/tmp/krb5cc_%u", pwd->pw_uid); - errout: - authdat = 0; - (void) strcpy(errbuf, "Read req failed: "); - (void) strcat(errbuf, error_message(r)); - Data(ap, KRB_REJECT, errbuf, -1); - if (auth_debug_mode) - printf("%s\r\n", errbuf); - return; - } - free(name); - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* do ap_rep stuff here */ - reply.ctime = authdat->authenticator->ctime; - reply.cusec = authdat->authenticator->cusec; - reply.subkey = 0; /* use the one he gave us, so don't - need to return one here */ - reply.seq_number = 0; /* we don't do seq #'s. */ + ret = krb5_cc_resolve (context, ccname, &ccache); + if (ret) { + if (auth_debug_mode) + printf ("Kerberos V5: could not get ccache: %s\r\n", + krb5_get_err_text(context, ret)); + break; + } - if (r = krb5_mk_rep(&reply, - authdat->authenticator->subkey ? - authdat->authenticator->subkey : - authdat->ticket->enc_part2->session, - &outbuf)) { - goto errout; - } - Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); - } - if (krb5_unparse_name(authdat->ticket->enc_part2 ->client, - &name)) - name = 0; - Data(ap, KRB_ACCEPT, name, name ? -1 : 0); - if (auth_debug_mode) { - printf("Kerberos5 identifies him as ``%s''\r\n", - name ? name : ""); - } - auth_finished(ap, AUTH_USER); + ret = krb5_cc_initialize (context, + ccache, + ticket->client); + if (ret) { + if (auth_debug_mode) + printf ("Kerberos V5: could not init ccache: %s\r\n", + krb5_get_err_text(context, ret)); + break; + } - free(name); - if (authdat->authenticator->subkey && - authdat->authenticator->subkey->keytype == KEYTYPE_DES) { - memmove((Voidptr )session_key, - (Voidptr )authdat->authenticator->subkey->contents, - sizeof(Block)); - } else if (authdat->ticket->enc_part2->session->keytype == - KEYTYPE_DES) { - memmove((Voidptr )session_key, - (Voidptr )authdat->ticket->enc_part2->session->contents, - sizeof(Block)); - } else - break; +#if defined(DCE) + esetenv("KRB5CCNAME", ccname, 1); +#endif + ret = krb5_rd_cred2 (context, + auth_context, + ccache, + &inbuf); + if(ret) { + char *errbuf; -#ifdef ENCRYPTION - skey.type = SK_DES; - skey.length = 8; - skey.data = session_key; - encrypt_session_key(&skey, 1); -#endif /* ENCRYPTION */ - break; -#ifdef FORWARD - case KRB_FORWARD: - inbuf.data = (char *)data; - inbuf.length = cnt; - if (r = rd_and_store_for_creds(&inbuf, authdat->ticket, - UserNameRequested)) { - char errbuf[128]; - - (void) strcpy(errbuf, "Read forwarded creds failed: "); - (void) strcat(errbuf, error_message(r)); - Data(ap, KRB_FORWARD_REJECT, errbuf, -1); - if (auth_debug_mode) - printf("Could not read forwarded credentials\r\n"); - } - else - Data(ap, KRB_FORWARD_ACCEPT, 0, 0); - if (auth_debug_mode) - printf("Forwarded credentials obtained\r\n"); - break; -#endif /* FORWARD */ - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - Data(ap, KRB_REJECT, 0, 0); - break; + asprintf (&errbuf, + "Read forwarded creds failed: %s", + krb5_get_err_text (context, ret)); + if(errbuf == NULL) + Data(ap, KRB_FORWARD_REJECT, NULL, 0); + else + Data(ap, KRB_FORWARD_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("Could not read forwarded credentials: %s\r\n", + errbuf); + free (errbuf); + } else { + Data(ap, KRB_FORWARD_ACCEPT, 0, 0); +#if defined(DCE) + dfsfwd = 1; +#endif } + chown (ccname + 5, pwd->pw_uid, -1); + if (auth_debug_mode) + printf("Forwarded credentials obtained\r\n"); + break; + } + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + Data(ap, KRB_REJECT, 0, 0); + break; + } } - void -kerberos5_reply(ap, data, cnt) - Authenticator *ap; - unsigned char *data; - int cnt; +void +kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) { + static int mutual_complete = 0; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_REJECT: + if (cnt > 0) { + printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ Kerberos V5 refuses authentication ]\r\n"); + auth_send_retry(); + return; + case KRB_ACCEPT: { + krb5_error_code ret; Session_Key skey; - static int mutual_complete = 0; + krb5_keyblock *keyblock; + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && + !mutual_complete) { + printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); + auth_send_retry(); + return; + } + if (cnt) + printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data); + else + printf("[ Kerberos V5 accepts you ]\r\n"); + + ret = krb5_auth_con_getlocalsubkey (context, + auth_context, + &keyblock); + if (ret) + ret = krb5_auth_con_getkey (context, + auth_context, + &keyblock); + if(ret) { + printf("[ krb5_auth_con_getkey: %s ]\r\n", + krb5_get_err_text(context, ret)); + auth_send_retry(); + return; + } + + skey.type = SK_DES; + skey.length = 8; + skey.data = keyblock->keyvalue.data; + encrypt_session_key(&skey, 0); + krb5_free_keyblock_contents (context, keyblock); + auth_finished(ap, AUTH_USER); + if (forward_flags & OPTS_FORWARD_CREDS) + kerberos5_forward(ap); + break; + } + case KRB_RESPONSE: + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* the rest of the reply should contain a krb_ap_rep */ + krb5_ap_rep_enc_part *reply; + krb5_data inbuf; + krb5_error_code ret; + + inbuf.length = cnt; + inbuf.data = (char *)data; - if (cnt-- < 1) - return; - switch (*data++) { - case KRB_REJECT: - if (cnt > 0) { - printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", - cnt, data); - } else - printf("[ Kerberos V5 refuses authentication ]\r\n"); - auth_send_retry(); - return; - case KRB_ACCEPT: - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && - !mutual_complete) { - printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n"); - auth_send_retry(); - return; - } - if (cnt) - printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data); - else - printf("[ Kerberos V5 accepts you ]\n"); - auth_finished(ap, AUTH_USER); -#ifdef FORWARD - if (forward_flags & OPTS_FORWARD_CREDS) - kerberos5_forward(ap); -#endif /* FORWARD */ - break; - case KRB_RESPONSE: - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* the rest of the reply should contain a krb_ap_rep */ - krb5_ap_rep_enc_part *reply; - krb5_data inbuf; - krb5_error_code r; - krb5_keyblock tmpkey; - - inbuf.length = cnt; - inbuf.data = (char *)data; - - tmpkey.keytype = KEYTYPE_DES; - tmpkey.contents = session_key; - tmpkey.length = sizeof(Block); - - if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) { - printf("[ Mutual authentication failed: %s ]\n", - error_message(r)); - auth_send_retry(); - return; - } - if (reply->ctime != authenticator.ctime || - reply->cusec != authenticator.cusec) { - printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n"); - auth_send_retry(); - return; - } - krb5_free_ap_rep_enc_part(reply); -#ifdef ENCRYPTION - skey.type = SK_DES; - skey.length = 8; - skey.data = session_key; - encrypt_session_key(&skey, 0); -#endif /* ENCRYPTION */ - mutual_complete = 1; - } - return; -#ifdef FORWARD - case KRB_FORWARD_ACCEPT: - printf("[ Kerberos V5 accepted forwarded credentials ]\n"); - return; - case KRB_FORWARD_REJECT: - printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", - cnt, data); - return; -#endif /* FORWARD */ - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - return; + ret = krb5_rd_rep(context, auth_context, &inbuf, &reply); + if (ret) { + printf("[ Mutual authentication failed: %s ]\r\n", + krb5_get_err_text (context, ret)); + auth_send_retry(); + return; + } + krb5_free_ap_rep_enc_part(context, reply); + mutual_complete = 1; } + return; + case KRB_FORWARD_ACCEPT: + printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); + return; + case KRB_FORWARD_REJECT: + printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", + cnt, data); + return; + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + return; + } } - int -kerberos5_status(ap, name, level) - Authenticator *ap; - char *name; - int level; +int +kerberos5_status(Authenticator *ap __unused, char *name, int level) { - if (level < AUTH_USER) - return(level); + if (level < AUTH_USER) + return(level); - if (UserNameRequested && - krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested)) + if (UserNameRequested && + krb5_kuserok(context, + ticket->client, + UserNameRequested)) { - strcpy(name, UserNameRequested); - return(AUTH_VALID); + strcpy(name, UserNameRequested); + return(AUTH_VALID); } else - return(AUTH_USER); + return(AUTH_USER); } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - void -kerberos5_printsub(data, cnt, buf, buflen) - unsigned char *data, *buf; - int cnt, buflen; +void +kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { - char lbuf[32]; - register int i; + int i; - buf[buflen-1] = '\0'; /* make sure its NULL terminated */ - buflen -= 1; + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; - switch(data[3]) { - case KRB_REJECT: /* Rejected (reason might follow) */ - strncpy((char *)buf, " REJECT ", buflen); - goto common; + switch(data[3]) { + case KRB_REJECT: /* Rejected (reason might follow) */ + strlcpy((char *)buf, " REJECT ", buflen); + goto common; - case KRB_ACCEPT: /* Accepted (name might follow) */ - strncpy((char *)buf, " ACCEPT ", buflen); - common: - BUMP(buf, buflen); - if (cnt <= 4) - break; - ADDC(buf, buflen, '"'); - for (i = 4; i < cnt; i++) - ADDC(buf, buflen, data[i]); - ADDC(buf, buflen, '"'); - ADDC(buf, buflen, '\0'); - break; + case KRB_ACCEPT: /* Accepted (name might follow) */ + strlcpy((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; - case KRB_AUTH: /* Authentication data follows */ - strncpy((char *)buf, " AUTH", buflen); - goto common2; + case KRB_AUTH: /* Authentication data follows */ + strlcpy((char *)buf, " AUTH", buflen); + goto common2; - case KRB_RESPONSE: - strncpy((char *)buf, " RESPONSE", buflen); - goto common2; + case KRB_RESPONSE: + strlcpy((char *)buf, " RESPONSE", buflen); + goto common2; -#ifdef FORWARD - case KRB_FORWARD: /* Forwarded credentials follow */ - strncpy((char *)buf, " FORWARD", buflen); - goto common2; + case KRB_FORWARD: /* Forwarded credentials follow */ + strlcpy((char *)buf, " FORWARD", buflen); + goto common2; - case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ - strncpy((char *)buf, " FORWARD_ACCEPT", buflen); - goto common2; + case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ + strlcpy((char *)buf, " FORWARD_ACCEPT", buflen); + goto common2; - case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ - /* (reason might follow) */ - strncpy((char *)buf, " FORWARD_REJECT", buflen); - goto common2; -#endif /* FORWARD */ + case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ + /* (reason might follow) */ + strlcpy((char *)buf, " FORWARD_REJECT", buflen); + goto common2; - default: - sprintf(lbuf, " %d (unknown)", data[3]); - strncpy((char *)buf, lbuf, buflen); - common2: - BUMP(buf, buflen); - for (i = 4; i < cnt; i++) { - sprintf(lbuf, " %d", data[i]); - strncpy((char *)buf, lbuf, buflen); - BUMP(buf, buflen); - } - break; + default: + snprintf(buf, buflen, " %d (unknown)", data[3]); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + snprintf(buf, buflen, " %d", data[i]); + BUMP(buf, buflen); } + break; + } } -#ifdef FORWARD - void -kerberos5_forward(ap) - Authenticator *ap; +void +kerberos5_forward(Authenticator *ap) { - struct hostent *hp; - krb5_creds *local_creds; - krb5_error_code r; - krb5_data forw_creds; - extern krb5_cksumtype krb5_kdc_req_sumtype; - krb5_ccache ccache; - int i; + krb5_error_code ret; + krb5_ccache ccache; + krb5_creds creds; + krb5_kdc_flags flags; + krb5_data out_data; + krb5_principal principal; - if (!(local_creds = (krb5_creds *) - calloc(1, sizeof(*local_creds)))) { + ret = krb5_cc_default (context, &ccache); + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: could not allocate memory for credentials\r\n"); + printf ("KerberosV5: could not get default ccache: %s\r\n", + krb5_get_err_text (context, ret)); return; } - if (r = krb5_sname_to_principal(RemoteHostName, "host", 1, - &local_creds->server)) { + ret = krb5_cc_get_principal (context, ccache, &principal); + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: could not build server name - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); + printf ("KerberosV5: could not get principal: %s\r\n", + krb5_get_err_text (context, ret)); return; } - if (r = krb5_cc_default(&ccache)) { - if (auth_debug_mode) - printf("Kerberos V5: could not get default ccache - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); - return; - } + memset (&creds, 0, sizeof(creds)); - if (r = krb5_cc_get_principal(ccache, &local_creds->client)) { - if (auth_debug_mode) - printf("Kerberos V5: could not get default principal - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); - return; - } + creds.client = principal; + + ret = krb5_build_principal (context, + &creds.server, + strlen(principal->realm), + principal->realm, + "krbtgt", + principal->realm, + NULL); - /* Get ticket from credentials cache */ - if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) { + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: could not obtain credentials - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); + printf ("KerberosV5: could not get principal: %s\r\n", + krb5_get_err_text (context, ret)); return; } - if (r = get_for_creds(ETYPE_DES_CBC_CRC, - krb5_kdc_req_sumtype, - RemoteHostName, - local_creds->client, - &local_creds->keyblock, - forward_flags & OPTS_FORWARDABLE_CREDS, - &forw_creds)) { + creds.times.endtime = 0; + + flags.i = 0; + flags.b.forwarded = 1; + if (forward_flags & OPTS_FORWARDABLE_CREDS) + flags.b.forwardable = 1; + + ret = krb5_get_forwarded_creds (context, + auth_context, + ccache, + flags.i, + RemoteHostName, + &creds, + &out_data); + if (ret) { if (auth_debug_mode) - printf("Kerberos V5: error getting forwarded creds - %s\r\n", - error_message(r)); - krb5_free_creds(local_creds); + printf ("Kerberos V5: error getting forwarded creds: %s\r\n", + krb5_get_err_text (context, ret)); return; } - /* Send forwarded credentials */ - if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) { + if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) { if (auth_debug_mode) - printf("Not enough room for authentication data\r\n"); - } - else { + printf("Not enough room for authentication data\r\n"); + } else { if (auth_debug_mode) - printf("Forwarded local Kerberos V5 credentials to server\r\n"); + printf("Forwarded local Kerberos V5 credentials to server\r\n"); } +} - krb5_free_creds(local_creds); +#if defined(DCE) +/* if this was a K5 authentication try and join a PAG for the user. */ +void +kerberos5_dfspag(void) +{ + if (dfsk5ok) { + dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client, + UserNameRequested); + } } -#endif /* FORWARD */ +#endif #endif /* KRB5 */ Index: head/crypto/telnet/libtelnet/key-proto.h =================================================================== --- head/crypto/telnet/libtelnet/key-proto.h (revision 87138) +++ head/crypto/telnet/libtelnet/key-proto.h (revision 87139) @@ -1,71 +1,65 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)key-proto.h 8.1 (Berkeley) 6/4/93 */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. + * + * $FreeBSD$ */ #ifndef __KEY_PROTO__ #define __KEY_PROTO__ -#if !defined(P) -#ifdef __STDC__ -#define P(x) x -#else -#define P(x) () -#endif -#endif - -int key_file_exists P((void)); -void key_lookup P((unsigned char *, Block)); -void key_stream_init P((Block, Block, int)); -unsigned char key_stream P((int, int)); +int key_file_exists(void); +void key_lookup(unsigned char *, Block); +void key_stream_init(Block, Block, int); +unsigned char key_stream(int, int); #endif Index: head/crypto/telnet/libtelnet/krb4encpwd.c =================================================================== --- head/crypto/telnet/libtelnet/krb4encpwd.c (revision 87138) +++ head/crypto/telnet/libtelnet/krb4encpwd.c (revision 87139) @@ -1,448 +1,428 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static char sccsid[] = "@(#)krb4encpwd.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ #ifdef KRB4_ENCPWD /* * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION * ALL RIGHTS RESERVED * * "Digital Equipment Corporation authorizes the reproduction, * distribution and modification of this software subject to the following * restrictions: * * 1. Any partial or whole copy of this software, or any modification * thereof, must include this copyright notice in its entirety. * * 2. This software is supplied "as is" with no warranty of any kind, * expressed or implied, for any purpose, including any warranty of fitness * or merchantibility. DIGITAL assumes no responsibility for the use or * reliability of this software, nor promises to provide any form of * support for it on any basis. * * 3. Distribution of this software is authorized only if no profit or * remuneration of any kind is received in exchange for such distribution. * * 4. This software produces public key authentication certificates * bearing an expiration date established by DIGITAL and RSA Data * Security, Inc. It may cease to generate certificates after the expiration * date. Any modification of this software that changes or defeats * the expiration date or its effect is unauthorized. * * 5. Software that will renew or extend the expiration date of * authentication certificates produced by this software may be obtained * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA * 94065, (415)595-8782, or from DIGITAL" * */ #include +#include #include +#include #include #include - -#include -#include -#ifdef __STDC__ #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif #include "encrypt.h" #include "auth.h" #include "misc.h" int krb_mk_encpwd_req P((KTEXT, char *, char *, char *, char *, char *, char *)); int krb_rd_encpwd_req P((KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *)); extern auth_debug_mode; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KRB4_ENCPWD, }; static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; #define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */ #define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ #define KRB4_ENCPWD_ACCEPT 2 /* Accepted */ #define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */ #define KRB4_ENCPWD_ACK 4 /* Acknowledge */ #define KRB_SERVICE_NAME "rcmd" static KTEXT_ST auth; static char name[ANAME_SZ]; static char user_passwd[ANAME_SZ]; static AUTH_DAT adat = { 0 }; #ifdef ENCRYPTION static Block session_key = { 0 }; #endif /* ENCRYPTION */ static char challenge[REALM_SZ]; static int Data(ap, type, d, c) Authenticator *ap; int type; void *d; int c; { unsigned char *p = str_data + 4; unsigned char *cd = (unsigned char *)d; if (c == -1) c = strlen((char *)cd); if (0) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } int krb4encpwd_init(ap, server) Authenticator *ap; int server; { char hostname[80], *cp, *realm; C_Block skey; if (server) { str_data[3] = TELQUAL_REPLY; } else { str_data[3] = TELQUAL_IS; gethostname(hostname, sizeof(hostname)); realm = krb_realmofhost(hostname); cp = strchr(hostname, '.'); if (*cp != NULL) *cp = NULL; if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0, KEYFILE, (char *)skey)) { return(0); } } return(1); } int krb4encpwd_send(ap) Authenticator *ap; { printf("[ Trying KRB4ENCPWD ... ]\n"); if (!UserNameRequested) { return(0); } if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { return(0); } if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) { return(0); } return(1); } void krb4encpwd_is(ap, data, cnt) Authenticator *ap; unsigned char *data; int cnt; { Session_Key skey; Block datablock; char r_passwd[ANAME_SZ], r_user[ANAME_SZ]; char lhostname[ANAME_SZ], *cp; int r; time_t now; if (cnt-- < 1) return; switch (*data++) { case KRB4_ENCPWD_AUTH: memmove((void *)auth.dat, (void *)data, auth.length = cnt); gethostname(lhostname, sizeof(lhostname)); if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) { Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1); auth_finished(ap, AUTH_REJECT); return; } auth_encrypt_userpwd(r_passwd); if (passwdok(UserNameRequested, UserPassword) == 0) { /* * illegal username and password */ Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1); auth_finished(ap, AUTH_REJECT); return; } memmove((void *)session_key, (void *)adat.session, sizeof(Block)); Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0); auth_finished(ap, AUTH_USER); break; case KRB4_ENCPWD_CHALLENGE: /* * Take the received random challenge text and save * for future authentication. */ memmove((void *)challenge, (void *)data, sizeof(Block)); break; case KRB4_ENCPWD_ACK: /* * Receive ack, if mutual then send random challenge */ /* * If we are doing mutual authentication, get set up to send * the challenge, and verify it when the response comes back. */ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { register int i; time(&now); sprintf(challenge, "%x", now); Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge)); } break; default: Data(ap, KRB4_ENCPWD_REJECT, 0, 0); break; } } void krb4encpwd_reply(ap, data, cnt) Authenticator *ap; unsigned char *data; int cnt; { Session_Key skey; KTEXT_ST krb_token; Block enckey; CREDENTIALS cred; int r; char randchal[REALM_SZ], instance[ANAME_SZ], *cp; char hostname[80], *realm; if (cnt-- < 1) return; switch (*data++) { case KRB4_ENCPWD_REJECT: if (cnt > 0) { printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n", cnt, data); } else printf("[ KRB4_ENCPWD refuses authentication ]\r\n"); auth_send_retry(); return; case KRB4_ENCPWD_ACCEPT: printf("[ KRB4_ENCPWD accepts you ]\n"); auth_finished(ap, AUTH_USER); return; case KRB4_ENCPWD_CHALLENGE: /* * Verify that the response to the challenge is correct. */ gethostname(hostname, sizeof(hostname)); realm = krb_realmofhost(hostname); memmove((void *)challenge, (void *)data, cnt); memset(user_passwd, 0, sizeof(user_passwd)); local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); UserPassword = user_passwd; Challenge = challenge; strcpy(instance, RemoteHostName); if ((cp = strchr(instance, '.')) != 0) *cp = '\0'; if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) { krb_token.length = 0; } if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) { return; } break; default: return; } } int krb4encpwd_status(ap, name, level) Authenticator *ap; char *name; int level; { if (level < AUTH_USER) return(level); if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) { strcpy(name, UserNameRequested); return(AUTH_VALID); } else { return(AUTH_USER); } } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} void krb4encpwd_printsub(data, cnt, buf, buflen) unsigned char *data, *buf; int cnt, buflen; { char lbuf[32]; register int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case KRB4_ENCPWD_AUTH: /* Authentication data follows */ strncpy((char *)buf, " AUTH", buflen); goto common2; case KRB4_ENCPWD_CHALLENGE: strncpy((char *)buf, " CHALLENGE", buflen); goto common2; case KRB4_ENCPWD_ACK: strncpy((char *)buf, " ACK", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } int passwdok(name, passwd) char *name, *passwd; { char *crypt(); char *salt, *p; struct passwd *pwd; int passwdok_status = 0; if (pwd = getpwnam(name)) salt = pwd->pw_passwd; else salt = "xx"; p = crypt(passwd, salt); if (pwd && !strcmp(p, pwd->pw_passwd)) { passwdok_status = 1; } else passwdok_status = 0; return(passwdok_status); } -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); -} #endif Index: head/crypto/telnet/libtelnet/misc-proto.h =================================================================== --- head/crypto/telnet/libtelnet/misc-proto.h (revision 87138) +++ head/crypto/telnet/libtelnet/misc-proto.h (revision 87139) @@ -1,81 +1,88 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)misc-proto.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * Copyright (C) 1990 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #ifndef __MISC_PROTO__ #define __MISC_PROTO__ #if !defined(P) #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif #endif -void auth_encrypt_init P((char *, char *, char *, int)); -void auth_encrypt_connect P((int)); -void printd P((unsigned char *, int)); +void auth_encrypt_init(char *, char *, const char *, int); +void auth_encrypt_connect(int); +void printd(const unsigned char *, int); +int isprefix(char *, const char *); +char **genget(char *, char **, int); +int Ambiguous(char **); + +int getent(char *, const char *); +char *Getstr(const char *, char **); + /* * These functions are imported from the application */ -int net_write P((unsigned char *, int)); -void net_encrypt P((void)); -int telnet_spin P((void)); -char *telnet_getenv P((char *)); -char *telnet_gets P((char *, char *, int, int)); -void printsub P((int, unsigned char *, int)); +int net_write(unsigned char *, int); +void net_encrypt(void); +int telnet_spin(void); +char *telnet_getenv(char *); +char *telnet_gets(const char *, char *, int, int); +void printsub(char, unsigned char *, int); #endif Index: head/crypto/telnet/libtelnet/misc.c =================================================================== --- head/crypto/telnet/libtelnet/misc.c (revision 87138) +++ head/crypto/telnet/libtelnet/misc.c (revision 87139) @@ -1,107 +1,108 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93"; #endif #endif /* not lint */ #include #include +#include + #include "misc.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include "auth.h" #endif #ifdef ENCRYPTION #include "encrypt.h" #endif /* ENCRYPTION */ char *RemoteHostName; char *LocalHostName; char *UserNameRequested = 0; int ConnectedCount = 0; - void -auth_encrypt_init(local, remote, name, server) - char *local; - char *remote; - char *name; - int server; +#ifndef AUTHENTICATION +#define undef1 __unused +#else +#define undef1 +#endif + +void +auth_encrypt_init(char *local, char *remote, const char *name undef1, int server undef1) { RemoteHostName = remote; LocalHostName = local; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION auth_init(name, server); #endif #ifdef ENCRYPTION encrypt_init(name, server); #endif /* ENCRYPTION */ if (UserNameRequested) { free(UserNameRequested); UserNameRequested = 0; } } - void -auth_encrypt_user(name) - char *name; +#ifdef ENCRYPTION +void +auth_encrypt_user(char *name) { - extern char *strdup(); - if (UserNameRequested) free(UserNameRequested); UserNameRequested = name ? strdup(name) : 0; } - void -auth_encrypt_connect(cnt) - int cnt; +void +auth_encrypt_connect(int cnt __unused) { } +#endif /* ENCRYPTION */ - void -printd(data, cnt) - unsigned char *data; - int cnt; +void +printd(const unsigned char *data, int cnt) { if (cnt > 16) cnt = 16; while (cnt-- > 0) { printf(" %02x", *data); ++data; } } Index: head/crypto/telnet/libtelnet/pk.c =================================================================== --- head/crypto/telnet/libtelnet/pk.c (revision 87138) +++ head/crypto/telnet/libtelnet/pk.c (revision 87139) @@ -1,272 +1,269 @@ /*- * Copyright (c) 1991, 1993 * Dave Safford. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ +#include + +__FBSDID("$FreeBSD$"); + /* public key routines */ /* functions: genkeys(char *public, char *secret) common_key(char *secret, char *public, desData *deskey) pk_encode(char *in, *out, DesData *deskey); pk_decode(char *in, *out, DesData *deskey); where char public[HEXKEYBYTES + 1]; char secret[HEXKEYBYTES + 1]; */ -#include -__FBSDID("$FreeBSD$"); - #include #include #include #include +#include #include + #include "mp.h" #include "pk.h" -#if defined(SOLARIS2) || defined(LINUX) || defined(__FreeBSD__) -#include -#endif static void adjust(char keyout[HEXKEYBYTES+1], char *keyin); /* * Choose top 128 bits of the common key to use as our idea key. */ static void extractideakey(MINT *ck, IdeaData *ideakey) { MINT *a; MINT *z; short r; int i; short base = (1 << 8); char *k; z = itom(0); a = itom(0); madd(ck, z, a); for (i = 0; i < ((KEYSIZE - 128) / 8); i++) { sdiv(a, base, a, &r); } k = (char *)ideakey; for (i = 0; i < 16; i++) { sdiv(a, base, a, &r); *k++ = r; } mfree(z); mfree(a); } /* * Choose middle 64 bits of the common key to use as our des key, possibly * overwriting the lower order bits by setting parity. */ static void extractdeskey(MINT *ck, DesData *deskey) { MINT *a; MINT *z; short r; int i; short base = (1 << 8); char *k; z = itom(0); a = itom(0); madd(ck, z, a); for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { sdiv(a, base, a, &r); } k = (char *)deskey; for (i = 0; i < 8; i++) { sdiv(a, base, a, &r); *k++ = r; } mfree(z); mfree(a); } /* * get common key from my secret key and his public key */ void common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey) { MINT *public; MINT *secret; MINT *common; MINT *modulus = xtom(HEXMODULUS); public = xtom(xpublic); secret = xtom(xsecret); common = itom(0); pow(public, secret, modulus, common); extractdeskey(common, deskey); extractideakey(common, ideakey); -#if DES_OSTHOLM - des_fixup_key_parity(deskey); -#else des_set_odd_parity(deskey); -#endif mfree(common); mfree(secret); mfree(public); mfree(modulus); } /* * Generate a seed */ -void +static void getseed(char *seed, int seedsize) { int i; srandomdev(); for (i = 0; i < seedsize; i++) { seed[i] = random() & 0xff; } } /* * Generate a random public/secret key pair */ void genkeys(char *public, char *secret) { - int i; + size_t i; # define BASEBITS (8*sizeof(short) - 1) # define BASE (1 << BASEBITS) MINT *pk = itom(0); MINT *sk = itom(0); MINT *tmp; MINT *base = itom(BASE); MINT *root = itom(PROOT); MINT *modulus = xtom(HEXMODULUS); short r; unsigned short seed[KEYSIZE/BASEBITS + 1]; char *xkey; getseed((char *)seed, sizeof(seed)); for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { r = seed[i] % BASE; tmp = itom(r); mult(sk, base, sk); madd(sk, tmp, sk); mfree(tmp); } tmp = itom(0); mdiv(sk, modulus, tmp, sk); mfree(tmp); pow(root, sk, modulus, pk); xkey = mtox(sk); adjust(secret, xkey); xkey = mtox(pk); adjust(public, xkey); mfree(sk); mfree(base); mfree(pk); mfree(root); mfree(modulus); } /* * Adjust the input key so that it is 0-filled on the left */ static void adjust(char keyout[HEXKEYBYTES+1], char *keyin) { char *p; char *s; for (p = keyin; *p; p++) ; for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { *s = *p; } while (s >= keyout) { *s-- = '0'; } } static char hextab[17] = "0123456789ABCDEF"; /* given a DES key, cbc encrypt and translate input to terminated hex */ void pk_encode(char *in, char *out, DesData *key) { char buf[256]; DesData i; des_key_schedule k; int l,op,deslen; memset(&i,0,sizeof(i)); memset(buf,0,sizeof(buf)); deslen = ((strlen(in) + 7)/8)*8; des_key_sched(key, k); des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT); for (l=0,op=0;l> 4]; out[op++] = hextab[(buf[l] & 0x0f)]; } out[op] = '\0'; } /* given a DES key, translate input from hex and decrypt */ void pk_decode(char *in, char *out, DesData *key) { char buf[256]; DesData i; des_key_schedule k; - int l,n1,n2,op; + int n1,n2,op; + size_t l; memset(&i,0,sizeof(i)); memset(buf,0,sizeof(buf)); for (l=0,op=0;l '9') n1 = in[op] - 'A' + 10; else n1 = in[op] - '0'; if (in[op+1] > '9') n2 = in[op+1] - 'A' + 10; else n2 = in[op+1] - '0'; buf[l] = n1*16 +n2; } des_key_sched(key, k); des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT); out[strlen(in)/2] = '\0'; } Index: head/crypto/telnet/libtelnet/pk.h =================================================================== --- head/crypto/telnet/libtelnet/pk.h (revision 87138) +++ head/crypto/telnet/libtelnet/pk.h (revision 87139) @@ -1,72 +1,59 @@ /*- * Copyright (c) 1991, 1993 * Dave Safford. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* header for the des routines that we will use */ typedef unsigned char byte, DesData[ 8], IdeaData[16]; -#if 0 -typedef unsigned long word, DesKeys[32]; -#else #define DesKeys des_key_schedule -#endif #define DES_DECRYPT 0 #define DES_ENCRYPT 1 -#if 0 -extern void des_fixup_key_parity(); /* (DesData *key) */ -extern int des_key_sched(); /* (DesData *key, DesKeys *m) */ -extern int des_ecb_encrypt(); /* (DesData *src, *dst, DesKeys *m, int mode) */ -extern int des_cbc_encrypt(); /* (char *src, *dst, int length, - DesKeys *m, DesData *init, int mode) */ -#endif - /* public key routines */ /* functions: genkeys(char *public, char *secret) common_key(char *secret, char *public, desData *deskey) where char public[HEXKEYBYTES + 1]; char secret[HEXKEYBYTES + 1]; */ #define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b" #define HEXKEYBYTES 48 #define KEYSIZE 192 #define KEYBYTES 24 #define PROOT 3 extern void genkeys(char *public, char *secret); extern void common_key(char *secret, char *public, IdeaData *common, DesData *deskey); extern void pk_encode(char *in, char *out, DesData *deskey); extern void pk_decode(char *in, char *out, DesData *deskey); - Index: head/crypto/telnet/libtelnet/read_password.c =================================================================== --- head/crypto/telnet/libtelnet/read_password.c (revision 87138) +++ head/crypto/telnet/libtelnet/read_password.c (revision 87139) @@ -1,150 +1,151 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint #if 0 static char sccsid[] = "@(#)read_password.c 8.3 (Berkeley) 5/30/95"; #endif #endif /* not lint */ /* * $Source: /mit/kerberos/src/lib/des/RCS/read_password.c,v $ * $Author: jon $ * * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute * of Technology. * * For copying and distribution information, please see the file * . * * This routine prints the supplied string to standard * output as a prompt, and reads a password string without * echoing. */ #if defined(RSA_ENCPWD) || defined(KRB4_ENCPWD) #include #include #include #include #include static jmp_buf env; /*** Routines ****************************************************** */ /* * This version just returns the string, doesn't map to key. * * Returns 0 on success, non-zero on failure. */ int local_des_read_pw_string(s,max,prompt,verify) char *s; int max; char *prompt; int verify; { int ok = 0; char *ptr; jmp_buf old_env; struct sgttyb tty_state; char key_string[BUFSIZ]; if (max > BUFSIZ) { return -1; } /* XXX assume jmp_buf is typedef'ed to an array */ memmove((char *)env, (char *)old_env, sizeof(env)); if (setjmp(env)) goto lose; /* save terminal state*/ if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1) return -1; /* push_signals(); */ /* Turn off echo */ tty_state.sg_flags &= ~ECHO; if (ioctl(0,TIOCSETP,(char *)&tty_state) == -1) return -1; while (!ok) { (void) printf("%s", prompt); (void) fflush(stdout); while (!fgets(s, max, stdin)); if ((ptr = strchr(s, '\n'))) *ptr = '\0'; if (verify) { printf("\nVerifying, please re-enter %s",prompt); (void) fflush(stdout); if (!fgets(key_string, sizeof(key_string), stdin)) { clearerr(stdin); continue; } if ((ptr = strchr(key_string, '\n'))) *ptr = '\0'; if (strcmp(s,key_string)) { printf("\n\07\07Mismatch - try again\n"); (void) fflush(stdout); continue; } } ok = 1; } lose: if (!ok) memset(s, 0, max); printf("\n"); /* turn echo back on */ tty_state.sg_flags |= ECHO; if (ioctl(0,TIOCSETP,(char *)&tty_state)) ok = 0; /* pop_signals(); */ memmove((char *)old_env, (char *)env, sizeof(env)); if (verify) memset(key_string, 0, sizeof (key_string)); s[max-1] = 0; /* force termination */ return !ok; /* return nonzero if not okay */ } #endif /* defined(RSA_ENCPWD) || defined(KRB4_ENCPWD) */ Index: head/crypto/telnet/libtelnet/rsaencpwd.c =================================================================== --- head/crypto/telnet/libtelnet/rsaencpwd.c (revision 87138) +++ head/crypto/telnet/libtelnet/rsaencpwd.c (revision 87139) @@ -1,495 +1,475 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include + __FBSDID("$FreeBSD$"); #ifndef lint static char sccsid[] = "@(#)rsaencpwd.c 8.3 (Berkeley) 5/30/95"; #endif /* not lint */ #ifdef RSA_ENCPWD /* * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION * ALL RIGHTS RESERVED * * "Digital Equipment Corporation authorizes the reproduction, * distribution and modification of this software subject to the following * restrictions: * * 1. Any partial or whole copy of this software, or any modification * thereof, must include this copyright notice in its entirety. * * 2. This software is supplied "as is" with no warranty of any kind, * expressed or implied, for any purpose, including any warranty of fitness * or merchantibility. DIGITAL assumes no responsibility for the use or * reliability of this software, nor promises to provide any form of * support for it on any basis. * * 3. Distribution of this software is authorized only if no profit or * remuneration of any kind is received in exchange for such distribution. * * 4. This software produces public key authentication certificates * bearing an expiration date established by DIGITAL and RSA Data * Security, Inc. It may cease to generate certificates after the expiration * date. Any modification of this software that changes or defeats * the expiration date or its effect is unauthorized. * * 5. Software that will renew or extend the expiration date of * authentication certificates produced by this software may be obtained * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA * 94065, (415)595-8782, or from DIGITAL" * */ #include #include #include #include - -#ifdef __STDC__ #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif #include "encrypt.h" #include "auth.h" #include "misc.h" #include "cdc.h" extern auth_debug_mode; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_RSA_ENCPWD, }; static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; #define RSA_ENCPWD_AUTH 0 /* Authentication data follows */ #define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ #define RSA_ENCPWD_ACCEPT 2 /* Accepted */ #define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */ #define NAME_SZ 40 #define CHAL_SZ 20 #define PWD_SZ 40 static KTEXT_ST auth; static char name[NAME_SZ]; static char user_passwd[PWD_SZ]; static char key_file[2*NAME_SZ]; static char lhostname[NAME_SZ]; static char challenge[CHAL_SZ]; static int challenge_len; static int Data(ap, type, d, c) Authenticator *ap; int type; void *d; int c; { unsigned char *p = str_data + 4; unsigned char *cd = (unsigned char *)d; if (c == -1) c = strlen((char *)cd); if (0) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; if (type != NULL) *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } int rsaencpwd_init(ap, server) Authenticator *ap; int server; { char *cp; FILE *fp; if (server) { str_data[3] = TELQUAL_REPLY; memset(key_file, 0, sizeof(key_file)); gethostname(lhostname, sizeof(lhostname)); if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; strcpy(key_file, "/etc/."); strcat(key_file, lhostname); strcat(key_file, "_privkey"); if ((fp=fopen(key_file, "r"))==NULL) return(0); fclose(fp); } else { str_data[3] = TELQUAL_IS; } return(1); } int rsaencpwd_send(ap) Authenticator *ap; { printf("[ Trying RSAENCPWD ... ]\n"); if (!UserNameRequested) { return(0); } if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { return(0); } if (!Data(ap, NULL, (void *)NULL, 0)) { return(0); } return(1); } void rsaencpwd_is(ap, data, cnt) Authenticator *ap; unsigned char *data; int cnt; { Session_Key skey; Block datablock; char r_passwd[PWD_SZ], r_user[NAME_SZ]; char *cp, key[160]; char chalkey[160], *ptr; FILE *fp; int r, i, j, chalkey_len, len; time_t now; cnt--; switch (*data++) { case RSA_ENCPWD_AUTH: memmove((void *)auth.dat, (void *)data, auth.length = cnt); if ((fp=fopen(key_file, "r"))==NULL) { Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); auth_finished(ap, AUTH_REJECT); return; } /* * get privkey */ fscanf(fp, "%x;", &len); for (i=0;iway & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) { register int i; time(&now); if ((now % 2) == 0) { sprintf(challenge, "%x", now); challenge_len = strlen(challenge); } else { strcpy(challenge, "randchal"); challenge_len = 8; } if ((fp=fopen(key_file, "r"))==NULL) { Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); auth_finished(ap, AUTH_REJECT); return; } /* * skip privkey */ fscanf(fp, "%x;", &len); for (i=0;i 0) { printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n", cnt, data); } else printf("[ RSA_ENCPWD refuses authentication ]\r\n"); auth_send_retry(); return; case RSA_ENCPWD_ACCEPT: printf("[ RSA_ENCPWD accepts you ]\n"); auth_finished(ap, AUTH_USER); return; case RSA_ENCPWD_CHALLENGEKEY: /* * Verify that the response to the challenge is correct. */ memmove((void *)chalkey, (void *)data, cnt); ptr = (char *) &chalkey[0]; ptr += DecodeHeaderLength(chalkey); if (*ptr != 0x04) { return; } *ptr++; challenge_len = DecodeValueLength(ptr); ptr += NumEncodeLengthOctets(challenge_len); memmove(challenge, ptr, challenge_len); ptr += challenge_len; if (*ptr != 0x04) { return; } *ptr++; pubkey_len = DecodeValueLength(ptr); ptr += NumEncodeLengthOctets(pubkey_len); memmove(pubkey, ptr, pubkey_len); memset(user_passwd, 0, sizeof(user_passwd)); local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); UserPassword = user_passwd; Challenge = challenge; r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey); if (r < 0) { token.length = 1; } if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) { return; } break; default: return; } } int rsaencpwd_status(ap, name, level) Authenticator *ap; char *name; int level; { if (level < AUTH_USER) return(level); if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) { strcpy(name, UserNameRequested); return(AUTH_VALID); } else { return(AUTH_USER); } } #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} void rsaencpwd_printsub(data, cnt, buf, buflen) unsigned char *data, *buf; int cnt, buflen; { char lbuf[32]; register int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case RSA_ENCPWD_AUTH: /* Authentication data follows */ strncpy((char *)buf, " AUTH", buflen); goto common2; case RSA_ENCPWD_CHALLENGEKEY: strncpy((char *)buf, " CHALLENGEKEY", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } int rsaencpwd_passwdok(name, passwd) char *name, *passwd; { char *crypt(); char *salt, *p; struct passwd *pwd; int passwdok_status = 0; if (pwd = getpwnam(name)) salt = pwd->pw_passwd; else salt = "xx"; p = crypt(passwd, salt); if (pwd && !strcmp(p, pwd->pw_passwd)) { passwdok_status = 1; } else passwdok_status = 0; return(passwdok_status); } -#endif - -#ifdef notdef - -prkey(msg, key) - char *msg; - unsigned char *key; -{ - register int i; - printf("%s:", msg); - for (i = 0; i < 8; i++) - printf(" %3d", key[i]); - printf("\r\n"); -} #endif Index: head/crypto/telnet/libtelnet/sra.c =================================================================== --- head/crypto/telnet/libtelnet/sra.c (revision 87138) +++ head/crypto/telnet/libtelnet/sra.c (revision 87139) @@ -1,669 +1,602 @@ /*- * Copyright (c) 1991, 1993 * Dave Safford. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include + __FBSDID("$FreeBSD$"); #ifdef SRA +#ifdef ENCRYPTION #include #include +#include #include -#ifdef __STDC__ #include -#endif -#ifdef NO_STRING_H -#include -#else #include -#endif +#include +#include -#if !defined(NOPAM) +#ifndef NOPAM #include #else #include #endif -#include -#include -#include - #include "auth.h" #include "misc.h" #include "encrypt.h" #include "pk.h" char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1]; -char *user,*pass,*xuser,*xpass; +char *user, *pass, *xuser, *xpass; DesData ck; IdeaData ik; extern int auth_debug_mode; extern char *line; static int sra_valid = 0; static int passwd_sent = 0; static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_SRA, }; #define SRA_KEY 0 #define SRA_USER 1 #define SRA_CONTINUE 2 #define SRA_PASS 3 #define SRA_ACCEPT 4 #define SRA_REJECT 5 -static int check_user(const char *, const char *); +static int check_user(char *, char *); /* support routine to send out authentication message */ static int Data(Authenticator *ap, int type, void *d, int c) { unsigned char *p = str_data + 4; unsigned char *cd = (unsigned char *)d; if (c == -1) c = strlen((char *)cd); if (auth_debug_mode) { printf("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd(d, c); printf("\r\n"); } *p++ = ap->type; *p++ = ap->way; *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub('>', &str_data[2], p - (&str_data[2])); return(net_write(str_data, p - str_data)); } int -sra_init(Authenticator *ap, int server) +sra_init(Authenticator *ap __unused, int server) { if (server) str_data[3] = TELQUAL_REPLY; else str_data[3] = TELQUAL_IS; user = (char *)malloc(256); xuser = (char *)malloc(513); pass = (char *)malloc(256); xpass = (char *)malloc(513); if (user == NULL || xuser == NULL || pass == NULL || xpass == NULL) return 0; /* malloc failed */ passwd_sent = 0; genkeys(pka,ska); return(1); } /* client received a go-ahead for sra */ int sra_send(Authenticator *ap) { /* send PKA */ if (auth_debug_mode) printf("Sent PKA to server.\r\n" ); printf("Trying SRA secure login:\r\n"); if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { if (auth_debug_mode) printf("Not enough room for authentication data\r\n"); return(0); } return(1); } /* server received an IS -- could be SRA KEY, USER, or PASS */ void sra_is(Authenticator *ap, unsigned char *data, int cnt) { int valid; Session_Key skey; if (cnt-- < 1) goto bad; switch (*data++) { case SRA_KEY: if (cnt < HEXKEYBYTES) { Data(ap, SRA_REJECT, (void *)0, 0); auth_finished(ap, AUTH_USER); if (auth_debug_mode) { printf("SRA user rejected for bad PKB\r\n"); } return; } if (auth_debug_mode) printf("Sent pka\r\n"); if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { if (auth_debug_mode) printf("Not enough room\r\n"); return; } memcpy(pkb,data,HEXKEYBYTES); pkb[HEXKEYBYTES] = '\0'; common_key(ska,pkb,&ik,&ck); return; case SRA_USER: /* decode KAB(u) */ if (cnt > 512) /* Attempted buffer overflow */ break; memcpy(xuser,data,cnt); xuser[cnt] = '\0'; pk_decode(xuser,user,&ck); auth_encrypt_user(user); Data(ap, SRA_CONTINUE, (void *)0, 0); return; case SRA_PASS: if (cnt > 512) /* Attempted buffer overflow */ break; /* decode KAB(P) */ memcpy(xpass,data,cnt); xpass[cnt] = '\0'; pk_decode(xpass,pass,&ck); /* check user's password */ valid = check_user(user,pass); if(valid) { Data(ap, SRA_ACCEPT, (void *)0, 0); -#ifdef DES_ENCRYPTION skey.data = ck; skey.type = SK_DES; skey.length = 8; encrypt_session_key(&skey, 1); -#endif sra_valid = 1; auth_finished(ap, AUTH_VALID); if (auth_debug_mode) { printf("SRA user accepted\r\n"); } } else { Data(ap, SRA_CONTINUE, (void *)0, 0); /* Data(ap, SRA_REJECT, (void *)0, 0); sra_valid = 0; auth_finished(ap, AUTH_REJECT); */ if (auth_debug_mode) { printf("SRA user failed\r\n"); } } return; default: if (auth_debug_mode) printf("Unknown SRA option %d\r\n", data[-1]); } bad: Data(ap, SRA_REJECT, 0, 0); sra_valid = 0; auth_finished(ap, AUTH_REJECT); } /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */ void sra_reply(Authenticator *ap, unsigned char *data, int cnt) { - extern char *telnet_gets(); char uprompt[256],tuser[256]; Session_Key skey; - int i; + size_t i; if (cnt-- < 1) return; switch (*data++) { case SRA_KEY: /* calculate common key */ if (cnt < HEXKEYBYTES) { if (auth_debug_mode) { printf("SRA user rejected for bad PKB\r\n"); } return; } memcpy(pkb,data,HEXKEYBYTES); pkb[HEXKEYBYTES] = '\0'; common_key(ska,pkb,&ik,&ck); enc_user: /* encode user */ memset(tuser,0,sizeof(tuser)); sprintf(uprompt,"User (%s): ",UserNameRequested); telnet_gets(uprompt,tuser,255,1); if (tuser[0] == '\n' || tuser[0] == '\r' ) strcpy(user,UserNameRequested); else { /* telnet_gets leaves the newline on */ for(i=0;i 0) {*(buf)++ = (c); --(len);} void sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) { char lbuf[32]; - register int i; + int i; buf[buflen-1] = '\0'; /* make sure its NULL terminated */ buflen -= 1; switch(data[3]) { case SRA_CONTINUE: strncpy((char *)buf, " CONTINUE ", buflen); goto common; case SRA_REJECT: /* Rejected (reason might follow) */ strncpy((char *)buf, " REJECT ", buflen); goto common; case SRA_ACCEPT: /* Accepted (name might follow) */ strncpy((char *)buf, " ACCEPT ", buflen); common: BUMP(buf, buflen); if (cnt <= 4) break; ADDC(buf, buflen, '"'); for (i = 4; i < cnt; i++) ADDC(buf, buflen, data[i]); ADDC(buf, buflen, '"'); ADDC(buf, buflen, '\0'); break; case SRA_KEY: /* Authentication data follows */ strncpy((char *)buf, " KEY ", buflen); goto common2; case SRA_USER: strncpy((char *)buf, " USER ", buflen); goto common2; case SRA_PASS: strncpy((char *)buf, " PASS ", buflen); goto common2; default: sprintf(lbuf, " %d (unknown)", data[3]); strncpy((char *)buf, lbuf, buflen); common2: BUMP(buf, buflen); for (i = 4; i < cnt; i++) { sprintf(lbuf, " %d", data[i]); strncpy((char *)buf, lbuf, buflen); BUMP(buf, buflen); } break; } } -struct passwd *pw; - -/* - * Helper function for sgetpwnam(). - */ -char * -sgetsave(char *s) -{ - char *new = malloc((unsigned) strlen(s) + 1); - - if (new == NULL) { - return(NULL); - } - (void) strcpy(new, s); - return (new); -} - -struct passwd * -sgetpwnam(char *name) -{ - static struct passwd save; - register struct passwd *p; - char *sgetsave(); - - if ((p = getpwnam(name)) == NULL) - return (p); - if (save.pw_name) { - free(save.pw_name); - free(save.pw_passwd); - free(save.pw_gecos); - free(save.pw_dir); - free(save.pw_shell); - } - save = *p; - save.pw_name = sgetsave(p->pw_name); - save.pw_passwd = sgetsave(p->pw_passwd); - save.pw_gecos = sgetsave(p->pw_gecos); - save.pw_dir = sgetsave(p->pw_dir); - save.pw_shell = sgetsave(p->pw_shell); -#if 0 -syslog(LOG_WARNING,"%s\n",save.pw_name); -syslog(LOG_WARNING,"%s\n",save.pw_passwd); -syslog(LOG_WARNING,"%s\n",save.pw_gecos); -syslog(LOG_WARNING,"%s\n",save.pw_dir); -#endif -#ifdef USE_SHADOW - { - struct spwd *sp; - sp = getspnam(name); - free(save.pw_passwd); - save.pw_passwd = sgetsave(sp->sp_pwdp); - } -#endif - return (&save); -} - static int -isroot(const char *user) +isroot(const char *usr) { - struct passwd *pw; + struct passwd *pwd; - if ((pw=getpwnam(user))==NULL) + if ((pwd=getpwnam(usr))==NULL) return 0; - return (!pw->pw_uid); + return (!pwd->pw_uid); } static int rootterm(char *ttyn) { struct ttyent *t; return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); } #ifdef NOPAM static int -check_user(const char *name, const char *pass) +check_user(char *name, char *cred) { - register char *cp; + char *cp; char *xpasswd, *salt; if (isroot(name) && !rootterm(line)) { crypt("AA","*"); /* Waste some time to simulate success */ return(0); } if (pw = sgetpwnam(name)) { if (pw->pw_shell == NULL) { pw = (struct passwd *) NULL; return(0); } salt = pw->pw_passwd; - xpasswd = crypt(pass, salt); + xpasswd = crypt(cred, salt); /* The strcmp does not catch null passwords! */ if (pw == NULL || *pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) { pw = (struct passwd *) NULL; return(0); } return(1); } return(0); } #else /* * The following is stolen from ftpd, which stole it from the imap-uw * PAM module and login.c. It is needed because we can't really * "converse" with the user, having already gone to the trouble of * getting their username and password through an encrypted channel. */ #define COPY_STRING(s) (s ? strdup(s):NULL) struct cred_t { const char *uname; const char *pass; }; typedef struct cred_t cred_t; -int -auth_conv(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata) +static int +auth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata) { int i; cred_t *cred = (cred_t *) appdata; struct pam_response *reply = malloc(sizeof(struct pam_response) * num_msg); if (reply == NULL) return PAM_BUF_ERR; for (i = 0; i < num_msg; i++) { switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON: /* assume want user name */ reply[i].resp_retcode = PAM_SUCCESS; reply[i].resp = COPY_STRING(cred->uname); /* PAM frees resp. */ break; case PAM_PROMPT_ECHO_OFF: /* assume want password */ reply[i].resp_retcode = PAM_SUCCESS; reply[i].resp = COPY_STRING(cred->pass); /* PAM frees resp. */ break; case PAM_TEXT_INFO: case PAM_ERROR_MSG: reply[i].resp_retcode = PAM_SUCCESS; reply[i].resp = NULL; break; default: /* unknown message style */ free(reply); return PAM_CONV_ERR; } } *resp = reply; return PAM_SUCCESS; } /* * The PAM version as a side effect may put a new username in *name. */ static int -check_user(const char *name, const char *pass) +check_user(char *name, char *cred) { pam_handle_t *pamh = NULL; const void *item; int rval; int e; - cred_t auth_cred = { name, pass }; + cred_t auth_cred = { name, cred }; struct pam_conv conv = { &auth_conv, &auth_cred }; e = pam_start("telnetd", name, &conv, &pamh); if (e != PAM_SUCCESS) { syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e)); return 0; } #if 0 /* Where can we find this value? */ e = pam_set_item(pamh, PAM_RHOST, remotehost); if (e != PAM_SUCCESS) { syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s", pam_strerror(pamh, e)); return 0; } #endif e = pam_authenticate(pamh, 0); switch (e) { case PAM_SUCCESS: /* * With PAM we support the concept of a "template" * user. The user enters a login name which is * authenticated by PAM, usually via a remote service * such as RADIUS or TACACS+. If authentication * succeeds, a different but related "template" name * is used for setting the credentials, shell, and * home directory. The name the user enters need only * exist on the remote authentication server, but the * template name must be present in the local password * database. * * This is supported by two various mechanisms in the * individual modules. However, from the application's * point of view, the template user is always passed * back as a changed value of the PAM_USER item. */ if ((e = pam_get_item(pamh, PAM_USER, &item)) == PAM_SUCCESS) { - strcpy((char *) name, (const char *) item); + strcpy(name, item); } else syslog(LOG_ERR, "Couldn't get PAM_USER: %s", pam_strerror(pamh, e)); if (isroot(name) && !rootterm(line)) rval = 0; else rval = 1; break; case PAM_AUTH_ERR: case PAM_USER_UNKNOWN: case PAM_MAXTRIES: rval = 0; break; default: syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e)); rval = 0; break; } if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); rval = 0; } return rval; } #endif -#endif - +#endif /* ENCRYPTION */ +#endif /* SRA */ Index: head/crypto/telnet/telnet/tn3270.c =================================================================== --- head/crypto/telnet/telnet/tn3270.c (revision 87138) +++ head/crypto/telnet/telnet/tn3270.c (nonexistent) @@ -1,416 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)tn3270.c 8.2 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; -#endif -#endif /* not lint */ - -#include -#include - -#include "general.h" - -#include "defines.h" -#include "ring.h" -#include "externs.h" -#include "fdset.h" - -#if defined(TN3270) - -#include "../ctlr/screen.h" -#include "../general/globals.h" - -#include "../sys_curses/telextrn.h" -#include "../ctlr/externs.h" - -#if defined(unix) -int - HaveInput, /* There is input available to scan */ - cursesdata, /* Do we dump curses data? */ - sigiocount; /* Number of times we got a SIGIO */ - -char tline[200]; -char *transcom = 0; /* transparent mode command (default: none) */ -#endif /* defined(unix) */ - -char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; - -static char sb_terminal[] = { IAC, SB, - TELOPT_TTYPE, TELQUAL_IS, - 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', - IAC, SE }; -#define SBTERMMODEL 13 - -static int - Sent3270TerminalType; /* Have we said we are a 3270? */ - -#endif /* defined(TN3270) */ - - - void -init_3270() -{ -#if defined(TN3270) -#if defined(unix) - HaveInput = 0; - sigiocount = 0; -#endif /* defined(unix) */ - Sent3270TerminalType = 0; - Ifrontp = Ibackp = Ibuf; - init_ctlr(); /* Initialize some things */ - init_keyboard(); - init_screen(); - init_system(); -#endif /* defined(TN3270) */ -} - - -#if defined(TN3270) - -/* - * DataToNetwork - queue up some data to go to network. If "done" is set, - * then when last byte is queued, we add on an IAC EOR sequence (so, - * don't call us with "done" until you want that done...) - * - * We actually do send all the data to the network buffer, since our - * only client needs for us to do that. - */ - - int -DataToNetwork(buffer, count, done) - register char *buffer; /* where the data is */ - register int count; /* how much to send */ - int done; /* is this the last of a logical block */ -{ - register int loop, c; - int origCount; - - origCount = count; - - while (count) { - /* If not enough room for EORs, IACs, etc., wait */ - if (NETROOM() < 6) { - fd_set o; - - FD_ZERO(&o); - netflush(); - while (NETROOM() < 6) { - FD_SET(net, &o); - (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, - (struct timeval *) 0); - netflush(); - } - } - c = ring_empty_count(&netoring); - if (c > count) { - c = count; - } - loop = c; - while (loop) { - if (((unsigned char)*buffer) == IAC) { - break; - } - buffer++; - loop--; - } - if ((c = c-loop)) { - ring_supply_data(&netoring, buffer-c, c); - count -= c; - } - if (loop) { - NET2ADD(IAC, IAC); - count--; - buffer++; - } - } - - if (done) { - NET2ADD(IAC, EOR); - netflush(); /* try to move along as quickly as ... */ - } - return(origCount - count); -} - - -#if defined(unix) - void -inputAvailable(signo) - int signo; -{ - HaveInput = 1; - sigiocount++; -} -#endif /* defined(unix) */ - - void -outputPurge() -{ - (void) ttyflush(1); -} - - -/* - * The following routines are places where the various tn3270 - * routines make calls into telnet.c. - */ - -/* - * DataToTerminal - queue up some data to go to terminal. - * - * Note: there are people who call us and depend on our processing - * *all* the data at one time (thus the select). - */ - - int -DataToTerminal(buffer, count) - register char *buffer; /* where the data is */ - register int count; /* how much to send */ -{ - register int c; - int origCount; - - origCount = count; - - while (count) { - if (TTYROOM() == 0) { -#if defined(unix) - fd_set o; - - FD_ZERO(&o); -#endif /* defined(unix) */ - (void) ttyflush(0); - while (TTYROOM() == 0) { -#if defined(unix) - FD_SET(tout, &o); - (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, - (struct timeval *) 0); -#endif /* defined(unix) */ - (void) ttyflush(0); - } - } - c = TTYROOM(); - if (c > count) { - c = count; - } - ring_supply_data(&ttyoring, buffer, c); - count -= c; - buffer += c; - } - return(origCount); -} - - -/* - * Push3270 - Try to send data along the 3270 output (to screen) direction. - */ - - int -Push3270() -{ - int save = ring_full_count(&netiring); - - if (save) { - if (Ifrontp+save > Ibuf+sizeof Ibuf) { - if (Ibackp != Ibuf) { - memmove(Ibuf, Ibackp, Ifrontp-Ibackp); - Ifrontp -= (Ibackp-Ibuf); - Ibackp = Ibuf; - } - } - if (Ifrontp+save < Ibuf+sizeof Ibuf) { - (void)telrcv(); - } - } - return save != ring_full_count(&netiring); -} - - -/* - * Finish3270 - get the last dregs of 3270 data out to the terminal - * before quitting. - */ - - void -Finish3270() -{ - while (Push3270() || !DoTerminalOutput()) { -#if defined(unix) - HaveInput = 0; -#endif /* defined(unix) */ - ; - } -} - - -/* StringToTerminal - output a null terminated string to the terminal */ - - void -StringToTerminal(s) - char *s; -{ - int count; - - count = strlen(s); - if (count) { - (void) DataToTerminal(s, count); /* we know it always goes... */ - } -} - - -#if ((!defined(NOT43)) || defined(PUTCHAR)) -/* _putchar - output a single character to the terminal. This name is so that - * curses(3x) can call us to send out data. - */ - - void -_putchar(c) - char c; -{ -#if defined(sun) /* SunOS 4.0 bug */ - c &= 0x7f; -#endif /* defined(sun) */ - if (cursesdata) { - Dump('>', &c, 1); - } - if (!TTYROOM()) { - (void) DataToTerminal(&c, 1); - } else { - TTYADD(c); - } -} -#endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ - - void -SetIn3270() -{ - if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY) - && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) { - if (!In3270) { - In3270 = 1; - Init3270(); /* Initialize 3270 functions */ - /* initialize terminal key mapping */ - InitTerminal(); /* Start terminal going */ - setconnmode(0); - } - } else { - if (In3270) { - StopScreen(1); - In3270 = 0; - Stop3270(); /* Tell 3270 we aren't here anymore */ - setconnmode(0); - } - } -} - -/* - * tn3270_ttype() - * - * Send a response to a terminal type negotiation. - * - * Return '0' if no more responses to send; '1' if a response sent. - */ - - int -tn3270_ttype() -{ - /* - * Try to send a 3270 type terminal name. Decide which one based - * on the format of our screen, and (in the future) color - * capaiblities. - */ - InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ - if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { - Sent3270TerminalType = 1; - if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { - MaxNumberLines = 27; - MaxNumberColumns = 132; - sb_terminal[SBTERMMODEL] = '5'; - } else if (MaxNumberLines >= 43) { - MaxNumberLines = 43; - MaxNumberColumns = 80; - sb_terminal[SBTERMMODEL] = '4'; - } else if (MaxNumberLines >= 32) { - MaxNumberLines = 32; - MaxNumberColumns = 80; - sb_terminal[SBTERMMODEL] = '3'; - } else { - MaxNumberLines = 24; - MaxNumberColumns = 80; - sb_terminal[SBTERMMODEL] = '2'; - } - NumberLines = 24; /* before we start out... */ - NumberColumns = 80; - ScreenSize = NumberLines*NumberColumns; - if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { - ExitString("Programming error: MAXSCREENSIZE too small.\n", - 1); - /*NOTREACHED*/ - } - printsub('>', sb_terminal+2, sizeof sb_terminal-2); - ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); - return 1; - } else { - return 0; - } -} - -#if defined(unix) - int -settranscom(argc, argv) - int argc; - char *argv[]; -{ - int i; - - if (argc == 1 && transcom) { - transcom = 0; - } - if (argc == 1) { - return 1; - } - transcom = tline; - (void) strcpy(transcom, argv[1]); - for (i = 2; i < argc; ++i) { - (void) strcat(transcom, " "); - (void) strcat(transcom, argv[i]); - } - return 1; -} -#endif /* defined(unix) */ - -#endif /* defined(TN3270) */ Property changes on: head/crypto/telnet/telnet/tn3270.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/crypto/telnet/telnet/authenc.c =================================================================== --- head/crypto/telnet/telnet/authenc.c (revision 87138) +++ head/crypto/telnet/telnet/authenc.c (revision 87139) @@ -1,116 +1,111 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)authenc.c 8.1 (Berkeley) 6/6/93"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION #include #include +#include +#include #include #include #include "general.h" #include "ring.h" #include "externs.h" #include "defines.h" #include "types.h" - int -net_write(str, len) - unsigned char *str; - int len; +int +net_write(unsigned char *str, int len) { if (NETROOM() > len) { ring_supply_data(&netoring, str, len); if (str[0] == IAC && str[1] == SE) printsub('>', &str[2], len-2); return(len); } return(0); } - void -net_encrypt() +void +net_encrypt(void) { #ifdef ENCRYPTION if (encrypt_output) ring_encrypt(&netoring, encrypt_output); else ring_clearto(&netoring); #endif /* ENCRYPTION */ } - int -telnet_spin() +int +telnet_spin(void) { return(-1); } - char * -telnet_getenv(val) - char *val; +char * +telnet_getenv(char *val) { return((char *)env_getvalue((unsigned char *)val)); } - char * -telnet_gets(prompt, result, length, echo) - char *prompt; - char *result; - int length; - int echo; +char * +telnet_gets(const char *prom, char *result, int length, int echo) { - extern char *getpass(); extern int globalmode; int om = globalmode; char *res; TerminalNewMode(-1); if (echo) { - printf("%s", prompt); + printf("%s", prom); res = fgets(result, length, stdin); - } else if ((res = getpass(prompt))) { + } else if ((res = getpass(prom))) { strncpy(result, res, length); res = result; } TerminalNewMode(om); return(res); } -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif /* ENCRYPTION */ +#endif /* AUTHENTICATION */ Index: head/crypto/telnet/telnet/commands.c =================================================================== --- head/crypto/telnet/telnet/commands.c (revision 87138) +++ head/crypto/telnet/telnet/commands.c (revision 87139) @@ -1,3225 +1,3005 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint static const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95"; -#endif /* not lint */ +#endif -#if defined(unix) #include #include #include -#else -#include -#endif /* defined(unix) */ #include #include -#include -#include -#include #include -#include -#include +#include #include -#include +#include +#include +#include +#include #include +#include +#include #include #include #include "general.h" #include "ring.h" #include "externs.h" #include "defines.h" #include "types.h" +#include "misc.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif #include -# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) -# include -# endif /* vax */ #include #include #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif MAXHOSTNAMELEN +typedef int (*intrtn_t)(int, char **); + +#ifdef AUTHENTICATION +extern int auth_togdebug P((int)); +#endif +#ifdef ENCRYPTION +extern int EncryptAutoEnc P((int)); +extern int EncryptAutoDec P((int)); +extern int EncryptDebug P((int)); +extern int EncryptVerbose P((int)); +#endif /* ENCRYPTION */ #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ char *hostname; static char _hostname[MAXHOSTNAMELEN]; -extern char *getenv(); +static int help(int, char **); +static int call(intrtn_t, ...); +static void cmdrc(char *, char *); +static int switch_af(struct addrinfo **); +static int togglehelp(void); +static int send_tncmd(void (*)(int, int), const char *, char *); +static int setmod(int); +static int clearmode(int); +static int modehelp(void); +static int sourceroute(struct addrinfo *, char *, char **, int *, int *, int *); -extern int isprefix(); -extern char **genget(); -extern int Ambiguous(); - -static int help(int argc, char *argv[]); -static int call(); -static void cmdrc(char *m1, char *m2); -static int switch_af(struct addrinfo **aip); -int quit(void); - typedef struct { - char *name; /* command name */ - char *help; /* help string (NULL for no help) */ - int (*handler)(); /* routine which executes command */ + const char *name; /* command name */ + const char *help; /* help string (NULL for no help) */ + int (*handler)(int, char **); /* routine which executes command */ int needconnect; /* Do we need to be connected to execute? */ } Command; static char line[256]; static char saveline[256]; static int margc; static char *margv[20]; -#if defined(OPIE) +#ifdef OPIE #include #define PATH_OPIEKEY "/usr/bin/opiekey" - int -opie_calc(argc, argv) - int argc; - char **argv; +static int +opie_calc(int argc, char *argv[]) { int status; if(argc != 3) { printf("%s sequence challenge\n", argv[0]); - return; + return (0); } switch(fork()) { case 0: execv(PATH_OPIEKEY, argv); exit (1); case -1: perror("fork"); break; default: (void) wait(&status); if (WIFEXITED(status)) return (WEXITSTATUS(status)); - return (0); } + return (0); } #endif - static void -makeargv() +static void +makeargv(void) { - register char *cp, *cp2, c; - register char **argp = margv; + char *cp, *cp2, c; + char **argp = margv; margc = 0; cp = line; if (*cp == '!') { /* Special case shell escape */ strcpy(saveline, line); /* save for shell command */ - *argp++ = "!"; /* No room in string to get this */ + *argp++ = strdup("!"); /* No room in string to get this */ margc++; cp++; } while ((c = *cp)) { - register int inquote = 0; + int inquote = 0; while (isspace(c)) c = *++cp; if (c == '\0') break; *argp++ = cp; margc += 1; for (cp2 = cp; c != '\0'; c = *++cp) { if (inquote) { if (c == inquote) { inquote = 0; continue; } } else { if (c == '\\') { if ((c = *++cp) == '\0') break; } else if (c == '"') { inquote = '"'; continue; } else if (c == '\'') { inquote = '\''; continue; } else if (isspace(c)) break; } *cp2++ = c; } *cp2 = '\0'; if (c == '\0') break; cp++; } *argp++ = 0; } /* * Make a character string into a number. * * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). */ - static int -special(s) - register char *s; +static int +special(char *s) { - register char c; + char c; char b; switch (*s) { case '^': b = *++s; if (b == '?') { c = b | 0x40; /* DEL */ } else { c = b & 0x1f; } break; default: c = *s; break; } return c; } /* * Construct a control character sequence * for a special character. */ - static char * -control(c) - register cc_t c; +static const char * +control(cc_t c) { static char buf[5]; /* * The only way I could get the Sun 3.5 compiler * to shut up about * if ((unsigned int)c >= 0x80) * was to assign "c" to an unsigned int variable... * Arggg.... */ - register unsigned int uic = (unsigned int)c; + unsigned int uic = (unsigned int)c; if (uic == 0x7f) return ("^?"); if (c == (cc_t)_POSIX_VDISABLE) { return "off"; } if (uic >= 0x80) { buf[0] = '\\'; buf[1] = ((c>>6)&07) + '0'; buf[2] = ((c>>3)&07) + '0'; buf[3] = (c&07) + '0'; buf[4] = 0; } else if (uic >= 0x20) { buf[0] = c; buf[1] = 0; } else { buf[0] = '^'; buf[1] = '@'+c; buf[2] = 0; } return (buf); } - - /* * The following are data structures and routines for * the "send" command. * */ struct sendlist { - char *name; /* How user refers to it (case independent) */ - char *help; /* Help information (0 ==> no help) */ + const char *name; /* How user refers to it (case independent) */ + const char *help; /* Help information (0 ==> no help) */ int needconnect; /* Need to be connected */ int narg; /* Number of arguments */ - int (*handler)(); /* Routine to perform (for special ops) */ + int (*handler)(char *, ...); /* Routine to perform (for special ops) */ int nbyte; /* Number of bytes to send this command */ int what; /* Character to be sent (<0 ==> special) */ }; static int send_esc P((void)), send_help P((void)), send_docmd P((char *)), send_dontcmd P((char *)), send_willcmd P((char *)), send_wontcmd P((char *)); static struct sendlist Sendlist[] = { - { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, - { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, - { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, - { "break", 0, 1, 0, 0, 2, BREAK }, - { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, - { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, - { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, - { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, - { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, - { "intp", 0, 1, 0, 0, 2, IP }, - { "interrupt", 0, 1, 0, 0, 2, IP }, - { "intr", 0, 1, 0, 0, 2, IP }, - { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, - { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, - { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, - { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, - { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, - { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, - { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, - { "?", "Display send options", 0, 0, send_help, 0, 0 }, - { "help", 0, 0, 0, send_help, 0, 0 }, - { "do", 0, 0, 1, send_docmd, 3, 0 }, - { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, - { "will", 0, 0, 1, send_willcmd, 3, 0 }, - { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, - { 0 } + { "ao", "Send Telnet Abort output", 1, 0, NULL, 2, AO }, + { "ayt", "Send Telnet 'Are You There'", 1, 0, NULL, 2, AYT }, + { "brk", "Send Telnet Break", 1, 0, NULL, 2, BREAK }, + { "break", NULL, 1, 0, NULL, 2, BREAK }, + { "ec", "Send Telnet Erase Character", 1, 0, NULL, 2, EC }, + { "el", "Send Telnet Erase Line", 1, 0, NULL, 2, EL }, + { "escape", "Send current escape character",1, 0, (int (*)(char *, ...))send_esc, 1, 0 }, + { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, NULL, 2, GA }, + { "ip", "Send Telnet Interrupt Process",1, 0, NULL, 2, IP }, + { "intp", NULL, 1, 0, NULL, 2, IP }, + { "interrupt", NULL, 1, 0, NULL, 2, IP }, + { "intr", NULL, 1, 0, NULL, 2, IP }, + { "nop", "Send Telnet 'No operation'", 1, 0, NULL, 2, NOP }, + { "eor", "Send Telnet 'End of Record'", 1, 0, NULL, 2, EOR }, + { "abort", "Send Telnet 'Abort Process'", 1, 0, NULL, 2, ABORT }, + { "susp", "Send Telnet 'Suspend Process'",1, 0, NULL, 2, SUSP }, + { "eof", "Send Telnet End of File Character", 1, 0, NULL, 2, xEOF }, + { "synch", "Perform Telnet 'Synch operation'", 1, 0, (int (*)(char *, ...))dosynch, 2, 0 }, + { "getstatus", "Send request for STATUS", 1, 0, (int (*)(char *, ...))get_status, 6, 0 }, + { "?", "Display send options", 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, + { "help", NULL, 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, + { "do", NULL, 0, 1, (int (*)(char *, ...))send_docmd, 3, 0 }, + { "dont", NULL, 0, 1, (int (*)(char *, ...))send_dontcmd, 3, 0 }, + { "will", NULL, 0, 1, (int (*)(char *, ...))send_willcmd, 3, 0 }, + { "wont", NULL, 0, 1, (int (*)(char *, ...))send_wontcmd, 3, 0 }, + { NULL, NULL, 0, 0, NULL, 0, 0 } }; #define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ sizeof(struct sendlist))) - static int -sendcmd(argc, argv) - int argc; - char **argv; +static int +sendcmd(int argc, char *argv[]) { int count; /* how many bytes we are going to need to send */ int i; struct sendlist *s; /* pointer to current command */ int success = 0; int needconnect = 0; if (argc < 2) { printf("need at least one argument for 'send' command\n"); printf("'send ?' for help\n"); return 0; } /* * First, validate all the send arguments. * In addition, we see how much space we are going to need, and * whether or not we will be doing a "SYNCH" operation (which * flushes the network queue). */ count = 0; for (i = 1; i < argc; i++) { s = GETSEND(argv[i]); if (s == 0) { printf("Unknown send argument '%s'\n'send ?' for help.\n", argv[i]); return 0; - } else if (Ambiguous(s)) { + } else if (Ambiguous((void *)s)) { printf("Ambiguous send argument '%s'\n'send ?' for help.\n", argv[i]); return 0; } if (i + s->narg >= argc) { fprintf(stderr, "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", s->narg, s->narg == 1 ? "" : "s", s->name, s->name); return 0; } count += s->nbyte; - if (s->handler == send_help) { + if ((void *)s->handler == (void *)send_help) { send_help(); return 0; } i += s->narg; needconnect += s->needconnect; } if (!connected && needconnect) { printf("?Need to be connected first.\n"); printf("'send ?' for help\n"); return 0; } /* Now, do we have enough room? */ if (NETROOM() < count) { printf("There is not enough room in the buffer TO the network\n"); printf("to process your request. Nothing will be done.\n"); printf("('send synch' will throw away most data in the network\n"); printf("buffer, if this might help.)\n"); return 0; } /* OK, they are all OK, now go through again and actually send */ count = 0; for (i = 1; i < argc; i++) { if ((s = GETSEND(argv[i])) == 0) { fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); - (void) quit(); + quit(); /*NOTREACHED*/ } if (s->handler) { count++; success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, (s->narg > 1) ? argv[i+2] : 0); i += s->narg; } else { NET2ADD(IAC, s->what); printoption("SENT", IAC, s->what); } } return (count == success); } - static int -send_esc() +static int +send_esc(void) { NETADD(escape); return 1; } - static int -send_docmd(name) - char *name; +static int +send_docmd(char *name) { return(send_tncmd(send_do, "do", name)); } - static int +static int send_dontcmd(name) char *name; { return(send_tncmd(send_dont, "dont", name)); } - static int -send_willcmd(name) - char *name; + +static int +send_willcmd(char *name) { return(send_tncmd(send_will, "will", name)); } - static int -send_wontcmd(name) - char *name; + +static int +send_wontcmd(char *name) { return(send_tncmd(send_wont, "wont", name)); } - int -send_tncmd(func, cmd, name) - void (*func)(); - char *cmd, *name; +static int +send_tncmd(void (*func)(int, int), const char *cmd, char *name) { char **cpp; extern char *telopts[]; - register int val = 0; + int val = 0; if (isprefix(name, "help") || isprefix(name, "?")) { - register int col, len; + int col, len; printf("Usage: send %s \n", cmd); printf("\"value\" must be from 0 to 255\n"); printf("Valid options are:\n\t"); col = 8; for (cpp = telopts; *cpp; cpp++) { len = strlen(*cpp) + 3; if (col + len > 65) { printf("\n\t"); col = 8; } printf(" \"%s\"", *cpp); col += len; } printf("\n"); return 0; } cpp = (char **)genget(name, telopts, sizeof(char *)); if (Ambiguous(cpp)) { fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", name, cmd); return 0; } if (cpp) { val = cpp - telopts; } else { - register char *cp = name; + char *cp = name; while (*cp >= '0' && *cp <= '9') { val *= 10; val += *cp - '0'; cp++; } if (*cp != 0) { fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", name, cmd); return 0; } else if (val < 0 || val > 255) { fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", name, cmd); return 0; } } if (!connected) { printf("?Need to be connected first.\n"); return 0; } (*func)(val, 1); return 1; } - static int -send_help() +static int +send_help(void) { struct sendlist *s; /* pointer to current command */ for (s = Sendlist; s->name; s++) { if (s->help) printf("%-15s %s\n", s->name, s->help); } return(0); } /* * The following are the routines and data structures referred * to by the arguments to the "toggle" command. */ - static int -lclchars() +static int +lclchars(void) { donelclchars = 1; return 1; } - static int -togdebug() +static int +togdebug(void) { #ifndef NOT43 if (net > 0 && (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { perror("setsockopt (SO_DEBUG)"); } #else /* NOT43 */ if (debug) { if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) perror("setsockopt (SO_DEBUG)"); } else printf("Cannot turn off socket debugging\n"); #endif /* NOT43 */ return 1; } - static int -togcrlf() +static int +togcrlf(void) { if (crlf) { printf("Will send carriage returns as telnet .\n"); } else { printf("Will send carriage returns as telnet .\n"); } return 1; } int binmode; - static int -togbinary(val) - int val; +static int +togbinary(int val) { donebinarytoggle = 1; if (val >= 0) { binmode = val; } else { if (my_want_state_is_will(TELOPT_BINARY) && my_want_state_is_do(TELOPT_BINARY)) { binmode = 1; } else if (my_want_state_is_wont(TELOPT_BINARY) && my_want_state_is_dont(TELOPT_BINARY)) { binmode = 0; } val = binmode ? 0 : 1; } if (val == 1) { if (my_want_state_is_will(TELOPT_BINARY) && my_want_state_is_do(TELOPT_BINARY)) { printf("Already operating in binary mode with remote host.\n"); } else { printf("Negotiating binary mode with remote host.\n"); tel_enter_binary(3); } } else { if (my_want_state_is_wont(TELOPT_BINARY) && my_want_state_is_dont(TELOPT_BINARY)) { printf("Already in network ascii mode with remote host.\n"); } else { printf("Negotiating network ascii mode with remote host.\n"); tel_leave_binary(3); } } return 1; } - static int -togrbinary(val) - int val; +static int +togrbinary(int val) { donebinarytoggle = 1; if (val == -1) val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; if (val == 1) { if (my_want_state_is_do(TELOPT_BINARY)) { printf("Already receiving in binary mode.\n"); } else { printf("Negotiating binary mode on input.\n"); tel_enter_binary(1); } } else { if (my_want_state_is_dont(TELOPT_BINARY)) { printf("Already receiving in network ascii mode.\n"); } else { printf("Negotiating network ascii mode on input.\n"); tel_leave_binary(1); } } return 1; } - static int -togxbinary(val) - int val; +static int +togxbinary(int val) { donebinarytoggle = 1; if (val == -1) val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; if (val == 1) { if (my_want_state_is_will(TELOPT_BINARY)) { printf("Already transmitting in binary mode.\n"); } else { printf("Negotiating binary mode on output.\n"); tel_enter_binary(2); } } else { if (my_want_state_is_wont(TELOPT_BINARY)) { printf("Already transmitting in network ascii mode.\n"); } else { printf("Negotiating network ascii mode on output.\n"); tel_leave_binary(2); } } return 1; } - -static int togglehelp P((void)); -#if defined(AUTHENTICATION) -extern int auth_togdebug P((int)); -#endif -#ifdef ENCRYPTION -extern int EncryptAutoEnc P((int)); -extern int EncryptAutoDec P((int)); -extern int EncryptDebug P((int)); -extern int EncryptVerbose P((int)); -#endif /* ENCRYPTION */ - struct togglelist { - char *name; /* name of toggle */ - char *help; /* help message */ - int (*handler)(); /* routine to do actual setting */ + const char *name; /* name of toggle */ + const char *help; /* help message */ + int (*handler)(int); /* routine to do actual setting */ int *variable; - char *actionexplanation; + const char *actionexplanation; }; static struct togglelist Togglelist[] = { { "autoflush", "flushing of output when sending interrupt characters", 0, &autoflush, "flush output when sending interrupt characters" }, { "autosynch", "automatic sending of interrupt characters in urgent mode", 0, &autosynch, "send interrupt characters in urgent mode" }, -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION { "autologin", "automatic sending of login and/or authentication info", 0, &autologin, "send login name and/or authentication information" }, { "authdebug", "Toggle authentication debugging", auth_togdebug, 0, "print authentication debugging information" }, #endif #ifdef ENCRYPTION { "autoencrypt", "automatic encryption of data stream", EncryptAutoEnc, 0, "automatically encrypt output" }, { "autodecrypt", "automatic decryption of data stream", EncryptAutoDec, 0, "automatically decrypt input" }, { "verbose_encrypt", "Toggle verbose encryption output", EncryptVerbose, 0, "print verbose encryption output" }, { "encdebug", "Toggle encryption debugging", EncryptDebug, 0, "print encryption debugging information" }, #endif /* ENCRYPTION */ { "skiprc", "don't read ~/.telnetrc file", 0, &skiprc, "skip reading of ~/.telnetrc file" }, { "binary", "sending and receiving of binary data", togbinary, 0, 0 }, { "inbinary", "receiving of binary data", togrbinary, 0, 0 }, { "outbinary", "sending of binary data", togxbinary, 0, 0 }, { "crlf", "sending carriage returns as telnet ", - togcrlf, + (int (*)(int))togcrlf, &crlf, 0 }, { "crmod", "mapping of received carriage returns", 0, &crmod, "map carriage return on output" }, { "localchars", "local recognition of certain control characters", - lclchars, + (int (*)(int))lclchars, &localchars, "recognize certain control characters" }, - { " ", "", 0 }, /* empty line */ -#if defined(unix) && defined(TN3270) - { "apitrace", - "(debugging) toggle tracing of API transactions", - 0, - &apitrace, - "trace API transactions" }, - { "cursesdata", - "(debugging) toggle printing of hexadecimal curses data", - 0, - &cursesdata, - "print hexadecimal representation of curses data" }, -#endif /* defined(unix) && defined(TN3270) */ + { " ", "", NULL, NULL, NULL }, /* empty line */ { "debug", "debugging", - togdebug, + (int (*)(int))togdebug, &debug, "turn on socket level debugging" }, { "netdata", "printing of hexadecimal network data (debugging)", 0, &netdata, "print hexadecimal representation of network traffic" }, { "prettydump", "output of \"netdata\" to user readable format (debugging)", 0, &prettydump, "print user readable output for \"netdata\"" }, { "options", "viewing of options processing (debugging)", 0, &showoptions, "show option processing" }, -#if defined(unix) { "termdata", "(debugging) toggle printing of hexadecimal terminal data", 0, &termdata, "print hexadecimal representation of terminal traffic" }, -#endif /* defined(unix) */ { "?", - 0, - togglehelp }, + NULL, + (int (*)(int))togglehelp, + NULL, + NULL }, + { NULL, NULL, NULL, NULL, NULL }, { "help", - 0, - togglehelp }, - { 0 } + NULL, + (int (*)(int))togglehelp, + NULL, + NULL }, + { NULL, NULL, NULL, NULL, NULL } }; - static int -togglehelp() +static int +togglehelp(void) { struct togglelist *c; for (c = Togglelist; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s toggle %s\n", c->name, c->help); else printf("\n"); } } printf("\n"); printf("%-15s %s\n", "?", "display help information"); return 0; } - static void -settogglehelp(set) - int set; +static void +settogglehelp(int set) { struct togglelist *c; for (c = Togglelist; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", c->help); else printf("\n"); } } } #define GETTOGGLE(name) (struct togglelist *) \ genget(name, (char **) Togglelist, sizeof(struct togglelist)) - static int -toggle(argc, argv) - int argc; - char *argv[]; +static int +toggle(int argc, char *argv[]) { int retval = 1; char *name; struct togglelist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); return 0; } argc--; argv++; while (argc--) { name = *argv++; c = GETTOGGLE(name); - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", name); return 0; } else if (c == 0) { fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", name); return 0; } else { if (c->variable) { *c->variable = !*c->variable; /* invert it */ if (c->actionexplanation) { printf("%s %s.\n", *c->variable? "Will" : "Won't", c->actionexplanation); } } if (c->handler) { retval &= (*c->handler)(-1); } } } return retval; } /* * The following perform the "set" command. */ #ifdef USE_TERMIO -struct termio new_tc = { 0 }; +struct termio new_tc = { 0, 0, 0, 0, {}, 0, 0 }; #endif struct setlist { - char *name; /* name */ - char *help; /* help information */ - void (*handler)(); + const char *name; /* name */ + const char *help; /* help information */ + void (*handler)(char *); cc_t *charp; /* where it is located at */ }; static struct setlist Setlist[] = { #ifdef KLUDGELINEMODE - { "echo", "character to toggle local echoing on/off", 0, &echoc }, + { "echo", "character to toggle local echoing on/off", NULL, &echoc }, #endif - { "escape", "character to escape back to telnet command mode", 0, &escape }, + { "escape", "character to escape back to telnet command mode", NULL, &escape }, { "rlogin", "rlogin escape character", 0, &rlogin }, { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, - { " ", "" }, - { " ", "The following need 'localchars' to be toggled true", 0, 0 }, - { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp }, - { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, - { "quit", "character to cause an Abort process", 0, termQuitCharp }, - { "eof", "character to cause an EOF ", 0, termEofCharp }, - { " ", "" }, - { " ", "The following are for local editing in linemode", 0, 0 }, - { "erase", "character to use to erase a character", 0, termEraseCharp }, - { "kill", "character to use to erase a line", 0, termKillCharp }, - { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, - { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, - { "reprint", "character to use for line reprint", 0, termRprntCharp }, - { "worderase", "character to use to erase a word", 0, termWerasCharp }, - { "start", "character to use for XON", 0, termStartCharp }, - { "stop", "character to use for XOFF", 0, termStopCharp }, - { "forw1", "alternate end of line character", 0, termForw1Charp }, - { "forw2", "alternate end of line character", 0, termForw2Charp }, - { "ayt", "alternate AYT character", 0, termAytCharp }, - { 0 } + { " ", "", NULL, NULL }, + { " ", "The following need 'localchars' to be toggled true", NULL, NULL }, + { "flushoutput", "character to cause an Abort Output", NULL, termFlushCharp }, + { "interrupt", "character to cause an Interrupt Process", NULL, termIntCharp }, + { "quit", "character to cause an Abort process", NULL, termQuitCharp }, + { "eof", "character to cause an EOF ", NULL, termEofCharp }, + { " ", "", NULL, NULL }, + { " ", "The following are for local editing in linemode", NULL, NULL }, + { "erase", "character to use to erase a character", NULL, termEraseCharp }, + { "kill", "character to use to erase a line", NULL, termKillCharp }, + { "lnext", "character to use for literal next", NULL, termLiteralNextCharp }, + { "susp", "character to cause a Suspend Process", NULL, termSuspCharp }, + { "reprint", "character to use for line reprint", NULL, termRprntCharp }, + { "worderase", "character to use to erase a word", NULL, termWerasCharp }, + { "start", "character to use for XON", NULL, termStartCharp }, + { "stop", "character to use for XOFF", NULL, termStopCharp }, + { "forw1", "alternate end of line character", NULL, termForw1Charp }, + { "forw2", "alternate end of line character", NULL, termForw2Charp }, + { "ayt", "alternate AYT character", NULL, termAytCharp }, + { NULL, NULL, NULL, NULL } }; - static struct setlist * -getset(name) - char *name; +static struct setlist * +getset(char *name) { return (struct setlist *) genget(name, (char **) Setlist, sizeof(struct setlist)); } - void -set_escape_char(s) - char *s; +void +set_escape_char(char *s) { if (rlogin != _POSIX_VDISABLE) { rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; printf("Telnet rlogin escape character is '%s'.\n", control(rlogin)); } else { escape = (s && *s) ? special(s) : _POSIX_VDISABLE; printf("Telnet escape character is '%s'.\n", control(escape)); } } - static int -setcmd(argc, argv) - int argc; - char *argv[]; +static int +setcmd(int argc, char *argv[]) { int value; struct setlist *ct; struct togglelist *c; if (argc < 2 || argc > 3) { printf("Format is 'set Name Value'\n'set ?' for help.\n"); return 0; } if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { for (ct = Setlist; ct->name; ct++) printf("%-15s %s\n", ct->name, ct->help); printf("\n"); settogglehelp(1); printf("%-15s %s\n", "?", "display help information"); return 0; } ct = getset(argv[1]); if (ct == 0) { c = GETTOGGLE(argv[1]); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", argv[1]); return 0; - } else if (Ambiguous(c)) { + } else if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); return 0; } if (c->variable) { if ((argc == 2) || (strcmp("on", argv[2]) == 0)) *c->variable = 1; else if (strcmp("off", argv[2]) == 0) *c->variable = 0; else { printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); return 0; } if (c->actionexplanation) { printf("%s %s.\n", *c->variable? "Will" : "Won't", c->actionexplanation); } } if (c->handler) (*c->handler)(1); } else if (argc != 3) { printf("Format is 'set Name Value'\n'set ?' for help.\n"); return 0; - } else if (Ambiguous(ct)) { + } else if (Ambiguous((void *)ct)) { fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); return 0; } else if (ct->handler) { (*ct->handler)(argv[2]); printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); } else { if (strcmp("off", argv[2])) { value = special(argv[2]); } else { value = _POSIX_VDISABLE; } *(ct->charp) = (cc_t)value; printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); } slc_check(); return 1; } - static int -unsetcmd(argc, argv) - int argc; - char *argv[]; +static int +unsetcmd(int argc, char *argv[]) { struct setlist *ct; struct togglelist *c; - register char *name; + char *name; if (argc < 2) { fprintf(stderr, "Need an argument to 'unset' command. 'unset ?' for help.\n"); return 0; } if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { for (ct = Setlist; ct->name; ct++) printf("%-15s %s\n", ct->name, ct->help); printf("\n"); settogglehelp(0); printf("%-15s %s\n", "?", "display help information"); return 0; } argc--; argv++; while (argc--) { name = *argv++; ct = getset(name); if (ct == 0) { c = GETTOGGLE(name); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", name); return 0; - } else if (Ambiguous(c)) { + } else if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", name); return 0; } if (c->variable) { *c->variable = 0; if (c->actionexplanation) { printf("%s %s.\n", *c->variable? "Will" : "Won't", c->actionexplanation); } } if (c->handler) (*c->handler)(0); - } else if (Ambiguous(ct)) { + } else if (Ambiguous((void *)ct)) { fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", name); return 0; } else if (ct->handler) { (*ct->handler)(0); printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); } else { *(ct->charp) = _POSIX_VDISABLE; printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); } } return 1; } /* * The following are the data structures and routines for the * 'mode' command. */ #ifdef KLUDGELINEMODE extern int kludgelinemode; - static int -dokludgemode() +static int +dokludgemode(void) { kludgelinemode = 1; send_wont(TELOPT_LINEMODE, 1); send_dont(TELOPT_SGA, 1); send_dont(TELOPT_ECHO, 1); return 1; } #endif - static int -dolinemode() +static int +dolinemode(void) { #ifdef KLUDGELINEMODE if (kludgelinemode) send_dont(TELOPT_SGA, 1); #endif send_will(TELOPT_LINEMODE, 1); send_dont(TELOPT_ECHO, 1); return 1; } - static int -docharmode() +static int +docharmode(void) { #ifdef KLUDGELINEMODE if (kludgelinemode) send_do(TELOPT_SGA, 1); else #endif send_wont(TELOPT_LINEMODE, 1); send_do(TELOPT_ECHO, 1); return 1; } - static int -dolmmode(bit, on) - int bit, on; +static int +dolmmode(int bit, int on) { unsigned char c; extern int linemode; if (my_want_state_is_wont(TELOPT_LINEMODE)) { printf("?Need to have LINEMODE option enabled first.\n"); printf("'mode ?' for help.\n"); return 0; } if (on) c = (linemode | bit); else c = (linemode & ~bit); lm_mode(&c, 1, 1); return 1; } - int -setmod(bit) +static int +setmod(int bit) { return dolmmode(bit, 1); } - int -clearmode(bit) +static int +clearmode(int bit) { return dolmmode(bit, 0); } struct modelist { - char *name; /* command name */ - char *help; /* help string */ - int (*handler)(); /* routine which executes command */ + const char *name; /* command name */ + const char *help; /* help string */ + int (*handler)(int);/* routine which executes command */ int needconnect; /* Do we need to be connected to execute? */ int arg1; }; -extern int modehelp(); - static struct modelist ModeList[] = { - { "character", "Disable LINEMODE option", docharmode, 1 }, + { "character", "Disable LINEMODE option", (int (*)(int))docharmode, 1, 0 }, #ifdef KLUDGELINEMODE - { "", "(or disable obsolete line-by-line mode)", 0 }, + { "", "(or disable obsolete line-by-line mode)", NULL, 0, 0 }, #endif - { "line", "Enable LINEMODE option", dolinemode, 1 }, + { "line", "Enable LINEMODE option", (int (*)(int))dolinemode, 1, 0 }, #ifdef KLUDGELINEMODE - { "", "(or enable obsolete line-by-line mode)", 0 }, + { "", "(or enable obsolete line-by-line mode)", NULL, 0, 0 }, #endif - { "", "", 0 }, - { "", "These require the LINEMODE option to be enabled", 0 }, + { "", "", NULL, 0, 0 }, + { "", "These require the LINEMODE option to be enabled", NULL, 0, 0 }, { "isig", "Enable signal trapping", setmod, 1, MODE_TRAPSIG }, { "+isig", 0, setmod, 1, MODE_TRAPSIG }, { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, { "edit", "Enable character editing", setmod, 1, MODE_EDIT }, { "+edit", 0, setmod, 1, MODE_EDIT }, { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, { "softtabs", "Enable tab expansion", setmod, 1, MODE_SOFT_TAB }, { "+softtabs", 0, setmod, 1, MODE_SOFT_TAB }, { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO }, { "+litecho", 0, setmod, 1, MODE_LIT_ECHO }, { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, - { "help", 0, modehelp, 0 }, + { "help", 0, (int (*)(int))modehelp, 0, 0 }, #ifdef KLUDGELINEMODE - { "kludgeline", 0, dokludgemode, 1 }, + { "kludgeline", 0, (int (*)(int))dokludgemode, 1, 0 }, #endif - { "", "", 0 }, - { "?", "Print help information", modehelp, 0 }, - { 0 }, + { "", "", NULL, 0, 0 }, + { "?", "Print help information", (int (*)(int))modehelp, 0, 0 }, + { NULL, NULL, NULL, 0, 0 }, }; - int -modehelp() +static int +modehelp(void) { struct modelist *mt; printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); for (mt = ModeList; mt->name; mt++) { if (mt->help) { if (*mt->help) printf("%-15s %s\n", mt->name, mt->help); else printf("\n"); } } return 0; } #define GETMODECMD(name) (struct modelist *) \ genget(name, (char **) ModeList, sizeof(struct modelist)) - static int -modecmd(argc, argv) - int argc; - char *argv[]; +static int +modecmd(int argc, char *argv[]) { struct modelist *mt; if (argc != 2) { printf("'mode' command requires an argument\n"); printf("'mode ?' for help.\n"); } else if ((mt = GETMODECMD(argv[1])) == 0) { fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); - } else if (Ambiguous(mt)) { + } else if (Ambiguous((void *)mt)) { fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); } else if (mt->needconnect && !connected) { printf("?Need to be connected first.\n"); printf("'mode ?' for help.\n"); } else if (mt->handler) { return (*mt->handler)(mt->arg1); } return 0; } /* * The following data structures and routines implement the * "display" command. */ - static int -display(argc, argv) - int argc; - char *argv[]; +static int +display(int argc, char *argv[]) { struct togglelist *tl; struct setlist *sl; #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ if (*tl->variable) { \ printf("will"); \ } else { \ printf("won't"); \ } \ printf(" %s.\n", tl->actionexplanation); \ } #define doset(sl) if (sl->name && *sl->name != ' ') { \ if (sl->handler == 0) \ printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ else \ printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ } if (argc == 1) { for (tl = Togglelist; tl->name; tl++) { dotog(tl); } printf("\n"); for (sl = Setlist; sl->name; sl++) { doset(sl); } } else { int i; for (i = 1; i < argc; i++) { sl = getset(argv[i]); tl = GETTOGGLE(argv[i]); - if (Ambiguous(sl) || Ambiguous(tl)) { + if (Ambiguous((void *)sl) || Ambiguous((void *)tl)) { printf("?Ambiguous argument '%s'.\n", argv[i]); return 0; } else if (!sl && !tl) { printf("?Unknown argument '%s'.\n", argv[i]); return 0; } else { if (tl) { dotog(tl); } if (sl) { doset(sl); } } } } /*@*/optionstatus(); #ifdef ENCRYPTION EncryptStatus(); #endif /* ENCRYPTION */ return 1; #undef doset #undef dotog } /* * The following are the data structures, and many of the routines, * relating to command processing. */ /* * Set the escape character. */ - static int -setescape(argc, argv) - int argc; - char *argv[]; +static int +setescape(int argc, char *argv[]) { - register char *arg; + char *arg; char buf[50]; printf( "Deprecated usage - please use 'set escape%s%s' in the future.\n", (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); if (argc > 2) arg = argv[1]; else { printf("new escape character: "); (void) fgets(buf, sizeof(buf), stdin); arg = buf; } if (arg[0] != '\0') escape = arg[0]; - if (!In3270) { - printf("Escape character is '%s'.\n", control(escape)); - } (void) fflush(stdout); return 1; } - /*VARARGS*/ - static int -togcrmod() +static int +togcrmod(void) { crmod = !crmod; printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); (void) fflush(stdout); return 1; } - /*VARARGS*/ - int -suspend() +static int +suspend(void) { #ifdef SIGTSTP setcommandmode(); { - long oldrows, oldcols, newrows, newcols, err; + long oldrows, oldcols, newrows, newcols, err_; - err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; (void) kill(0, SIGTSTP); /* * If we didn't get the window size before the SUSPEND, but we * can get them now (?), then send the NAWS to make sure that * we are set up for the right window size. */ if (TerminalWindowSize(&newrows, &newcols) && connected && - (err || ((oldrows != newrows) || (oldcols != newcols)))) { + (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { sendnaws(); } } /* reget parameters in case they were changed */ TerminalSaveState(); setconnmode(0); #else printf("Suspend is not supported. Try the '!' command instead\n"); #endif return 1; } -#if !defined(TN3270) - /*ARGSUSED*/ - int -shell(argc, argv) - int argc; - char *argv[]; +static int +shell(int argc, char *argv[] __unused) { - long oldrows, oldcols, newrows, newcols, err; + long oldrows, oldcols, newrows, newcols, err_; setcommandmode(); - err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; switch(vfork()) { case -1: perror("Fork failed\n"); break; case 0: { /* * Fire up the shell in the child. */ - register char *shellp, *shellname; + const char *shellp, *shellname; shellp = getenv("SHELL"); if (shellp == NULL) shellp = "/bin/sh"; if ((shellname = strrchr(shellp, '/')) == 0) shellname = shellp; else shellname++; if (argc > 1) execl(shellp, shellname, "-c", &saveline[1], (char *)0); else execl(shellp, shellname, (char *)0); perror("Execl"); _exit(1); } default: (void)wait((int *)0); /* Wait for the shell to complete */ if (TerminalWindowSize(&newrows, &newcols) && connected && - (err || ((oldrows != newrows) || (oldcols != newcols)))) { + (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { sendnaws(); } break; } return 1; } -#else /* !defined(TN3270) */ -extern int shell(); -#endif /* !defined(TN3270) */ - /*VARARGS*/ - static int -bye(argc, argv) - int argc; /* Number of arguments */ - char *argv[]; /* arguments */ +static int +bye(int argc, char *argv[]) { extern int resettermname; if (connected) { (void) shutdown(net, 2); printf("Connection closed.\n"); (void) NetClose(net); connected = 0; resettermname = 1; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION auth_encrypt_connect(connected); -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif +#endif /* reset options */ tninit(); -#if defined(TN3270) - SetIn3270(); /* Get out of 3270 mode */ -#endif /* defined(TN3270) */ } if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { longjmp(toplevel, 1); /* NOTREACHED */ } return 1; /* Keep lint, etc., happy */ } -/*VARARGS*/ - int -quit() +void +quit(void) { (void) call(bye, "bye", "fromquit", 0); Exit(0); - /*NOTREACHED*/ } -/*VARARGS*/ - int -logout() +static int +logout(void) { send_do(TELOPT_LOGOUT, 1); (void) netflush(); return 1; } /* * The SLC command. */ struct slclist { - char *name; - char *help; - void (*handler)(); + const char *name; + const char *help; + void (*handler)(int); int arg; }; -static void slc_help(); +static void slc_help(void); struct slclist SlcList[] = { { "export", "Use local special character definitions", - slc_mode_export, 0 }, + (void (*)(int))slc_mode_export, 0 }, { "import", "Use remote special character definitions", slc_mode_import, 1 }, { "check", "Verify remote special character definitions", slc_mode_import, 0 }, - { "help", 0, slc_help, 0 }, - { "?", "Print help information", slc_help, 0 }, - { 0 }, + { "help", NULL, (void (*)(int))slc_help, 0 }, + { "?", "Print help information", (void (*)(int))slc_help, 0 }, + { NULL, NULL, NULL, 0 }, }; - static void -slc_help() +static void +slc_help(void) { struct slclist *c; for (c = SlcList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } } - static struct slclist * -getslc(name) - char *name; +static struct slclist * +getslc(char *name) { return (struct slclist *) genget(name, (char **) SlcList, sizeof(struct slclist)); } - static int -slccmd(argc, argv) - int argc; - char *argv[]; +static int +slccmd(int argc, char *argv[]) { struct slclist *c; if (argc != 2) { fprintf(stderr, "Need an argument to 'slc' command. 'slc ?' for help.\n"); return 0; } c = getslc(argv[1]); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", argv[1]); return 0; } (*c->handler)(c->arg); slcstate(); return 1; } /* * The ENVIRON command. */ struct envlist { - char *name; - char *help; - void (*handler)(); + const char *name; + const char *help; + void (*handler)(unsigned char *, unsigned char *); int narg; }; extern struct env_lst * - env_define P((unsigned char *, unsigned char *)); + env_define P((const unsigned char *, unsigned char *)); extern void env_undefine P((unsigned char *)), - env_export P((unsigned char *)), - env_unexport P((unsigned char *)), + env_export P((const unsigned char *)), + env_unexport P((const unsigned char *)), env_send P((unsigned char *)), #if defined(OLD_ENVIRON) && defined(ENV_HACK) env_varval P((unsigned char *)), #endif env_list P((void)); static void env_help P((void)); struct envlist EnvList[] = { { "define", "Define an environment variable", - (void (*)())env_define, 2 }, + (void (*)(unsigned char *, unsigned char *))env_define, 2 }, { "undefine", "Undefine an environment variable", - env_undefine, 1 }, + (void (*)(unsigned char *, unsigned char *))env_undefine, 1 }, { "export", "Mark an environment variable for automatic export", - env_export, 1 }, + (void (*)(unsigned char *, unsigned char *))env_export, 1 }, { "unexport", "Don't mark an environment variable for automatic export", - env_unexport, 1 }, - { "send", "Send an environment variable", env_send, 1 }, + (void (*)(unsigned char *, unsigned char *))env_unexport, 1 }, + { "send", "Send an environment variable", (void (*)(unsigned char *, unsigned char *))env_send, 1 }, { "list", "List the current environment variables", - env_list, 0 }, + (void (*)(unsigned char *, unsigned char *))env_list, 0 }, #if defined(OLD_ENVIRON) && defined(ENV_HACK) { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", - env_varval, 1 }, + (void (*)(unsigned char *, unsigned char *))env_varval, 1 }, #endif - { "help", 0, env_help, 0 }, - { "?", "Print help information", env_help, 0 }, - { 0 }, + { "help", NULL, (void (*)(unsigned char *, unsigned char *))env_help, 0 }, + { "?", "Print help information", (void (*)(unsigned char *, unsigned char *))env_help, 0 }, + { NULL, NULL, NULL, 0 }, }; - static void -env_help() +static void +env_help(void) { struct envlist *c; for (c = EnvList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } } - static struct envlist * -getenvcmd(name) - char *name; +static struct envlist * +getenvcmd(char *name) { return (struct envlist *) genget(name, (char **) EnvList, sizeof(struct envlist)); } - int -env_cmd(argc, argv) - int argc; - char *argv[]; +static int +env_cmd(int argc, char *argv[]) { struct envlist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'environ' command. 'environ ?' for help.\n"); return 0; } c = getenvcmd(argv[1]); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", argv[1]); return 0; } if (c->narg + 2 != argc) { fprintf(stderr, "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", c->narg < argc + 2 ? "only " : "", c->narg, c->narg == 1 ? "" : "s", c->name); return 0; } (*c->handler)(argv[2], argv[3]); return 1; } struct env_lst { struct env_lst *next; /* pointer to next structure */ struct env_lst *prev; /* pointer to previous structure */ unsigned char *var; /* pointer to variable name */ unsigned char *value; /* pointer to variable value */ int export; /* 1 -> export with default list of variables */ int welldefined; /* A well defined variable */ }; struct env_lst envlisthead; - struct env_lst * -env_find(var) - unsigned char *var; +static struct env_lst * +env_find(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; for (ep = envlisthead.next; ep; ep = ep->next) { - if (strcmp((char *)ep->var, (char *)var) == 0) + if (strcmp(ep->var, var) == 0) return(ep); } return(NULL); } - void -env_init() +void +env_init(void) { extern char **environ; - register char **epp, *cp; - register struct env_lst *ep; + char **epp, *cp; + struct env_lst *ep; for (epp = environ; *epp; epp++) { if ((cp = strchr(*epp, '='))) { *cp = '\0'; ep = env_define((unsigned char *)*epp, (unsigned char *)cp+1); ep->export = 0; *cp = '='; } } /* * Special case for DISPLAY variable. If it is ":0.0" or * "unix:0.0", we have to get rid of "unix" and insert our * hostname. */ if ((ep = env_find("DISPLAY")) && ((*ep->value == ':') || (strncmp((char *)ep->value, "unix:", 5) == 0))) { char hbuf[256+1]; char *cp2 = strchr((char *)ep->value, ':'); gethostname(hbuf, 256); hbuf[256] = '\0'; cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); sprintf((char *)cp, "%s%s", hbuf, cp2); free(ep->value); ep->value = (unsigned char *)cp; } /* * If USER is not defined, but LOGNAME is, then add * USER with the value from LOGNAME. By default, we * don't export the USER variable. */ if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { - env_define((unsigned char *)"USER", ep->value); - env_unexport((unsigned char *)"USER"); + env_define("USER", ep->value); + env_unexport("USER"); } - env_export((unsigned char *)"DISPLAY"); - env_export((unsigned char *)"PRINTER"); + env_export("DISPLAY"); + env_export("PRINTER"); } - struct env_lst * -env_define(var, value) - unsigned char *var, *value; +struct env_lst * +env_define(const unsigned char *var, unsigned char *value) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) { if (ep->var) free(ep->var); if (ep->value) free(ep->value); } else { ep = (struct env_lst *)malloc(sizeof(struct env_lst)); ep->next = envlisthead.next; envlisthead.next = ep; ep->prev = &envlisthead; if (ep->next) ep->next->prev = ep; } ep->welldefined = opt_welldefined(var); ep->export = 1; - ep->var = (unsigned char *)strdup((char *)var); - ep->value = (unsigned char *)strdup((char *)value); + ep->var = strdup(var); + ep->value = strdup(value); return(ep); } - void -env_undefine(var) - unsigned char *var; +void +env_undefine(unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) { ep->prev->next = ep->next; if (ep->next) ep->next->prev = ep->prev; if (ep->var) free(ep->var); if (ep->value) free(ep->value); free(ep); } } - void -env_export(var) - unsigned char *var; +void +env_export(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) ep->export = 1; } - void -env_unexport(var) - unsigned char *var; +void +env_unexport(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) ep->export = 0; } - void -env_send(var) - unsigned char *var; +void +env_send(unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if (my_state_is_wont(TELOPT_NEW_ENVIRON) #ifdef OLD_ENVIRON && my_state_is_wont(TELOPT_OLD_ENVIRON) #endif ) { fprintf(stderr, "Cannot send '%s': Telnet ENVIRON option not enabled\n", var); return; } ep = env_find(var); if (ep == 0) { fprintf(stderr, "Cannot send '%s': variable not defined\n", var); return; } env_opt_start_info(); env_opt_add(ep->var); env_opt_end(0); } - void -env_list() +void +env_list(void) { - register struct env_lst *ep; + struct env_lst *ep; for (ep = envlisthead.next; ep; ep = ep->next) { printf("%c %-20s %s\n", ep->export ? '*' : ' ', ep->var, ep->value); } } - unsigned char * -env_default(init, welldefined) - int init; +unsigned char * +env_default(int init, int welldefined) { static struct env_lst *nep = NULL; if (init) { nep = &envlisthead; return(NULL); } if (nep) { while ((nep = nep->next)) { if (nep->export && (nep->welldefined == welldefined)) return(nep->var); } } return(NULL); } - unsigned char * -env_getvalue(var) - unsigned char *var; +unsigned char * +env_getvalue(const unsigned char *var) { - register struct env_lst *ep; + struct env_lst *ep; if ((ep = env_find(var))) return(ep->value); return(NULL); } #if defined(OLD_ENVIRON) && defined(ENV_HACK) - void -env_varval(what) - unsigned char *what; +void +env_varval(unsigned char *what) { extern int old_env_var, old_env_value, env_auto; int len = strlen((char *)what); if (len == 0) goto unknown; if (strncasecmp((char *)what, "status", len) == 0) { if (env_auto) printf("%s%s", "VAR and VALUE are/will be ", "determined automatically\n"); if (old_env_var == OLD_ENV_VAR) printf("VAR and VALUE set to correct definitions\n"); else printf("VAR and VALUE definitions are reversed\n"); } else if (strncasecmp((char *)what, "auto", len) == 0) { env_auto = 1; old_env_var = OLD_ENV_VALUE; old_env_value = OLD_ENV_VAR; } else if (strncasecmp((char *)what, "right", len) == 0) { env_auto = 0; old_env_var = OLD_ENV_VAR; old_env_value = OLD_ENV_VALUE; } else if (strncasecmp((char *)what, "wrong", len) == 0) { env_auto = 0; old_env_var = OLD_ENV_VALUE; old_env_value = OLD_ENV_VAR; } else { unknown: printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); } } #endif -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION /* * The AUTHENTICATE command. */ struct authlist { - char *name; - char *help; - int (*handler)(); + const char *name; + const char *help; + int (*handler)(char *); int narg; }; extern int auth_enable P((char *)), auth_disable P((char *)), auth_status P((void)); static int auth_help P((void)); struct authlist AuthList[] = { { "status", "Display current status of authentication information", - auth_status, 0 }, + (int (*)(char *))auth_status, 0 }, { "disable", "Disable an authentication type ('auth disable ?' for more)", auth_disable, 1 }, { "enable", "Enable an authentication type ('auth enable ?' for more)", auth_enable, 1 }, - { "help", 0, auth_help, 0 }, - { "?", "Print help information", auth_help, 0 }, - { 0 }, + { "help", NULL, (int (*)(char *))auth_help, 0 }, + { "?", "Print help information", (int (*)(char *))auth_help, 0 }, + { NULL, NULL, NULL, 0 }, }; - static int -auth_help() +static int +auth_help(void) { struct authlist *c; for (c = AuthList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } return 0; } - int -auth_cmd(argc, argv) - int argc; - char *argv[]; +int +auth_cmd(int argc, char *argv[]) { struct authlist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'auth' command. 'auth ?' for help.\n"); return 0; } c = (struct authlist *) genget(argv[1], (char **) AuthList, sizeof(struct authlist)); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", argv[1]); return 0; } if (c->narg + 2 != argc) { fprintf(stderr, "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", c->narg < argc + 2 ? "only " : "", c->narg, c->narg == 1 ? "" : "s", c->name); return 0; } - return((*c->handler)(argv[2], argv[3])); + return((*c->handler)(argv[2])); } #endif #ifdef ENCRYPTION /* * The ENCRYPT command. */ struct encryptlist { - char *name; - char *help; - int (*handler)(); + const char *name; + const char *help; + int (*handler)(char *, char *); int needconnect; int minarg; int maxarg; }; extern int EncryptEnable P((char *, char *)), EncryptDisable P((char *, char *)), EncryptType P((char *, char *)), EncryptStart P((char *)), EncryptStartInput P((void)), EncryptStartOutput P((void)), EncryptStop P((char *)), EncryptStopInput P((void)), EncryptStopOutput P((void)), EncryptStatus P((void)); static int EncryptHelp P((void)); struct encryptlist EncryptList[] = { { "enable", "Enable encryption. ('encrypt enable ?' for more)", EncryptEnable, 1, 1, 2 }, { "disable", "Disable encryption. ('encrypt enable ?' for more)", EncryptDisable, 0, 1, 2 }, { "type", "Set encryption type. ('encrypt type ?' for more)", EncryptType, 0, 1, 1 }, { "start", "Start encryption. ('encrypt start ?' for more)", - EncryptStart, 1, 0, 1 }, + (int (*)(char *, char *))EncryptStart, 1, 0, 1 }, { "stop", "Stop encryption. ('encrypt stop ?' for more)", - EncryptStop, 1, 0, 1 }, + (int (*)(char *, char *))EncryptStop, 1, 0, 1 }, { "input", "Start encrypting the input stream", - EncryptStartInput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStartInput, 1, 0, 0 }, { "-input", "Stop encrypting the input stream", - EncryptStopInput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStopInput, 1, 0, 0 }, { "output", "Start encrypting the output stream", - EncryptStartOutput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStartOutput, 1, 0, 0 }, { "-output", "Stop encrypting the output stream", - EncryptStopOutput, 1, 0, 0 }, + (int (*)(char *, char *))EncryptStopOutput, 1, 0, 0 }, { "status", "Display current status of authentication information", - EncryptStatus, 0, 0, 0 }, - { "help", 0, EncryptHelp, 0, 0, 0 }, - { "?", "Print help information", EncryptHelp, 0, 0, 0 }, - { 0 }, + (int (*)(char *, char *))EncryptStatus, 0, 0, 0 }, + { "help", NULL, (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, + { "?", "Print help information", (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, + { NULL, NULL, NULL, 0, 0, 0 }, }; - static int -EncryptHelp() +static int +EncryptHelp(void) { struct encryptlist *c; for (c = EncryptList; c->name; c++) { if (c->help) { if (*c->help) printf("%-15s %s\n", c->name, c->help); else printf("\n"); } } return 0; } - int -encrypt_cmd(argc, argv) - int argc; - char *argv[]; +static int +encrypt_cmd(int argc, char *argv[]) { struct encryptlist *c; if (argc < 2) { fprintf(stderr, "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); return 0; } c = (struct encryptlist *) genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); if (c == 0) { fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", argv[1]); return 0; } - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", argv[1]); return 0; } argc -= 2; if (argc < c->minarg || argc > c->maxarg) { if (c->minarg == c->maxarg) { fprintf(stderr, "Need %s%d argument%s ", c->minarg < argc ? "only " : "", c->minarg, c->minarg == 1 ? "" : "s"); } else { fprintf(stderr, "Need %s%d-%d arguments ", c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); } fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", c->name); return 0; } if (c->needconnect && !connected) { if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { printf("?Need to be connected first.\n"); return 0; } } return ((*c->handler)(argc > 0 ? argv[2] : 0, - argc > 1 ? argv[3] : 0, - argc > 2 ? argv[4] : 0)); + argc > 1 ? argv[3] : 0)); } #endif /* ENCRYPTION */ -#if defined(unix) && defined(TN3270) - static void -filestuff(fd) - int fd; -{ - int res; - -#ifdef F_GETOWN - setconnmode(0); - res = fcntl(fd, F_GETOWN, 0); - setcommandmode(); - - if (res == -1) { - perror("fcntl"); - return; - } - printf("\tOwner is %d.\n", res); -#endif - - setconnmode(0); - res = fcntl(fd, F_GETFL, 0); - setcommandmode(); - - if (res == -1) { - perror("fcntl"); - return; - } -#ifdef notdef - printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); -#endif -} -#endif /* defined(unix) && defined(TN3270) */ - /* * Print status about the connection. */ - /*ARGSUSED*/ - static int -status(argc, argv) - int argc; - char *argv[]; +/*ARGSUSED*/ +static int +status(int argc, char *argv[]) { if (connected) { printf("Connected to %s.\n", hostname); if ((argc < 2) || strcmp(argv[1], "notmuch")) { int mode = getconnmode(); if (my_want_state_is_will(TELOPT_LINEMODE)) { printf("Operating with LINEMODE option\n"); printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); printf("%s catching of signals\n", (mode&MODE_TRAPSIG) ? "Local" : "No"); slcstate(); #ifdef KLUDGELINEMODE } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { printf("Operating in obsolete linemode\n"); #endif } else { printf("Operating in single character mode\n"); if (localchars) printf("Catching signals locally\n"); } printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); if (my_want_state_is_will(TELOPT_LFLOW)) printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); #ifdef ENCRYPTION encrypt_display(); #endif /* ENCRYPTION */ } } else { printf("No connection.\n"); } -# if !defined(TN3270) printf("Escape character is '%s'.\n", control(escape)); (void) fflush(stdout); -# else /* !defined(TN3270) */ - if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { - printf("Escape character is '%s'.\n", control(escape)); - } -# if defined(unix) - if ((argc >= 2) && !strcmp(argv[1], "everything")) { - printf("SIGIO received %d time%s.\n", - sigiocount, (sigiocount == 1)? "":"s"); - if (In3270) { - printf("Process ID %d, process group %d.\n", - getpid(), getpgrp(getpid())); - printf("Terminal input:\n"); - filestuff(tin); - printf("Terminal output:\n"); - filestuff(tout); - printf("Network socket:\n"); - filestuff(net); - } - } - if (In3270 && transcom) { - printf("Transparent mode command is '%s'.\n", transcom); - } -# endif /* defined(unix) */ - (void) fflush(stdout); - if (In3270) { - return 0; - } -# endif /* defined(TN3270) */ return 1; } #ifdef SIGINFO /* * Function that gets called when SIGINFO is received. */ - void -ayt_status() +void +ayt_status(void) { (void) call(status, "status", "notmuch", 0); } #endif static const char * -sockaddr_ntop(sa) - struct sockaddr *sa; +sockaddr_ntop(struct sockaddr *sa) { void *addr; static char addrbuf[INET6_ADDRSTRLEN]; switch (sa->sa_family) { case AF_INET: addr = &((struct sockaddr_in *)sa)->sin_addr; break; case AF_UNIX: addr = &((struct sockaddr_un *)sa)->sun_path; break; #ifdef INET6 case AF_INET6: addr = &((struct sockaddr_in6 *)sa)->sin6_addr; break; #endif default: return NULL; } inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); return addrbuf; } #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) static int -setpolicy(net, res, policy) - int net; - struct addrinfo *res; - char *policy; +setpolicy(int lnet, struct addrinfo *res, char *policy) { char *buf; int level; int optname; if (policy == NULL) return 0; buf = ipsec_set_policy(policy, strlen(policy)); if (buf == NULL) { printf("%s\n", ipsec_strerror()); return -1; } level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; - if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){ + if (setsockopt(lnet, level, optname, buf, ipsec_get_policylen(buf)) < 0){ perror("setsockopt"); return -1; } free(buf); + return 0; } #endif #ifdef INET6 /* * When an Address Family related error happend, check if retry with * another AF is possible or not. * Return 1, if retry with another af is OK. Else, return 0. */ static int -switch_af(aip) - struct addrinfo **aip; +switch_af(struct addrinfo **aip) { int nextaf; struct addrinfo *ai; ai = *aip; nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET; do ai=ai->ai_next; while (ai != NULL && ai->ai_family != nextaf); *aip = ai; if (*aip != NULL) { return 1; } return 0; } #endif - int -tn(argc, argv) - int argc; - char *argv[]; +int +tn(int argc, char *argv[]) { char *srp = 0; int proto, opt; - int sourceroute(), srlen; + int srlen; int srcroute = 0, result; char *cmd, *hostp = 0, *portp = 0, *user = 0; char *src_addr = NULL; struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL; int error = 0, af_error = 0; if (connected) { printf("?Already connected to %s\n", hostname); setuid(getuid()); return 0; } if (argc < 2) { (void) strcpy(line, "open "); printf("(to) "); (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); makeargv(); argc = margc; argv = margv; } cmd = *argv; --argc; ++argv; while (argc) { if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) goto usage; if (strcmp(*argv, "-l") == 0) { --argc; ++argv; if (argc == 0) goto usage; user = *argv++; --argc; continue; } if (strcmp(*argv, "-a") == 0) { --argc; ++argv; autologin = 1; continue; } if (strcmp(*argv, "-s") == 0) { --argc; ++argv; if (argc == 0) goto usage; src_addr = *argv++; --argc; continue; } if (hostp == 0) { hostp = *argv++; --argc; continue; } if (portp == 0) { portp = *argv++; --argc; continue; } usage: printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd); setuid(getuid()); return 0; } if (hostp == 0) goto usage; if (src_addr != NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(src_addr, 0, &hints, &src_res); if (error == EAI_NODATA) { hints.ai_flags = 0; error = getaddrinfo(src_addr, 0, &hints, &src_res); } if (error != 0) { fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "%s: %s\n", src_addr, strerror(errno)); setuid(getuid()); return 0; } src_res0 = src_res; } if (hostp[0] == '/') { struct sockaddr_un su; if (strlen(hostp) >= sizeof(su.sun_path)) { fprintf(stderr, "hostname too long for unix domain socket: %s", hostp); goto fail; } memset(&su, 0, sizeof su); su.sun_family = AF_UNIX; strncpy(su.sun_path, hostp, sizeof su.sun_path); - printf("Trying %s...\n", &su.sun_path); + printf("Trying %s...\n", hostp); net = socket(PF_UNIX, SOCK_STREAM, 0); if ( net < 0) { perror("socket"); goto fail; } if (connect(net, (struct sockaddr *)&su, sizeof su) == -1) { perror(su.sun_path); (void) NetClose(net); goto fail; } goto af_unix; } else if (hostp[0] == '@' || hostp[0] == '!') { if ( #ifdef INET6 family == AF_INET6 || #endif (hostname = strrchr(hostp, ':')) == NULL) hostname = strrchr(hostp, '@'); hostname++; srcroute = 1; } else hostname = hostp; if (!portp) { telnetport = 1; - portp = "telnet"; + portp = strdup("telnet"); } else if (*portp == '-') { portp++; telnetport = 1; } else telnetport = 0; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(hostname, portp, &hints, &res); if (error) { hints.ai_flags = AI_CANONNAME; error = getaddrinfo(hostname, portp, &hints, &res); } if (error != 0) { fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "%s: %s\n", hostname, strerror(errno)); setuid(getuid()); goto fail; } if (hints.ai_flags == AI_NUMERICHOST) { /* hostname has numeric */ int gni_err = 1; if (doaddrlookup) gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len, _hostname, sizeof(_hostname) - 1, NULL, 0, NI_NAMEREQD); if (gni_err != 0) (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); _hostname[sizeof(_hostname)-1] = '\0'; hostname = _hostname; } else { /* hostname has FQDN */ if (srcroute != 0) (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1); else if (res->ai_canonname != NULL) strcpy(_hostname, res->ai_canonname); else (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); _hostname[sizeof(_hostname)-1] = '\0'; hostname = _hostname; } res0 = res; af_again: if (srcroute != 0) { static char hostbuf[BUFSIZ]; if (af_error == 0) { /* save intermediate hostnames for retry */ strncpy(hostbuf, hostp, BUFSIZ - 1); hostbuf[BUFSIZ - 1] = '\0'; } else hostp = hostbuf; srp = 0; result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); if (result == 0) { #ifdef INET6 if (family == AF_UNSPEC && af_error == 0 && switch_af(&res) == 1) { af_error = 1; goto af_again; } #endif setuid(getuid()); goto fail; } else if (result == -1) { printf("Bad source route option: %s\n", hostp); setuid(getuid()); goto fail; } } do { printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); setuid(getuid()); if (net < 0) { #ifdef INET6 if (family == AF_UNSPEC && af_error == 0 && switch_af(&res) == 1) { af_error = 1; goto af_again; } #endif perror("telnet: socket"); goto fail; } if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0) perror("setsockopt (source route)"); #if defined(IPPROTO_IP) && defined(IP_TOS) if (res->ai_family == PF_INET) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = IPTOS_LOWDELAY; if (tos && (setsockopt(net, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) && (errno != ENOPROTOOPT)) perror("telnet: setsockopt (IP_TOS) (ignored)"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { perror("setsockopt (SO_DEBUG)"); } if (src_addr != NULL) { for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next) if (src_res->ai_family == res->ai_family) break; if (src_res == NULL) src_res = src_res0; if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) { #ifdef INET6 if (family == AF_UNSPEC && af_error == 0 && switch_af(&res) == 1) { af_error = 1; (void) NetClose(net); goto af_again; } #endif perror("bind"); (void) NetClose(net); goto fail; } } #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) if (setpolicy(net, res, ipsec_policy_in) < 0) { (void) NetClose(net); goto fail; } if (setpolicy(net, res, ipsec_policy_out) < 0) { (void) NetClose(net); goto fail; } #endif if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { struct addrinfo *next; next = res->ai_next; /* If already an af failed, only try same af. */ if (af_error != 0) while (next != NULL && next->ai_family != res->ai_family) next = next->ai_next; warn("connect to address %s", sockaddr_ntop(res->ai_addr)); if (next != NULL) { res = next; (void) NetClose(net); continue; } warnx("Unable to connect to remote host"); (void) NetClose(net); goto fail; } connected++; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION auth_encrypt_connect(connected); -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif +#endif } while (connected == 0); freeaddrinfo(res0); if (src_res0 != NULL) freeaddrinfo(src_res0); cmdrc(hostp, hostname); af_unix: if (autologin && user == NULL) { struct passwd *pw; user = getenv("USER"); if (user == NULL || ((pw = getpwnam(user)) && pw->pw_uid != getuid())) { if ((pw = getpwuid(getuid()))) user = pw->pw_name; else user = NULL; } } if (user) { - env_define((unsigned char *)"USER", (unsigned char *)user); - env_export((unsigned char *)"USER"); + env_define("USER", user); + env_export("USER"); } (void) call(status, "status", "notmuch", 0); if (setjmp(peerdied) == 0) telnet(user); (void) NetClose(net); ExitString("Connection closed by foreign host.\n",1); /*NOTREACHED*/ fail: if (res0 != NULL) freeaddrinfo(res0); if (src_res0 != NULL) freeaddrinfo(src_res0); return 0; } #define HELPINDENT (sizeof ("connect")) static char openhelp[] = "connect to a site", closehelp[] = "close current connection", logouthelp[] = "forcibly logout remote user and close the connection", quithelp[] = "exit telnet", statushelp[] = "print status information", helphelp[] = "print help information", sendhelp[] = "transmit special characters ('send ?' for more)", sethelp[] = "set operating parameters ('set ?' for more)", unsethelp[] = "unset operating parameters ('unset ?' for more)", togglestring[] ="toggle operating parameters ('toggle ?' for more)", slchelp[] = "change state of special charaters ('slc ?' for more)", displayhelp[] = "display operating parameters", -#if defined(TN3270) && defined(unix) - transcomhelp[] = "specify Unix command for transparent mode pipe", -#endif /* defined(TN3270) && defined(unix) */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION authhelp[] = "turn on (off) authentication ('auth ?' for more)", #endif #ifdef ENCRYPTION encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", #endif /* ENCRYPTION */ -#if defined(unix) zhelp[] = "suspend telnet", -#endif /* defined(unix) */ -#if defined(OPIE) +#ifdef OPIE opiehelp[] = "compute response to OPIE challenge", #endif shellhelp[] = "invoke a subshell", envhelp[] = "change environment variables ('environ ?' for more)", modestring[] = "try to enter line or character mode ('mode ?' for more)"; static Command cmdtab[] = { { "close", closehelp, bye, 1 }, - { "logout", logouthelp, logout, 1 }, + { "logout", logouthelp, (int (*)(int, char **))logout, 1 }, { "display", displayhelp, display, 0 }, { "mode", modestring, modecmd, 0 }, { "telnet", openhelp, tn, 0 }, { "open", openhelp, tn, 0 }, - { "quit", quithelp, quit, 0 }, + { "quit", quithelp, (int (*)(int, char **))quit, 0 }, { "send", sendhelp, sendcmd, 0 }, { "set", sethelp, setcmd, 0 }, { "unset", unsethelp, unsetcmd, 0 }, { "status", statushelp, status, 0 }, { "toggle", togglestring, toggle, 0 }, { "slc", slchelp, slccmd, 0 }, -#if defined(TN3270) && defined(unix) - { "transcom", transcomhelp, settranscom, 0 }, -#endif /* defined(TN3270) && defined(unix) */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION { "auth", authhelp, auth_cmd, 0 }, #endif #ifdef ENCRYPTION { "encrypt", encrypthelp, encrypt_cmd, 0 }, #endif /* ENCRYPTION */ -#if defined(unix) - { "z", zhelp, suspend, 0 }, -#endif /* defined(unix) */ -#if defined(TN3270) + { "z", zhelp, (int (*)(int, char **))suspend, 0 }, { "!", shellhelp, shell, 1 }, -#else - { "!", shellhelp, shell, 0 }, -#endif { "environ", envhelp, env_cmd, 0 }, { "?", helphelp, help, 0 }, -#if defined(OPIE) +#ifdef OPIE { "opie", opiehelp, opie_calc, 0 }, #endif - { 0, 0, 0, 0 } + { NULL, NULL, NULL, 0 } }; static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; static char escapehelp[] = "deprecated command -- use 'set escape' instead"; static Command cmdtab2[] = { { "help", 0, help, 0 }, { "escape", escapehelp, setescape, 0 }, - { "crmod", crmodhelp, togcrmod, 0 }, - { 0, 0, 0, 0 } + { "crmod", crmodhelp, (int (*)(int, char **))togcrmod, 0 }, + { NULL, NULL, NULL, 0 } }; /* * Call routine with argc, argv set from args (terminated by 0). */ - /*VARARGS1*/ - static int -call(va_alist) - va_dcl +static int +call(intrtn_t routine, ...) { va_list ap; - typedef int (*intrtn_t)(); - intrtn_t routine; char *args[100]; int argno = 0; - va_start(ap); - routine = (va_arg(ap, intrtn_t)); - while ((args[argno++] = va_arg(ap, char *)) != 0) { - ; - } + va_start(ap, routine); + while ((args[argno++] = va_arg(ap, char *)) != 0); va_end(ap); return (*routine)(argno-1, args); } - static Command * -getcmd(name) - char *name; +static Command * +getcmd(char *name) { Command *cm; if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) return cm; return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); } - void -command(top, tbuf, cnt) - int top; - char *tbuf; - int cnt; +void +command(int top, const char *tbuf, int cnt) { - register Command *c; + Command *c; setcommandmode(); if (!top) { putchar('\n'); -#if defined(unix) } else { (void) signal(SIGINT, SIG_DFL); (void) signal(SIGQUIT, SIG_DFL); -#endif /* defined(unix) */ } for (;;) { if (rlogin == _POSIX_VDISABLE) printf("%s> ", prompt); if (tbuf) { - register char *cp; + char *cp; cp = line; while (cnt > 0 && (*cp++ = *tbuf++) != '\n') cnt--; tbuf = 0; if (cp == line || *--cp != '\n' || cp == line) goto getline; *cp = '\0'; if (rlogin == _POSIX_VDISABLE) printf("%s\n", line); } else { getline: if (rlogin != _POSIX_VDISABLE) printf("%s> ", prompt); if (fgets(line, sizeof(line), stdin) == NULL) { if (feof(stdin) || ferror(stdin)) { (void) quit(); /*NOTREACHED*/ } break; } } if (line[0] == 0) break; makeargv(); if (margv[0] == 0) { break; } c = getcmd(margv[0]); - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { printf("?Ambiguous command\n"); continue; } if (c == 0) { printf("?Invalid command\n"); continue; } if (c->needconnect && !connected) { printf("?Need to be connected first.\n"); continue; } if ((*c->handler)(margc, margv)) { break; } } if (!top) { if (!connected) { longjmp(toplevel, 1); /*NOTREACHED*/ } -#if defined(TN3270) - if (shell_active == 0) { - setconnmode(0); - } -#else /* defined(TN3270) */ setconnmode(0); -#endif /* defined(TN3270) */ } } /* * Help command. */ - static int -help(argc, argv) - int argc; - char *argv[]; +static int +help(int argc, char *argv[]) { - register Command *c; + Command *c; if (argc == 1) { printf("Commands may be abbreviated. Commands are:\n\n"); for (c = cmdtab; c->name; c++) if (c->help) { printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); } return 0; } else while (--argc > 0) { - register char *arg; + char *arg; arg = *++argv; c = getcmd(arg); - if (Ambiguous(c)) + if (Ambiguous((void *)c)) printf("?Ambiguous help command %s\n", arg); else if (c == (Command *)0) printf("?Invalid help command %s\n", arg); else printf("%s\n", c->help); } return 0; } static char *rcname = 0; static char rcbuf[128]; - void -cmdrc(m1, m2) - char *m1, *m2; +void +cmdrc(char *m1, char *m2) { - register Command *c; + Command *c; FILE *rcfile; int gotmachine = 0; int l1 = strlen(m1); int l2 = strlen(m2); char m1save[MAXHOSTNAMELEN]; if (skiprc) return; strlcpy(m1save, m1, sizeof(m1save)); m1 = m1save; if (rcname == 0) { rcname = getenv("HOME"); if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf)) strcpy(rcbuf, rcname); else rcbuf[0] = '\0'; strcat(rcbuf, "/.telnetrc"); rcname = rcbuf; } if ((rcfile = fopen(rcname, "r")) == 0) { return; } for (;;) { if (fgets(line, sizeof(line), rcfile) == NULL) break; if (line[0] == 0) break; if (line[0] == '#') continue; if (gotmachine) { if (!isspace(line[0])) gotmachine = 0; } if (gotmachine == 0) { if (isspace(line[0])) continue; if (strncasecmp(line, m1, l1) == 0) strncpy(line, &line[l1], sizeof(line) - l1); else if (strncasecmp(line, m2, l2) == 0) strncpy(line, &line[l2], sizeof(line) - l2); else if (strncasecmp(line, "DEFAULT", 7) == 0) strncpy(line, &line[7], sizeof(line) - 7); else continue; if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') continue; gotmachine = 1; } makeargv(); if (margv[0] == 0) continue; c = getcmd(margv[0]); - if (Ambiguous(c)) { + if (Ambiguous((void *)c)) { printf("?Ambiguous command: %s\n", margv[0]); continue; } if (c == 0) { printf("?Invalid command: %s\n", margv[0]); continue; } /* * This should never happen... */ if (c->needconnect && !connected) { printf("?Need to be connected first for %s.\n", margv[0]); continue; } (*c->handler)(margc, margv); } fclose(rcfile); } /* * Source route is handed in as * [!]@hop1@hop2...[@|:]dst * If the leading ! is present, it is a * strict source route, otherwise it is * assmed to be a loose source route. * * We fill in the source route option as * hop1,hop2,hop3...dest * and return a pointer to hop1, which will * be the address to connect() to. * * Arguments: * * res: ponter to addrinfo structure which contains sockaddr to * the host to connect to. * * arg: pointer to route list to decipher * * cpp: If *cpp is not equal to NULL, this is a * pointer to a pointer to a character array * that should be filled in with the option. * * lenp: pointer to an integer that contains the * length of *cpp if *cpp != NULL. * * protop: pointer to an integer that should be filled in with * appropriate protocol for setsockopt, as socket * protocol family. * * optp: pointer to an integer that should be filled in with * appropriate option for setsockopt, as socket protocol * family. * * Return values: * * If the return value is 1, then all operations are * successful. If the * return value is -1, there was a syntax error in the * option, either unknown characters, or too many hosts. * If the return value is 0, one of the hostnames in the * path is unknown, and *cpp is set to point to the bad * hostname. * * *cpp: If *cpp was equal to NULL, it will be filled * in with a pointer to our static area that has * the option filled in. This will be 32bit aligned. * * *lenp: This will be filled in with how long the option * pointed to by *cpp is. * * *protop: This will be filled in with appropriate protocol for * setsockopt, as socket protocol family. * * *optp: This will be filled in with appropriate option for * setsockopt, as socket protocol family. */ -int -sourceroute(ai, arg, cpp, lenp, protop, optp) - struct addrinfo *ai; - char *arg; - char **cpp; - int *lenp; - int *protop; - int *optp; +static int +sourceroute(struct addrinfo *ai, char *arg, char **cpp, int *lenp, int *protop, int *optp) { static char buf[1024 + ALIGNBYTES]; /*XXX*/ struct cmsghdr *cmsg; -#ifdef sysV88 - static IOPTN ipopt; -#endif char *cp, *cp2, *lsrp, *ep; - register int tmp; - struct sockaddr_in *sin; + struct sockaddr_in *_sin; struct sockaddr_in6 *sin6; struct addrinfo hints, *res; int error; - register char c; + char c; /* * Verify the arguments, and make sure we have * at least 7 bytes for the option. */ if (cpp == NULL || lenp == NULL) return -1; if (*cpp != NULL) { switch (res->ai_family) { case AF_INET: if (*lenp < 7) return -1; break; #ifdef INET6 case AF_INET6: - if (*lenp < CMSG_SPACE(sizeof(struct ip6_rthdr) + + if (*lenp < (int)CMSG_SPACE(sizeof(struct ip6_rthdr) + sizeof(struct in6_addr))) return -1; break; #endif } } /* * Decide whether we have a buffer passed to us, * or if we need to use our own static buffer. */ if (*cpp) { lsrp = *cpp; ep = lsrp + *lenp; } else { *cpp = lsrp = (char *)ALIGN(buf); ep = lsrp + 1024; } cp = arg; #ifdef INET6 if (ai->ai_family == AF_INET6) { cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0); if (*cp != '@') return -1; *protop = IPPROTO_IPV6; *optp = IPV6_PKTOPTIONS; } else #endif { /* * Next, decide whether we have a loose source * route or a strict source route, and fill in * the begining of the option. */ -#ifndef sysV88 if (*cp == '!') { cp++; *lsrp++ = IPOPT_SSRR; } else *lsrp++ = IPOPT_LSRR; -#else - if (*cp == '!') { - cp++; - ipopt.io_type = IPOPT_SSRR; - } else - ipopt.io_type = IPOPT_LSRR; -#endif if (*cp != '@') return -1; -#ifndef sysV88 lsrp++; /* skip over length, we'll fill it in later */ *lsrp++ = 4; -#endif *protop = IPPROTO_IP; *optp = IP_OPTIONS; } cp++; memset(&hints, 0, sizeof(hints)); hints.ai_family = ai->ai_family; hints.ai_socktype = SOCK_STREAM; for (c = 0;;) { if ( #ifdef INET6 ai->ai_family != AF_INET6 && #endif c == ':') cp2 = 0; else for (cp2 = cp; (c = *cp2); cp2++) { if (c == ',') { *cp2++ = '\0'; if (*cp2 == '@') cp2++; } else if (c == '@') { *cp2++ = '\0'; } else if ( #ifdef INET6 ai->ai_family != AF_INET6 && #endif c == ':') { *cp2++ = '\0'; } else continue; break; } if (!c) cp2 = 0; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(cp, NULL, &hints, &res); if (error == EAI_NODATA) { hints.ai_flags = 0; error = getaddrinfo(cp, NULL, &hints, &res); } if (error != 0) { fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); if (error == EAI_SYSTEM) fprintf(stderr, "%s: %s\n", cp, strerror(errno)); *cpp = cp; return(0); } #ifdef INET6 if (res->ai_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)res->ai_addr; inet6_rthdr_add(cmsg, &sin6->sin6_addr, IPV6_RTHDR_LOOSE); } else #endif { - sin = (struct sockaddr_in *)res->ai_addr; - memcpy(lsrp, (char *)&sin->sin_addr, 4); + _sin = (struct sockaddr_in *)res->ai_addr; + memcpy(lsrp, (char *)&_sin->sin_addr, 4); lsrp += 4; } if (cp2) cp = cp2; else break; /* * Check to make sure there is space for next address */ #ifdef INET6 if (res->ai_family == AF_INET6) { if (((char *)CMSG_DATA(cmsg) + sizeof(struct ip6_rthdr) + ((inet6_rthdr_segments(cmsg) + 1) * sizeof(struct in6_addr))) > ep) return -1; } else #endif if (lsrp + 4 > ep) return -1; freeaddrinfo(res); } #ifdef INET6 if (res->ai_family == AF_INET6) { inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); *lenp = cmsg->cmsg_len; } else #endif { -#ifndef sysV88 if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { *cpp = 0; *lenp = 0; return -1; } *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ *lenp = lsrp - *cpp; -#else - ipopt.io_len = lsrp - *cpp; - if (ipopt.io_len <= 5) { /* Is 3 better ? */ - *cpp = 0; - *lenp = 0; - return -1; - } - *lenp = sizeof(ipopt); - *cpp = (char *) &ipopt; -#endif } freeaddrinfo(res); return 1; } Index: head/crypto/telnet/telnet/defines.h =================================================================== --- head/crypto/telnet/telnet/defines.h (revision 87138) +++ head/crypto/telnet/telnet/defines.h (revision 87139) @@ -1,61 +1,56 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)defines.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD$ */ #define settimer(x) clocks.x = clocks.system++ - -#if !defined(TN3270) - -#define SetIn3270() - -#endif /* !defined(TN3270) */ #define NETADD(c) { *netoring.supply = c; ring_supplied(&netoring, 1); } #define NET2ADD(c1,c2) { NETADD(c1); NETADD(c2); } #define NETBYTES() (ring_full_count(&netoring)) #define NETROOM() (ring_empty_count(&netoring)) #define TTYADD(c) if (!(SYNCHing||flushout)) { \ *ttyoring.supply = c; \ ring_supplied(&ttyoring, 1); \ } #define TTYBYTES() (ring_full_count(&ttyoring)) #define TTYROOM() (ring_empty_count(&ttyoring)) /* Various modes */ #define MODE_LOCAL_CHARS(m) ((m)&(MODE_EDIT|MODE_TRAPSIG)) #define MODE_LOCAL_ECHO(m) ((m)&MODE_ECHO) #define MODE_COMMAND_LINE(m) ((m)==-1) #define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */ Index: head/crypto/telnet/telnet/externs.h =================================================================== --- head/crypto/telnet/telnet/externs.h (revision 87138) +++ head/crypto/telnet/telnet/externs.h (revision 87139) @@ -1,493 +1,491 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)externs.h 8.3 (Berkeley) 5/30/95 * $FreeBSD$ */ #ifndef BSD # define BSD 43 #endif /* * ucb stdio.h defines BSD as something weird */ #if defined(sun) && defined(__svr4__) #define BSD 43 #endif #ifndef USE_TERMIO # if BSD > 43 || defined(SYSV_TERMIO) # define USE_TERMIO # endif #endif #include #include -#ifndef FILIO_H #include -#else -#include -#endif -# include +#include #ifdef USE_TERMIO # ifndef VINTR -# ifdef SYSV_TERMIO -# include -# else -# include -# define termio termios -# endif +# include # endif +# define termio termios #endif #if defined(NO_CC_T) || !defined(USE_TERMIO) # if !defined(USE_TERMIO) typedef char cc_t; # else typedef unsigned char cc_t; # endif #endif -#ifndef NO_STRING_H #include -#else -#include -#endif #if defined(IPSEC) #include #if defined(IPSEC_POLICY_IPSEC) extern char *ipsec_policy_in; extern char *ipsec_policy_out; #endif #endif #ifndef _POSIX_VDISABLE # ifdef sun # include /* pick up VDISABLE definition, mayby */ # endif # ifdef VDISABLE # define _POSIX_VDISABLE VDISABLE # else # define _POSIX_VDISABLE ((cc_t)'\377') # endif #endif #define SUBBUFSIZE 256 #if !defined(P) # ifdef __STDC__ # define P(x) x # else # define P(x) () # endif #endif extern int autologin, /* Autologin enabled */ skiprc, /* Don't process the ~/.telnetrc file */ eight, /* use eight bit mode (binary in and/or out */ family, /* address family of peer */ flushout, /* flush output */ connected, /* Are we connected to the other side? */ globalmode, /* Mode tty should be in */ - In3270, /* Are we in 3270 mode? */ telnetport, /* Are we connected to the telnet port? */ localflow, /* Flow control handled locally */ restartany, /* If flow control, restart output on any character */ localchars, /* we recognize interrupt/quit */ donelclchars, /* the user has set "localchars" */ showoptions, net, /* Network file descriptor */ tin, /* Terminal input file descriptor */ tout, /* Terminal output file descriptor */ crlf, /* Should '\r' be mapped to (or )? */ autoflush, /* flush output when interrupting? */ autosynch, /* send interrupt characters with SYNCH? */ SYNCHing, /* Is the stream in telnet SYNCH mode? */ donebinarytoggle, /* the user has put us in binary */ dontlecho, /* do we suppress local echoing right now? */ crmod, netdata, /* Print out network data flow */ prettydump, /* Print "netdata" output in user readable format */ -#if defined(unix) -#if defined(TN3270) - cursesdata, /* Print out curses data flow */ - apitrace, /* Trace API transactions */ -#endif /* defined(TN3270) */ termdata, /* Print out terminal data flow */ -#endif /* defined(unix) */ debug, /* Debug level */ doaddrlookup, /* do a reverse lookup? */ clienteof; /* Client received EOF */ extern cc_t escape; /* Escape to command mode */ extern cc_t rlogin; /* Rlogin mode escape character */ #ifdef KLUDGELINEMODE extern cc_t echoc; /* Toggle local echoing */ #endif extern char *prompt; /* Prompt for command. */ extern char doopt[], dont[], will[], wont[], options[], /* All the little options */ *hostname; /* Who are we connected to? */ #ifdef ENCRYPTION extern void (*encrypt_output) P((unsigned char *, int)); extern int (*decrypt_input) P((int)); #endif /* ENCRYPTION */ /* * We keep track of each side of the option negotiation. */ #define MY_STATE_WILL 0x01 #define MY_WANT_STATE_WILL 0x02 #define MY_STATE_DO 0x04 #define MY_WANT_STATE_DO 0x08 /* * Macros to check the current state of things */ #define my_state_is_do(opt) (options[opt]&MY_STATE_DO) #define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) #define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) #define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) #define my_state_is_dont(opt) (!my_state_is_do(opt)) #define my_state_is_wont(opt) (!my_state_is_will(opt)) #define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) #define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) #define set_my_state_do(opt) {options[opt] |= MY_STATE_DO;} #define set_my_state_will(opt) {options[opt] |= MY_STATE_WILL;} #define set_my_want_state_do(opt) {options[opt] |= MY_WANT_STATE_DO;} #define set_my_want_state_will(opt) {options[opt] |= MY_WANT_STATE_WILL;} #define set_my_state_dont(opt) {options[opt] &= ~MY_STATE_DO;} #define set_my_state_wont(opt) {options[opt] &= ~MY_STATE_WILL;} #define set_my_want_state_dont(opt) {options[opt] &= ~MY_WANT_STATE_DO;} #define set_my_want_state_wont(opt) {options[opt] &= ~MY_WANT_STATE_WILL;} /* * Make everything symetrical */ #define HIS_STATE_WILL MY_STATE_DO #define HIS_WANT_STATE_WILL MY_WANT_STATE_DO #define HIS_STATE_DO MY_STATE_WILL #define HIS_WANT_STATE_DO MY_WANT_STATE_WILL #define his_state_is_do my_state_is_will #define his_state_is_will my_state_is_do #define his_want_state_is_do my_want_state_is_will #define his_want_state_is_will my_want_state_is_do #define his_state_is_dont my_state_is_wont #define his_state_is_wont my_state_is_dont #define his_want_state_is_dont my_want_state_is_wont #define his_want_state_is_wont my_want_state_is_dont #define set_his_state_do set_my_state_will #define set_his_state_will set_my_state_do #define set_his_want_state_do set_my_want_state_will #define set_his_want_state_will set_my_want_state_do #define set_his_state_dont set_my_state_wont #define set_his_state_wont set_my_state_dont #define set_his_want_state_dont set_my_want_state_wont #define set_his_want_state_wont set_my_want_state_dont +#if defined(USE_TERMIO) +#define SIG_FUNC_RET void +#else +#define SIG_FUNC_RET int +#endif +#ifdef SIGINFO +extern SIG_FUNC_RET + ayt_status P((void)); +#endif + extern FILE *NetTrace; /* Where debugging output goes */ extern unsigned char NetTraceFile[]; /* Name of file where debugging output goes */ extern void SetNetTrace P((char *)); /* Function to change where debugging goes */ extern jmp_buf peerdied, toplevel; /* For error conditions. */ extern void - command P((int, char *, int)), - Dump P((int, unsigned char *, int)), - ExitString P((char *, int)), - init_3270 P((void)), - printoption P((char *, int, int)), - printsub P((int, unsigned char *, int)), + command P((int, const char *, int)), + Dump P((char, unsigned char *, int)), + env_init P((void)), + Exit P((int)), + ExitString P((const char *, int)), + init_network P((void)), + init_sys P((void)), + init_telnet P((void)), + init_terminal P((void)), + intp P((void)), + optionstatus P((void)), + printoption P((const char *, int, int)), + printsub P((char, unsigned char *, int)), + quit P((void)), + sendabort P((void)), + sendbrk P((void)), + sendeof P((void)), + sendsusp P((void)), sendnaws P((void)), + sendayt P((void)), setconnmode P((int)), setcommandmode P((void)), + set_escape_char P((char *s)), setneturg P((void)), sys_telnet_init P((void)), telnet P((char *)), tel_enter_binary P((int)), + tel_leave_binary P((int)), TerminalFlushOutput P((void)), TerminalNewMode P((int)), TerminalRestoreState P((void)), TerminalSaveState P((void)), + TerminalDefaultChars P((void)), + TerminalSpeeds P((long *, long *)), tninit P((void)), upcase P((char *)), willoption P((int)), wontoption P((int)); extern void send_do P((int, int)), send_dont P((int, int)), send_will P((int, int)), send_wont P((int, int)); extern void lm_will P((unsigned char *, int)), lm_wont P((unsigned char *, int)), lm_do P((unsigned char *, int)), lm_dont P((unsigned char *, int)), lm_mode P((unsigned char *, int, int)); extern void slc_init P((void)), slcstate P((void)), slc_mode_export P((void)), slc_mode_import P((int)), slc_import P((int)), slc_export P((void)), slc P((unsigned char *, int)), slc_check P((void)), slc_start_reply P((void)), - slc_add_reply P((int, int, int)), + slc_add_reply P((unsigned char, unsigned char, cc_t)), slc_end_reply P((void)); extern int + getconnmode P((void)), + opt_welldefined P((const char *)), NetClose P((int)), netflush P((void)), + process_rings P((int, int, int, int, int, int)), + rlogin_susp P((void)), SetSockOpt P((int, int, int, int)), slc_update P((void)), + stilloob P((void)), telrcv P((void)), + TerminalRead P((char *, int)), TerminalWrite P((char *, int)), TerminalAutoFlush P((void)), + TerminalWindowSize P((long *, long *)), + TerminalSpecialChars P((int)), + tn P((int, char **)), ttyflush P((int)); extern void env_opt P((unsigned char *, int)), env_opt_start P((void)), env_opt_start_info P((void)), env_opt_add P((unsigned char *)), env_opt_end P((int)); extern unsigned char *env_default P((int, int)), - *env_getvalue P((unsigned char *)); + *env_getvalue P((const unsigned char *)); extern int - get_status P((void)), - dosynch P((void)); + get_status P((char *)), + dosynch P((char *)); extern cc_t *tcval P((int)); #ifndef USE_TERMIO extern struct tchars ntc; extern struct ltchars nltc; extern struct sgttyb nttyb; # define termEofChar ntc.t_eofc # define termEraseChar nttyb.sg_erase # define termFlushChar nltc.t_flushc # define termIntChar ntc.t_intrc # define termKillChar nttyb.sg_kill # define termLiteralNextChar nltc.t_lnextc # define termQuitChar ntc.t_quitc # define termSuspChar nltc.t_suspc # define termRprntChar nltc.t_rprntc # define termWerasChar nltc.t_werasc # define termStartChar ntc.t_startc # define termStopChar ntc.t_stopc # define termForw1Char ntc.t_brkc extern cc_t termForw2Char; extern cc_t termAytChar; # define termEofCharp (cc_t *)&ntc.t_eofc # define termEraseCharp (cc_t *)&nttyb.sg_erase # define termFlushCharp (cc_t *)&nltc.t_flushc # define termIntCharp (cc_t *)&ntc.t_intrc # define termKillCharp (cc_t *)&nttyb.sg_kill # define termLiteralNextCharp (cc_t *)&nltc.t_lnextc # define termQuitCharp (cc_t *)&ntc.t_quitc # define termSuspCharp (cc_t *)&nltc.t_suspc # define termRprntCharp (cc_t *)&nltc.t_rprntc # define termWerasCharp (cc_t *)&nltc.t_werasc # define termStartCharp (cc_t *)&ntc.t_startc # define termStopCharp (cc_t *)&ntc.t_stopc # define termForw1Charp (cc_t *)&ntc.t_brkc # define termForw2Charp (cc_t *)&termForw2Char # define termAytCharp (cc_t *)&termAytChar # else extern struct termio new_tc; # define termEofChar new_tc.c_cc[VEOF] # define termEraseChar new_tc.c_cc[VERASE] # define termIntChar new_tc.c_cc[VINTR] # define termKillChar new_tc.c_cc[VKILL] # define termQuitChar new_tc.c_cc[VQUIT] # ifndef VSUSP extern cc_t termSuspChar; # else # define termSuspChar new_tc.c_cc[VSUSP] # endif # if defined(VFLUSHO) && !defined(VDISCARD) # define VDISCARD VFLUSHO # endif # ifndef VDISCARD extern cc_t termFlushChar; # else # define termFlushChar new_tc.c_cc[VDISCARD] # endif # ifndef VWERASE extern cc_t termWerasChar; # else # define termWerasChar new_tc.c_cc[VWERASE] # endif # ifndef VREPRINT extern cc_t termRprntChar; # else # define termRprntChar new_tc.c_cc[VREPRINT] # endif # ifndef VLNEXT extern cc_t termLiteralNextChar; # else # define termLiteralNextChar new_tc.c_cc[VLNEXT] # endif # ifndef VSTART extern cc_t termStartChar; # else # define termStartChar new_tc.c_cc[VSTART] # endif # ifndef VSTOP extern cc_t termStopChar; # else # define termStopChar new_tc.c_cc[VSTOP] # endif # ifndef VEOL extern cc_t termForw1Char; # else # define termForw1Char new_tc.c_cc[VEOL] # endif # ifndef VEOL2 extern cc_t termForw2Char; # else # define termForw2Char new_tc.c_cc[VEOL] # endif # ifndef VSTATUS extern cc_t termAytChar; #else # define termAytChar new_tc.c_cc[VSTATUS] #endif # if defined(__STDC__) # define termEofCharp &termEofChar # define termEraseCharp &termEraseChar # define termIntCharp &termIntChar # define termKillCharp &termKillChar # define termQuitCharp &termQuitChar # define termSuspCharp &termSuspChar # define termFlushCharp &termFlushChar # define termWerasCharp &termWerasChar # define termRprntCharp &termRprntChar # define termLiteralNextCharp &termLiteralNextChar # define termStartCharp &termStartChar # define termStopCharp &termStopChar # define termForw1Charp &termForw1Char # define termForw2Charp &termForw2Char # define termAytCharp &termAytChar # else /* Work around a compiler bug */ # define termEofCharp 0 # define termEraseCharp 0 # define termIntCharp 0 # define termKillCharp 0 # define termQuitCharp 0 # define termSuspCharp 0 # define termFlushCharp 0 # define termWerasCharp 0 # define termRprntCharp 0 # define termLiteralNextCharp 0 # define termStartCharp 0 # define termStopCharp 0 # define termForw1Charp 0 # define termForw2Charp 0 # define termAytCharp 0 # endif #endif /* Ring buffer structures which are shared */ extern Ring netoring, netiring, ttyoring, ttyiring; -/* Tn3270 section */ -#if defined(TN3270) - -extern int - HaveInput, /* Whether an asynchronous I/O indication came in */ - noasynchtty, /* Don't do signals on I/O (SIGURG, SIGIO) */ - noasynchnet, /* Don't do signals on I/O (SIGURG, SIGIO) */ - sigiocount, /* Count of SIGIO receptions */ - shell_active; /* Subshell is active */ - -extern char - *Ibackp, /* Oldest byte of 3270 data */ - Ibuf[], /* 3270 buffer */ - *Ifrontp, /* Where next 3270 byte goes */ - tline[], - *transcom; /* Transparent command */ - -extern int - settranscom P((int, char**)); - extern void - inputAvailable P((int)); -#endif /* defined(TN3270) */ + xmitAO P((void)), + xmitEC P((void)), + xmitEL P((void)); Index: head/crypto/telnet/telnet/main.c =================================================================== --- head/crypto/telnet/telnet/main.c (revision 87138) +++ head/crypto/telnet/telnet/main.c (revision 87139) @@ -1,410 +1,377 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1988, 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); + #ifndef lint static const char sccsid[] = "@(#)main.c 8.3 (Berkeley) 5/30/95"; -#endif /* not lint */ +#endif #include #include #include #include #include #include "ring.h" #include "externs.h" #include "defines.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif /* These values need to be the same as defined in libtelnet/kerberos5.c */ /* Either define them in both places, or put in some common header file. */ #define OPTS_FORWARD_CREDS 0x00000002 #define OPTS_FORWARDABLE_CREDS 0x00000001 #if 0 #define FORWARD #endif -void init_terminal(void); -void init_network(void); -void init_telnet(void); -void init_sys(void); -void init_3270(void); - #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) char *ipsec_policy_in = NULL; char *ipsec_policy_out = NULL; #endif int family = AF_UNSPEC; /* * Initialize variables. */ - void -tninit() +void +tninit(void) { init_terminal(); init_network(); init_telnet(); init_sys(); - -#if defined(TN3270) - init_3270(); -#endif } - void -usage() +static void +usage(void) { fprintf(stderr, "Usage: %s %s%s%s%s\n", prompt, #ifdef AUTHENTICATION "[-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-c] [-d]", "\n\t[-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ", #else "[-4] [-6] [-8] [-E] [-L] [-N] [-S tos] [-c] [-d]", "\n\t[-e char] [-l user] [-n tracefile] ", #endif -#if defined(TN3270) && defined(unix) - "[-noasynch] [-noasynctty] [-noasyncnet] [-r]\n\t" - "[-s src_addr] [-t transcom] ", -#else "[-r] [-s src_addr] [-u] ", -#endif #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) "[-P policy] " #endif #ifdef ENCRYPTION "[-y] [host-name [port]]" #else /* ENCRYPTION */ "[host-name [port]]" #endif /* ENCRYPTION */ ); exit(1); } /* * main. Parse arguments, invoke the protocol or command parser. */ - int -main(argc, argv) - int argc; - char *argv[]; +int +main(int argc, char *argv[]) { int ch; char *user; char *src_addr = NULL; #ifdef FORWARD extern int forward_flags; #endif /* FORWARD */ tninit(); /* Clear out things */ TerminalSaveState(); if ((prompt = strrchr(argv[0], '/'))) ++prompt; else prompt = argv[0]; user = NULL; rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE; #ifdef AUTHENTICATION autologin = 1; #else autologin = -1; #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION encrypt_auto(1); decrypt_auto(1); #endif #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) #define IPSECOPT "P:" #else #define IPSECOPT #endif while ((ch = getopt(argc, argv, "468EKLNS:X:acde:fFk:l:n:rs:t:uxy" IPSECOPT)) != -1) #undef IPSECOPT { switch(ch) { case '4': family = AF_INET; break; #ifdef INET6 case '6': family = AF_INET6; break; #endif case '8': eight = 3; /* binary output and input */ break; case 'E': rlogin = escape = _POSIX_VDISABLE; break; case 'K': #ifdef AUTHENTICATION autologin = 0; #endif break; case 'L': eight |= 2; /* binary output only */ break; case 'N': doaddrlookup = 0; break; case 'S': { #ifdef HAS_GETTOS extern int tos; if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s%s\n", prompt, ": Bad TOS argument '", optarg, "; will try to use default TOS"); #else fprintf(stderr, "%s: Warning: -S ignored, no parsetos() support.\n", prompt); #endif } break; case 'X': #ifdef AUTHENTICATION auth_disable_name(optarg); #endif break; case 'a': #ifdef AUTHENTICATION /* It's the default now, so ignore */ #else autologin = 1; #endif break; case 'c': skiprc = 1; break; case 'd': debug = 1; break; case 'e': set_escape_char(optarg); break; case 'f': -#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) +#ifdef AUTHENTICATION +#if defined(KRB5) && defined(FORWARD) if (forward_flags & OPTS_FORWARD_CREDS) { fprintf(stderr, "%s: Only one of -f and -F allowed.\n", prompt); usage(); } forward_flags |= OPTS_FORWARD_CREDS; #else fprintf(stderr, "%s: Warning: -f ignored, no Kerberos V5 support.\n", prompt); #endif +#else + fprintf(stderr, + "%s: Warning: -f ignored, no Kerberos V5 support.\n", + prompt); +#endif break; case 'F': -#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) +#ifdef AUTHENTICATION +#if defined(KRB5) && defined(FORWARD) if (forward_flags & OPTS_FORWARD_CREDS) { fprintf(stderr, "%s: Only one of -f and -F allowed.\n", prompt); usage(); } forward_flags |= OPTS_FORWARD_CREDS; forward_flags |= OPTS_FORWARDABLE_CREDS; #else fprintf(stderr, "%s: Warning: -F ignored, no Kerberos V5 support.\n", prompt); #endif +#else + fprintf(stderr, + "%s: Warning: -F ignored, no Kerberos V5 support.\n", + prompt); +#endif break; case 'k': -#if defined(AUTHENTICATION) && defined(KRB4) +#ifdef AUTHENTICATION +#if defined(KRB4) { extern char *dest_realm, dst_realm_buf[], dst_realm_sz; dest_realm = dst_realm_buf; (void)strncpy(dest_realm, optarg, dst_realm_sz); } #else fprintf(stderr, "%s: Warning: -k ignored, no Kerberos V4 support.\n", prompt); #endif +#else + fprintf(stderr, + "%s: Warning: -k ignored, no Kerberos V4 support.\n", + prompt); +#endif break; case 'l': #ifdef AUTHENTICATION /* This is the default now, so ignore it */ #else autologin = 1; #endif user = optarg; break; case 'n': -#if defined(TN3270) && defined(unix) - /* distinguish between "-n oasynch" and "-noasynch" */ - if (argv[optind - 1][0] == '-' && argv[optind - 1][1] - == 'n' && argv[optind - 1][2] == 'o') { - if (!strcmp(optarg, "oasynch")) { - noasynchtty = 1; - noasynchnet = 1; - } else if (!strcmp(optarg, "oasynchtty")) - noasynchtty = 1; - else if (!strcmp(optarg, "oasynchnet")) - noasynchnet = 1; - } else -#endif /* defined(TN3270) && defined(unix) */ SetNetTrace(optarg); break; case 'r': rlogin = '~'; break; case 's': src_addr = optarg; break; - case 't': -#if defined(TN3270) && defined(unix) - transcom = tline; - (void)strcpy(transcom, optarg); -#else - fprintf(stderr, - "%s: Warning: -t ignored, no TN3270 support.\n", - prompt); -#endif - break; case 'u': family = AF_UNIX; break; case 'x': -#ifdef ENCRYPTION - /* This is the default now, so ignore it */ -#else +#ifndef ENCRYPTION fprintf(stderr, "%s: Warning: -x ignored, no ENCRYPT support.\n", prompt); #endif /* ENCRYPTION */ break; case 'y': #ifdef ENCRYPTION encrypt_auto(0); decrypt_auto(0); #else fprintf(stderr, "%s: Warning: -y ignored, no ENCRYPT support.\n", prompt); #endif /* ENCRYPTION */ break; #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) case 'P': if (!strncmp("in", optarg, 2)) ipsec_policy_in = strdup(optarg); else if (!strncmp("out", optarg, 3)) ipsec_policy_out = strdup(optarg); else usage(); break; #endif case '?': default: usage(); /* NOTREACHED */ } } if (autologin == -1) autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1; argc -= optind; argv += optind; if (argc) { char *args[9], **argp = args; if (argc > 2) usage(); *argp++ = prompt; if (user) { - *argp++ = "-l"; + *argp++ = strdup("-l"); *argp++ = user; } if (src_addr) { - *argp++ = "-s"; + *argp++ = strdup("-s"); *argp++ = src_addr; } *argp++ = argv[0]; /* host */ if (argc > 1) *argp++ = argv[1]; /* port */ *argp = 0; if (setjmp(toplevel) != 0) Exit(0); if (tn(argp - args, args) == 1) return (0); else return (1); } (void)setjmp(toplevel); for (;;) { -#ifdef TN3270 - if (shell_active) - shell_continue(); - else -#endif command(1, 0, 0); } return 0; } Index: head/crypto/telnet/telnet/network.c =================================================================== --- head/crypto/telnet/telnet/network.c (revision 87138) +++ head/crypto/telnet/telnet/network.c (revision 87139) @@ -1,183 +1,181 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)network.c 8.2 (Berkeley) 12/15/93"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #include #include #include #include #include #include #include "ring.h" #include "defines.h" #include "externs.h" #include "fdset.h" Ring netoring, netiring; unsigned char netobuf[2*BUFSIZ], netibuf[BUFSIZ]; /* * Initialize internal network data structures. */ - void -init_network() +void +init_network(void) { if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) { exit(1); } if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) { exit(1); } NetTrace = stdout; } /* * Check to see if any out-of-band data exists on a socket (for * Telnet "synch" processing). */ - int -stilloob() +int +stilloob(void) { - static struct timeval timeout = { 0 }; + static struct timeval timeout = { 0, 0 }; fd_set excepts; int value; do { FD_ZERO(&excepts); FD_SET(net, &excepts); value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); } while ((value == -1) && (errno == EINTR)); if (value < 0) { perror("select"); (void) quit(); /* NOTREACHED */ } if (FD_ISSET(net, &excepts)) { return 1; } else { return 0; } } /* * setneturg() * * Sets "neturg" to the current location. */ - void -setneturg() +void +setneturg(void) { ring_mark(&netoring); } /* * netflush * Send as much data as possible to the network, * handling requests for urgent data. * * The return value indicates whether we did any * useful work. */ - - int -netflush() +int +netflush(void) { - register int n, n1; + int n, n1; #ifdef ENCRYPTION if (encrypt_output) ring_encrypt(&netoring, encrypt_output); #endif /* ENCRYPTION */ if ((n1 = n = ring_full_consecutive(&netoring)) > 0) { if (!ring_at_mark(&netoring)) { n = send(net, (char *)netoring.consume, n, 0); /* normal write */ } else { /* * In 4.2 (and 4.3) systems, there is some question about * what byte in a sendOOB operation is the "OOB" data. * To make ourselves compatible, we only send ONE byte * out of band, the one WE THINK should be OOB (though * we really have more the TCP philosophy of urgent data * rather than the Unix philosophy of OOB data). */ n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */ } } if (n < 0) { if (errno != ENOBUFS && errno != EWOULDBLOCK) { setcommandmode(); perror(hostname); (void)NetClose(net); ring_clear_mark(&netoring); longjmp(peerdied, -1); /*NOTREACHED*/ } n = 0; } if (netdata && n) { Dump('>', netoring.consume, n); } if (n) { ring_consumed(&netoring, n); /* * If we sent all, and more to send, then recurse to pick * up the other half. */ if ((n1 == n) && ring_full_consecutive(&netoring)) { (void) netflush(); } return 1; } else { return 0; } } Index: head/crypto/telnet/telnet/ring.c =================================================================== --- head/crypto/telnet/telnet/ring.c (revision 87138) +++ head/crypto/telnet/telnet/ring.c (revision 87139) @@ -1,369 +1,322 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)ring.c 8.2 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ /* * This defines a structure for a ring buffer. * * The circular buffer has two parts: *((( * full: [consume, supply) * empty: [supply, consume) *]]] * */ #include #include #include #ifdef size_t #undef size_t #endif #include #ifndef FILIO_H #include #endif #include #include "ring.h" #include "general.h" /* Internal macros */ #if !defined(MIN) #define MIN(a,b) (((a)<(b))? (a):(b)) #endif /* !defined(MIN) */ #define ring_subtract(d,a,b) (((a)-(b) >= 0)? \ (a)-(b): (((a)-(b))+(d)->size)) #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ (a)+(c) : (((a)+(c))-(d)->size)) #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \ (a)-(c) : (((a)-(c))-(d)->size)) /* * The following is a clock, used to determine full, empty, etc. * * There is some trickiness here. Since the ring buffers are initialized * to ZERO on allocation, we need to make sure, when interpreting the * clock, that when the times are EQUAL, then the buffer is FULL. */ static u_long ring_clock = 0; #define ring_empty(d) (((d)->consume == (d)->supply) && \ ((d)->consumetime >= (d)->supplytime)) #define ring_full(d) (((d)->supply == (d)->consume) && \ ((d)->supplytime > (d)->consumetime)) - - - - /* Buffer state transition routines */ - int -ring_init(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; +int +ring_init(Ring *ring, unsigned char *buffer, int count) { memset((char *)ring, 0, sizeof *ring); ring->size = count; ring->supply = ring->consume = ring->bottom = buffer; ring->top = ring->bottom+ring->size; #ifdef ENCRYPTION ring->clearto = 0; #endif /* ENCRYPTION */ return 1; } /* Mark routines */ /* * Mark the most recently supplied byte. */ - void -ring_mark(ring) - Ring *ring; +void +ring_mark(Ring *ring) { ring->mark = ring_decrement(ring, ring->supply, 1); } /* * Is the ring pointing to the mark? */ - int -ring_at_mark(ring) - Ring *ring; +int +ring_at_mark(Ring *ring) { if (ring->mark == ring->consume) { return 1; } else { return 0; } } /* * Clear any mark set on the ring. */ - void -ring_clear_mark(ring) - Ring *ring; +void +ring_clear_mark(Ring *ring) { ring->mark = 0; } /* * Add characters from current segment to ring buffer. */ - void -ring_supplied(ring, count) - Ring *ring; - int count; +void +ring_supplied(Ring *ring, int count) { ring->supply = ring_increment(ring, ring->supply, count); ring->supplytime = ++ring_clock; } /* * We have just consumed "c" bytes. */ - void -ring_consumed(ring, count) - Ring *ring; - int count; +void +ring_consumed(Ring *ring, int count) { if (count == 0) /* don't update anything */ return; if (ring->mark && (ring_subtract(ring, ring->mark, ring->consume) < count)) { ring->mark = 0; } #ifdef ENCRYPTION if (ring->consume < ring->clearto && ring->clearto <= ring->consume + count) ring->clearto = 0; else if (ring->consume + count > ring->top && ring->bottom <= ring->clearto && ring->bottom + ((ring->consume + count) - ring->top)) ring->clearto = 0; #endif /* ENCRYPTION */ ring->consume = ring_increment(ring, ring->consume, count); ring->consumetime = ++ring_clock; /* * Try to encourage "ring_empty_consecutive()" to be large. */ if (ring_empty(ring)) { ring->consume = ring->supply = ring->bottom; } } /* Buffer state query routines */ /* Number of bytes that may be supplied */ - int -ring_empty_count(ring) - Ring *ring; +int +ring_empty_count(Ring *ring) { if (ring_empty(ring)) { /* if empty */ return ring->size; } else { return ring_subtract(ring, ring->consume, ring->supply); } } /* number of CONSECUTIVE bytes that may be supplied */ - int -ring_empty_consecutive(ring) - Ring *ring; +int +ring_empty_consecutive(Ring *ring) { if ((ring->consume < ring->supply) || ring_empty(ring)) { /* * if consume is "below" supply, or empty, then * return distance to the top */ return ring_subtract(ring, ring->top, ring->supply); } else { /* * else, return what we may. */ return ring_subtract(ring, ring->consume, ring->supply); } } /* Return the number of bytes that are available for consuming * (but don't give more than enough to get to cross over set mark) */ - int -ring_full_count(ring) - Ring *ring; +int +ring_full_count(Ring *ring) { if ((ring->mark == 0) || (ring->mark == ring->consume)) { if (ring_full(ring)) { return ring->size; /* nothing consumed, but full */ } else { return ring_subtract(ring, ring->supply, ring->consume); } } else { return ring_subtract(ring, ring->mark, ring->consume); } } /* * Return the number of CONSECUTIVE bytes available for consuming. * However, don't return more than enough to cross over set mark. */ - int -ring_full_consecutive(ring) - Ring *ring; +int +ring_full_consecutive(Ring *ring) { if ((ring->mark == 0) || (ring->mark == ring->consume)) { if ((ring->supply < ring->consume) || ring_full(ring)) { return ring_subtract(ring, ring->top, ring->consume); } else { return ring_subtract(ring, ring->supply, ring->consume); } } else { if (ring->mark < ring->consume) { return ring_subtract(ring, ring->top, ring->consume); } else { /* Else, distance to mark */ return ring_subtract(ring, ring->mark, ring->consume); } } } /* * Move data into the "supply" portion of of the ring buffer. */ - void -ring_supply_data(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; +void +ring_supply_data(Ring *ring, unsigned char *buffer, int count) { int i; while (count) { i = MIN(count, ring_empty_consecutive(ring)); memcpy(ring->supply, buffer, i); ring_supplied(ring, i); count -= i; buffer += i; } } -#ifdef notdef - -/* - * Move data from the "consume" portion of the ring buffer - */ - void -ring_consume_data(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; -{ - int i; - - while (count) { - i = MIN(count, ring_full_consecutive(ring)); - memcpy(buffer, ring->consume, i); - ring_consumed(ring, i); - count -= i; - buffer += i; - } -} -#endif - #ifdef ENCRYPTION - void -ring_encrypt(ring, encryptor) - Ring *ring; - void (*encryptor)(); +void +ring_encrypt(Ring *ring, void (*encryptor)(unsigned char *, int)) { unsigned char *s, *c; if (ring_empty(ring) || ring->clearto == ring->supply) return; if (!(c = ring->clearto)) c = ring->consume; s = ring->supply; if (s <= c) { (*encryptor)(c, ring->top - c); (*encryptor)(ring->bottom, s - ring->bottom); } else (*encryptor)(c, s - c); ring->clearto = ring->supply; } void ring_clearto(ring) Ring *ring; { if (!ring_empty(ring)) ring->clearto = ring->supply; else ring->clearto = 0; } #endif /* ENCRYPTION */ Index: head/crypto/telnet/telnet/ring.h =================================================================== --- head/crypto/telnet/telnet/ring.h (revision 87138) +++ head/crypto/telnet/telnet/ring.h (revision 87139) @@ -1,106 +1,107 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ring.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #if defined(P) # undef P #endif #if defined(__STDC__) || defined(LINT_ARGS) # define P(x) x #else # define P(x) () #endif /* * This defines a structure for a ring buffer. * * The circular buffer has two parts: *((( * full: [consume, supply) * empty: [supply, consume) *]]] * */ typedef struct { unsigned char *consume, /* where data comes out of */ *supply, /* where data comes in to */ *bottom, /* lowest address in buffer */ *top, /* highest address+1 in buffer */ *mark; /* marker (user defined) */ #ifdef ENCRYPTION unsigned char *clearto; /* Data to this point is clear text */ unsigned char *encryyptedto; /* Data is encrypted to here */ #endif /* ENCRYPTION */ int size; /* size in bytes of buffer */ u_long consumetime, /* help us keep straight full, empty, etc. */ supplytime; } Ring; /* Here are some functions and macros to deal with the ring buffer */ /* Initialization routine */ extern int ring_init P((Ring *ring, unsigned char *buffer, int count)); /* Data movement routines */ extern void ring_supply_data P((Ring *ring, unsigned char *buffer, int count)); #ifdef notdef extern void ring_consume_data P((Ring *ring, unsigned char *buffer, int count)); #endif /* Buffer state transition routines */ extern void ring_supplied P((Ring *ring, int count)), ring_consumed P((Ring *ring, int count)); /* Buffer state query routines */ extern int + ring_at_mark P((Ring *)), ring_empty_count P((Ring *ring)), ring_empty_consecutive P((Ring *ring)), ring_full_count P((Ring *ring)), ring_full_consecutive P((Ring *ring)); #ifdef ENCRYPTION extern void - ring_encrypt P((Ring *ring, void (*func)())), + ring_encrypt P((Ring *ring, void (*func)(unsigned char *, int))), ring_clearto P((Ring *ring)); #endif /* ENCRYPTION */ extern void - ring_clear_mark P((Ring *)), - ring_mark P((Ring *)); + ring_clear_mark P((Ring *)), + ring_mark P((Ring *)); Index: head/crypto/telnet/telnet/sys_bsd.c =================================================================== --- head/crypto/telnet/telnet/sys_bsd.c (revision 87138) +++ head/crypto/telnet/telnet/sys_bsd.c (revision 87139) @@ -1,1244 +1,1121 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ /* * The following routines try to encapsulate what is system dependent * (at least between 4.x and dos) which is used in telnet.c. */ - -#include #include -#include #include -#include +#include #include -#include +#include +#include #include +#include #include "ring.h" - #include "fdset.h" - #include "defines.h" #include "externs.h" #include "types.h" -#if defined(USE_TERMIO) && !defined(SYSV_TERMIO) -#define SIG_FUNC_RET void -#else -#define SIG_FUNC_RET int -#endif - -#ifdef SIGINFO -extern SIG_FUNC_RET ayt_status(); -#endif - int tout, /* Output file descriptor */ tin, /* Input file descriptor */ net; #ifndef USE_TERMIO struct tchars otc = { 0 }, ntc = { 0 }; struct ltchars oltc = { 0 }, nltc = { 0 }; struct sgttyb ottyb = { 0 }, nttyb = { 0 }; int olmode = 0; # define cfgetispeed(ptr) (ptr)->sg_ispeed # define cfgetospeed(ptr) (ptr)->sg_ospeed # define old_tc ottyb #else /* USE_TERMIO */ -struct termio old_tc = { 0 }; -extern struct termio new_tc; +struct termio old_tc = { 0, 0, 0, 0, {}, 0, 0 }; # ifndef TCSANOW # ifdef TCSETS # define TCSANOW TCSETS # define TCSADRAIN TCSETSW # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) # else # ifdef TCSETA # define TCSANOW TCSETA # define TCSADRAIN TCSETAW # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) # else # define TCSANOW TIOCSETA # define TCSADRAIN TIOCSETAW # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) # endif # endif # define tcsetattr(f, a, t) ioctl(f, a, (char *)t) # define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) # ifdef CIBAUD # define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) # else # define cfgetispeed(ptr) cfgetospeed(ptr) # endif # endif /* TCSANOW */ # ifdef sysV88 # define TIOCFLUSH TC_PX_DRAIN # endif #endif /* USE_TERMIO */ static fd_set ibits, obits, xbits; +#ifdef SIGINT +static SIG_FUNC_RET intr(int); +#endif /* SIGINT */ +#ifdef SIGQUIT +static SIG_FUNC_RET intr2(int); +#endif /* SIGQUIT */ +#ifdef SIGTSTP +static SIG_FUNC_RET susp(int); +#endif /* SIGTSTP */ +#ifdef SIGINFO +static SIG_FUNC_RET ayt(int); +#endif - void -init_sys() +void +init_sys(void) { tout = fileno(stdout); tin = fileno(stdin); FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&xbits); errno = 0; } - - int -TerminalWrite(buf, n) - char *buf; - int n; +int +TerminalWrite(char *buf, int n) { return write(tout, buf, n); } - int -TerminalRead(buf, n) - char *buf; - int n; +int +TerminalRead(char *buf, int n) { return read(tin, buf, n); } /* * */ - int -TerminalAutoFlush() +int +TerminalAutoFlush(void) { #if defined(LNOFLSH) int flush; ioctl(0, TIOCLGET, (char *)&flush); return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ #else /* LNOFLSH */ return 1; #endif /* LNOFLSH */ } #ifdef KLUDGELINEMODE extern int kludgelinemode; #endif /* * TerminalSpecialChars() * * Look at an input character to see if it is a special character * and decide what to do. * * Output: * * 0 Don't add this character. * 1 Do add this character */ -extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); - - int -TerminalSpecialChars(c) - int c; +int +TerminalSpecialChars(int c) { if (c == termIntChar) { intp(); return 0; } else if (c == termQuitChar) { #ifdef KLUDGELINEMODE if (kludgelinemode) sendbrk(); else #endif sendabort(); return 0; } else if (c == termEofChar) { if (my_want_state_is_will(TELOPT_LINEMODE)) { sendeof(); return 0; } return 1; } else if (c == termSuspChar) { sendsusp(); return(0); } else if (c == termFlushChar) { xmitAO(); /* Transmit Abort Output */ return 0; } else if (!MODE_LOCAL_CHARS(globalmode)) { if (c == termKillChar) { xmitEL(); return 0; } else if (c == termEraseChar) { xmitEC(); /* Transmit Erase Character */ return 0; } } return 1; } /* * Flush output to the terminal */ - void -TerminalFlushOutput() +void +TerminalFlushOutput(void) { #ifdef TIOCFLUSH (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); #else (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); #endif } - void -TerminalSaveState() +void +TerminalSaveState(void) { #ifndef USE_TERMIO ioctl(0, TIOCGETP, (char *)&ottyb); ioctl(0, TIOCGETC, (char *)&otc); ioctl(0, TIOCGLTC, (char *)&oltc); ioctl(0, TIOCLGET, (char *)&olmode); ntc = otc; nltc = oltc; nttyb = ottyb; #else /* USE_TERMIO */ tcgetattr(0, &old_tc); new_tc = old_tc; #ifndef VDISCARD termFlushChar = CONTROL('O'); #endif #ifndef VWERASE termWerasChar = CONTROL('W'); #endif #ifndef VREPRINT termRprntChar = CONTROL('R'); #endif #ifndef VLNEXT termLiteralNextChar = CONTROL('V'); #endif #ifndef VSTART termStartChar = CONTROL('Q'); #endif #ifndef VSTOP termStopChar = CONTROL('S'); #endif #ifndef VSTATUS termAytChar = CONTROL('T'); #endif #endif /* USE_TERMIO */ } - cc_t * -tcval(func) - register int func; +cc_t * +tcval(int func) { switch(func) { case SLC_IP: return(&termIntChar); case SLC_ABORT: return(&termQuitChar); case SLC_EOF: return(&termEofChar); case SLC_EC: return(&termEraseChar); case SLC_EL: return(&termKillChar); case SLC_XON: return(&termStartChar); case SLC_XOFF: return(&termStopChar); case SLC_FORW1: return(&termForw1Char); #ifdef USE_TERMIO case SLC_FORW2: return(&termForw2Char); # ifdef VDISCARD case SLC_AO: return(&termFlushChar); # endif # ifdef VSUSP case SLC_SUSP: return(&termSuspChar); # endif # ifdef VWERASE case SLC_EW: return(&termWerasChar); # endif # ifdef VREPRINT case SLC_RP: return(&termRprntChar); # endif # ifdef VLNEXT case SLC_LNEXT: return(&termLiteralNextChar); # endif # ifdef VSTATUS case SLC_AYT: return(&termAytChar); # endif #endif case SLC_SYNCH: case SLC_BRK: case SLC_EOR: default: return((cc_t *)0); } } - void -TerminalDefaultChars() +void +TerminalDefaultChars(void) { #ifndef USE_TERMIO ntc = otc; nltc = oltc; nttyb.sg_kill = ottyb.sg_kill; nttyb.sg_erase = ottyb.sg_erase; #else /* USE_TERMIO */ memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); # ifndef VDISCARD termFlushChar = CONTROL('O'); # endif # ifndef VWERASE termWerasChar = CONTROL('W'); # endif # ifndef VREPRINT termRprntChar = CONTROL('R'); # endif # ifndef VLNEXT termLiteralNextChar = CONTROL('V'); # endif # ifndef VSTART termStartChar = CONTROL('Q'); # endif # ifndef VSTOP termStopChar = CONTROL('S'); # endif # ifndef VSTATUS termAytChar = CONTROL('T'); # endif #endif /* USE_TERMIO */ } -#ifdef notdef -void -TerminalRestoreState() -{ -} -#endif - /* * TerminalNewMode - set up terminal to a specific mode. * MODE_ECHO: do local terminal echo * MODE_FLOW: do local flow control * MODE_TRAPSIG: do local mapping to TELNET IAC sequences * MODE_EDIT: do local line editing * * Command mode: * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG * local echo * local editing * local xon/xoff * local signal mapping * * Linemode: * local/no editing * Both Linemode and Single Character mode: * local/remote echo * local/no xon/xoff * local/no signal mapping */ - - void -TerminalNewMode(f) - register int f; +void +TerminalNewMode(int f) { static int prevmode = 0; #ifndef USE_TERMIO struct tchars tc; struct ltchars ltc; struct sgttyb sb; int lmode; #else /* USE_TERMIO */ struct termio tmp_tc; #endif /* USE_TERMIO */ int onoff; int old; cc_t esc; globalmode = f&~MODE_FORCE; if (prevmode == f) return; /* * Write any outstanding data before switching modes * ttyflush() returns 0 only when there is no more data * left to write out, it returns -1 if it couldn't do * anything at all, otherwise it returns 1 + the number * of characters left to write. #ifndef USE_TERMIO * We would really like ask the kernel to wait for the output * to drain, like we can do with the TCSADRAIN, but we don't have * that option. The only ioctl that waits for the output to * drain, TIOCSETP, also flushes the input queue, which is NOT * what we want (TIOCSETP is like TCSADFLUSH). #endif */ old = ttyflush(SYNCHing|flushout); if (old < 0 || old > 1) { #ifdef USE_TERMIO tcgetattr(tin, &tmp_tc); #endif /* USE_TERMIO */ do { /* * Wait for data to drain, then flush again. */ #ifdef USE_TERMIO tcsetattr(tin, TCSADRAIN, &tmp_tc); #endif /* USE_TERMIO */ old = ttyflush(SYNCHing|flushout); } while (old < 0 || old > 1); } old = prevmode; prevmode = f&~MODE_FORCE; #ifndef USE_TERMIO sb = nttyb; tc = ntc; ltc = nltc; lmode = olmode; #else tmp_tc = new_tc; #endif if (f&MODE_ECHO) { #ifndef USE_TERMIO sb.sg_flags |= ECHO; #else tmp_tc.c_lflag |= ECHO; tmp_tc.c_oflag |= ONLCR; if (crlf) tmp_tc.c_iflag |= ICRNL; #endif } else { #ifndef USE_TERMIO sb.sg_flags &= ~ECHO; #else tmp_tc.c_lflag &= ~ECHO; tmp_tc.c_oflag &= ~ONLCR; -# ifdef notdef - if (crlf) - tmp_tc.c_iflag &= ~ICRNL; -# endif #endif } if ((f&MODE_FLOW) == 0) { #ifndef USE_TERMIO tc.t_startc = _POSIX_VDISABLE; tc.t_stopc = _POSIX_VDISABLE; #else tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ } else { if (restartany < 0) { tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ } else if (restartany > 0) { tmp_tc.c_iflag |= IXOFF|IXON|IXANY; } else { tmp_tc.c_iflag |= IXOFF|IXON; tmp_tc.c_iflag &= ~IXANY; } #endif } if ((f&MODE_TRAPSIG) == 0) { #ifndef USE_TERMIO tc.t_intrc = _POSIX_VDISABLE; tc.t_quitc = _POSIX_VDISABLE; tc.t_eofc = _POSIX_VDISABLE; ltc.t_suspc = _POSIX_VDISABLE; ltc.t_dsuspc = _POSIX_VDISABLE; #else tmp_tc.c_lflag &= ~ISIG; #endif localchars = 0; } else { #ifdef USE_TERMIO tmp_tc.c_lflag |= ISIG; #endif localchars = 1; } if (f&MODE_EDIT) { #ifndef USE_TERMIO sb.sg_flags &= ~CBREAK; sb.sg_flags |= CRMOD; #else tmp_tc.c_lflag |= ICANON; #endif } else { #ifndef USE_TERMIO sb.sg_flags |= CBREAK; if (f&MODE_ECHO) sb.sg_flags |= CRMOD; else sb.sg_flags &= ~CRMOD; #else tmp_tc.c_lflag &= ~ICANON; tmp_tc.c_iflag &= ~ICRNL; tmp_tc.c_cc[VMIN] = 1; tmp_tc.c_cc[VTIME] = 0; #endif } if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { #ifndef USE_TERMIO ltc.t_lnextc = _POSIX_VDISABLE; #else # ifdef VLNEXT tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); # endif #endif } if (f&MODE_SOFT_TAB) { #ifndef USE_TERMIO sb.sg_flags |= XTABS; #else # ifdef OXTABS tmp_tc.c_oflag |= OXTABS; # endif # ifdef TABDLY tmp_tc.c_oflag &= ~TABDLY; tmp_tc.c_oflag |= TAB3; # endif #endif } else { #ifndef USE_TERMIO sb.sg_flags &= ~XTABS; #else # ifdef OXTABS tmp_tc.c_oflag &= ~OXTABS; # endif # ifdef TABDLY tmp_tc.c_oflag &= ~TABDLY; # endif #endif } if (f&MODE_LIT_ECHO) { #ifndef USE_TERMIO lmode &= ~LCTLECH; #else # ifdef ECHOCTL tmp_tc.c_lflag &= ~ECHOCTL; # endif #endif } else { #ifndef USE_TERMIO lmode |= LCTLECH; #else # ifdef ECHOCTL tmp_tc.c_lflag |= ECHOCTL; # endif #endif } if (f == -1) { onoff = 0; } else { #ifndef USE_TERMIO if (f & MODE_OUTBIN) lmode |= LLITOUT; else lmode &= ~LLITOUT; if (f & MODE_INBIN) lmode |= LPASS8; else lmode &= ~LPASS8; #else if (f & MODE_INBIN) tmp_tc.c_iflag &= ~ISTRIP; else tmp_tc.c_iflag |= ISTRIP; if (f & MODE_OUTBIN) { tmp_tc.c_cflag &= ~(CSIZE|PARENB); tmp_tc.c_cflag |= CS8; tmp_tc.c_oflag &= ~OPOST; } else { tmp_tc.c_cflag &= ~(CSIZE|PARENB); tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); tmp_tc.c_oflag |= OPOST; } #endif onoff = 1; } if (f != -1) { -#ifdef SIGINT - SIG_FUNC_RET intr(); -#endif /* SIGINT */ -#ifdef SIGQUIT - SIG_FUNC_RET intr2(); -#endif /* SIGQUIT */ -#ifdef SIGTSTP - SIG_FUNC_RET susp(); -#endif /* SIGTSTP */ -#ifdef SIGINFO - SIG_FUNC_RET ayt(); -#endif - #ifdef SIGINT (void) signal(SIGINT, intr); #endif #ifdef SIGQUIT (void) signal(SIGQUIT, intr2); #endif #ifdef SIGTSTP (void) signal(SIGTSTP, susp); #endif /* SIGTSTP */ #ifdef SIGINFO (void) signal(SIGINFO, ayt); #endif #if defined(USE_TERMIO) && defined(NOKERNINFO) tmp_tc.c_lflag |= NOKERNINFO; #endif /* * We don't want to process ^Y here. It's just another * character that we'll pass on to the back end. It has * to process it because it will be processed when the * user attempts to read it, not when we send it. */ #ifndef USE_TERMIO ltc.t_dsuspc = _POSIX_VDISABLE; #else # ifdef VDSUSP tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); # endif #endif #ifdef USE_TERMIO /* * If the VEOL character is already set, then use VEOL2, * otherwise use VEOL. */ esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; if ((tmp_tc.c_cc[VEOL] != esc) # ifdef VEOL2 && (tmp_tc.c_cc[VEOL2] != esc) # endif ) { if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) tmp_tc.c_cc[VEOL] = esc; # ifdef VEOL2 else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) tmp_tc.c_cc[VEOL2] = esc; # endif } #else if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) tc.t_brkc = esc; #endif } else { #ifdef SIGINFO - SIG_FUNC_RET ayt_status(); - - (void) signal(SIGINFO, ayt_status); + (void) signal(SIGINFO, (void (*)(int))ayt_status); #endif #ifdef SIGINT (void) signal(SIGINT, SIG_DFL); #endif #ifdef SIGQUIT (void) signal(SIGQUIT, SIG_DFL); #endif #ifdef SIGTSTP (void) signal(SIGTSTP, SIG_DFL); # ifndef SOLARIS (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); # else SOLARIS (void) sigrelse(SIGTSTP); # endif SOLARIS #endif /* SIGTSTP */ #ifndef USE_TERMIO ltc = oltc; tc = otc; sb = ottyb; lmode = olmode; #else tmp_tc = old_tc; #endif } #ifndef USE_TERMIO ioctl(tin, TIOCLSET, (char *)&lmode); ioctl(tin, TIOCSLTC, (char *)<c); ioctl(tin, TIOCSETC, (char *)&tc); ioctl(tin, TIOCSETN, (char *)&sb); #else if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) tcsetattr(tin, TCSANOW, &tmp_tc); #endif -#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) -# if !defined(sysV88) ioctl(tin, FIONBIO, (char *)&onoff); ioctl(tout, FIONBIO, (char *)&onoff); -# endif -#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ -#if defined(TN3270) - if (noasynchtty == 0) { - ioctl(tin, FIOASYNC, (char *)&onoff); - } -#endif /* defined(TN3270) */ } /* * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). */ #if B4800 != 4800 #define DECODE_BAUD #endif #ifdef DECODE_BAUD #ifndef B7200 #define B7200 B4800 #endif #ifndef B14400 #define B14400 B9600 #endif #ifndef B19200 # define B19200 B14400 #endif #ifndef B28800 #define B28800 B19200 #endif #ifndef B38400 # define B38400 B28800 #endif #ifndef B57600 #define B57600 B38400 #endif #ifndef B76800 #define B76800 B57600 #endif #ifndef B115200 #define B115200 B76800 #endif #ifndef B230400 #define B230400 B115200 #endif /* * This code assumes that the values B0, B50, B75... * are in ascending order. They do not have to be * contiguous. */ struct termspeeds { long speed; long value; } termspeeds[] = { { 0, B0 }, { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, { 230400, B230400 }, { -1, B230400 } }; #endif /* DECODE_BAUD */ - void -TerminalSpeeds(ispeed, ospeed) - long *ispeed; - long *ospeed; +void +TerminalSpeeds(long *ispeed, long *ospeed) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; #endif /* DECODE_BAUD */ - register long in, out; + long in, out; out = cfgetospeed(&old_tc); in = cfgetispeed(&old_tc); if (in == 0) in = out; #ifdef DECODE_BAUD tp = termspeeds; while ((tp->speed != -1) && (tp->value < in)) tp++; *ispeed = tp->speed; tp = termspeeds; while ((tp->speed != -1) && (tp->value < out)) tp++; *ospeed = tp->speed; #else /* DECODE_BAUD */ *ispeed = in; *ospeed = out; #endif /* DECODE_BAUD */ } - int -TerminalWindowSize(rows, cols) - long *rows, *cols; +int +TerminalWindowSize(long *rows, long *cols) { #ifdef TIOCGWINSZ struct winsize ws; if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { *rows = ws.ws_row; *cols = ws.ws_col; return 1; } #endif /* TIOCGWINSZ */ return 0; } - int -NetClose(fd) - int fd; +int +NetClose(int fd) { return close(fd); } - - void -NetNonblockingIO(fd, onoff) - int fd; - int onoff; +static void +NetNonblockingIO(int fd, int onoff) { ioctl(fd, FIONBIO, (char *)&onoff); } -#if defined(TN3270) - void -NetSigIO(fd, onoff) - int fd; - int onoff; -{ - ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ -} - - void -NetSetPgrp(fd) - int fd; -{ - int myPid; - - myPid = getpid(); - fcntl(fd, F_SETOWN, myPid); -} -#endif /*defined(TN3270)*/ /* * Various signal handling routines. */ - /* ARGSUSED */ - SIG_FUNC_RET -deadpeer(sig) - int sig; +/* ARGSUSED */ +static SIG_FUNC_RET +deadpeer(int sig __unused) { setcommandmode(); longjmp(peerdied, -1); } - /* ARGSUSED */ - SIG_FUNC_RET -intr(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +intr(int sig __unused) { if (localchars) { intp(); return; } setcommandmode(); longjmp(toplevel, -1); } - /* ARGSUSED */ - SIG_FUNC_RET -intr2(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +intr2(int sig __unused) { if (localchars) { #ifdef KLUDGELINEMODE if (kludgelinemode) sendbrk(); else #endif sendabort(); return; } } #ifdef SIGTSTP - /* ARGSUSED */ - SIG_FUNC_RET -susp(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +susp(int sig __unused) { if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) return; if (localchars) sendsusp(); } #endif #ifdef SIGWINCH - /* ARGSUSED */ - SIG_FUNC_RET -sendwin(sig) - int sig; +/* ARGSUSED */ +static SIG_FUNC_RET +sendwin(int sig __unused) { if (connected) { sendnaws(); } } #endif #ifdef SIGINFO - /* ARGSUSED */ - SIG_FUNC_RET -ayt(sig) - int sig; +/* ARGSUSED */ +SIG_FUNC_RET +ayt(int sig __unused) { if (connected) sendayt(); else ayt_status(); } #endif - void -sys_telnet_init() +void +sys_telnet_init(void) { (void) signal(SIGINT, intr); (void) signal(SIGQUIT, intr2); (void) signal(SIGPIPE, deadpeer); #ifdef SIGWINCH (void) signal(SIGWINCH, sendwin); #endif #ifdef SIGTSTP (void) signal(SIGTSTP, susp); #endif #ifdef SIGINFO (void) signal(SIGINFO, ayt); #endif setconnmode(0); NetNonblockingIO(net, 1); -#if defined(TN3270) - if (noasynchnet == 0) { /* DBX can't handle! */ - NetSigIO(net, 1); - NetSetPgrp(net); - } -#endif /* defined(TN3270) */ - #if defined(SO_OOBINLINE) if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { perror("SetSockOpt"); } #endif /* defined(SO_OOBINLINE) */ } /* * Process rings - * * This routine tries to fill up/empty our various rings. * * The parameter specifies whether this is a poll operation, * or a block-until-something-happens operation. * * The return value is 1 if something happened, 0 if not. */ - int -process_rings(netin, netout, netex, ttyin, ttyout, poll) - int poll; /* If 0, then block until something to do */ +int +process_rings(int netin, int netout, int netex, int ttyin, int ttyout, int poll) { - register int c; - /* One wants to be a bit careful about setting returnValue - * to one, since a one implies we did some useful work, - * and therefore probably won't be called to block next - * time (TN3270 mode only). - */ + int c; int returnValue = 0; - static struct timeval TimeValue = { 0 }; + static struct timeval TimeValue = { 0, 0 }; if (netout) { FD_SET(net, &obits); } if (ttyout) { FD_SET(tout, &obits); } -#if defined(TN3270) if (ttyin) { FD_SET(tin, &ibits); } -#else /* defined(TN3270) */ - if (ttyin) { - FD_SET(tin, &ibits); - } -#endif /* defined(TN3270) */ -#if defined(TN3270) if (netin) { FD_SET(net, &ibits); } -# else /* !defined(TN3270) */ - if (netin) { - FD_SET(net, &ibits); - } -# endif /* !defined(TN3270) */ if (netex) { FD_SET(net, &xbits); } if ((c = select(16, &ibits, &obits, &xbits, (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { if (c == -1) { /* * we can get EINTR if we are in line mode, * and the user does an escape (TSTP), or * some other signal generator. */ if (errno == EINTR) { return 0; } -# if defined(TN3270) - /* - * we can get EBADF if we were in transparent - * mode, and the transcom process died. - */ - if (errno == EBADF) { - /* - * zero the bits (even though kernel does it) - * to make sure we are selecting on the right - * ones. - */ - FD_ZERO(&ibits); - FD_ZERO(&obits); - FD_ZERO(&xbits); - return 0; - } -# endif /* defined(TN3270) */ /* I don't like this, does it ever happen? */ printf("sleep(5) from telnet, after select: %s\r\n", strerror(errno)); sleep(5); } return 0; } /* * Any urgent data? */ if (FD_ISSET(net, &xbits)) { FD_CLR(net, &xbits); SYNCHing = 1; (void) ttyflush(1); /* flush already enqueued data */ } /* * Something to read from the network... */ if (FD_ISSET(net, &ibits)) { int canread; FD_CLR(net, &ibits); canread = ring_empty_consecutive(&netiring); #if !defined(SO_OOBINLINE) /* * In 4.2 (and some early 4.3) systems, the * OOB indication and data handling in the kernel * is such that if two separate TCP Urgent requests * come in, one byte of TCP data will be overlaid. * This is fatal for Telnet, but we try to live * with it. * * In addition, in 4.2 (and...), a special protocol * is needed to pick up the TCP Urgent data in * the correct sequence. * * What we do is: if we think we are in urgent * mode, we look to see if we are "at the mark". * If we are, we do an OOB receive. If we run * this twice, we will do the OOB receive twice, * but the second will fail, since the second * time we were "at the mark", but there wasn't * any data there (the kernel doesn't reset * "at the mark" until we do a normal read). * Once we've read the OOB data, we go ahead * and do normal reads. * * There is also another problem, which is that * since the OOB byte we read doesn't put us * out of OOB state, and since that byte is most * likely the TELNET DM (data mark), we would * stay in the TELNET SYNCH (SYNCHing) state. * So, clocks to the rescue. If we've "just" * received a DM, then we test for the * presence of OOB data when the receive OOB * fails (and AFTER we did the normal mode read * to clear "at the mark"). */ if (SYNCHing) { int atmark; static int bogus_oob = 0, first = 1; ioctl(net, SIOCATMARK, (char *)&atmark); if (atmark) { c = recv(net, netiring.supply, canread, MSG_OOB); if ((c == -1) && (errno == EINVAL)) { c = recv(net, netiring.supply, canread, 0); if (clocks.didnetreceive < clocks.gotDM) { SYNCHing = stilloob(net); } } else if (first && c > 0) { /* * Bogosity check. Systems based on 4.2BSD * do not return an error if you do a second * recv(MSG_OOB). So, we do one. If it * succeeds and returns exactly the same * data, then assume that we are running * on a broken system and set the bogus_oob * flag. (If the data was different, then * we probably got some valid new data, so * increment the count...) */ int i; i = recv(net, netiring.supply + c, canread - c, MSG_OOB); if (i == c && memcmp(netiring.supply, netiring.supply + c, i) == 0) { bogus_oob = 1; first = 0; } else if (i < 0) { bogus_oob = 0; first = 0; } else c += i; } if (bogus_oob && c > 0) { int i; /* * Bogosity. We have to do the read * to clear the atmark to get out of * an infinate loop. */ i = read(net, netiring.supply + c, canread - c); if (i > 0) c += i; } } else { c = recv(net, netiring.supply, canread, 0); } } else { c = recv(net, netiring.supply, canread, 0); } settimer(didnetreceive); #else /* !defined(SO_OOBINLINE) */ c = recv(net, (char *)netiring.supply, canread, 0); #endif /* !defined(SO_OOBINLINE) */ if (c < 0 && errno == EWOULDBLOCK) { c = 0; } else if (c <= 0) { return -1; } if (netdata) { Dump('<', netiring.supply, c); } if (c) ring_supplied(&netiring, c); returnValue = 1; } /* * Something to read from the tty... */ if (FD_ISSET(tin, &ibits)) { FD_CLR(tin, &ibits); c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); if (c < 0 && errno == EIO) c = 0; if (c < 0 && errno == EWOULDBLOCK) { c = 0; } else { /* EOF detection for line mode!!!! */ if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { /* must be an EOF... */ *ttyiring.supply = termEofChar; c = 1; } if (c <= 0) { return -1; } if (termdata) { Dump('<', ttyiring.supply, c); } ring_supplied(&ttyiring, c); } returnValue = 1; /* did something useful */ } if (FD_ISSET(net, &obits)) { FD_CLR(net, &obits); returnValue |= netflush(); } if (FD_ISSET(tout, &obits)) { FD_CLR(tout, &obits); returnValue |= (ttyflush(SYNCHing|flushout) > 0); } return returnValue; } Index: head/crypto/telnet/telnet/telnet.c =================================================================== --- head/crypto/telnet/telnet/telnet.c (revision 87138) +++ head/crypto/telnet/telnet/telnet.c (revision 87139) @@ -1,2671 +1,2378 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #include -#if defined(unix) -#include /* By the way, we need to include curses.h before telnet.h since, * among other things, telnet.h #defines 'DO', which is a variable * declared in curses.h. */ -#endif /* defined(unix) */ -#include #include +#include +#include #include +#include #include +#include #include "ring.h" #include "defines.h" #include "externs.h" #include "types.h" #include "general.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif #include #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x)) static unsigned char subbuffer[SUBBUFSIZE], *subpointer, *subend; /* buffer for sub-options */ #define SB_CLEAR() subpointer = subbuffer; #define SB_TERM() { subend = subpointer; SB_CLEAR(); } #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ *subpointer++ = (c); \ } #define SB_GET() ((*subpointer++)&0xff) #define SB_PEEK() ((*subpointer)&0xff) #define SB_EOF() (subpointer >= subend) #define SB_LEN() (subend - subpointer) char options[256]; /* The combined options */ char do_dont_resp[256]; char will_wont_resp[256]; int eight = 0, autologin = 0, /* Autologin anyone? */ skiprc = 0, connected, showoptions, - In3270, /* Are we in 3270 mode? */ ISend, /* trying to send network data in */ debug = 0, crmod, netdata, /* Print out network data flow */ crlf, /* Should '\r' be mapped to (or )? */ -#if defined(TN3270) - noasynchtty = 0,/* User specified "-noasynch" on command line */ - noasynchnet = 0,/* User specified "-noasynch" on command line */ - askedSGA = 0, /* We have talked about suppress go ahead */ -#endif /* defined(TN3270) */ telnetport, SYNCHing, /* we are in TELNET SYNCH mode */ flushout, /* flush output */ autoflush = 0, /* flush output when interrupting? */ autosynch, /* send interrupt characters with SYNCH? */ localflow, /* we handle flow control locally */ restartany, /* if flow control enabled, restart on any character */ localchars, /* we recognize interrupt/quit */ donelclchars, /* the user has set "localchars" */ donebinarytoggle, /* the user has put us in binary */ dontlecho, /* do we suppress local echoing right now? */ globalmode, doaddrlookup = 1, /* do a reverse address lookup? */ clienteof = 0; char *prompt = 0; #ifdef ENCRYPTION char *line; /* hack around breakage in sra.c :-( !! */ #endif cc_t escape; cc_t rlogin; #ifdef KLUDGELINEMODE cc_t echoc; #endif /* * Telnet receiver states for fsm */ #define TS_DATA 0 #define TS_IAC 1 #define TS_WILL 2 #define TS_WONT 3 #define TS_DO 4 #define TS_DONT 5 #define TS_CR 6 #define TS_SB 7 /* sub-option collection */ #define TS_SE 8 /* looking for sub-option end */ static int telrcv_state; #ifdef OLD_ENVIRON unsigned char telopt_environ = TELOPT_NEW_ENVIRON; #else # define telopt_environ TELOPT_NEW_ENVIRON #endif -jmp_buf toplevel = { 0 }; +jmp_buf toplevel; jmp_buf peerdied; int flushline; int linemode; #ifdef KLUDGELINEMODE int kludgelinemode = 1; #endif +static int is_unique(char *, char **, char **); + /* * The following are some clocks used to decide how to interpret * the relationship between various variables. */ Clocks clocks; -#ifdef notdef -Modelist modelist[] = { - { "telnet command mode", COMMAND_LINE }, - { "character-at-a-time mode", 0 }, - { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, - { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, - { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, - { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, - { "3270 mode", 0 }, -}; -#endif - - /* * Initialize telnet environment. */ - void -init_telnet() +void +init_telnet(void) { env_init(); SB_CLEAR(); ClearArray(options); - connected = In3270 = ISend = localflow = donebinarytoggle = 0; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) + connected = ISend = localflow = donebinarytoggle = 0; +#ifdef AUTHENTICATION +#ifdef ENCRYPTION auth_encrypt_connect(connected); -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif +#endif restartany = -1; SYNCHing = 0; /* Don't change NetTrace */ escape = CONTROL(']'); rlogin = _POSIX_VDISABLE; #ifdef KLUDGELINEMODE echoc = CONTROL('E'); #endif flushline = 1; telrcv_state = TS_DATA; } -#ifdef notdef -#include - - /*VARARGS*/ - static void -printring(va_alist) - va_dcl -{ - va_list ap; - char buffer[100]; /* where things go */ - char *ptr; - char *format; - char *string; - Ring *ring; - int i; - - va_start(ap); - - ring = va_arg(ap, Ring *); - format = va_arg(ap, char *); - ptr = buffer; - - while ((i = *format++) != 0) { - if (i == '%') { - i = *format++; - switch (i) { - case 'c': - *ptr++ = va_arg(ap, int); - break; - case 's': - string = va_arg(ap, char *); - ring_supply_data(ring, buffer, ptr-buffer); - ring_supply_data(ring, string, strlen(string)); - ptr = buffer; - break; - case 0: - ExitString("printring: trailing %%.\n", 1); - /*NOTREACHED*/ - default: - ExitString("printring: unknown format character.\n", 1); - /*NOTREACHED*/ - } - } else { - *ptr++ = i; - } - } - ring_supply_data(ring, buffer, ptr-buffer); -} -#endif - /* * These routines are in charge of sending option negotiations * to the other side. * * The basic idea is that we send the negotiation if either side * is in disagreement as to what the current state should be. */ - void -send_do(c, init) - register int c, init; +void +send_do(int c, int init) { if (init) { if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || my_want_state_is_do(c)) return; set_my_want_state_do(c); do_dont_resp[c]++; } NET2ADD(IAC, DO); NETADD(c); printoption("SENT", DO, c); } - void -send_dont(c, init) - register int c, init; +void +send_dont(int c, int init) { if (init) { if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || my_want_state_is_dont(c)) return; set_my_want_state_dont(c); do_dont_resp[c]++; } NET2ADD(IAC, DONT); NETADD(c); printoption("SENT", DONT, c); } - void -send_will(c, init) - register int c, init; +void +send_will(int c, int init) { if (init) { if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || my_want_state_is_will(c)) return; set_my_want_state_will(c); will_wont_resp[c]++; } NET2ADD(IAC, WILL); NETADD(c); printoption("SENT", WILL, c); } - void -send_wont(c, init) - register int c, init; +void +send_wont(int c, int init) { if (init) { if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || my_want_state_is_wont(c)) return; set_my_want_state_wont(c); will_wont_resp[c]++; } NET2ADD(IAC, WONT); NETADD(c); printoption("SENT", WONT, c); } - - void -willoption(option) - int option; +void +willoption(int option) { int new_state_ok = 0; if (do_dont_resp[option]) { --do_dont_resp[option]; if (do_dont_resp[option] && my_state_is_do(option)) --do_dont_resp[option]; } if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { switch (option) { case TELOPT_ECHO: -# if defined(TN3270) - /* - * The following is a pain in the rear-end. - * Various IBM servers (some versions of Wiscnet, - * possibly Fibronics/Spartacus, and who knows who - * else) will NOT allow us to send "DO SGA" too early - * in the setup proceedings. On the other hand, - * 4.2 servers (telnetd) won't set SGA correctly. - * So, we are stuck. Empirically (but, based on - * a VERY small sample), the IBM servers don't send - * out anything about ECHO, so we postpone our sending - * "DO SGA" until we see "WILL ECHO" (which 4.2 servers - * DO send). - */ - { - if (askedSGA == 0) { - askedSGA = 1; - if (my_want_state_is_dont(TELOPT_SGA)) - send_do(TELOPT_SGA, 1); - } - } - /* Fall through */ - case TELOPT_EOR: -#endif /* defined(TN3270) */ case TELOPT_BINARY: case TELOPT_SGA: settimer(modenegotiated); /* FALL THROUGH */ case TELOPT_STATUS: -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: #endif /* ENCRYPTION */ new_state_ok = 1; break; case TELOPT_TM: if (flushout) flushout = 0; /* * Special case for TM. If we get back a WILL, * pretend we got back a WONT. */ set_my_want_state_dont(option); set_my_state_dont(option); return; /* Never reply to TM will's/wont's */ case TELOPT_LINEMODE: default: break; } if (new_state_ok) { set_my_want_state_do(option); send_do(option, 0); setconnmode(0); /* possibly set new tty mode */ } else { do_dont_resp[option]++; send_dont(option, 0); } } set_my_state_do(option); #ifdef ENCRYPTION if (option == TELOPT_ENCRYPT) encrypt_send_support(); #endif /* ENCRYPTION */ } - void -wontoption(option) - int option; +void +wontoption(int option) { if (do_dont_resp[option]) { --do_dont_resp[option]; if (do_dont_resp[option] && my_state_is_dont(option)) --do_dont_resp[option]; } if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { switch (option) { #ifdef KLUDGELINEMODE case TELOPT_SGA: if (!kludgelinemode) break; /* FALL THROUGH */ #endif case TELOPT_ECHO: settimer(modenegotiated); break; case TELOPT_TM: if (flushout) flushout = 0; set_my_want_state_dont(option); set_my_state_dont(option); return; /* Never reply to TM will's/wont's */ default: break; } set_my_want_state_dont(option); if (my_state_is_do(option)) send_dont(option, 0); setconnmode(0); /* Set new tty mode */ } else if (option == TELOPT_TM) { /* * Special case for TM. */ if (flushout) flushout = 0; set_my_want_state_dont(option); } set_my_state_dont(option); } - static void -dooption(option) - int option; +static void +dooption(int option) { int new_state_ok = 0; if (will_wont_resp[option]) { --will_wont_resp[option]; if (will_wont_resp[option] && my_state_is_will(option)) --will_wont_resp[option]; } if (will_wont_resp[option] == 0) { if (my_want_state_is_wont(option)) { switch (option) { case TELOPT_TM: /* * Special case for TM. We send a WILL, but pretend * we sent WONT. */ send_will(option, 0); set_my_want_state_wont(TELOPT_TM); set_my_state_wont(TELOPT_TM); return; -# if defined(TN3270) - case TELOPT_EOR: /* end of record */ -# endif /* defined(TN3270) */ case TELOPT_BINARY: /* binary mode */ case TELOPT_NAWS: /* window size */ case TELOPT_TSPEED: /* terminal speed */ case TELOPT_LFLOW: /* local flow control */ case TELOPT_TTYPE: /* terminal type option */ case TELOPT_SGA: /* no big deal */ #ifdef ENCRYPTION case TELOPT_ENCRYPT: /* encryption variable option */ #endif /* ENCRYPTION */ new_state_ok = 1; break; case TELOPT_NEW_ENVIRON: /* New environment variable option */ #ifdef OLD_ENVIRON if (my_state_is_will(TELOPT_OLD_ENVIRON)) send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */ goto env_common; case TELOPT_OLD_ENVIRON: /* Old environment variable option */ if (my_state_is_will(TELOPT_NEW_ENVIRON)) break; /* Don't enable if new one is in use! */ env_common: telopt_environ = option; #endif new_state_ok = 1; break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: if (autologin) new_state_ok = 1; break; #endif case TELOPT_XDISPLOC: /* X Display location */ - if (env_getvalue((unsigned char *)"DISPLAY")) + if (env_getvalue("DISPLAY")) new_state_ok = 1; break; case TELOPT_LINEMODE: #ifdef KLUDGELINEMODE kludgelinemode = 0; send_do(TELOPT_SGA, 1); #endif set_my_want_state_will(TELOPT_LINEMODE); send_will(option, 0); set_my_state_will(TELOPT_LINEMODE); slc_init(); return; case TELOPT_ECHO: /* We're never going to echo... */ default: break; } if (new_state_ok) { set_my_want_state_will(option); send_will(option, 0); setconnmode(0); /* Set new tty mode */ } else { will_wont_resp[option]++; send_wont(option, 0); } } else { /* * Handle options that need more things done after the * other side has acknowledged the option. */ switch (option) { case TELOPT_LINEMODE: #ifdef KLUDGELINEMODE kludgelinemode = 0; send_do(TELOPT_SGA, 1); #endif set_my_state_will(option); slc_init(); send_do(TELOPT_SGA, 0); return; } } } set_my_state_will(option); } - static void -dontoption(option) - int option; +static void +dontoption(int option) { if (will_wont_resp[option]) { --will_wont_resp[option]; if (will_wont_resp[option] && my_state_is_wont(option)) --will_wont_resp[option]; } if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { switch (option) { case TELOPT_LINEMODE: linemode = 0; /* put us back to the default state */ break; #ifdef OLD_ENVIRON case TELOPT_NEW_ENVIRON: /* * The new environ option wasn't recognized, try * the old one. */ send_will(TELOPT_OLD_ENVIRON, 1); telopt_environ = TELOPT_OLD_ENVIRON; break; #endif } /* we always accept a DONT */ set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); setconnmode(0); /* Set new tty mode */ } set_my_state_wont(option); } /* * Given a buffer returned by tgetent(), this routine will turn * the pipe separated list of names in the buffer into an array * of pointers to null terminated names. We toss out any bad, * duplicate, or verbose names (names with spaces). */ -static char *name_unknown = "UNKNOWN"; -static char *unknown[] = { 0, 0 }; +static const char *name_unknown = "UNKNOWN"; +static const char *unknown[] = { NULL, NULL }; - char ** -mklist(buf, name) - char *buf, *name; +static const char ** +mklist(char *buf, char *name) { - register int n; - register char c, *cp, **argvp, *cp2, **argv, **avt; + int n; + char c, *cp, **argvp, *cp2, **argv, **avt; if (name) { if (strlen(name) > 40) { name = 0; unknown[0] = name_unknown; } else { unknown[0] = name; upcase(name); } } else unknown[0] = name_unknown; /* * Count up the number of names. */ for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { if (*cp == '|') n++; } /* * Allocate an array to put the name pointers into */ argv = (char **)malloc((n+3)*sizeof(char *)); if (argv == 0) return(unknown); /* * Fill up the array of pointers to names. */ *argv = 0; argvp = argv+1; n = 0; for (cp = cp2 = buf; (c = *cp); cp++) { if (c == '|' || c == ':') { *cp++ = '\0'; /* * Skip entries that have spaces or are over 40 * characters long. If this is our environment * name, then put it up front. Otherwise, as * long as this is not a duplicate name (case * insensitive) add it to the list. */ if (n || (cp - cp2 > 41)) ; else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) *argv = cp2; else if (is_unique(cp2, argv+1, argvp)) *argvp++ = cp2; if (c == ':') break; /* * Skip multiple delimiters. Reset cp2 to * the beginning of the next name. Reset n, * the flag for names with spaces. */ while ((c = *cp) == '|') cp++; cp2 = cp; n = 0; } /* * Skip entries with spaces or non-ascii values. * Convert lower case letters to upper case. */ if ((c == ' ') || !isascii(c)) n = 1; else if (islower(c)) *cp = toupper(c); } /* * Check for an old V6 2 character name. If the second * name points to the beginning of the buffer, and is * only 2 characters long, move it to the end of the array. */ if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { --argvp; for (avt = &argv[1]; avt < argvp; avt++) *avt = *(avt+1); *argvp++ = buf; } /* * Duplicate last name, for TTYPE option, and null * terminate the array. If we didn't find a match on * our terminal name, put that name at the beginning. */ cp = *(argvp-1); *argvp++ = cp; *argvp = 0; if (*argv == 0) { if (name) *argv = name; else { --argvp; for (avt = argv; avt < argvp; avt++) *avt = *(avt+1); } } if (*argv) - return(argv); + return((const char **)argv); else return(unknown); } - int -is_unique(name, as, ae) - register char *name, **as, **ae; +static int +is_unique(char *name, char **as, char **ae) { - register char **ap; - register int n; + char **ap; + int n; n = strlen(name) + 1; for (ap = as; ap < ae; ap++) if (strncasecmp(*ap, name, n) == 0) return(0); return (1); } #ifdef TERMCAP char termbuf[1024]; - /*ARGSUSED*/ - int -setupterm(tname, fd, errp) - char *tname; - int fd, *errp; +/*ARGSUSED*/ +static int +setupterm(char *tname, int fd, int *errp) { if (tgetent(termbuf, tname) == 1) { termbuf[1023] = '\0'; if (errp) *errp = 1; return(0); } if (errp) *errp = 0; return(-1); } #else #define termbuf ttytype extern char ttytype[]; #endif int resettermname = 1; - char * -gettermname() +static const char * +gettermname(void) { char *tname; - static char **tnamep = 0; - static char **next; + static const char **tnamep = 0; + static const char **next; int err; if (resettermname) { resettermname = 0; if (tnamep && tnamep != unknown) free(tnamep); - if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && + if ((tname = env_getvalue("TERM")) && (setupterm(tname, 1, &err) == 0)) { tnamep = mklist(termbuf, tname); } else { if (tname && (strlen(tname) <= 40)) { unknown[0] = tname; upcase(tname); } else unknown[0] = name_unknown; tnamep = unknown; } next = tnamep; } if (*next == 0) next = tnamep; return(*next++); } /* * suboption() * * Look at the sub-option buffer, and try to be helpful to the other * side. * * Currently we recognize: * * Terminal type, send request. * Terminal speed (send request). * Local flow control (is request). * Linemode */ - static void -suboption() +static void +suboption(void) { unsigned char subchar; printsub('<', subbuffer, SB_LEN()+2); switch (subchar = SB_GET()) { case TELOPT_TTYPE: if (my_want_state_is_wont(TELOPT_TTYPE)) return; if (SB_EOF() || SB_GET() != TELQUAL_SEND) { return; } else { - char *name; + const char *name; unsigned char temp[50]; int len; -#if defined(TN3270) - if (tn3270_ttype()) { - return; - } -#endif /* defined(TN3270) */ name = gettermname(); len = strlen(name) + 4 + 2; if (len < NETROOM()) { - sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, + sprintf(temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE); ring_supply_data(&netoring, temp, len); printsub('>', &temp[2], len-2); } else { ExitString("No room in buffer for terminal type.\n", 1); /*NOTREACHED*/ } } break; case TELOPT_TSPEED: if (my_want_state_is_wont(TELOPT_TSPEED)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { long ospeed, ispeed; unsigned char temp[50]; int len; TerminalSpeeds(&ispeed, &ospeed); sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, TELQUAL_IS, ospeed, ispeed, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; case TELOPT_LFLOW: if (my_want_state_is_wont(TELOPT_LFLOW)) return; if (SB_EOF()) return; switch(SB_GET()) { case LFLOW_RESTART_ANY: restartany = 1; break; case LFLOW_RESTART_XON: restartany = 0; break; case LFLOW_ON: localflow = 1; break; case LFLOW_OFF: localflow = 0; break; default: return; } setcommandmode(); setconnmode(0); break; case TELOPT_LINEMODE: if (my_want_state_is_wont(TELOPT_LINEMODE)) return; if (SB_EOF()) return; switch (SB_GET()) { case WILL: lm_will(subpointer, SB_LEN()); break; case WONT: lm_wont(subpointer, SB_LEN()); break; case DO: lm_do(subpointer, SB_LEN()); break; case DONT: lm_dont(subpointer, SB_LEN()); break; case LM_SLC: slc(subpointer, SB_LEN()); break; case LM_MODE: lm_mode(subpointer, SB_LEN(), 0); break; default: break; } break; #ifdef OLD_ENVIRON case TELOPT_OLD_ENVIRON: #endif case TELOPT_NEW_ENVIRON: if (SB_EOF()) return; switch(SB_PEEK()) { case TELQUAL_IS: case TELQUAL_INFO: if (my_want_state_is_dont(subchar)) return; break; case TELQUAL_SEND: if (my_want_state_is_wont(subchar)) { return; } break; default: return; } env_opt(subpointer, SB_LEN()); break; case TELOPT_XDISPLOC: if (my_want_state_is_wont(TELOPT_XDISPLOC)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { unsigned char temp[50], *dp; int len; - if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL || + if ((dp = env_getvalue("DISPLAY")) == NULL || strlen(dp) > sizeof(temp) - 7) { /* * Something happened, we no longer have a DISPLAY * variable. Or it is too long. So, turn off the option. */ send_wont(TELOPT_XDISPLOC, 1); break; } - snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, + snprintf(temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: { if (!autologin) break; if (SB_EOF()) return; switch(SB_GET()) { case TELQUAL_IS: if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) return; auth_is(subpointer, SB_LEN()); break; case TELQUAL_SEND: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) return; auth_send(subpointer, SB_LEN()); break; case TELQUAL_REPLY: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) return; auth_reply(subpointer, SB_LEN()); break; case TELQUAL_NAME: if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) return; auth_name(subpointer, SB_LEN()); break; } } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: if (SB_EOF()) return; switch(SB_GET()) { case ENCRYPT_START: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_start(subpointer, SB_LEN()); break; case ENCRYPT_END: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_end(); break; case ENCRYPT_SUPPORT: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_support(subpointer, SB_LEN()); break; case ENCRYPT_REQSTART: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_request_start(subpointer, SB_LEN()); break; case ENCRYPT_REQEND: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; /* * We can always send an REQEND so that we cannot * get stuck encrypting. We should only get this * if we have been able to get in the correct mode * anyhow. */ encrypt_request_end(); break; case ENCRYPT_IS: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_is(subpointer, SB_LEN()); break; case ENCRYPT_REPLY: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_reply(subpointer, SB_LEN()); break; case ENCRYPT_ENC_KEYID: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_enc_keyid(subpointer, SB_LEN()); break; case ENCRYPT_DEC_KEYID: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_dec_keyid(subpointer, SB_LEN()); break; default: break; } break; #endif /* ENCRYPTION */ default: break; } } static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; - void -lm_will(cmd, len) - unsigned char *cmd; - int len; +void +lm_will(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: /* We shouldn't ever get this... */ default: str_lm[3] = DONT; str_lm[4] = cmd[0]; - if (NETROOM() > sizeof(str_lm)) { + if (NETROOM() > (int)sizeof(str_lm)) { ring_supply_data(&netoring, str_lm, sizeof(str_lm)); printsub('>', &str_lm[2], sizeof(str_lm)-2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); break; } } - void -lm_wont(cmd, len) - unsigned char *cmd; - int len; +void +lm_wont(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: /* We shouldn't ever get this... */ default: /* We are always DONT, so don't respond */ return; } } - void -lm_do(cmd, len) - unsigned char *cmd; - int len; +void +lm_do(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: default: str_lm[3] = WONT; str_lm[4] = cmd[0]; - if (NETROOM() > sizeof(str_lm)) { + if (NETROOM() > (int)sizeof(str_lm)) { ring_supply_data(&netoring, str_lm, sizeof(str_lm)); printsub('>', &str_lm[2], sizeof(str_lm)-2); } /*@*/ else printf("lm_do: not enough room in buffer\n"); break; } } - void -lm_dont(cmd, len) - unsigned char *cmd; - int len; +void +lm_dont(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: default: /* we are always WONT, so don't respond */ break; } } static unsigned char str_lm_mode[] = { IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE }; - void -lm_mode(cmd, len, init) - unsigned char *cmd; - int len, init; +void +lm_mode(unsigned char *cmd, int len, int init) { if (len != 1) return; if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) return; if (*cmd&MODE_ACK) return; linemode = *cmd&(MODE_MASK&~MODE_ACK); str_lm_mode[4] = linemode; if (!init) str_lm_mode[4] |= MODE_ACK; - if (NETROOM() > sizeof(str_lm_mode)) { + if (NETROOM() > (int)sizeof(str_lm_mode)) { ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); } /*@*/ else printf("lm_mode: not enough room in buffer\n"); setconnmode(0); /* set changed mode */ } /* * slc() * Handle special character suboption of LINEMODE. */ struct spc { cc_t val; cc_t *valp; char flags; /* Current flags & level */ char mylevel; /* Maximum level & flags */ } spc_data[NSLC+1]; #define SLC_IMPORT 0 #define SLC_EXPORT 1 #define SLC_RVALUE 2 static int slc_mode = SLC_EXPORT; - void -slc_init() +void +slc_init(void) { - register struct spc *spcp; + struct spc *spcp; localchars = 1; for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { spcp->val = 0; spcp->valp = 0; spcp->flags = spcp->mylevel = SLC_NOSUPPORT; } #define initfunc(func, flags) { \ spcp = &spc_data[func]; \ if ((spcp->valp = tcval(func))) { \ spcp->val = *spcp->valp; \ spcp->mylevel = SLC_VARIABLE|flags; \ } else { \ spcp->val = 0; \ spcp->mylevel = SLC_DEFAULT; \ } \ } initfunc(SLC_SYNCH, 0); /* No BRK */ initfunc(SLC_AO, 0); initfunc(SLC_AYT, 0); /* No EOR */ initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); initfunc(SLC_EOF, 0); #ifndef SYSV_TERMIO initfunc(SLC_SUSP, SLC_FLUSHIN); #endif initfunc(SLC_EC, 0); initfunc(SLC_EL, 0); #ifndef SYSV_TERMIO initfunc(SLC_EW, 0); initfunc(SLC_RP, 0); initfunc(SLC_LNEXT, 0); #endif initfunc(SLC_XON, 0); initfunc(SLC_XOFF, 0); #ifdef SYSV_TERMIO spc_data[SLC_XON].mylevel = SLC_CANTCHANGE; spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE; #endif initfunc(SLC_FORW1, 0); #ifdef USE_TERMIO initfunc(SLC_FORW2, 0); /* No FORW2 */ #endif initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); #undef initfunc if (slc_mode == SLC_EXPORT) slc_export(); else slc_import(1); } - void -slcstate() +void +slcstate(void) { printf("Special characters are %s values\n", slc_mode == SLC_IMPORT ? "remote default" : slc_mode == SLC_EXPORT ? "local" : "remote"); } - void -slc_mode_export() +void +slc_mode_export(void) { slc_mode = SLC_EXPORT; if (my_state_is_will(TELOPT_LINEMODE)) slc_export(); } - void -slc_mode_import(def) - int def; +void +slc_mode_import(int def) { slc_mode = def ? SLC_IMPORT : SLC_RVALUE; if (my_state_is_will(TELOPT_LINEMODE)) slc_import(def); } unsigned char slc_import_val[] = { IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE }; unsigned char slc_import_def[] = { IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE }; - void -slc_import(def) - int def; +void +slc_import(int def) { - if (NETROOM() > sizeof(slc_import_val)) { + if (NETROOM() > (int)sizeof(slc_import_val)) { if (def) { ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); } else { ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); } } /*@*/ else printf("slc_import: not enough room\n"); } - void -slc_export() +void +slc_export(void) { - register struct spc *spcp; + struct spc *spcp; TerminalDefaultChars(); slc_start_reply(); for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { if (spcp->mylevel != SLC_NOSUPPORT) { if (spcp->val == (cc_t)(_POSIX_VDISABLE)) spcp->flags = SLC_NOSUPPORT; else spcp->flags = spcp->mylevel; if (spcp->valp) spcp->val = *spcp->valp; slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); } } slc_end_reply(); (void)slc_update(); setconnmode(1); /* Make sure the character values are set */ } - void -slc(cp, len) - register unsigned char *cp; - int len; +void +slc(unsigned char *cp, int len) { - register struct spc *spcp; - register int func,level; + struct spc *spcp; + int func,level; slc_start_reply(); for (; len >= 3; len -=3, cp +=3) { func = cp[SLC_FUNC]; if (func == 0) { /* * Client side: always ignore 0 function. */ continue; } if (func > NSLC) { if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) slc_add_reply(func, SLC_NOSUPPORT, 0); continue; } spcp = &spc_data[func]; level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { continue; } if (level == (SLC_DEFAULT|SLC_ACK)) { /* * This is an error condition, the SLC_ACK * bit should never be set for the SLC_DEFAULT * level. Our best guess to recover is to * ignore the SLC_ACK bit. */ cp[SLC_FLAGS] &= ~SLC_ACK; } if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { spcp->val = (cc_t)cp[SLC_VALUE]; spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ continue; } level &= ~SLC_ACK; if (level <= (spcp->mylevel&SLC_LEVELBITS)) { spcp->flags = cp[SLC_FLAGS]|SLC_ACK; spcp->val = (cc_t)cp[SLC_VALUE]; } if (level == SLC_DEFAULT) { if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) spcp->flags = spcp->mylevel; else spcp->flags = SLC_NOSUPPORT; } slc_add_reply(func, spcp->flags, spcp->val); } slc_end_reply(); if (slc_update()) setconnmode(1); /* set the new character values */ } - void -slc_check() +void +slc_check(void) { - register struct spc *spcp; + struct spc *spcp; slc_start_reply(); for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { if (spcp->valp && spcp->val != *spcp->valp) { spcp->val = *spcp->valp; if (spcp->val == (cc_t)(_POSIX_VDISABLE)) spcp->flags = SLC_NOSUPPORT; else spcp->flags = spcp->mylevel; slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); } } slc_end_reply(); setconnmode(1); } - unsigned char slc_reply[128]; unsigned char *slc_replyp; - void -slc_start_reply() +void +slc_start_reply(void) { slc_replyp = slc_reply; *slc_replyp++ = IAC; *slc_replyp++ = SB; *slc_replyp++ = TELOPT_LINEMODE; *slc_replyp++ = LM_SLC; } - void -slc_add_reply(func, flags, value) - unsigned char func; - unsigned char flags; - cc_t value; +void +slc_add_reply(unsigned char func, unsigned char flags, cc_t value) { if ((*slc_replyp++ = func) == IAC) *slc_replyp++ = IAC; if ((*slc_replyp++ = flags) == IAC) *slc_replyp++ = IAC; if ((*slc_replyp++ = (unsigned char)value) == IAC) *slc_replyp++ = IAC; } - void -slc_end_reply() +void +slc_end_reply(void) { - register int len; + int len; *slc_replyp++ = IAC; *slc_replyp++ = SE; len = slc_replyp - slc_reply; if (len <= 6) return; if (NETROOM() > len) { ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); } /*@*/else printf("slc_end_reply: not enough room\n"); } - int -slc_update() +int +slc_update(void) { - register struct spc *spcp; + struct spc *spcp; int need_update = 0; for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { if (!(spcp->flags&SLC_ACK)) continue; spcp->flags &= ~SLC_ACK; if (spcp->valp && (*spcp->valp != spcp->val)) { *spcp->valp = spcp->val; need_update = 1; } } return(need_update); } #ifdef OLD_ENVIRON # ifdef ENV_HACK /* * Earlier version of telnet/telnetd from the BSD code had * the definitions of VALUE and VAR reversed. To ensure * maximum interoperability, we assume that the server is * an older BSD server, until proven otherwise. The newer * BSD servers should be able to handle either definition, * so it is better to use the wrong values if we don't * know what type of server it is. */ int env_auto = 1; int old_env_var = OLD_ENV_VAR; int old_env_value = OLD_ENV_VALUE; # else # define old_env_var OLD_ENV_VAR # define old_env_value OLD_ENV_VALUE # endif #endif - void -env_opt(buf, len) - register unsigned char *buf; - register int len; +void +env_opt(unsigned char *buf, int len) { - register unsigned char *ep = 0, *epc = 0; - register int i; + unsigned char *ep = 0, *epc = 0; + int i; switch(buf[0]&0xff) { case TELQUAL_SEND: env_opt_start(); if (len == 1) { env_opt_add(NULL); } else for (i = 1; i < len; i++) { switch (buf[i]&0xff) { #ifdef OLD_ENVIRON case OLD_ENV_VAR: # ifdef ENV_HACK if (telopt_environ == TELOPT_OLD_ENVIRON && env_auto) { /* Server has the same definitions */ old_env_var = OLD_ENV_VAR; old_env_value = OLD_ENV_VALUE; } /* FALL THROUGH */ # endif case OLD_ENV_VALUE: /* * Although OLD_ENV_VALUE is not legal, we will * still recognize it, just in case it is an * old server that has VAR & VALUE mixed up... */ /* FALL THROUGH */ #else case NEW_ENV_VAR: #endif case ENV_USERVAR: if (ep) { *epc = 0; env_opt_add(ep); } ep = epc = &buf[i+1]; break; case ENV_ESC: i++; /*FALL THROUGH*/ default: if (epc) *epc++ = buf[i]; break; } } if (ep) { *epc = 0; env_opt_add(ep); } env_opt_end(1); break; case TELQUAL_IS: case TELQUAL_INFO: /* Ignore for now. We shouldn't get it anyway. */ break; default: break; } } #define OPT_REPLY_SIZE 256 unsigned char *opt_reply; unsigned char *opt_replyp; unsigned char *opt_replyend; - void -env_opt_start() +void +env_opt_start(void) { if (opt_reply) opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); else opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE); if (opt_reply == NULL) { /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n"); opt_reply = opt_replyp = opt_replyend = NULL; return; } opt_replyp = opt_reply; opt_replyend = opt_reply + OPT_REPLY_SIZE; *opt_replyp++ = IAC; *opt_replyp++ = SB; *opt_replyp++ = telopt_environ; *opt_replyp++ = TELQUAL_IS; } - void -env_opt_start_info() +void +env_opt_start_info(void) { env_opt_start(); if (opt_replyp) opt_replyp[-1] = TELQUAL_INFO; } - void -env_opt_add(ep) - register unsigned char *ep; +void +env_opt_add(unsigned char *ep) { - register unsigned char *vp, c; + unsigned char *vp, c; if (opt_reply == NULL) /*XXX*/ return; /*XXX*/ if (ep == NULL || *ep == '\0') { /* Send user defined variables first. */ env_default(1, 0); while ((ep = env_default(0, 0))) env_opt_add(ep); /* Now add the list of well know variables. */ env_default(1, 1); while ((ep = env_default(0, 1))) env_opt_add(ep); return; } vp = env_getvalue(ep); if (opt_replyp + (vp ? strlen((char *)vp) : 0) + strlen((char *)ep) + 6 > opt_replyend) { - register int len; + int len; opt_replyend += OPT_REPLY_SIZE; len = opt_replyend - opt_reply; opt_reply = (unsigned char *)realloc(opt_reply, len); if (opt_reply == NULL) { /*@*/ printf("env_opt_add: realloc() failed!!!\n"); opt_reply = opt_replyp = opt_replyend = NULL; return; } opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); opt_replyend = opt_reply + len; } if (opt_welldefined(ep)) #ifdef OLD_ENVIRON if (telopt_environ == TELOPT_OLD_ENVIRON) *opt_replyp++ = old_env_var; else #endif *opt_replyp++ = NEW_ENV_VAR; else *opt_replyp++ = ENV_USERVAR; for (;;) { while ((c = *ep++)) { switch(c&0xff) { case IAC: *opt_replyp++ = IAC; break; case NEW_ENV_VAR: case NEW_ENV_VALUE: case ENV_ESC: case ENV_USERVAR: *opt_replyp++ = ENV_ESC; break; } *opt_replyp++ = c; } if ((ep = vp)) { #ifdef OLD_ENVIRON if (telopt_environ == TELOPT_OLD_ENVIRON) *opt_replyp++ = old_env_value; else #endif *opt_replyp++ = NEW_ENV_VALUE; vp = NULL; } else break; } } - int -opt_welldefined(ep) - char *ep; +int +opt_welldefined(const char *ep) { if ((strcmp(ep, "USER") == 0) || (strcmp(ep, "DISPLAY") == 0) || (strcmp(ep, "PRINTER") == 0) || (strcmp(ep, "SYSTEMTYPE") == 0) || (strcmp(ep, "JOB") == 0) || (strcmp(ep, "ACCT") == 0)) return(1); return(0); } - void -env_opt_end(emptyok) - register int emptyok; + +void +env_opt_end(int emptyok) { - register int len; + int len; len = opt_replyp - opt_reply + 2; if (emptyok || len > 6) { *opt_replyp++ = IAC; *opt_replyp++ = SE; if (NETROOM() > len) { ring_supply_data(&netoring, opt_reply, len); printsub('>', &opt_reply[2], len - 2); } /*@*/ else printf("slc_end_reply: not enough room\n"); } if (opt_reply) { free(opt_reply); opt_reply = opt_replyp = opt_replyend = NULL; } } - int -telrcv() +int +telrcv(void) { - register int c; - register int scc; - register unsigned char *sbp; + int c; + int scc; + unsigned char *sbp; int count; int returnValue = 0; scc = 0; count = 0; while (TTYROOM() > 2) { if (scc == 0) { if (count) { ring_consumed(&netiring, count); returnValue = 1; count = 0; } sbp = netiring.consume; scc = ring_full_consecutive(&netiring); if (scc == 0) { /* No more data coming in */ break; } } c = *sbp++ & 0xff, scc--; count++; #ifdef ENCRYPTION if (decrypt_input) c = (*decrypt_input)(c); #endif /* ENCRYPTION */ switch (telrcv_state) { case TS_CR: telrcv_state = TS_DATA; if (c == '\0') { break; /* Ignore \0 after CR */ } else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { TTYADD(c); break; } /* Else, fall through */ case TS_DATA: if (c == IAC) { telrcv_state = TS_IAC; break; } -# if defined(TN3270) - if (In3270) { - *Ifrontp++ = c; - while (scc > 0) { - c = *sbp++ & 0377, scc--; count++; -#ifdef ENCRYPTION - if (decrypt_input) - c = (*decrypt_input)(c); -#endif /* ENCRYPTION */ - if (c == IAC) { - telrcv_state = TS_IAC; - break; - } - *Ifrontp++ = c; - } - } else -# endif /* defined(TN3270) */ /* * The 'crmod' hack (see following) is needed * since we can't * set CRMOD on output only. * Machines like MULTICS like to send \r without * \n; since we must turn off CRMOD to get proper * input, the mapping is done here (sigh). */ if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { if (scc > 0) { c = *sbp&0xff; #ifdef ENCRYPTION if (decrypt_input) c = (*decrypt_input)(c); #endif /* ENCRYPTION */ if (c == 0) { sbp++, scc--; count++; /* a "true" CR */ TTYADD('\r'); } else if (my_want_state_is_dont(TELOPT_ECHO) && (c == '\n')) { sbp++, scc--; count++; TTYADD('\n'); } else { #ifdef ENCRYPTION if (decrypt_input) (*decrypt_input)(-1); #endif /* ENCRYPTION */ TTYADD('\r'); if (crmod) { TTYADD('\n'); } } } else { telrcv_state = TS_CR; TTYADD('\r'); if (crmod) { TTYADD('\n'); } } } else { TTYADD(c); } continue; case TS_IAC: process_iac: switch (c) { case WILL: telrcv_state = TS_WILL; continue; case WONT: telrcv_state = TS_WONT; continue; case DO: telrcv_state = TS_DO; continue; case DONT: telrcv_state = TS_DONT; continue; case DM: /* * We may have missed an urgent notification, * so make sure we flush whatever is in the * buffer currently. */ printoption("RCVD", IAC, DM); SYNCHing = 1; (void) ttyflush(1); SYNCHing = stilloob(); settimer(gotDM); break; case SB: SB_CLEAR(); telrcv_state = TS_SB; continue; -# if defined(TN3270) - case EOR: - if (In3270) { - if (Ibackp == Ifrontp) { - Ibackp = Ifrontp = Ibuf; - ISend = 0; /* should have been! */ - } else { - Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1); - ISend = 1; - } - } - printoption("RCVD", IAC, EOR); - break; -# endif /* defined(TN3270) */ - case IAC: -# if !defined(TN3270) TTYADD(IAC); -# else /* !defined(TN3270) */ - if (In3270) { - *Ifrontp++ = IAC; - } else { - TTYADD(IAC); - } -# endif /* !defined(TN3270) */ break; case NOP: case GA: default: printoption("RCVD", IAC, c); break; } telrcv_state = TS_DATA; continue; case TS_WILL: printoption("RCVD", WILL, c); willoption(c); - SetIn3270(); telrcv_state = TS_DATA; continue; case TS_WONT: printoption("RCVD", WONT, c); wontoption(c); - SetIn3270(); telrcv_state = TS_DATA; continue; case TS_DO: printoption("RCVD", DO, c); dooption(c); - SetIn3270(); if (c == TELOPT_NAWS) { sendnaws(); } else if (c == TELOPT_LFLOW) { localflow = 1; setcommandmode(); setconnmode(0); } telrcv_state = TS_DATA; continue; case TS_DONT: printoption("RCVD", DONT, c); dontoption(c); flushline = 1; setconnmode(0); /* set new tty mode (maybe) */ - SetIn3270(); telrcv_state = TS_DATA; continue; case TS_SB: if (c == IAC) { telrcv_state = TS_SE; } else { SB_ACCUM(c); } continue; case TS_SE: if (c != SE) { if (c != IAC) { /* * This is an error. We only expect to get * "IAC IAC" or "IAC SE". Several things may * have happend. An IAC was not doubled, the * IAC SE was left off, or another option got * inserted into the suboption are all possibilities. * If we assume that the IAC was not doubled, * and really the IAC SE was left off, we could * get into an infinate loop here. So, instead, * we terminate the suboption, and process the * partial suboption if we can. */ SB_ACCUM(IAC); SB_ACCUM(c); subpointer -= 2; SB_TERM(); printoption("In SUBOPTION processing, RCVD", IAC, c); suboption(); /* handle sub-option */ - SetIn3270(); telrcv_state = TS_IAC; goto process_iac; } SB_ACCUM(c); telrcv_state = TS_SB; } else { SB_ACCUM(IAC); SB_ACCUM(SE); subpointer -= 2; SB_TERM(); suboption(); /* handle sub-option */ - SetIn3270(); telrcv_state = TS_DATA; } } } if (count) ring_consumed(&netiring, count); return returnValue||count; } static int bol = 1, local = 0; - int -rlogin_susp() +int +rlogin_susp(void) { if (local) { local = 0; bol = 1; command(0, "z\n", 2); return(1); } return(0); } - static int -telsnd() +static int +telsnd(void) { int tcc; int count; int returnValue = 0; unsigned char *tbp; tcc = 0; count = 0; while (NETROOM() > 2) { - register int sc; - register int c; + int sc; + int c; if (tcc == 0) { if (count) { ring_consumed(&ttyiring, count); returnValue = 1; count = 0; } tbp = ttyiring.consume; tcc = ring_full_consecutive(&ttyiring); if (tcc == 0) { break; } } c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; if (rlogin != _POSIX_VDISABLE) { if (bol) { bol = 0; if (sc == rlogin) { local = 1; continue; } } else if (local) { local = 0; if (sc == '.' || c == termEofChar) { bol = 1; command(0, "close\n", 6); continue; } if (sc == termSuspChar) { bol = 1; command(0, "z\n", 2); continue; } if (sc == escape) { - command(0, (char *)tbp, tcc); + command(0, tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } if (sc != rlogin) { ++tcc; --tbp; --count; c = sc = rlogin; } } if ((sc == '\n') || (sc == '\r')) bol = 1; } else if (escape != _POSIX_VDISABLE && sc == escape) { /* * Double escape is a pass through of a single escape character. */ if (tcc && strip(*tbp) == escape) { tbp++; tcc--; count++; bol = 0; } else { command(0, (char *)tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } } else bol = 0; #ifdef KLUDGELINEMODE if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { if (tcc > 0 && strip(*tbp) == echoc) { tcc--; tbp++; count++; } else { dontlecho = !dontlecho; settimer(echotoggle); setconnmode(0); flushline = 1; break; } } #endif if (MODE_LOCAL_CHARS(globalmode)) { if (TerminalSpecialChars(sc) == 0) { bol = 1; break; } } if (my_want_state_is_wont(TELOPT_BINARY)) { switch (c) { case '\n': /* * If we are in CRMOD mode (\r ==> \n) * on our local machine, then probably * a newline (unix) is CRLF (TELNET). */ if (MODE_LOCAL_CHARS(globalmode)) { NETADD('\r'); } NETADD('\n'); bol = flushline = 1; break; case '\r': if (!crlf) { NET2ADD('\r', '\0'); } else { NET2ADD('\r', '\n'); } bol = flushline = 1; break; case IAC: NET2ADD(IAC, IAC); break; default: NETADD(c); break; } } else if (c == IAC) { NET2ADD(IAC, IAC); } else { NETADD(c); } } if (count) ring_consumed(&ttyiring, count); return returnValue||count; /* Non-zero if we did anything */ } /* * Scheduler() * * Try to do something. * * If we do something useful, return 1; else return 0. * */ - - int -Scheduler(block) - int block; /* should we block in the select ? */ +static int +Scheduler(int block) { /* One wants to be a bit careful about setting returnValue * to one, since a one implies we did some useful work, * and therefore probably won't be called to block next - * time (TN3270 mode only). */ int returnValue; int netin, netout, netex, ttyin, ttyout; /* Decide which rings should be processed */ netout = ring_full_count(&netoring) && (flushline || (my_want_state_is_wont(TELOPT_LINEMODE) #ifdef KLUDGELINEMODE && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)) #endif ) || my_want_state_is_will(TELOPT_BINARY)); ttyout = ring_full_count(&ttyoring); -#if defined(TN3270) - ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0); -#else /* defined(TN3270) */ ttyin = ring_empty_count(&ttyiring) && (clienteof == 0); -#endif /* defined(TN3270) */ -#if defined(TN3270) - netin = ring_empty_count(&netiring); -# else /* !defined(TN3270) */ netin = !ISend && ring_empty_count(&netiring); -# endif /* !defined(TN3270) */ netex = !SYNCHing; - /* If we have seen a signal recently, reset things */ -# if defined(TN3270) && defined(unix) - if (HaveInput) { - HaveInput = 0; - (void) signal(SIGIO, inputAvailable); - } -#endif /* defined(TN3270) && defined(unix) */ - /* Call to system code to process rings */ returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); /* Now, look at the input rings, looking for work to do. */ if (ring_full_count(&ttyiring)) { -# if defined(TN3270) - if (In3270) { - int c; - - c = DataFromTerminal(ttyiring.consume, - ring_full_consecutive(&ttyiring)); - if (c) { - returnValue = 1; - ring_consumed(&ttyiring, c); - } - } else { -# endif /* defined(TN3270) */ returnValue |= telsnd(); -# if defined(TN3270) - } -# endif /* defined(TN3270) */ } if (ring_full_count(&netiring)) { -# if !defined(TN3270) returnValue |= telrcv(); -# else /* !defined(TN3270) */ - returnValue = Push3270(); -# endif /* !defined(TN3270) */ } return returnValue; } +#ifdef AUTHENTICATION +#define __unusedhere +#else +#define __unusedhere __unused +#endif /* * Select from tty and network... */ - void -telnet(user) - char *user; +void +telnet(char *user __unusedhere) { sys_telnet_init(); -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION { static char local_host[256] = { 0 }; if (!local_host[0]) { gethostname(local_host, sizeof(local_host)); local_host[sizeof(local_host)-1] = 0; } auth_encrypt_init(local_host, hostname, "TELNET", 0); auth_encrypt_user(user); } -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ -# if !defined(TN3270) +#endif +#endif if (telnetport) { -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION if (autologin) send_will(TELOPT_AUTHENTICATION, 1); #endif #ifdef ENCRYPTION send_do(TELOPT_ENCRYPT, 1); send_will(TELOPT_ENCRYPT, 1); #endif /* ENCRYPTION */ send_do(TELOPT_SGA, 1); send_will(TELOPT_TTYPE, 1); send_will(TELOPT_NAWS, 1); send_will(TELOPT_TSPEED, 1); send_will(TELOPT_LFLOW, 1); send_will(TELOPT_LINEMODE, 1); send_will(TELOPT_NEW_ENVIRON, 1); send_do(TELOPT_STATUS, 1); - if (env_getvalue((unsigned char *)"DISPLAY")) + if (env_getvalue("DISPLAY")) send_will(TELOPT_XDISPLOC, 1); if (eight) tel_enter_binary(eight); } -# endif /* !defined(TN3270) */ -# if !defined(TN3270) for (;;) { int schedValue; while ((schedValue = Scheduler(0)) != 0) { if (schedValue == -1) { setcommandmode(); return; } } if (Scheduler(1) == -1) { setcommandmode(); return; } } -# else /* !defined(TN3270) */ - for (;;) { - int schedValue; - - while (!In3270 && !shell_active) { - if (Scheduler(1) == -1) { - setcommandmode(); - return; - } - } - - while ((schedValue = Scheduler(0)) != 0) { - if (schedValue == -1) { - setcommandmode(); - return; - } - } - /* If there is data waiting to go out to terminal, don't - * schedule any more data for the terminal. - */ - if (ring_full_count(&ttyoring)) { - schedValue = 1; - } else { - if (shell_active) { - if (shell_continue() == 0) { - ConnectScreen(); - } - } else if (In3270) { - schedValue = DoTerminalOutput(); - } - } - if (schedValue && (shell_active == 0)) { - if (Scheduler(1) == -1) { - setcommandmode(); - return; - } - } - } -# endif /* !defined(TN3270) */ } #if 0 /* XXX - this not being in is a bug */ /* * nextitem() * * Return the address of the next "item" in the TELNET data * stream. This will be the address of the next character if * the current address is a user data character, or it will * be the address of the character following the TELNET command * if the current address is a TELNET IAC ("I Am a Command") * character. */ - static char * -nextitem(current) - char *current; +static char * +nextitem(char *current) { if ((*current&0xff) != IAC) { return current+1; } switch (*(current+1)&0xff) { case DO: case DONT: case WILL: case WONT: return current+3; case SB: /* loop forever looking for the SE */ { - register char *look = current+2; + char *look = current+2; for (;;) { if ((*look++&0xff) == IAC) { if ((*look++&0xff) == SE) { return look; } } } } default: return current+2; } } #endif /* 0 */ /* * netclear() * * We are about to do a TELNET SYNCH operation. Clear * the path to the network. * * Things are a bit tricky since we may have sent the first * byte or so of a previous TELNET command into the network. * So, we have to scan the network buffer from the beginning * until we are up to where we want to be. * * A side effect of what we do, just to keep things * simple, is to clear the urgent data pointer. The principal * caller should be setting the urgent data pointer AFTER calling * us in any case. */ - static void -netclear() +static void +netclear(void) { -#if 0 /* XXX */ - register char *thisitem, *next; - char *good; -#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ - ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) - - thisitem = netobuf; - - while ((next = nextitem(thisitem)) <= netobuf.send) { - thisitem = next; - } - - /* Now, thisitem is first before/at boundary. */ - - good = netobuf; /* where the good bytes go */ - - while (netoring.add > thisitem) { - if (wewant(thisitem)) { - int length; - - next = thisitem; - do { - next = nextitem(next); - } while (wewant(next) && (nfrontp > next)); - length = next-thisitem; - memcpy(good, thisitem, length); - good += length; - thisitem = next; - } else { - thisitem = nextitem(thisitem); - } - } - -#endif /* 0 */ + /* Deleted */ } /* * These routines add various telnet commands to the data stream. */ - static void -doflush() +static void +doflush(void) { NET2ADD(IAC, DO); NETADD(TELOPT_TM); flushline = 1; flushout = 1; (void) ttyflush(1); /* Flush/drop output */ /* do printoption AFTER flush, otherwise the output gets tossed... */ printoption("SENT", DO, TELOPT_TM); } - void -xmitAO() +void +xmitAO(void) { NET2ADD(IAC, AO); printoption("SENT", IAC, AO); if (autoflush) { doflush(); } } - - void -xmitEL() +void +xmitEL(void) { NET2ADD(IAC, EL); printoption("SENT", IAC, EL); } - void -xmitEC() +void +xmitEC(void) { NET2ADD(IAC, EC); printoption("SENT", IAC, EC); } - - int -dosynch() +int +dosynch(char *ch __unused) { netclear(); /* clear the path to the network */ NETADD(IAC); setneturg(); NETADD(DM); printoption("SENT", IAC, DM); return 1; } int want_status_response = 0; - int -get_status() +int +get_status(char *ch __unused) { unsigned char tmp[16]; - register unsigned char *cp; + unsigned char *cp; if (my_want_state_is_dont(TELOPT_STATUS)) { printf("Remote side does not support STATUS option\n"); return 0; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_STATUS; *cp++ = TELQUAL_SEND; *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); } ++want_status_response; return 1; } - void -intp() +void +intp(void) { NET2ADD(IAC, IP); printoption("SENT", IAC, IP); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendbrk() +void +sendbrk(void) { NET2ADD(IAC, BREAK); printoption("SENT", IAC, BREAK); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendabort() +void +sendabort(void) { NET2ADD(IAC, ABORT); printoption("SENT", IAC, ABORT); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendsusp() +void +sendsusp(void) { NET2ADD(IAC, SUSP); printoption("SENT", IAC, SUSP); flushline = 1; if (autoflush) { doflush(); } if (autosynch) { - dosynch(); + dosynch(NULL); } } - void -sendeof() +void +sendeof(void) { NET2ADD(IAC, xEOF); printoption("SENT", IAC, xEOF); } - void -sendayt() +void +sendayt(void) { NET2ADD(IAC, AYT); printoption("SENT", IAC, AYT); } /* * Send a window size update to the remote system. */ - void -sendnaws() +void +sendnaws(void) { long rows, cols; unsigned char tmp[16]; - register unsigned char *cp; + unsigned char *cp; if (my_state_is_wont(TELOPT_NAWS)) return; #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ return; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_NAWS; PUTSHORT(cp, cols); PUTSHORT(cp, rows); *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); } } - void -tel_enter_binary(rw) - int rw; +void +tel_enter_binary(int rw) { if (rw&1) send_do(TELOPT_BINARY, 1); if (rw&2) send_will(TELOPT_BINARY, 1); } - void -tel_leave_binary(rw) - int rw; +void +tel_leave_binary(int rw) { if (rw&1) send_dont(TELOPT_BINARY, 1); if (rw&2) send_wont(TELOPT_BINARY, 1); } Index: head/crypto/telnet/telnet/terminal.c =================================================================== --- head/crypto/telnet/telnet/terminal.c (revision 87138) +++ head/crypto/telnet/telnet/terminal.c (revision 87139) @@ -1,249 +1,240 @@ /* * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)terminal.c 8.2 (Berkeley) 2/16/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #include #include #include "ring.h" #include "externs.h" #include "types.h" -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif Ring ttyoring, ttyiring; unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ]; int termdata; /* Debugging flag */ #ifdef USE_TERMIO # ifndef VDISCARD cc_t termFlushChar; # endif # ifndef VLNEXT cc_t termLiteralNextChar; # endif # ifndef VSUSP cc_t termSuspChar; # endif # ifndef VWERASE cc_t termWerasChar; # endif # ifndef VREPRINT cc_t termRprntChar; # endif # ifndef VSTART cc_t termStartChar; # endif # ifndef VSTOP cc_t termStopChar; # endif # ifndef VEOL cc_t termForw1Char; # endif # ifndef VEOL2 cc_t termForw2Char; # endif # ifndef VSTATUS cc_t termAytChar; # endif #else cc_t termForw2Char; cc_t termAytChar; #endif /* * initialize the terminal data structures. */ - void -init_terminal() +void +init_terminal(void) { if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) { exit(1); } if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) { exit(1); } autoflush = TerminalAutoFlush(); } - /* * Send as much data as possible to the terminal. * * Return value: * -1: No useful work done, data waiting to go out. * 0: No data was waiting, so nothing was done. * 1: All waiting data was written out. * n: All data - n was written out. */ - - int -ttyflush(drop) - int drop; +int +ttyflush(int drop) { - register int n, n0, n1; + int n, n0, n1; n0 = ring_full_count(&ttyoring); if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) { if (drop) { TerminalFlushOutput(); /* we leave 'n' alone! */ } else { n = TerminalWrite(ttyoring.consume, n); } } if (n > 0) { if (termdata && n) { Dump('>', ttyoring.consume, n); } /* * If we wrote everything, and the full count is * larger than what we wrote, then write the * rest of the buffer. */ if (n1 == n && n0 > n) { n1 = n0 - n; if (!drop) n1 = TerminalWrite(ttyoring.bottom, n1); if (n1 > 0) n += n1; } ring_consumed(&ttyoring, n); } if (n < 0) return -1; if (n == n0) { if (n0) return -1; return 0; } return n0 - n + 1; } /* * These routines decides on what the mode should be (based on the values * of various global variables). */ - int -getconnmode() +int +getconnmode(void) { extern int linemode; int mode = 0; #ifdef KLUDGELINEMODE extern int kludgelinemode; #endif - if (In3270) - return(MODE_FLOW); - if (my_want_state_is_dont(TELOPT_ECHO)) mode |= MODE_ECHO; if (localflow) mode |= MODE_FLOW; if (my_want_state_is_will(TELOPT_BINARY)) mode |= MODE_INBIN; if (his_want_state_is_will(TELOPT_BINARY)) mode |= MODE_OUTBIN; #ifdef KLUDGELINEMODE if (kludgelinemode) { if (my_want_state_is_dont(TELOPT_SGA)) { mode |= (MODE_TRAPSIG|MODE_EDIT); if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) { mode &= ~MODE_ECHO; } } return(mode); } #endif if (my_want_state_is_will(TELOPT_LINEMODE)) mode |= linemode; return(mode); } - void -setconnmode(force) - int force; +void +setconnmode(int force) { #ifdef ENCRYPTION static int enc_passwd = 0; #endif /* ENCRYPTION */ - register int newmode; + int newmode; newmode = getconnmode()|(force?MODE_FORCE:0); TerminalNewMode(newmode); #ifdef ENCRYPTION if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) { if (my_want_state_is_will(TELOPT_ENCRYPT) && (enc_passwd == 0) && !encrypt_output) { encrypt_request_start(0, 0); enc_passwd = 1; } } else { if (enc_passwd) { encrypt_request_end(); enc_passwd = 0; } } #endif /* ENCRYPTION */ } - - void -setcommandmode() +void +setcommandmode(void) { TerminalNewMode(-1); } Index: head/crypto/telnet/telnet/utilities.c =================================================================== --- head/crypto/telnet/telnet/utilities.c (revision 87138) +++ head/crypto/telnet/telnet/utilities.c (revision 87139) @@ -1,950 +1,911 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95"; -#else -static const char rcsid[] = - "$FreeBSD$"; #endif -#endif /* not lint */ #define TELOPTS #define TELCMDS #define SLC_NAMES #include #include #include #include #include #include #include "general.h" #include "fdset.h" #include "ring.h" #include "defines.h" #include "externs.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif FILE *NetTrace = 0; /* Not in bss, since needs to stay */ int prettydump; /* * upcase() * * Upcase (in place) the argument. */ - void -upcase(argument) - register char *argument; +void +upcase(char *argument) { - register int c; + int c; while ((c = *argument) != 0) { if (islower(c)) { *argument = toupper(c); } argument++; } } /* * SetSockOpt() * * Compensate for differences in 4.2 and 4.3 systems. */ - int -SetSockOpt(fd, level, option, yesno) - int fd, level, option, yesno; +int +SetSockOpt(int fd, int level, int option, int yesno) { -#ifndef NOT43 return setsockopt(fd, level, option, (char *)&yesno, sizeof yesno); -#else /* NOT43 */ - if (yesno == 0) { /* Can't do that in 4.2! */ - fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", - option); - return -1; - } - return setsockopt(fd, level, option, 0, 0); -#endif /* NOT43 */ } /* * The following are routines used to print out debugging information. */ unsigned char NetTraceFile[256] = "(standard output)"; - void -SetNetTrace(file) - register char *file; +void +SetNetTrace(char *file) { if (NetTrace && NetTrace != stdout) fclose(NetTrace); if (file && (strcmp(file, "-") != 0)) { NetTrace = fopen(file, "w"); if (NetTrace) { strcpy((char *)NetTraceFile, file); return; } fprintf(stderr, "Cannot open %s.\n", file); } NetTrace = stdout; strcpy((char *)NetTraceFile, "(standard output)"); } - void -Dump(direction, buffer, length) - char direction; - unsigned char *buffer; - int length; +void +Dump(char direction, unsigned char *buffer, int length) { # define BYTES_PER_LINE 32 # define min(x,y) ((x' */ - unsigned char *pointer; /* where suboption data sits */ - int length; /* length of suboption data */ +void +printsub(char direction, unsigned char *pointer, int length) { - register int i; + int i; +#ifdef AUTHENTICATION char buf[512]; +#endif extern int want_status_response; if (showoptions || direction == 0 || (want_status_response && (pointer[0] == TELOPT_STATUS))) { if (direction) { fprintf(NetTrace, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); if (length >= 3) { - register int j; + int j; i = pointer[length-2]; j = pointer[length-1]; if (i != IAC || j != SE) { fprintf(NetTrace, "(terminated by "); if (TELOPT_OK(i)) fprintf(NetTrace, "%s ", TELOPT(i)); else if (TELCMD_OK(i)) fprintf(NetTrace, "%s ", TELCMD(i)); else fprintf(NetTrace, "%d ", i); if (TELOPT_OK(j)) fprintf(NetTrace, "%s", TELOPT(j)); else if (TELCMD_OK(j)) fprintf(NetTrace, "%s", TELCMD(j)); else fprintf(NetTrace, "%d", j); fprintf(NetTrace, ", not IAC SE!) "); } } length -= 2; } if (length < 1) { fprintf(NetTrace, "(Empty suboption??\?)"); if (NetTrace == stdout) fflush(NetTrace); return; } switch (pointer[0]) { case TELOPT_TTYPE: fprintf(NetTrace, "TERMINAL-TYPE "); switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: fprintf(NetTrace, "SEND"); break; default: fprintf(NetTrace, "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_TSPEED: fprintf(NetTrace, "TERMINAL-SPEED"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, " IS "); fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); break; default: if (pointer[1] == 1) fprintf(NetTrace, " SEND"); else fprintf(NetTrace, " %d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; } break; case TELOPT_LFLOW: fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case LFLOW_OFF: fprintf(NetTrace, " OFF"); break; case LFLOW_ON: fprintf(NetTrace, " ON"); break; case LFLOW_RESTART_ANY: fprintf(NetTrace, " RESTART-ANY"); break; case LFLOW_RESTART_XON: fprintf(NetTrace, " RESTART-XON"); break; default: fprintf(NetTrace, " %d (unknown)", pointer[1]); } for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; case TELOPT_NAWS: fprintf(NetTrace, "NAWS"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } if (length == 2) { fprintf(NetTrace, " ?%d?", pointer[1]); break; } fprintf(NetTrace, " %d %d (%d)", pointer[1], pointer[2], (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); if (length == 4) { fprintf(NetTrace, " ?%d?", pointer[3]); break; } fprintf(NetTrace, " %d %d (%d)", pointer[3], pointer[4], (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); for (i = 5; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: fprintf(NetTrace, "AUTHENTICATION"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_REPLY: case TELQUAL_IS: fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? "IS" : "REPLY"); if (AUTHTYPE_NAME_OK(pointer[2])) fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); else fprintf(NetTrace, "%d ", pointer[2]); if (length < 3) { fprintf(NetTrace, "(partial suboption??\?)"); break; } fprintf(NetTrace, "%s|%s", ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); fprintf(NetTrace, "%s", buf); break; case TELQUAL_SEND: i = 2; fprintf(NetTrace, " SEND "); while (i < length) { if (AUTHTYPE_NAME_OK(pointer[i])) fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); else fprintf(NetTrace, "%d ", pointer[i]); if (++i >= length) { fprintf(NetTrace, "(partial suboption??\?)"); break; } fprintf(NetTrace, "%s|%s ", ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); ++i; } break; case TELQUAL_NAME: i = 2; fprintf(NetTrace, " NAME \""); while (i < length) putc(pointer[i++], NetTrace); putc('"', NetTrace); break; default: for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: fprintf(NetTrace, "ENCRYPT"); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case ENCRYPT_START: fprintf(NetTrace, " START"); break; case ENCRYPT_END: fprintf(NetTrace, " END"); break; case ENCRYPT_REQSTART: fprintf(NetTrace, " REQUEST-START"); break; case ENCRYPT_REQEND: fprintf(NetTrace, " REQUEST-END"); break; case ENCRYPT_IS: case ENCRYPT_REPLY: fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? "IS" : "REPLY"); if (length < 3) { fprintf(NetTrace, " (partial suboption??\?)"); break; } if (ENCTYPE_NAME_OK(pointer[2])) fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); else fprintf(NetTrace, " %d (unknown)", pointer[2]); encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); fprintf(NetTrace, "%s", buf); break; case ENCRYPT_SUPPORT: i = 2; fprintf(NetTrace, " SUPPORT "); while (i < length) { if (ENCTYPE_NAME_OK(pointer[i])) fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); else fprintf(NetTrace, "%d ", pointer[i]); i++; } break; case ENCRYPT_ENC_KEYID: fprintf(NetTrace, " ENC_KEYID "); goto encommon; case ENCRYPT_DEC_KEYID: fprintf(NetTrace, " DEC_KEYID "); goto encommon; default: fprintf(NetTrace, " %d (unknown)", pointer[1]); encommon: for (i = 2; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); break; } break; #endif /* ENCRYPTION */ case TELOPT_LINEMODE: fprintf(NetTrace, "LINEMODE "); if (length < 2) { fprintf(NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case WILL: fprintf(NetTrace, "WILL "); goto common; case WONT: fprintf(NetTrace, "WONT "); goto common; case DO: fprintf(NetTrace, "DO "); goto common; case DONT: fprintf(NetTrace, "DONT "); common: if (length < 3) { fprintf(NetTrace, "(no option??\?)"); break; } switch (pointer[2]) { case LM_FORWARDMASK: fprintf(NetTrace, "Forward Mask"); for (i = 3; i < length; i++) fprintf(NetTrace, " %x", pointer[i]); break; default: fprintf(NetTrace, "%d (unknown)", pointer[2]); for (i = 3; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); break; } break; case LM_SLC: fprintf(NetTrace, "SLC"); for (i = 2; i < length - 2; i += 3) { if (SLC_NAME_OK(pointer[i+SLC_FUNC])) fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); else fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { case SLC_NOSUPPORT: fprintf(NetTrace, " NOSUPPORT"); break; case SLC_CANTCHANGE: fprintf(NetTrace, " CANTCHANGE"); break; case SLC_VARIABLE: fprintf(NetTrace, " VARIABLE"); break; case SLC_DEFAULT: fprintf(NetTrace, " DEFAULT"); break; } fprintf(NetTrace, "%s%s%s", pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| SLC_FLUSHOUT| SLC_LEVELBITS)) fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); if ((pointer[i+SLC_VALUE] == IAC) && (pointer[i+SLC_VALUE+1] == IAC)) i++; } for (; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; case LM_MODE: fprintf(NetTrace, "MODE "); if (length < 3) { fprintf(NetTrace, "(no mode??\?)"); break; } { char tbuf[64]; sprintf(tbuf, "%s%s%s%s%s", pointer[2]&MODE_EDIT ? "|EDIT" : "", pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", pointer[2]&MODE_ACK ? "|ACK" : ""); fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); } if (pointer[2]&~(MODE_MASK)) fprintf(NetTrace, " (0x%x)", pointer[2]); for (i = 3; i < length; i++) fprintf(NetTrace, " ?0x%x?", pointer[i]); break; default: fprintf(NetTrace, "%d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); } break; case TELOPT_STATUS: { - register char *cp; - register int j, k; + const char *cp; + int j, k; fprintf(NetTrace, "STATUS"); switch (pointer[1]) { default: if (pointer[1] == TELQUAL_SEND) fprintf(NetTrace, " SEND"); else fprintf(NetTrace, " %d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf(NetTrace, " ?%d?", pointer[i]); break; case TELQUAL_IS: if (--want_status_response < 0) want_status_response = 0; if (NetTrace == stdout) fprintf(NetTrace, " IS\r\n"); else fprintf(NetTrace, " IS\n"); for (i = 2; i < length; i++) { switch(pointer[i]) { case DO: cp = "DO"; goto common2; case DONT: cp = "DONT"; goto common2; case WILL: cp = "WILL"; goto common2; case WONT: cp = "WONT"; goto common2; common2: i++; if (TELOPT_OK((int)pointer[i])) fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); else fprintf(NetTrace, " %s %d", cp, pointer[i]); if (NetTrace == stdout) fprintf(NetTrace, "\r\n"); else fprintf(NetTrace, "\n"); break; case SB: fprintf(NetTrace, " SB "); i++; j = k = i; while (j < length) { if (pointer[j] == SE) { if (j+1 == length) break; if (pointer[j+1] == SE) j++; else break; } pointer[k++] = pointer[j++]; } printsub(0, &pointer[i], k - i); if (i < length) { fprintf(NetTrace, " SE"); i = j; } else i = j - 1; if (NetTrace == stdout) fprintf(NetTrace, "\r\n"); else fprintf(NetTrace, "\n"); break; default: fprintf(NetTrace, " %d", pointer[i]); break; } } break; } break; } case TELOPT_XDISPLOC: fprintf(NetTrace, "X-DISPLAY-LOCATION "); switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: fprintf(NetTrace, "SEND"); break; default: fprintf(NetTrace, "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_NEW_ENVIRON: fprintf(NetTrace, "NEW-ENVIRON "); #ifdef OLD_ENVIRON goto env_common1; case TELOPT_OLD_ENVIRON: fprintf(NetTrace, "OLD-ENVIRON"); env_common1: #endif switch (pointer[1]) { case TELQUAL_IS: fprintf(NetTrace, "IS "); goto env_common; case TELQUAL_SEND: fprintf(NetTrace, "SEND "); goto env_common; case TELQUAL_INFO: fprintf(NetTrace, "INFO "); env_common: { - register int noquote = 2; + int noquote = 2; #if defined(ENV_HACK) && defined(OLD_ENVIRON) extern int old_env_var, old_env_value; #endif for (i = 2; i < length; i++ ) { switch (pointer[i]) { case NEW_ENV_VALUE: #ifdef OLD_ENVIRON /* case NEW_ENV_OVAR: */ if (pointer[0] == TELOPT_OLD_ENVIRON) { # ifdef ENV_HACK if (old_env_var == OLD_ENV_VALUE) fprintf(NetTrace, "\" (VALUE) " + noquote); else # endif fprintf(NetTrace, "\" VAR " + noquote); } else #endif /* OLD_ENVIRON */ fprintf(NetTrace, "\" VALUE " + noquote); noquote = 2; break; case NEW_ENV_VAR: #ifdef OLD_ENVIRON /* case OLD_ENV_VALUE: */ if (pointer[0] == TELOPT_OLD_ENVIRON) { # ifdef ENV_HACK if (old_env_value == OLD_ENV_VAR) fprintf(NetTrace, "\" (VAR) " + noquote); else # endif fprintf(NetTrace, "\" VALUE " + noquote); } else #endif /* OLD_ENVIRON */ fprintf(NetTrace, "\" VAR " + noquote); noquote = 2; break; case ENV_ESC: fprintf(NetTrace, "\" ESC " + noquote); noquote = 2; break; case ENV_USERVAR: fprintf(NetTrace, "\" USERVAR " + noquote); noquote = 2; break; default: if (isprint(pointer[i]) && pointer[i] != '"') { if (noquote) { putc('"', NetTrace); noquote = 0; } putc(pointer[i], NetTrace); } else { fprintf(NetTrace, "\" %03o " + noquote, pointer[i]); noquote = 2; } break; } } if (!noquote) putc('"', NetTrace); break; } } break; default: if (TELOPT_OK(pointer[0])) fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); else fprintf(NetTrace, "%d (unknown)", pointer[0]); for (i = 1; i < length; i++) fprintf(NetTrace, " %d", pointer[i]); break; } if (direction) { if (NetTrace == stdout) fprintf(NetTrace, "\r\n"); else fprintf(NetTrace, "\n"); } if (NetTrace == stdout) fflush(NetTrace); } } /* EmptyTerminal - called to make sure that the terminal buffer is empty. * Note that we consider the buffer to run all the * way to the kernel (thus the select). */ - void -EmptyTerminal() +static void +EmptyTerminal(void) { -#if defined(unix) fd_set o; FD_ZERO(&o); -#endif /* defined(unix) */ if (TTYBYTES() == 0) { -#if defined(unix) FD_SET(tout, &o); (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, (struct timeval *) 0); /* wait for TTLOWAT */ -#endif /* defined(unix) */ } else { while (TTYBYTES()) { (void) ttyflush(0); -#if defined(unix) FD_SET(tout, &o); (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, (struct timeval *) 0); /* wait for TTLOWAT */ -#endif /* defined(unix) */ } } } - void -SetForExit() +static void +SetForExit(void) { setconnmode(0); -#if defined(TN3270) - if (In3270) { - Finish3270(); - } -#else /* defined(TN3270) */ do { (void)telrcv(); /* Process any incoming data */ EmptyTerminal(); } while (ring_full_count(&netiring)); /* While there is any */ -#endif /* defined(TN3270) */ setcommandmode(); fflush(stdout); fflush(stderr); -#if defined(TN3270) - if (In3270) { - StopScreen(1); - } -#endif /* defined(TN3270) */ setconnmode(0); EmptyTerminal(); /* Flush the path to the tty */ setcommandmode(); } - void -Exit(returnCode) - int returnCode; +void +Exit(int returnCode) { SetForExit(); exit(returnCode); } - void -ExitString(string, returnCode) - char *string; - int returnCode; +void +ExitString(const char *string, int returnCode) { SetForExit(); fwrite(string, 1, strlen(string), stderr); exit(returnCode); } Index: head/crypto/telnet/telnetd/authenc.c =================================================================== --- head/crypto/telnet/telnetd/authenc.c (revision 87138) +++ head/crypto/telnet/telnetd/authenc.c (revision 87139) @@ -1,93 +1,90 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)authenc.c 8.2 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION +/* Above "#ifdef"s actually "or"'ed together. XXX MarkM + */ #include "telnetd.h" #include - int -net_write(str, len) - unsigned char *str; - int len; +int +net_write(unsigned char *str, int len) { if (nfrontp + len < netobuf + BUFSIZ) { output_datalen(str, len); return(len); } return(0); } - void -net_encrypt() +void +net_encrypt(void) { #ifdef ENCRYPTION char *s = (nclearto > nbackp) ? nclearto : nbackp; if (s < nfrontp && encrypt_output) { (*encrypt_output)((unsigned char *)s, nfrontp - s); } nclearto = nfrontp; #endif /* ENCRYPTION */ } - int -telnet_spin() +int +telnet_spin(void) { ttloop(); return(0); } - char * -telnet_getenv(val) - char *val; +char * +telnet_getenv(char *val) { return(getenv(val)); } - char * -telnet_gets(prompt, result, length, echo) - char *prompt; - char *result; - int length; - int echo; +char * +telnet_gets(const char *prompt __unused, char *result __unused, int length __unused, int echo __unused) { - return((char *)0); + return(NULL); } -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +#endif /* ENCRYPTION */ +#endif /* AUTHENTICATION */ Index: head/crypto/telnet/telnetd/ext.h =================================================================== --- head/crypto/telnet/telnetd/ext.h (revision 87138) +++ head/crypto/telnet/telnetd/ext.h (revision 87139) @@ -1,227 +1,226 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ext.h 8.2 (Berkeley) 12/15/93 * $FreeBSD$ */ /* * Telnet server variable declarations */ extern char options[256]; extern char do_dont_resp[256]; extern char will_wont_resp[256]; extern int linemode; /* linemode on/off */ #ifdef LINEMODE extern int uselinemode; /* what linemode to use (on/off) */ extern int editmode; /* edit modes in use */ extern int useeditmode; /* edit modes to use */ extern int alwayslinemode; /* command line option */ extern int lmodetype; /* Client support for linemode */ #endif /* LINEMODE */ extern int flowmode; /* current flow control state */ extern int restartany; /* restart output on any character state */ #ifdef DIAGNOSTICS extern int diagnostic; /* telnet diagnostic capabilities */ #endif /* DIAGNOSTICS */ #ifdef BFTPDAEMON extern int bftpd; /* behave as bftp daemon */ #endif /* BFTPDAEMON */ -#if defined(SecurID) -extern int require_SecurID; -#endif -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION extern int auth_level; #endif extern slcfun slctab[NSLC + 1]; /* slc mapping table */ char *terminaltype; /* * I/O data buffers, pointers, and counters. */ extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; extern char netibuf[BUFSIZ], *netip; extern char netobuf[BUFSIZ], *nfrontp, *nbackp; extern char *neturg; /* one past last bye of urgent data */ extern int pcc, ncc; extern int pty, net; extern char line[16]; extern int SYNCHing; /* we are in TELNET SYNCH mode */ #ifndef P # ifdef __STDC__ # define P(x) x # else # define P(x) () # endif #endif extern void _termstat P((void)), - add_slc P((int, int, int)), + add_slc P((char, char, cc_t)), check_slc P((void)), - change_slc P((int, int, int)), + change_slc P((char, char, cc_t)), cleanup P((int)), clientstat P((int, int, int)), - copy_termbuf P((char *, int)), + copy_termbuf P((char *, size_t)), deferslc P((void)), defer_terminit P((void)), do_opt_slc P((unsigned char *, int)), doeof P((void)), dooption P((int)), dontoption P((int)), edithost P((char *, char *)), - fatal P((int, char *)), - fatalperror P((int, char *)), + fatal P((int, const char *)), + fatalperror P((int, const char *)), get_slc_defaults P((void)), init_env P((void)), init_termbuf P((void)), interrupt P((void)), localstat P((void)), flowstat P((void)), netclear P((void)), netflush P((void)), #ifdef DIAGNOSTICS - printoption P((char *, int)), - printdata P((char *, char *, int)), - printsub P((int, unsigned char *, int)), + printoption P((const char *, int)), + printdata P((const char *, char *, int)), + printsub P((char, unsigned char *, int)), #endif + process_slc P((unsigned char, unsigned char, cc_t)), ptyflush P((void)), putchr P((int)), putf P((char *, char *)), recv_ayt P((void)), send_do P((int, int)), send_dont P((int, int)), send_slc P((void)), send_status P((void)), send_will P((int, int)), send_wont P((int, int)), sendbrk P((void)), sendsusp P((void)), set_termbuf P((void)), start_login P((char *, int, char *)), start_slc P((int)), -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION start_slave P((char *)), #else start_slave P((char *, int, char *)), #endif suboption P((void)), telrcv P((void)), ttloop P((void)), tty_binaryin P((int)), tty_binaryout P((int)); extern int end_slc P((unsigned char **)), getnpty P((void)), #ifndef convex getpty P((int *)), #endif login_tty P((int)), spcset P((int, cc_t *, cc_t **)), stilloob P((int)), terminit P((void)), termstat P((void)), tty_flowmode P((void)), tty_restartany P((void)), tty_isbinaryin P((void)), tty_isbinaryout P((void)), tty_iscrnl P((void)), tty_isecho P((void)), tty_isediting P((void)), tty_islitecho P((void)), tty_isnewmap P((void)), tty_israw P((void)), tty_issofttab P((void)), tty_istrapsig P((void)), tty_linemode P((void)); extern void tty_rspeed P((int)), tty_setecho P((int)), tty_setedit P((int)), tty_setlinemode P((int)), tty_setlitecho P((int)), tty_setsig P((int)), tty_setsofttab P((int)), tty_tspeed P((int)), willoption P((int)), wontoption P((int)); int output_data __P((const char *, ...)) __printflike(1, 2); void output_datalen __P((const char *, int)); +void startslave __P((char *, int, char *)); #ifdef ENCRYPTION extern void (*encrypt_output) P((unsigned char *, int)); extern int (*decrypt_input) P((int)); extern char *nclearto; #endif /* ENCRYPTION */ /* * The following are some clocks used to decide how to interpret * the relationship between various variables. */ extern struct { int system, /* what the current time is */ echotoggle, /* last time user entered echo character */ modenegotiated, /* last time operating mode negotiated */ didnetreceive, /* last time we read data from network */ ttypesubopt, /* ttype subopt is received */ tspeedsubopt, /* tspeed subopt is received */ environsubopt, /* environ subopt is received */ oenvironsubopt, /* old environ subopt is received */ xdisplocsubopt, /* xdisploc subopt is received */ baseline, /* time started to do timed action */ gotDM; /* when did we last see a data mark */ } clocks; #ifndef DEFAULT_IM # ifdef ultrix # define DEFAULT_IM "\r\n\r\nULTRIX (%h) (%t)\r\n\r\r\n\r" # else # ifdef __FreeBSD__ # define DEFAULT_IM "\r\n\r\nFreeBSD (%h) (%t)\r\n\r\r\n\r" # else # define DEFAULT_IM "\r\n\r\n4.4 BSD UNIX (%h) (%t)\r\n\r\r\n\r" # endif # endif #endif Index: head/crypto/telnet/telnetd/slc.c =================================================================== --- head/crypto/telnet/telnetd/slc.c (revision 87138) +++ head/crypto/telnet/telnetd/slc.c (revision 87139) @@ -1,494 +1,484 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)slc.c 8.2 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include "telnetd.h" #ifdef LINEMODE /* * local variables */ static unsigned char *def_slcbuf = (unsigned char *)0; static int def_slclen = 0; static int slcchange; /* change to slc is requested */ static unsigned char *slcptr; /* pointer into slc buffer */ static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */ /* * send_slc * * Write out the current special characters to the client. */ - void -send_slc() +void +send_slc(void) { - register int i; + int i; /* * Send out list of triplets of special characters * to client. We only send info on the characters * that are currently supported. */ for (i = 1; i <= NSLC; i++) { if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT) continue; add_slc((unsigned char)i, slctab[i].current.flag, slctab[i].current.val); } } /* end of send_slc */ /* * default_slc * * Set pty special characters to all the defaults. */ - void -default_slc() +static void +default_slc(void) { - register int i; + int i; for (i = 1; i <= NSLC; i++) { slctab[i].current.val = slctab[i].defset.val; if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE)) slctab[i].current.flag = SLC_NOSUPPORT; else slctab[i].current.flag = slctab[i].defset.flag; if (slctab[i].sptr) { *(slctab[i].sptr) = slctab[i].defset.val; } } slcchange = 1; } /* end of default_slc */ #endif /* LINEMODE */ /* * get_slc_defaults * * Initialize the slc mapping table. */ - void -get_slc_defaults() +void +get_slc_defaults(void) { - register int i; + int i; init_termbuf(); for (i = 1; i <= NSLC; i++) { slctab[i].defset.flag = spcset(i, &slctab[i].defset.val, &slctab[i].sptr); slctab[i].current.flag = SLC_NOSUPPORT; slctab[i].current.val = 0; } } /* end of get_slc_defaults */ #ifdef LINEMODE /* * add_slc * * Add an slc triplet to the slc buffer. */ - void -add_slc(func, flag, val) - register char func, flag; - register cc_t val; +void +add_slc(char func, char flag, cc_t val) { if ((*slcptr++ = (unsigned char)func) == 0xff) *slcptr++ = 0xff; if ((*slcptr++ = (unsigned char)flag) == 0xff) *slcptr++ = 0xff; if ((*slcptr++ = (unsigned char)val) == 0xff) *slcptr++ = 0xff; } /* end of add_slc */ /* * start_slc * * Get ready to process incoming slc's and respond to them. * * The parameter getit is non-zero if it is necessary to grab a copy * of the terminal control structures. */ - void -start_slc(getit) - register int getit; +void +start_slc(int getit) { slcchange = 0; if (getit) init_termbuf(); (void) sprintf((char *)slcbuf, "%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC); slcptr = slcbuf + 4; } /* end of start_slc */ /* * end_slc * * Finish up the slc negotiation. If something to send, then send it. */ - int -end_slc(bufp) - register unsigned char **bufp; +int +end_slc(unsigned char **bufp) { - register int len; + int len; /* * If a change has occured, store the new terminal control * structures back to the terminal driver. */ if (slcchange) { set_termbuf(); } /* * If the pty state has not yet been fully processed and there is a * deferred slc request from the client, then do not send any * sort of slc negotiation now. We will respond to the client's * request very soon. */ if (def_slcbuf && (terminit() == 0)) { return(0); } if (slcptr > (slcbuf + 4)) { if (bufp) { *bufp = &slcbuf[4]; return(slcptr - slcbuf - 4); } else { (void) sprintf((char *)slcptr, "%c%c", IAC, SE); slcptr += 2; len = slcptr - slcbuf; output_datalen(slcbuf, len); netflush(); /* force it out immediately */ DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2);); } } return (0); } /* end of end_slc */ /* * process_slc * * Figure out what to do about the client's slc */ - void -process_slc(func, flag, val) - register unsigned char func, flag; - register cc_t val; +void +process_slc(unsigned char func, unsigned char flag, cc_t val) { - register int hislevel, mylevel, ack; + int hislevel, mylevel, ack; /* * Ensure that we know something about this function */ if (func > NSLC) { add_slc(func, SLC_NOSUPPORT, 0); return; } /* * Process the special case requests of 0 SLC_DEFAULT 0 * and 0 SLC_VARIABLE 0. Be a little forgiving here, don't * worry about whether the value is actually 0 or not. */ if (func == 0) { if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) { default_slc(); send_slc(); } else if (flag == SLC_VARIABLE) { send_slc(); } return; } /* * Appears to be a function that we know something about. So * get on with it and see what we know. */ hislevel = flag & SLC_LEVELBITS; mylevel = slctab[func].current.flag & SLC_LEVELBITS; ack = flag & SLC_ACK; /* * ignore the command if: * the function value and level are the same as what we already have; * or the level is the same and the ack bit is set */ if (hislevel == mylevel && (val == slctab[func].current.val || ack)) { return; } else if (ack) { /* * If we get here, we got an ack, but the levels don't match. * This shouldn't happen. If it does, it is probably because * we have sent two requests to set a variable without getting * a response between them, and this is the first response. * So, ignore it, and wait for the next response. */ return; } else { change_slc(func, flag, val); } } /* end of process_slc */ /* * change_slc * * Process a request to change one of our special characters. * Compare client's request with what we are capable of supporting. */ - void -change_slc(func, flag, val) - register char func, flag; - register cc_t val; +void +change_slc(char func, char flag, cc_t val) { - register int hislevel, mylevel; + int hislevel, mylevel; hislevel = flag & SLC_LEVELBITS; mylevel = slctab[(int)func].defset.flag & SLC_LEVELBITS; /* * If client is setting a function to NOSUPPORT * or DEFAULT, then we can easily and directly * accomodate the request. */ if (hislevel == SLC_NOSUPPORT) { slctab[(int)func].current.flag = flag; slctab[(int)func].current.val = (cc_t)_POSIX_VDISABLE; flag |= SLC_ACK; add_slc(func, flag, val); return; } if (hislevel == SLC_DEFAULT) { /* * Special case here. If client tells us to use * the default on a function we don't support, then * return NOSUPPORT instead of what we may have as a * default level of DEFAULT. */ if (mylevel == SLC_DEFAULT) { slctab[(int)func].current.flag = SLC_NOSUPPORT; } else { slctab[(int)func].current.flag = slctab[(int)func].defset.flag; } slctab[(int)func].current.val = slctab[(int)func].defset.val; add_slc(func, slctab[(int)func].current.flag, slctab[(int)func].current.val); return; } /* * Client wants us to change to a new value or he * is telling us that he can't change to our value. * Some of the slc's we support and can change, * some we do support but can't change, * and others we don't support at all. * If we can change it then we have a pointer to * the place to put the new value, so change it, * otherwise, continue the negotiation. */ if (slctab[(int)func].sptr) { /* * We can change this one. */ slctab[(int)func].current.val = val; *(slctab[(int)func].sptr) = val; slctab[(int)func].current.flag = flag; flag |= SLC_ACK; slcchange = 1; add_slc(func, flag, val); } else { /* * It is not possible for us to support this * request as he asks. * * If our level is DEFAULT, then just ack whatever was * sent. * * If he can't change and we can't change, * then degenerate to NOSUPPORT. * * Otherwise we send our level back to him, (CANTCHANGE * or NOSUPPORT) and if CANTCHANGE, send * our value as well. */ if (mylevel == SLC_DEFAULT) { slctab[(int)func].current.flag = flag; slctab[(int)func].current.val = val; flag |= SLC_ACK; } else if (hislevel == SLC_CANTCHANGE && mylevel == SLC_CANTCHANGE) { flag &= ~SLC_LEVELBITS; flag |= SLC_NOSUPPORT; slctab[(int)func].current.flag = flag; } else { flag &= ~SLC_LEVELBITS; flag |= mylevel; slctab[(int)func].current.flag = flag; if (mylevel == SLC_CANTCHANGE) { slctab[(int)func].current.val = slctab[(int)func].defset.val; val = slctab[(int)func].current.val; } } add_slc(func, flag, val); } } /* end of change_slc */ #if defined(USE_TERMIO) && (VEOF == VMIN) cc_t oldeofc = '\004'; #endif /* * check_slc * * Check the special characters in use and notify the client if any have * changed. Only those characters that are capable of being changed are * likely to have changed. If a local change occurs, kick the support level * and flags up to the defaults. */ - void -check_slc() +void +check_slc(void) { - register int i; + int i; for (i = 1; i <= NSLC; i++) { #if defined(USE_TERMIO) && (VEOF == VMIN) /* * In a perfect world this would be a neat little * function. But in this world, we should not notify * client of changes to the VEOF char when * ICANON is off, because it is not representing * a special character. */ if (i == SLC_EOF) { if (!tty_isediting()) continue; else if (slctab[i].sptr) oldeofc = *(slctab[i].sptr); } #endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */ if (slctab[i].sptr && (*(slctab[i].sptr) != slctab[i].current.val)) { slctab[i].current.val = *(slctab[i].sptr); if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE) slctab[i].current.flag = SLC_NOSUPPORT; else slctab[i].current.flag = slctab[i].defset.flag; add_slc((unsigned char)i, slctab[i].current.flag, slctab[i].current.val); } } } /* check_slc */ /* * do_opt_slc * * Process an slc option buffer. Defer processing of incoming slc's * until after the terminal state has been processed. Save the first slc * request that comes along, but discard all others. * * ptr points to the beginning of the buffer, len is the length. */ - void -do_opt_slc(ptr, len) - register unsigned char *ptr; - register int len; +void +do_opt_slc(unsigned char *ptr, int len) { - register unsigned char func, flag; + unsigned char func, flag; cc_t val; - register unsigned char *end = ptr + len; + unsigned char *end = ptr + len; if (terminit()) { /* go ahead */ while (ptr < end) { func = *ptr++; if (ptr >= end) break; flag = *ptr++; if (ptr >= end) break; val = (cc_t)*ptr++; process_slc(func, flag, val); } } else { /* * save this slc buffer if it is the first, otherwise dump * it. */ if (def_slcbuf == (unsigned char *)0) { def_slclen = len; def_slcbuf = (unsigned char *)malloc((unsigned)len); if (def_slcbuf == (unsigned char *)0) return; /* too bad */ memmove(def_slcbuf, ptr, len); } } } /* end of do_opt_slc */ /* * deferslc * * Do slc stuff that was deferred. */ - void -deferslc() +void +deferslc(void) { if (def_slcbuf) { start_slc(1); do_opt_slc(def_slcbuf, def_slclen); (void) end_slc(0); free(def_slcbuf); def_slcbuf = (unsigned char *)0; def_slclen = 0; } } /* end of deferslc */ #endif /* LINEMODE */ Index: head/crypto/telnet/telnetd/state.c =================================================================== --- head/crypto/telnet/telnetd/state.c (revision 87138) +++ head/crypto/telnet/telnetd/state.c (revision 87139) @@ -1,1647 +1,1631 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)state.c 8.5 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include #include "telnetd.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; unsigned char will[] = { IAC, WILL, '%', 'c', 0 }; unsigned char wont[] = { IAC, WONT, '%', 'c', 0 }; int not42 = 1; /* * Buffer for sub-options, and macros * for suboptions buffer manipulations */ unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer; #define SB_CLEAR() subpointer = subbuffer #define SB_TERM() { subend = subpointer; SB_CLEAR(); } #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ *subpointer++ = (c); \ } #define SB_GET() ((*subpointer++)&0xff) #define SB_EOF() (subpointer >= subend) #define SB_LEN() (subend - subpointer) #ifdef ENV_HACK unsigned char *subsave; #define SB_SAVE() subsave = subpointer; #define SB_RESTORE() subpointer = subsave; #endif /* * State for recv fsm */ #define TS_DATA 0 /* base state */ #define TS_IAC 1 /* look for double IAC's */ #define TS_CR 2 /* CR-LF ->'s CR */ #define TS_SB 3 /* throw away begin's... */ #define TS_SE 4 /* ...end's (suboption negotiation) */ #define TS_WILL 5 /* will option negotiation */ #define TS_WONT 6 /* wont " */ #define TS_DO 7 /* do " */ #define TS_DONT 8 /* dont " */ - void -telrcv() +static void doclientstat(void); + +void +telrcv(void) { - register int c; + int c; static int state = TS_DATA; while (ncc > 0) { if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) break; c = *netip++ & 0377, ncc--; #ifdef ENCRYPTION if (decrypt_input) c = (*decrypt_input)(c); #endif /* ENCRYPTION */ switch (state) { case TS_CR: state = TS_DATA; /* Strip off \n or \0 after a \r */ if ((c == 0) || (c == '\n')) { break; } /* FALL THROUGH */ case TS_DATA: if (c == IAC) { state = TS_IAC; break; } /* * We now map \r\n ==> \r for pragmatic reasons. * Many client implementations send \r\n when * the user hits the CarriageReturn key. * * We USED to map \r\n ==> \n, since \r\n says * that we want to be in column 1 of the next * printable line, and \n is the standard * unix way of saying that (\r is only good * if CRMOD is set, which it normally is). */ if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { int nc = *netip; #ifdef ENCRYPTION if (decrypt_input) nc = (*decrypt_input)(nc & 0xff); #endif /* ENCRYPTION */ #ifdef LINEMODE /* * If we are operating in linemode, * convert to local end-of-line. */ if (linemode && (ncc > 0) && (('\n' == nc) || ((0 == nc) && tty_iscrnl())) ) { netip++; ncc--; c = '\n'; } else #endif { #ifdef ENCRYPTION if (decrypt_input) (void)(*decrypt_input)(-1); #endif /* ENCRYPTION */ state = TS_CR; } } *pfrontp++ = c; break; case TS_IAC: gotiac: switch (c) { /* * Send the process on the pty side an * interrupt. Do this with a NULL or * interrupt char; depending on the tty mode. */ case IP: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); interrupt(); break; case BREAK: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); sendbrk(); break; /* * Are You There? */ case AYT: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); recv_ayt(); break; /* * Abort Output */ case AO: { DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (slctab[SLC_AO].sptr && *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { *pfrontp++ = (unsigned char)*slctab[SLC_AO].sptr; } netclear(); /* clear buffer back */ output_data("%c%c", IAC, DM); neturg = nfrontp-1; /* off by one XXX */ DIAG(TD_OPTIONS, printoption("td: send IAC", DM)); break; } /* * Erase Character and * Erase Line */ case EC: case EL: { cc_t ch; DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (c == EC) ch = *slctab[SLC_EC].sptr; else ch = *slctab[SLC_EL].sptr; if (ch != (cc_t)(_POSIX_VDISABLE)) *pfrontp++ = (unsigned char)ch; break; } /* * Check for urgent data... */ case DM: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); SYNCHing = stilloob(net); settimer(gotDM); break; /* * Begin option subnegotiation... */ case SB: state = TS_SB; SB_CLEAR(); continue; case WILL: state = TS_WILL; continue; case WONT: state = TS_WONT; continue; case DO: state = TS_DO; continue; case DONT: state = TS_DONT; continue; case EOR: if (his_state_is_will(TELOPT_EOR)) doeof(); break; /* * Handle RFC 10xx Telnet linemode option additions * to command stream (EOF, SUSP, ABORT). */ case xEOF: doeof(); break; case SUSP: sendsusp(); break; case ABORT: sendbrk(); break; case IAC: *pfrontp++ = c; break; } state = TS_DATA; break; case TS_SB: if (c == IAC) { state = TS_SE; } else { SB_ACCUM(c); } break; case TS_SE: if (c != SE) { if (c != IAC) { /* * bad form of suboption negotiation. * handle it in such a way as to avoid * damage to local state. Parse * suboption buffer found so far, * then treat remaining stream as * another command sequence. */ /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(c); subpointer -= 2; SB_TERM(); suboption(); state = TS_IAC; goto gotiac; } SB_ACCUM(c); state = TS_SB; } else { /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(SE); subpointer -= 2; SB_TERM(); suboption(); /* handle sub-option */ state = TS_DATA; } break; case TS_WILL: willoption(c); state = TS_DATA; continue; case TS_WONT: wontoption(c); state = TS_DATA; continue; case TS_DO: dooption(c); state = TS_DATA; continue; case TS_DONT: dontoption(c); state = TS_DATA; continue; default: syslog(LOG_ERR, "panic state=%d", state); printf("telnetd: panic state=%d\n", state); exit(1); } } } /* end of telrcv */ /* * The will/wont/do/dont state machines are based on Dave Borman's * Telnet option processing state machine. * * These correspond to the following states: * my_state = the last negotiated state * want_state = what I want the state to go to * want_resp = how many requests I have sent * All state defaults are negative, and resp defaults to 0. * * When initiating a request to change state to new_state: * * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { * do nothing; * } else { * want_state = new_state; * send new_state; * want_resp++; * } * * When receiving new_state: * * if (want_resp) { * want_resp--; * if (want_resp && (new_state == my_state)) * want_resp--; * } * if ((want_resp == 0) && (new_state != want_state)) { * if (ok_to_switch_to new_state) * want_state = new_state; * else * want_resp++; * send want_state; * } * my_state = new_state; * * Note that new_state is implied in these functions by the function itself. * will and do imply positive new_state, wont and dont imply negative. * * Finally, there is one catch. If we send a negative response to a * positive request, my_state will be the positive while want_state will * remain negative. my_state will revert to negative when the negative * acknowlegment arrives from the peer. Thus, my_state generally tells * us not only the last negotiated state, but also tells us what the peer * wants to be doing as well. It is important to understand this difference * as we may wish to be processing data streams based on our desired state * (want_state) or based on what the peer thinks the state is (my_state). * * This all works fine because if the peer sends a positive request, the data * that we receive prior to negative acknowlegment will probably be affected * by the positive state, and we can process it as such (if we can; if we * can't then it really doesn't matter). If it is that important, then the * peer probably should be buffering until this option state negotiation * is complete. * */ - void -send_do(option, init) - int option, init; +void +send_do(int option, int init) { if (init) { if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || his_want_state_is_will(option)) return; /* * Special case for TELOPT_TM: We send a DO, but pretend * that we sent a DONT, so that we can send more DOs if * we want to. */ if (option == TELOPT_TM) set_his_want_state_wont(option); else set_his_want_state_will(option); do_dont_resp[option]++; } output_data((const char *)doopt, option); DIAG(TD_OPTIONS, printoption("td: send do", option)); } -#ifdef AUTHENTICATION -extern void auth_request(); -#endif -#ifdef LINEMODE -extern void doclientstat(); -#endif -#ifdef ENCRYPTION -extern void encrypt_send_support(); -#endif /* ENCRYPTION */ - - void -willoption(option) - int option; +void +willoption(int option) { int changeok = 0; - void (*func)() = 0; + void (*func)(void) = 0; /* * process input from peer. */ DIAG(TD_OPTIONS, printoption("td: recv will", option)); if (do_dont_resp[option]) { do_dont_resp[option]--; if (do_dont_resp[option] && his_state_is_will(option)) do_dont_resp[option]--; } if (do_dont_resp[option] == 0) { if (his_want_state_is_wont(option)) { switch (option) { case TELOPT_BINARY: init_termbuf(); tty_binaryin(1); set_termbuf(); changeok++; break; case TELOPT_ECHO: /* * See comments below for more info. */ not42 = 0; /* looks like a 4.2 system */ break; case TELOPT_TM: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * This telnetd implementation does not really * support timing marks, it just uses them to * support the kludge linemode stuff. If we * receive a will or wont TM in response to our * do TM request that may have been sent to * determine kludge linemode support, process * it, otherwise TM should get a negative * response back. */ /* * Handle the linemode kludge stuff. * If we are not currently supporting any * linemode at all, then we assume that this * is the client telling us to use kludge * linemode in response to our query. Set the * linemode type that is to be supported, note * that the client wishes to use linemode, and * eat the will TM as though it never arrived. */ if (lmodetype < KLUDGE_LINEMODE) { lmodetype = KLUDGE_LINEMODE; clientstat(TELOPT_LINEMODE, WILL, 0); send_wont(TELOPT_SGA, 1); } else if (lmodetype == NO_AUTOKLUDGE) { lmodetype = KLUDGE_OK; } #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ /* * We never respond to a WILL TM, and * we leave the state WONT. */ return; case TELOPT_LFLOW: /* * If we are going to support flow control * option, then don't worry peer that we can't * change the flow control characters. */ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XON].defset.flag |= SLC_DEFAULT; slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; case TELOPT_TTYPE: case TELOPT_SGA: case TELOPT_NAWS: case TELOPT_TSPEED: case TELOPT_XDISPLOC: case TELOPT_NEW_ENVIRON: case TELOPT_OLD_ENVIRON: changeok++; break; #ifdef LINEMODE case TELOPT_LINEMODE: # ifdef KLUDGELINEMODE /* * Note client's desire to use linemode. */ lmodetype = REAL_LINEMODE; # endif /* KLUDGELINEMODE */ func = doclientstat; changeok++; break; #endif /* LINEMODE */ #ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: func = auth_request; changeok++; break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: func = encrypt_send_support; changeok++; break; #endif /* ENCRYPTION */ default: break; } if (changeok) { set_his_want_state_will(option); send_do(option, 0); } else { do_dont_resp[option]++; send_dont(option, 0); } } else { /* * Option processing that should happen when * we receive conformation of a change in * state that we had requested. */ switch (option) { case TELOPT_ECHO: not42 = 0; /* looks like a 4.2 system */ /* * Egads, he responded "WILL ECHO". Turn * it off right now! */ send_dont(option, 1); /* * "WILL ECHO". Kludge upon kludge! * A 4.2 client is now echoing user input at * the tty. This is probably undesireable and * it should be stopped. The client will * respond WONT TM to the DO TM that we send to * check for kludge linemode. When the WONT TM * arrives, linemode will be turned off and a * change propogated to the pty. This change * will cause us to process the new pty state * in localstat(), which will notice that * linemode is off and send a WILL ECHO * so that we are properly in character mode and * all is well. */ break; #ifdef LINEMODE case TELOPT_LINEMODE: # ifdef KLUDGELINEMODE /* * Note client's desire to use linemode. */ lmodetype = REAL_LINEMODE; # endif /* KLUDGELINEMODE */ func = doclientstat; break; #endif /* LINEMODE */ #ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: func = auth_request; break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: func = encrypt_send_support; break; #endif /* ENCRYPTION */ case TELOPT_LFLOW: func = flowstat; break; } } } set_his_state_will(option); if (func) (*func)(); } /* end of willoption */ - void -send_dont(option, init) - int option, init; +void +send_dont(int option, int init) { if (init) { if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || his_want_state_is_wont(option)) return; set_his_want_state_wont(option); do_dont_resp[option]++; } output_data((const char *)dont, option); DIAG(TD_OPTIONS, printoption("td: send dont", option)); } - void -wontoption(option) - int option; +void +wontoption(int option) { /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv wont", option)); if (do_dont_resp[option]) { do_dont_resp[option]--; if (do_dont_resp[option] && his_state_is_wont(option)) do_dont_resp[option]--; } if (do_dont_resp[option] == 0) { if (his_want_state_is_will(option)) { /* it is always ok to change to negative state */ switch (option) { case TELOPT_ECHO: not42 = 1; /* doesn't seem to be a 4.2 system */ break; case TELOPT_BINARY: init_termbuf(); tty_binaryin(0); set_termbuf(); break; #ifdef LINEMODE case TELOPT_LINEMODE: # ifdef KLUDGELINEMODE /* * If real linemode is supported, then client is * asking to turn linemode off. */ if (lmodetype != REAL_LINEMODE) break; lmodetype = KLUDGE_LINEMODE; # endif /* KLUDGELINEMODE */ clientstat(TELOPT_LINEMODE, WONT, 0); break; #endif /* LINEMODE */ case TELOPT_TM: /* * If we get a WONT TM, and had sent a DO TM, * don't respond with a DONT TM, just leave it * as is. Short circut the state machine to * achive this. */ set_his_want_state_wont(TELOPT_TM); return; case TELOPT_LFLOW: /* * If we are not going to support flow control * option, then let peer know that we can't * change the flow control characters. */ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: auth_finished(0, AUTH_REJECT); break; #endif /* * For options that we might spin waiting for * sub-negotiation, if the client turns off the * option rather than responding to the request, * we have to treat it here as if we got a response * to the sub-negotiation, (by updating the timers) * so that we'll break out of the loop. */ case TELOPT_TTYPE: settimer(ttypesubopt); break; case TELOPT_TSPEED: settimer(tspeedsubopt); break; case TELOPT_XDISPLOC: settimer(xdisplocsubopt); break; case TELOPT_OLD_ENVIRON: settimer(oenvironsubopt); break; case TELOPT_NEW_ENVIRON: settimer(environsubopt); break; default: break; } set_his_want_state_wont(option); if (his_state_is_will(option)) send_dont(option, 0); } else { switch (option) { case TELOPT_TM: #if defined(LINEMODE) && defined(KLUDGELINEMODE) if (lmodetype < NO_AUTOKLUDGE) { lmodetype = NO_LINEMODE; clientstat(TELOPT_LINEMODE, WONT, 0); send_will(TELOPT_SGA, 1); send_will(TELOPT_ECHO, 1); } #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: auth_finished(0, AUTH_REJECT); break; #endif default: break; } } } set_his_state_wont(option); } /* end of wontoption */ - void -send_will(option, init) - int option, init; +void +send_will(int option, int init) { if (init) { if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| my_want_state_is_will(option)) return; set_my_want_state_will(option); will_wont_resp[option]++; } output_data((const char *)will, option); DIAG(TD_OPTIONS, printoption("td: send will", option)); } #if !defined(LINEMODE) || !defined(KLUDGELINEMODE) /* * When we get a DONT SGA, we will try once to turn it * back on. If the other side responds DONT SGA, we * leave it at that. This is so that when we talk to * clients that understand KLUDGELINEMODE but not LINEMODE, * we'll keep them in char-at-a-time mode. */ int turn_on_sga = 0; #endif - void -dooption(option) - int option; +void +dooption(int option) { int changeok = 0; /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv do", option)); if (will_wont_resp[option]) { will_wont_resp[option]--; if (will_wont_resp[option] && my_state_is_will(option)) will_wont_resp[option]--; } if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { switch (option) { case TELOPT_ECHO: #ifdef LINEMODE # ifdef KLUDGELINEMODE if (lmodetype == NO_LINEMODE) # else if (his_state_is_wont(TELOPT_LINEMODE)) # endif #endif { init_termbuf(); tty_setecho(1); set_termbuf(); } changeok++; break; case TELOPT_BINARY: init_termbuf(); tty_binaryout(1); set_termbuf(); changeok++; break; case TELOPT_SGA: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * If kludge linemode is in use, then we must * process an incoming do SGA for linemode * purposes. */ if (lmodetype == KLUDGE_LINEMODE) { /* * Receipt of "do SGA" in kludge * linemode is the peer asking us to * turn off linemode. Make note of * the request. */ clientstat(TELOPT_LINEMODE, WONT, 0); /* * If linemode did not get turned off * then don't tell peer that we did. * Breaking here forces a wont SGA to * be returned. */ if (linemode) break; } #else turn_on_sga = 0; #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ changeok++; break; case TELOPT_STATUS: changeok++; break; case TELOPT_TM: /* * Special case for TM. We send a WILL, but * pretend we sent a WONT. */ send_will(option, 0); set_my_want_state_wont(option); set_my_state_wont(option); return; case TELOPT_LOGOUT: /* * When we get a LOGOUT option, respond * with a WILL LOGOUT, make sure that * it gets written out to the network, * and then just go away... */ set_my_want_state_will(TELOPT_LOGOUT); send_will(TELOPT_LOGOUT, 0); set_my_state_will(TELOPT_LOGOUT); (void)netflush(); cleanup(0); /* NOT REACHED */ break; #ifdef ENCRYPTION case TELOPT_ENCRYPT: changeok++; break; #endif /* ENCRYPTION */ case TELOPT_LINEMODE: case TELOPT_TTYPE: case TELOPT_NAWS: case TELOPT_TSPEED: case TELOPT_LFLOW: case TELOPT_XDISPLOC: #ifdef TELOPT_ENVIRON case TELOPT_NEW_ENVIRON: #endif case TELOPT_OLD_ENVIRON: default: break; } if (changeok) { set_my_want_state_will(option); send_will(option, 0); } else { will_wont_resp[option]++; send_wont(option, 0); } } set_my_state_will(option); } /* end of dooption */ - void -send_wont(option, init) - int option, init; +void +send_wont(int option, int init) { if (init) { if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || my_want_state_is_wont(option)) return; set_my_want_state_wont(option); will_wont_resp[option]++; } output_data((const char *)wont, option); DIAG(TD_OPTIONS, printoption("td: send wont", option)); } - void -dontoption(option) - int option; +void +dontoption(int option) { /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv dont", option)); if (will_wont_resp[option]) { will_wont_resp[option]--; if (will_wont_resp[option] && my_state_is_wont(option)) will_wont_resp[option]--; } if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { switch (option) { case TELOPT_BINARY: init_termbuf(); tty_binaryout(0); set_termbuf(); break; case TELOPT_ECHO: /* we should stop echoing */ #ifdef LINEMODE # ifdef KLUDGELINEMODE if ((lmodetype != REAL_LINEMODE) && (lmodetype != KLUDGE_LINEMODE)) # else if (his_state_is_wont(TELOPT_LINEMODE)) # endif #endif { init_termbuf(); tty_setecho(0); set_termbuf(); } break; case TELOPT_SGA: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * If kludge linemode is in use, then we * must process an incoming do SGA for * linemode purposes. */ if ((lmodetype == KLUDGE_LINEMODE) || (lmodetype == KLUDGE_OK)) { /* * The client is asking us to turn * linemode on. */ lmodetype = KLUDGE_LINEMODE; clientstat(TELOPT_LINEMODE, WILL, 0); /* * If we did not turn line mode on, * then what do we say? Will SGA? * This violates design of telnet. * Gross. Very Gross. */ } break; #else set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); set_my_state_wont(option); if (turn_on_sga ^= 1) send_will(option, 1); return; #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ default: break; } set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); } set_my_state_wont(option); } /* end of dontoption */ #ifdef ENV_HACK int env_ovar = -1; int env_ovalue = -1; #else /* ENV_HACK */ # define env_ovar OLD_ENV_VAR # define env_ovalue OLD_ENV_VALUE #endif /* ENV_HACK */ /* * suboption() * * Look at the sub-option buffer, and try to be helpful to the other * side. * * Currently we recognize: * * Terminal type is * Linemode * Window size * Terminal speed */ - void -suboption() +void +suboption(void) { - register int subchar; + int subchar; DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); subchar = SB_GET(); switch (subchar) { case TELOPT_TSPEED: { - register int xspeed, rspeed; + int xspeed, rspeed; if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ break; settimer(tspeedsubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) return; xspeed = atoi((char *)subpointer); while (SB_GET() != ',' && !SB_EOF()); if (SB_EOF()) return; rspeed = atoi((char *)subpointer); clientstat(TELOPT_TSPEED, xspeed, rspeed); break; } /* end of case TELOPT_TSPEED */ case TELOPT_TTYPE: { /* Yaaaay! */ static char terminalname[41]; if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ break; settimer(ttypesubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) { return; /* ??? XXX but, this is the most robust */ } terminaltype = terminalname; while ((terminaltype < (terminalname + sizeof terminalname-1)) && !SB_EOF()) { - register int c; + int c; c = SB_GET(); if (isupper(c)) { c = tolower(c); } *terminaltype++ = c; /* accumulate name */ } *terminaltype = 0; terminaltype = terminalname; break; } /* end of case TELOPT_TTYPE */ case TELOPT_NAWS: { - register int xwinsize, ywinsize; + int xwinsize, ywinsize; if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ break; if (SB_EOF()) return; xwinsize = SB_GET() << 8; if (SB_EOF()) return; xwinsize |= SB_GET(); if (SB_EOF()) return; ywinsize = SB_GET() << 8; if (SB_EOF()) return; ywinsize |= SB_GET(); clientstat(TELOPT_NAWS, xwinsize, ywinsize); break; } /* end of case TELOPT_NAWS */ #ifdef LINEMODE case TELOPT_LINEMODE: { - register int request; + int request; if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ break; /* * Process linemode suboptions. */ if (SB_EOF()) break; /* garbage was sent */ request = SB_GET(); /* get will/wont */ if (SB_EOF()) break; /* another garbage check */ if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */ /* * Process suboption buffer of slc's */ start_slc(1); do_opt_slc(subpointer, subend - subpointer); (void) end_slc(0); break; } else if (request == LM_MODE) { if (SB_EOF()) return; useeditmode = SB_GET(); /* get mode flag */ clientstat(LM_MODE, 0, 0); break; } if (SB_EOF()) break; switch (SB_GET()) { /* what suboption? */ case LM_FORWARDMASK: /* * According to spec, only server can send request for * forwardmask, and client can only return a positive response. * So don't worry about it. */ default: break; } break; } /* end of case TELOPT_LINEMODE */ #endif case TELOPT_STATUS: { int mode; if (SB_EOF()) break; mode = SB_GET(); switch (mode) { case TELQUAL_SEND: if (my_state_is_will(TELOPT_STATUS)) send_status(); break; case TELQUAL_IS: break; default: break; } break; } /* end of case TELOPT_STATUS */ case TELOPT_XDISPLOC: { if (SB_EOF() || SB_GET() != TELQUAL_IS) return; settimer(xdisplocsubopt); subpointer[SB_LEN()] = '\0'; (void)setenv("DISPLAY", (char *)subpointer, 1); break; } /* end of case TELOPT_XDISPLOC */ #ifdef TELOPT_NEW_ENVIRON case TELOPT_NEW_ENVIRON: #endif case TELOPT_OLD_ENVIRON: { - register int c; - register char *cp, *varp, *valp; + int c; + char *cp, *varp, *valp; if (SB_EOF()) return; c = SB_GET(); if (c == TELQUAL_IS) { if (subchar == TELOPT_OLD_ENVIRON) settimer(oenvironsubopt); else settimer(environsubopt); } else if (c != TELQUAL_INFO) { return; } #ifdef TELOPT_NEW_ENVIRON if (subchar == TELOPT_NEW_ENVIRON) { while (!SB_EOF()) { c = SB_GET(); if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) break; } } else #endif { #ifdef ENV_HACK /* * We only want to do this if we haven't already decided * whether or not the other side has its VALUE and VAR * reversed. */ if (env_ovar < 0) { - register int last = -1; /* invalid value */ + int last = -1; /* invalid value */ int empty = 0; int got_var = 0, got_value = 0, got_uservar = 0; /* * The other side might have its VALUE and VAR values * reversed. To be interoperable, we need to determine * which way it is. If the first recognized character * is a VAR or VALUE, then that will tell us what * type of client it is. If the fist recognized * character is a USERVAR, then we continue scanning * the suboption looking for two consecutive * VAR or VALUE fields. We should not get two * consecutive VALUE fields, so finding two * consecutive VALUE or VAR fields will tell us * what the client is. */ SB_SAVE(); while (!SB_EOF()) { c = SB_GET(); switch(c) { case OLD_ENV_VAR: if (last < 0 || last == OLD_ENV_VAR || (empty && (last == OLD_ENV_VALUE))) goto env_ovar_ok; got_var++; last = OLD_ENV_VAR; break; case OLD_ENV_VALUE: if (last < 0 || last == OLD_ENV_VALUE || (empty && (last == OLD_ENV_VAR))) goto env_ovar_wrong; got_value++; last = OLD_ENV_VALUE; break; case ENV_USERVAR: /* count strings of USERVAR as one */ if (last != ENV_USERVAR) got_uservar++; if (empty) { if (last == OLD_ENV_VALUE) goto env_ovar_ok; if (last == OLD_ENV_VAR) goto env_ovar_wrong; } last = ENV_USERVAR; break; case ENV_ESC: if (!SB_EOF()) c = SB_GET(); /* FALL THROUGH */ default: empty = 0; continue; } empty = 1; } if (empty) { if (last == OLD_ENV_VALUE) goto env_ovar_ok; if (last == OLD_ENV_VAR) goto env_ovar_wrong; } /* * Ok, the first thing was a USERVAR, and there * are not two consecutive VAR or VALUE commands, * and none of the VAR or VALUE commands are empty. * If the client has sent us a well-formed option, * then the number of VALUEs received should always * be less than or equal to the number of VARs and * USERVARs received. * * If we got exactly as many VALUEs as VARs and * USERVARs, the client has the same definitions. * * If we got exactly as many VARs as VALUEs and * USERVARS, the client has reversed definitions. */ if (got_uservar + got_var == got_value) { env_ovar_ok: env_ovar = OLD_ENV_VAR; env_ovalue = OLD_ENV_VALUE; } else if (got_uservar + got_value == got_var) { env_ovar_wrong: env_ovar = OLD_ENV_VALUE; env_ovalue = OLD_ENV_VAR; DIAG(TD_OPTIONS, output_data("ENVIRON VALUE and VAR are reversed!\r\n")); } } SB_RESTORE(); #endif while (!SB_EOF()) { c = SB_GET(); if ((c == env_ovar) || (c == ENV_USERVAR)) break; } } if (SB_EOF()) return; cp = varp = (char *)subpointer; valp = 0; while (!SB_EOF()) { c = SB_GET(); if (subchar == TELOPT_OLD_ENVIRON) { if (c == env_ovar) c = NEW_ENV_VAR; else if (c == env_ovalue) c = NEW_ENV_VALUE; } switch (c) { case NEW_ENV_VALUE: *cp = '\0'; cp = valp = (char *)subpointer; break; case NEW_ENV_VAR: case ENV_USERVAR: *cp = '\0'; if (valp) (void)setenv(varp, valp, 1); else unsetenv(varp); cp = varp = (char *)subpointer; valp = 0; break; case ENV_ESC: if (SB_EOF()) break; c = SB_GET(); /* FALL THROUGH */ default: *cp++ = c; break; } } *cp = '\0'; if (valp) (void)setenv(varp, valp, 1); else unsetenv(varp); break; } /* end of case TELOPT_NEW_ENVIRON */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: if (SB_EOF()) break; switch(SB_GET()) { case TELQUAL_SEND: case TELQUAL_REPLY: /* * These are sent by us and cannot be sent by * the client. */ break; case TELQUAL_IS: auth_is(subpointer, SB_LEN()); break; case TELQUAL_NAME: auth_name(subpointer, SB_LEN()); break; } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: if (SB_EOF()) break; switch(SB_GET()) { case ENCRYPT_SUPPORT: encrypt_support(subpointer, SB_LEN()); break; case ENCRYPT_IS: encrypt_is(subpointer, SB_LEN()); break; case ENCRYPT_REPLY: encrypt_reply(subpointer, SB_LEN()); break; case ENCRYPT_START: encrypt_start(subpointer, SB_LEN()); break; case ENCRYPT_END: encrypt_end(); break; case ENCRYPT_REQSTART: encrypt_request_start(subpointer, SB_LEN()); break; case ENCRYPT_REQEND: /* * We can always send an REQEND so that we cannot * get stuck encrypting. We should only get this * if we have been able to get in the correct mode * anyhow. */ encrypt_request_end(); break; case ENCRYPT_ENC_KEYID: encrypt_enc_keyid(subpointer, SB_LEN()); break; case ENCRYPT_DEC_KEYID: encrypt_dec_keyid(subpointer, SB_LEN()); break; default: break; } break; #endif /* ENCRYPTION */ default: break; } /* end of switch */ } /* end of suboption */ - void -doclientstat() +static void +doclientstat(void) { clientstat(TELOPT_LINEMODE, WILL, 0); } #define ADD(c) *ncp++ = c #define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } - void -send_status() +void +send_status(void) { unsigned char statusbuf[256]; - register unsigned char *ncp; - register unsigned char i; + unsigned char *ncp; + unsigned char i; ncp = statusbuf; netflush(); /* get rid of anything waiting to go out */ ADD(IAC); ADD(SB); ADD(TELOPT_STATUS); ADD(TELQUAL_IS); /* * We check the want_state rather than the current state, * because if we received a DO/WILL for an option that we * don't support, and the other side didn't send a DONT/WONT * in response to our WONT/DONT, then the "state" will be * WILL/DO, and the "want_state" will be WONT/DONT. We * need to go by the latter. */ for (i = 0; i < (unsigned char)NTELOPTS; i++) { if (my_want_state_is_will(i)) { ADD(WILL); ADD_DATA(i); if (i == IAC) ADD(IAC); } if (his_want_state_is_will(i)) { ADD(DO); ADD_DATA(i); if (i == IAC) ADD(IAC); } } if (his_want_state_is_will(TELOPT_LFLOW)) { ADD(SB); ADD(TELOPT_LFLOW); if (flowmode) { ADD(LFLOW_ON); } else { ADD(LFLOW_OFF); } ADD(SE); if (restartany >= 0) { ADD(SB); ADD(TELOPT_LFLOW); if (restartany) { ADD(LFLOW_RESTART_ANY); } else { ADD(LFLOW_RESTART_XON); } ADD(SE); } } #ifdef LINEMODE if (his_want_state_is_will(TELOPT_LINEMODE)) { unsigned char *cp, *cpe; int len; ADD(SB); ADD(TELOPT_LINEMODE); ADD(LM_MODE); ADD_DATA(editmode); ADD(SE); ADD(SB); ADD(TELOPT_LINEMODE); ADD(LM_SLC); start_slc(0); send_slc(); len = end_slc(&cp); for (cpe = cp + len; cp < cpe; cp++) ADD_DATA(*cp); ADD(SE); } #endif /* LINEMODE */ ADD(IAC); ADD(SE); output_datalen(statusbuf, ncp - statusbuf); netflush(); /* Send it on its way */ DIAG(TD_OPTIONS, {printsub('>', statusbuf, ncp - statusbuf); netflush();}); } /* * This function appends data to nfrontp and advances nfrontp. * Returns the number of characters written altogether (the * buffer may have been flushed in the process). */ int output_data(const char *format, ...) { va_list args; int len; char *buf; va_start(args, format); if ((len = vasprintf(&buf, format, args)) == -1) return -1; output_datalen(buf, len); va_end(args); free(buf); return (len); } void output_datalen(const char *buf, int len) { int remaining, copied; remaining = BUFSIZ - (nfrontp - netobuf); while (len > 0) { /* Free up enough space if the room is too low*/ if ((len > BUFSIZ ? BUFSIZ : len) > remaining) { netflush(); remaining = BUFSIZ - (nfrontp - netobuf); } /* Copy out as much as will fit */ copied = remaining > len ? len : remaining; memmove(nfrontp, buf, copied); nfrontp += copied; len -= copied; remaining -= copied; buf += copied; } return; } Index: head/crypto/telnet/telnetd/sys_term.c =================================================================== --- head/crypto/telnet/telnetd/sys_term.c (revision 87138) +++ head/crypto/telnet/telnetd/sys_term.c (revision 87139) @@ -1,1855 +1,1331 @@ -/* + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ +#include +#include +#include +#include +#include + #include "telnetd.h" #include "pathnames.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -extern char *altlogin; -int cleanopen(char *line); +int cleanopen(char *); void scrub_env(void); -#ifdef NEWINIT -#include -#else /* NEWINIT*/ -# ifdef UTMPX -# include -struct utmpx wtmp; -# else -# include struct utmp wtmp; -# endif /* UTMPX */ -# ifndef PARENT_DOES_UTMP #ifdef _PATH_WTMP char wtmpf[] = _PATH_WTMP; #else -char wtmpf[] = "/usr/adm/wtmp"; +char wtmpf[] = "/var/log/wtmp"; #endif #ifdef _PATH_UTMP char utmpf[] = _PATH_UTMP; #else -char utmpf[] = "/etc/utmp"; +char utmpf[] = "/var/run/utmp"; #endif -# else /* PARENT_DOES_UTMP */ -char wtmpf[] = "/etc/wtmp"; -# endif /* PARENT_DOES_UTMP */ -#include +char *envinit[3]; +extern char **environ; -#endif /* NEWINIT */ - -#ifdef STREAMSPTY -#include -#include -#endif - #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) #define SCMPN(a, b) strncmp(a, b, sizeof(a)) -#ifdef STREAMS -#include -#endif -#include #ifdef t_erase #undef t_erase #undef t_kill #undef t_intrc #undef t_quitc #undef t_startc #undef t_stopc #undef t_eofc #undef t_brkc #undef t_suspc #undef t_dsuspc #undef t_rprntc #undef t_flushc #undef t_werasc #undef t_lnextc #endif #ifndef USE_TERMIO struct termbuf { struct sgttyb sg; struct tchars tc; struct ltchars ltc; int state; int lflags; } termbuf, termbuf2; # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) # define cfgetospeed(tp) (tp)->sg.sg_ospeed # define cfgetispeed(tp) (tp)->sg.sg_ispeed #else /* USE_TERMIO */ -# ifdef SYSV_TERMIO -# define termios termio -# endif # ifndef TCSANOW # ifdef TCSETS # define TCSANOW TCSETS # define TCSADRAIN TCSETSW # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) # else # ifdef TCSETA # define TCSANOW TCSETA # define TCSADRAIN TCSETAW # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) # else # define TCSANOW TIOCSETA # define TCSADRAIN TIOCSETAW # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) # endif # endif # define tcsetattr(f, a, t) ioctl(f, a, t) # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ (tp)->c_cflag |= (val) # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) # ifdef CIBAUD # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ (tp)->c_cflag |= ((val)<c_cflag & CIBAUD)>>IBSHIFT) # else # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ (tp)->c_cflag |= (val) # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) # endif # endif /* TCSANOW */ struct termios termbuf, termbuf2; /* pty control structure */ -# ifdef STREAMSPTY -int ttyfd = -1; -# endif #endif /* USE_TERMIO */ #include #include int cleanopen __P((char *)); void scrub_env __P((void)); +static char **addarg __P((char **, const char *)); /* * init_termbuf() * copy_termbuf(cp) * set_termbuf() * * These three routines are used to get and set the "termbuf" structure * to and from the kernel. init_termbuf() gets the current settings. * copy_termbuf() hands in a new "termbuf" to write to the kernel, and * set_termbuf() writes the structure into the kernel. */ - void -init_termbuf() +void +init_termbuf(void) { #ifndef USE_TERMIO (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); # ifdef TIOCGSTATE (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); # endif #else -# ifdef STREAMSPTY - (void) tcgetattr(ttyfd, &termbuf); -# else (void) tcgetattr(pty, &termbuf); -# endif #endif termbuf2 = termbuf; } #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) - void -copy_termbuf(cp, len) - char *cp; - int len; +void +copy_termbuf(char *cp, size_t len) { if (len > sizeof(termbuf)) len = sizeof(termbuf); memmove((char *)&termbuf, cp, len); termbuf2 = termbuf; } #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ - void -set_termbuf() +void +set_termbuf(void) { /* * Only make the necessary changes. */ #ifndef USE_TERMIO if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, sizeof(termbuf.ltc))) (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); if (termbuf.lflags != termbuf2.lflags) (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); #else /* USE_TERMIO */ if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) -# ifdef STREAMSPTY - (void) tcsetattr(ttyfd, TCSANOW, &termbuf); -# else (void) tcsetattr(pty, TCSANOW, &termbuf); -# endif #endif /* USE_TERMIO */ } /* * spcset(func, valp, valpp) * * This function takes various special characters (func), and * sets *valp to the current value of that character, and * *valpp to point to where in the "termbuf" structure that * value is kept. * * It returns the SLC_ level of support for this function. */ #ifndef USE_TERMIO - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; +int +spcset(int func, cc_t *valp, cc_t **valpp) { switch(func) { case SLC_EOF: *valp = termbuf.tc.t_eofc; *valpp = (cc_t *)&termbuf.tc.t_eofc; return(SLC_VARIABLE); case SLC_EC: *valp = termbuf.sg.sg_erase; *valpp = (cc_t *)&termbuf.sg.sg_erase; return(SLC_VARIABLE); case SLC_EL: *valp = termbuf.sg.sg_kill; *valpp = (cc_t *)&termbuf.sg.sg_kill; return(SLC_VARIABLE); case SLC_IP: *valp = termbuf.tc.t_intrc; *valpp = (cc_t *)&termbuf.tc.t_intrc; return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_ABORT: *valp = termbuf.tc.t_quitc; *valpp = (cc_t *)&termbuf.tc.t_quitc; return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_XON: *valp = termbuf.tc.t_startc; *valpp = (cc_t *)&termbuf.tc.t_startc; return(SLC_VARIABLE); case SLC_XOFF: *valp = termbuf.tc.t_stopc; *valpp = (cc_t *)&termbuf.tc.t_stopc; return(SLC_VARIABLE); case SLC_AO: *valp = termbuf.ltc.t_flushc; *valpp = (cc_t *)&termbuf.ltc.t_flushc; return(SLC_VARIABLE); case SLC_SUSP: *valp = termbuf.ltc.t_suspc; *valpp = (cc_t *)&termbuf.ltc.t_suspc; return(SLC_VARIABLE); case SLC_EW: *valp = termbuf.ltc.t_werasc; *valpp = (cc_t *)&termbuf.ltc.t_werasc; return(SLC_VARIABLE); case SLC_RP: *valp = termbuf.ltc.t_rprntc; *valpp = (cc_t *)&termbuf.ltc.t_rprntc; return(SLC_VARIABLE); case SLC_LNEXT: *valp = termbuf.ltc.t_lnextc; *valpp = (cc_t *)&termbuf.ltc.t_lnextc; return(SLC_VARIABLE); case SLC_FORW1: *valp = termbuf.tc.t_brkc; *valpp = (cc_t *)&termbuf.ltc.t_lnextc; return(SLC_VARIABLE); case SLC_BRK: case SLC_SYNCH: case SLC_AYT: case SLC_EOR: *valp = (cc_t)0; *valpp = (cc_t *)0; return(SLC_DEFAULT); default: *valp = (cc_t)0; *valpp = (cc_t *)0; return(SLC_NOSUPPORT); } } #else /* USE_TERMIO */ - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; -{ #define setval(a, b) *valp = termbuf.c_cc[a]; \ *valpp = &termbuf.c_cc[a]; \ return(b); #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); +int +spcset(int func, cc_t *valp, cc_t **valpp) +{ switch(func) { case SLC_EOF: setval(VEOF, SLC_VARIABLE); case SLC_EC: setval(VERASE, SLC_VARIABLE); case SLC_EL: setval(VKILL, SLC_VARIABLE); case SLC_IP: setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_ABORT: setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); case SLC_XON: #ifdef VSTART setval(VSTART, SLC_VARIABLE); #else defval(0x13); #endif case SLC_XOFF: #ifdef VSTOP setval(VSTOP, SLC_VARIABLE); #else defval(0x11); #endif case SLC_EW: #ifdef VWERASE setval(VWERASE, SLC_VARIABLE); #else defval(0); #endif case SLC_RP: #ifdef VREPRINT setval(VREPRINT, SLC_VARIABLE); #else defval(0); #endif case SLC_LNEXT: #ifdef VLNEXT setval(VLNEXT, SLC_VARIABLE); #else defval(0); #endif case SLC_AO: #if !defined(VDISCARD) && defined(VFLUSHO) # define VDISCARD VFLUSHO #endif #ifdef VDISCARD setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); #else defval(0); #endif case SLC_SUSP: #ifdef VSUSP setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); #else defval(0); #endif #ifdef VEOL case SLC_FORW1: setval(VEOL, SLC_VARIABLE); #endif #ifdef VEOL2 case SLC_FORW2: setval(VEOL2, SLC_VARIABLE); #endif case SLC_AYT: #ifdef VSTATUS setval(VSTATUS, SLC_VARIABLE); #else defval(0); #endif case SLC_BRK: case SLC_SYNCH: case SLC_EOR: defval(0); default: *valp = 0; *valpp = 0; return(SLC_NOSUPPORT); } } #endif /* USE_TERMIO */ -#ifndef convex /* * getpty() * * Allocate a pty. As a side effect, the external character * array "line" contains the name of the slave side. * * Returns the file descriptor of the opened pty. */ +char alpha[] = "0123456789abcdefghijklmnopqrstuv"; char line[16]; - int -getpty(ptynum) -int *ptynum; +int +getpty(int *ptynum __unused) { - register int p; -#ifdef STREAMSPTY - int t; - char *ptsname(); + int p; + const char *cp; + char *p1, *p2; + int i; - p = open("/dev/ptmx", 2); - if (p > 0) { - grantpt(p); - unlockpt(p); - strcpy(line, ptsname(p)); - return(p); - } - -#else /* ! STREAMSPTY */ - register char *cp, *p1, *p2; - register int i; - (void) strcpy(line, _PATH_DEV); (void) strcat(line, "ptyXX"); p1 = &line[8]; p2 = &line[9]; for (cp = "pqrsPQRS"; *cp; cp++) { struct stat stb; *p1 = *cp; *p2 = '0'; /* * This stat() check is just to keep us from * looping through all 256 combinations if there * aren't that many ptys available. */ if (stat(line, &stb) < 0) break; for (i = 0; i < 32; i++) { - *p2 = "0123456789abcdefghijklmnopqrstuv"[i]; + *p2 = alpha[i]; p = open(line, 2); if (p > 0) { line[5] = 't'; chown(line, 0, 0); chmod(line, 0600); return(p); } } } -#endif /* STREAMSPTY */ return(-1); } -#endif /* convex */ #ifdef LINEMODE /* * tty_flowmode() Find out if flow control is enabled or disabled. * tty_linemode() Find out if linemode (external processing) is enabled. * tty_setlinemod(on) Turn on/off linemode. * tty_isecho() Find out if echoing is turned on. * tty_setecho(on) Enable/disable character echoing. * tty_israw() Find out if terminal is in RAW mode. * tty_binaryin(on) Turn on/off BINARY on input. * tty_binaryout(on) Turn on/off BINARY on output. * tty_isediting() Find out if line editing is enabled. * tty_istrapsig() Find out if signal trapping is enabled. * tty_setedit(on) Turn on/off line editing. * tty_setsig(on) Turn on/off signal trapping. * tty_issofttab() Find out if tab expansion is enabled. * tty_setsofttab(on) Turn on/off soft tab expansion. * tty_islitecho() Find out if typed control chars are echoed literally * tty_setlitecho() Turn on/off literal echo of control chars * tty_tspeed(val) Set transmit speed to val. * tty_rspeed(val) Set receive speed to val. */ -#ifdef convex -static int linestate; -#endif - int -tty_linemode() +int +tty_linemode(void) { -#ifndef convex #ifndef USE_TERMIO return(termbuf.state & TS_EXTPROC); #else return(termbuf.c_lflag & EXTPROC); #endif -#else - return(linestate); -#endif } - void -tty_setlinemode(on) - int on; +void +tty_setlinemode(int on) { #ifdef TIOCEXT -# ifndef convex set_termbuf(); -# else - linestate = on; -# endif (void) ioctl(pty, TIOCEXT, (char *)&on); -# ifndef convex init_termbuf(); -# endif #else /* !TIOCEXT */ # ifdef EXTPROC if (on) termbuf.c_lflag |= EXTPROC; else termbuf.c_lflag &= ~EXTPROC; # endif #endif /* TIOCEXT */ } #endif /* LINEMODE */ - int -tty_isecho() +int +tty_isecho(void) { #ifndef USE_TERMIO return (termbuf.sg.sg_flags & ECHO); #else return (termbuf.c_lflag & ECHO); #endif } - int -tty_flowmode() +int +tty_flowmode(void) { #ifndef USE_TERMIO return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); #else return((termbuf.c_iflag & IXON) ? 1 : 0); #endif } - int -tty_restartany() +int +tty_restartany(void) { #ifndef USE_TERMIO # ifdef DECCTQ return((termbuf.lflags & DECCTQ) ? 0 : 1); # else return(-1); # endif #else return((termbuf.c_iflag & IXANY) ? 1 : 0); #endif } - void -tty_setecho(on) - int on; +void +tty_setecho(int on) { #ifndef USE_TERMIO if (on) termbuf.sg.sg_flags |= ECHO|CRMOD; else termbuf.sg.sg_flags &= ~(ECHO|CRMOD); #else if (on) termbuf.c_lflag |= ECHO; else termbuf.c_lflag &= ~ECHO; #endif } - int -tty_israw() +int +tty_israw(void) { #ifndef USE_TERMIO return(termbuf.sg.sg_flags & RAW); #else return(!(termbuf.c_lflag & ICANON)); #endif } -#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - int -tty_setraw(on) +#ifdef AUTHENTICATION +#if defined(NO_LOGIN_F) && defined(LOGIN_R) +int +tty_setraw(int on) { # ifndef USE_TERMIO if (on) termbuf.sg.sg_flags |= RAW; else termbuf.sg.sg_flags &= ~RAW; # else if (on) termbuf.c_lflag &= ~ICANON; else termbuf.c_lflag |= ICANON; # endif } #endif +#endif /* AUTHENTICATION */ - void -tty_binaryin(on) - int on; +void +tty_binaryin(int on) { #ifndef USE_TERMIO if (on) termbuf.lflags |= LPASS8; else termbuf.lflags &= ~LPASS8; #else if (on) { termbuf.c_iflag &= ~ISTRIP; } else { termbuf.c_iflag |= ISTRIP; } #endif } - void -tty_binaryout(on) - int on; +void +tty_binaryout(int on) { #ifndef USE_TERMIO if (on) termbuf.lflags |= LLITOUT; else termbuf.lflags &= ~LLITOUT; #else if (on) { termbuf.c_cflag &= ~(CSIZE|PARENB); termbuf.c_cflag |= CS8; termbuf.c_oflag &= ~OPOST; } else { termbuf.c_cflag &= ~CSIZE; termbuf.c_cflag |= CS7|PARENB; termbuf.c_oflag |= OPOST; } #endif } - int -tty_isbinaryin() +int +tty_isbinaryin(void) { #ifndef USE_TERMIO return(termbuf.lflags & LPASS8); #else return(!(termbuf.c_iflag & ISTRIP)); #endif } - int -tty_isbinaryout() +int +tty_isbinaryout(void) { #ifndef USE_TERMIO return(termbuf.lflags & LLITOUT); #else return(!(termbuf.c_oflag&OPOST)); #endif } #ifdef LINEMODE - int -tty_isediting() +int +tty_isediting(void) { #ifndef USE_TERMIO return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); #else return(termbuf.c_lflag & ICANON); #endif } - int -tty_istrapsig() +int +tty_istrapsig(void) { #ifndef USE_TERMIO return(!(termbuf.sg.sg_flags&RAW)); #else return(termbuf.c_lflag & ISIG); #endif } - void -tty_setedit(on) - int on; +void +tty_setedit(int on) { #ifndef USE_TERMIO if (on) termbuf.sg.sg_flags &= ~CBREAK; else termbuf.sg.sg_flags |= CBREAK; #else if (on) termbuf.c_lflag |= ICANON; else termbuf.c_lflag &= ~ICANON; #endif } - void -tty_setsig(on) - int on; +void +tty_setsig(int on) { #ifndef USE_TERMIO if (on) ; #else if (on) termbuf.c_lflag |= ISIG; else termbuf.c_lflag &= ~ISIG; #endif } #endif /* LINEMODE */ - int -tty_issofttab() +int +tty_issofttab(void) { #ifndef USE_TERMIO return (termbuf.sg.sg_flags & XTABS); #else # ifdef OXTABS return (termbuf.c_oflag & OXTABS); # endif # ifdef TABDLY return ((termbuf.c_oflag & TABDLY) == TAB3); # endif #endif } - void -tty_setsofttab(on) - int on; +void +tty_setsofttab(int on) { #ifndef USE_TERMIO if (on) termbuf.sg.sg_flags |= XTABS; else termbuf.sg.sg_flags &= ~XTABS; #else if (on) { # ifdef OXTABS termbuf.c_oflag |= OXTABS; # endif # ifdef TABDLY termbuf.c_oflag &= ~TABDLY; termbuf.c_oflag |= TAB3; # endif } else { # ifdef OXTABS termbuf.c_oflag &= ~OXTABS; # endif # ifdef TABDLY termbuf.c_oflag &= ~TABDLY; termbuf.c_oflag |= TAB0; # endif } #endif } - int -tty_islitecho() +int +tty_islitecho(void) { #ifndef USE_TERMIO return (!(termbuf.lflags & LCTLECH)); #else # ifdef ECHOCTL return (!(termbuf.c_lflag & ECHOCTL)); # endif # ifdef TCTLECH return (!(termbuf.c_lflag & TCTLECH)); # endif # if !defined(ECHOCTL) && !defined(TCTLECH) return (0); /* assumes ctl chars are echoed '^x' */ # endif #endif } - void -tty_setlitecho(on) - int on; +void +tty_setlitecho(int on) { #ifndef USE_TERMIO if (on) termbuf.lflags &= ~LCTLECH; else termbuf.lflags |= LCTLECH; #else # ifdef ECHOCTL if (on) termbuf.c_lflag &= ~ECHOCTL; else termbuf.c_lflag |= ECHOCTL; # endif # ifdef TCTLECH if (on) termbuf.c_lflag &= ~TCTLECH; else termbuf.c_lflag |= TCTLECH; # endif #endif } - int -tty_iscrnl() +int +tty_iscrnl(void) { #ifndef USE_TERMIO return (termbuf.sg.sg_flags & CRMOD); #else return (termbuf.c_iflag & ICRNL); #endif } /* * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). */ #if B4800 != 4800 #define DECODE_BAUD #endif #ifdef DECODE_BAUD /* * A table of available terminal speeds */ struct termspeeds { int speed; int value; } termspeeds[] = { { 0, B0 }, { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, #ifdef B7200 { 7200, B7200 }, #endif { 9600, B9600 }, #ifdef B14400 { 14400, B14400 }, #endif #ifdef B19200 { 19200, B19200 }, #endif #ifdef B28800 { 28800, B28800 }, #endif #ifdef B38400 { 38400, B38400 }, #endif #ifdef B57600 { 57600, B57600 }, #endif #ifdef B115200 { 115200, B115200 }, #endif #ifdef B230400 { 230400, B230400 }, #endif { -1, 0 } }; #endif /* DECODE_BAUD */ - void -tty_tspeed(val) - int val; +void +tty_tspeed(int val) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ; if (tp->speed == -1) /* back up to last valid value */ --tp; cfsetospeed(&termbuf, tp->value); #else /* DECODE_BAUD */ cfsetospeed(&termbuf, val); #endif /* DECODE_BAUD */ } - void -tty_rspeed(val) - int val; +void +tty_rspeed(int val) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ; if (tp->speed == -1) /* back up to last valid value */ --tp; cfsetispeed(&termbuf, tp->value); #else /* DECODE_BAUD */ cfsetispeed(&termbuf, val); #endif /* DECODE_BAUD */ } -#ifdef PARENT_DOES_UTMP -# ifndef NEWINIT -extern struct utmp wtmp; -extern char wtmpf[]; -# else /* NEWINIT */ -int gotalarm; - - /* ARGSUSED */ - void -nologinproc(sig) - int sig; -{ - gotalarm++; -} -# endif /* NEWINIT */ -#endif /* PARENT_DOES_UTMP */ - -#ifndef NEWINIT -# ifdef PARENT_DOES_UTMP -extern void utmp_sig_init P((void)); -extern void utmp_sig_reset P((void)); -extern void utmp_sig_wait P((void)); -extern void utmp_sig_notify P((int)); -# endif /* PARENT_DOES_UTMP */ -#endif - /* * getptyslave() * * Open the slave side of the pty, and do any initialization * that is necessary. */ - void -getptyslave() +static void +getptyslave(void) { - register int t = -1; + int t = -1; char erase; # ifdef LINEMODE int waslm; # endif # ifdef TIOCGWINSZ struct winsize ws; extern int def_row, def_col; # endif extern int def_tspeed, def_rspeed; /* * Opening the slave side may cause initilization of the * kernel tty structure. We need remember the state of * if linemode was turned on * terminal window size * terminal speed * erase character * so that we can re-set them if we need to. */ # ifdef LINEMODE waslm = tty_linemode(); # endif erase = termbuf.c_cc[VERASE]; /* * Make sure that we don't have a controlling tty, and * that we are the session (process group) leader. */ # ifdef TIOCNOTTY t = open(_PATH_TTY, O_RDWR); if (t >= 0) { (void) ioctl(t, TIOCNOTTY, (char *)0); (void) close(t); } # endif - -# ifdef PARENT_DOES_UTMP - /* - * Wait for our parent to get the utmp stuff to get done. - */ - utmp_sig_wait(); -# endif - t = cleanopen(line); if (t < 0) fatalperror(net, line); -#ifdef STREAMSPTY -#ifdef USE_TERMIO - ttyfd = t; -#endif - if (ioctl(t, I_PUSH, "ptem") < 0) - fatal(net, "I_PUSH ptem"); - if (ioctl(t, I_PUSH, "ldterm") < 0) - fatal(net, "I_PUSH ldterm"); - if (ioctl(t, I_PUSH, "ttcompat") < 0) - fatal(net, "I_PUSH ttcompat"); - if (ioctl(pty, I_PUSH, "pckt") < 0) - fatal(net, "I_PUSH pckt"); -#endif /* * set up the tty modes as we like them to be. */ init_termbuf(); # ifdef TIOCGWINSZ if (def_row || def_col) { memset((char *)&ws, 0, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; (void)ioctl(t, TIOCSWINSZ, (char *)&ws); } # endif /* * Settings for sgtty based systems */ # ifndef USE_TERMIO termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; # endif /* USE_TERMIO */ /* * Settings for all other termios/termio based * systems, other than 4.4BSD. In 4.4BSD the * kernel does the initial terminal setup. */ -# if defined(USE_TERMIO) && (BSD <= 43) -# ifndef OXTABS -# define OXTABS 0 -# endif - termbuf.c_lflag |= ECHO; - termbuf.c_oflag |= ONLCR|OXTABS; - termbuf.c_iflag |= ICRNL; - termbuf.c_iflag &= ~IXOFF; -# endif /* defined(USE_TERMIO) && (BSD <= 43) */ tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); if (erase) termbuf.c_cc[VERASE] = erase; # ifdef LINEMODE if (waslm) tty_setlinemode(1); # endif /* LINEMODE */ /* * Set the tty modes, and make this our controlling tty. */ set_termbuf(); if (login_tty(t) == -1) fatalperror(net, "login_tty"); if (net > 2) (void) close(net); -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) +#ifdef AUTHENTICATION +#if defined(NO_LOGIN_F) && defined(LOGIN_R) /* * Leave the pty open so that we can write out the rlogin * protocol for /bin/login, if the authentication works. */ #else if (pty > 2) { (void) close(pty); pty = -1; } #endif +#endif /* AUTHENTICATION */ } #ifndef O_NOCTTY #define O_NOCTTY 0 #endif /* * Open the specified slave side of the pty, * making sure that we have a clean tty. */ - int -cleanopen(line) - char *line; +int +cleanopen(char *li) { - register int t; + int t; -#ifndef STREAMSPTY /* * Make sure that other people can't open the * slave side of the connection. */ - (void) chown(line, 0, 0); - (void) chmod(line, 0600); -#endif + (void) chown(li, 0, 0); + (void) chmod(li, 0600); - (void) revoke(line); + (void) revoke(li); t = open(line, O_RDWR|O_NOCTTY); if (t < 0) return(-1); - /* - * Hangup anybody else using this ttyp, then reopen it for - * ourselves. - */ -# if (BSD <= 43) && !defined(STREAMSPTY) - (void) signal(SIGHUP, SIG_IGN); - vhangup(); - (void) signal(SIGHUP, SIG_DFL); - t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); -# endif return(t); } -#if BSD <= 43 - - int -login_tty(t) - int t; -{ - if (setsid() < 0) { -#ifdef ultrix - /* - * The setsid() may have failed because we - * already have a pgrp == pid. Zero out - * our pgrp and try again... - */ - if ((setpgrp(0, 0) < 0) || (setsid() < 0)) -#endif - fatalperror(net, "setsid()"); - } -# ifdef TIOCSCTTY - if (ioctl(t, TIOCSCTTY, (char *)0) < 0) - fatalperror(net, "ioctl(sctty)"); -# else - /* - * We get our controlling tty assigned as a side-effect - * of opening up a tty device. But on BSD based systems, - * this only happens if our process group is zero. The - * setsid() call above may have set our pgrp, so clear - * it out before opening the tty... - */ - (void) setpgrp(0, 0); - close(open(line, O_RDWR)); -# endif - if (t != 0) - (void) dup2(t, 0); - if (t != 1) - (void) dup2(t, 1); - if (t != 2) - (void) dup2(t, 2); - if (t > 2) - close(t); - return(0); -} -#endif /* BSD <= 43 */ - -#ifdef NEWINIT -char *gen_id = "fe"; -#endif - /* * startslave(host) * * Given a hostname, do whatever * is necessary to startup the login process on the slave side of the pty. */ /* ARGSUSED */ - void -startslave(host, autologin, autoname) - char *host; - int autologin; - char *autoname; +void +startslave(char *host, int autologin, char *autoname) { - register int i; -#ifdef NEWINIT - extern char *ptyip; - struct init_request request; - void nologinproc(); - register int n; -#endif /* NEWINIT */ + int i; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION if (!autoname || !autoname[0]) autologin = 0; if (autologin < auth_level) { fatal(net, "Authorization failed"); exit(1); } #endif -#ifndef NEWINIT -# ifdef PARENT_DOES_UTMP - utmp_sig_init(); -# endif /* PARENT_DOES_UTMP */ if ((i = fork()) < 0) fatalperror(net, "fork"); if (i) { -# ifdef PARENT_DOES_UTMP - /* - * Cray parent will create utmp entry for child and send - * signal to child to tell when done. Child waits for signal - * before doing anything important. - */ - register int pid = i; - void sigjob P((int)); - - setpgrp(); - utmp_sig_reset(); /* reset handler to default */ - /* - * Create utmp entry for child - */ - (void) time(&wtmp.ut_time); - wtmp.ut_type = LOGIN_PROCESS; - wtmp.ut_pid = pid; - SCPYN(wtmp.ut_user, "LOGIN"); - SCPYN(wtmp.ut_host, host); - SCPYN(wtmp.ut_line, line + sizeof(_PATH_DEV) - 1); - SCPYN(wtmp.ut_id, wtmp.ut_line+3); - pututline(&wtmp); - endutent(); - if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { - (void) write(i, (char *)&wtmp, sizeof(struct utmp)); - (void) close(i); - } - utmp_sig_notify(pid); -# endif /* PARENT_DOES_UTMP */ } else { - getptyslave(autologin); + getptyslave(); start_login(host, autologin, autoname); /*NOTREACHED*/ } -#else /* NEWINIT */ - - /* - * Init will start up login process if we ask nicely. We only wait - * for it to start up and begin normal telnet operation. - */ - if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { - char tbuf[128]; - (void) snprintf(tbuf, sizeof(tbuf), "Can't open %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - memset((char *)&request, 0, sizeof(request)); - request.magic = INIT_MAGIC; - SCPYN(request.gen_id, gen_id); - SCPYN(request.tty_id, &line[8]); - SCPYN(request.host, host); - SCPYN(request.term_type, terminaltype ? terminaltype : "network"); - request.signal = SIGCLD; - request.pid = getpid(); -#ifdef BFTPDAEMON - /* - * Are we working as the bftp daemon? - */ - if (bftpd) { - SCPYN(request.exec_name, BFTPPATH); - } -#endif /* BFTPDAEMON */ - if (write(i, (char *)&request, sizeof(request)) < 0) { - char tbuf[128]; - (void) snprintf(tbuf, sizeof(tbuf), "Can't write to %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - (void) close(i); - (void) signal(SIGALRM, nologinproc); - for (i = 0; ; i++) { - char tbuf[128]; - alarm(15); - n = read(pty, ptyip, BUFSIZ); - if (i == 3 || n >= 0 || !gotalarm) - break; - gotalarm = 0; - snprintf(tbuf, sizeof(tbuf), "telnetd: waiting for /etc/init to start login process on %s\r\n", line); - (void) write(net, tbuf, strlen(tbuf)); - } - if (n < 0 && gotalarm) - fatal(net, "/etc/init didn't start login process"); - pcc += n; - alarm(0); - (void) signal(SIGALRM, SIG_DFL); - - return; -#endif /* NEWINIT */ } -char *envinit[3]; -extern char **environ; - - void -init_env() +void +init_env(void) { - extern char *getenv(); char **envp; envp = envinit; if ((*envp = getenv("TZ"))) *envp++ -= 3; *envp = 0; environ = envinit; } -#ifndef NEWINIT /* * start_login(host) * * Assuming that we are now running as a child processes, this * function will turn us into the login process. */ - void -start_login(host, autologin, name) - char *host; - int autologin; - char *name; -{ - register char **argv; - char **addarg(), *user; - extern char *getenv(); -#ifdef UTMPX - register int pid = getpid(); - struct utmpx utmpx; +#ifndef AUTHENTICATION +#define undef1 __unused +#else +#define undef1 #endif -#ifdef SOLARIS - char *term; - char termbuf[64]; -#endif -#ifdef UTMPX - /* - * Create utmp entry for child - */ +void +start_login(char *host undef1, int autologin undef1, char *name undef1) +{ + char **argv; - memset(&utmpx, 0, sizeof(utmpx)); - SCPYN(utmpx.ut_user, ".telnet"); - SCPYN(utmpx.ut_line, line + sizeof(_PATH_DEV) - 1); - utmpx.ut_pid = pid; - utmpx.ut_id[0] = 't'; - utmpx.ut_id[1] = 'n'; - utmpx.ut_id[2] = SC_WILDC; - utmpx.ut_id[3] = SC_WILDC; - utmpx.ut_type = LOGIN_PROCESS; - (void) time(&utmpx.ut_tv.tv_sec); - if (makeutx(&utmpx) == NULL) - fatal(net, "makeutx failed"); -#endif - scrub_env(); /* * -h : pass on name of host. * WARNING: -h is accepted by login if and only if * getuid() == 0. * -p : don't clobber the environment (so terminal type stays set). * * -f : force this login, he has already been authenticated */ argv = addarg(0, "login"); #if !defined(NO_LOGIN_H) - -# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) +#ifdef AUTHENTICATION +# if defined(NO_LOGIN_F) && defined(LOGIN_R) /* * Don't add the "-h host" option if we are going * to be adding the "-r host" option down below... */ if ((auth_level < 0) || (autologin != AUTH_VALID)) # endif { argv = addarg(argv, "-h"); argv = addarg(argv, host); -#ifdef SOLARIS - /* - * SVR4 version of -h takes TERM= as second arg, or - - */ - term = getenv("TERM"); - if (term == NULL || term[0] == 0) { - term = "-"; - } else { - strcpy(termbuf, "TERM="); - strncat(termbuf, term, sizeof(termbuf) - 6); - term = termbuf; - } - argv = addarg(argv, term); -#endif } +#endif /* AUTHENTICATION */ #endif #if !defined(NO_LOGIN_P) argv = addarg(argv, "-p"); #endif #ifdef LINEMODE /* * Set the environment variable "LINEMODE" to either * "real" or "kludge" if we are operating in either * real or kludge linemode. */ if (lmodetype == REAL_LINEMODE) setenv("LINEMODE", "real", 1); # ifdef KLUDGELINEMODE else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) setenv("LINEMODE", "kludge", 1); # endif #endif #ifdef BFTPDAEMON /* * Are we working as the bftp daemon? If so, then ask login * to start bftp instead of shell. */ if (bftpd) { argv = addarg(argv, "-e"); argv = addarg(argv, BFTPPATH); } else #endif -#if defined (SecurID) - /* - * don't worry about the -f that might get sent. - * A -s is supposed to override it anyhow. - */ - if (require_SecurID) - argv = addarg(argv, "-s"); -#endif -#if defined (AUTHENTICATION) +#ifdef AUTHENTICATION if (auth_level >= 0 && autologin == AUTH_VALID) { # if !defined(NO_LOGIN_F) argv = addarg(argv, "-f"); argv = addarg(argv, "--"); argv = addarg(argv, name); # else # if defined(LOGIN_R) /* * We don't have support for "login -f", but we * can fool /bin/login into thinking that we are * rlogind, and allow us to log in without a * password. The rlogin protocol expects * local-user\0remote-user\0term/speed\0 */ if (pty > 2) { - register char *cp; + char *cp; char speed[128]; int isecho, israw, xpty, len; extern int def_rspeed; # ifndef LOGIN_HOST /* * Tell login that we are coming from "localhost". * If we passed in the real host name, then the * user would have to allow .rhost access from * every machine that they want authenticated * access to work from, which sort of defeats * the purpose of an authenticated login... * So, we tell login that the session is coming * from "localhost", and the user will only have * to have "localhost" in their .rhost file. */ # define LOGIN_HOST "localhost" # endif argv = addarg(argv, "-r"); argv = addarg(argv, LOGIN_HOST); xpty = pty; -# ifndef STREAMSPTY pty = 0; -# else - ttyfd = 0; -# endif init_termbuf(); isecho = tty_isecho(); israw = tty_israw(); if (isecho || !israw) { tty_setecho(0); /* Turn off echo */ tty_setraw(1); /* Turn on raw */ set_termbuf(); } len = strlen(name)+1; write(xpty, name, len); write(xpty, name, len); snprintf(speed, sizeof(speed), "%s/%d", (cp = getenv("TERM")) ? cp : "", (def_rspeed > 0) ? def_rspeed : 9600); len = strlen(speed)+1; write(xpty, speed, len); if (isecho || !israw) { init_termbuf(); tty_setecho(isecho); tty_setraw(israw); set_termbuf(); if (!israw) { /* * Write a newline to ensure * that login will be able to * read the line... */ write(xpty, "\n", 1); } } pty = xpty; } # else argv = addarg(argv, "--"); argv = addarg(argv, name); # endif # endif } else #endif if (getenv("USER")) { argv = addarg(argv, "--"); argv = addarg(argv, getenv("USER")); #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) { - register char **cpp; + char **cpp; for (cpp = environ; *cpp; cpp++) argv = addarg(argv, *cpp); } #endif /* * Assume that login will set the USER variable * correctly. For SysV systems, this means that * USER will no longer be set, just LOGNAME by * login. (The problem is that if the auto-login * fails, and the user then specifies a different * account name, he can get logged in with both * LOGNAME and USER in his environment, but the * USER value will be wrong. */ unsetenv("USER"); } -#ifdef SOLARIS - else { - char **p; - - argv = addarg(argv, ""); /* no login name */ - for (p = environ; *p; p++) { - argv = addarg(argv, *p); - } - } -#endif /* SOLARIS */ -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) +#ifdef AUTHENTICATION +#if defined(NO_LOGIN_F) && defined(LOGIN_R) if (pty > 2) close(pty); #endif +#endif /* AUTHENTICATION */ closelog(); if (altlogin == NULL) { altlogin = _PATH_LOGIN; } execv(altlogin, argv); syslog(LOG_ERR, "%s: %m", altlogin); fatalperror(net, altlogin); /*NOTREACHED*/ } - char ** -addarg(argv, val) - register char **argv; - register char *val; +static char ** +addarg(char **argv, const char *val) { - register char **cpp; + char **cpp; if (argv == NULL) { /* * 10 entries, a leading length, and a null */ argv = (char **)malloc(sizeof(*argv) * 12); if (argv == NULL) return(NULL); *argv++ = (char *)10; *argv = (char *)0; } for (cpp = argv; *cpp; cpp++) ; if (cpp == &argv[(int)argv[-1]]) { --argv; *argv = (char *)((int)(*argv) + 10); argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2)); if (argv == NULL) return(NULL); argv++; cpp = &argv[(int)argv[-1] - 10]; } - *cpp++ = val; + *cpp++ = strdup(val); *cpp = 0; return(argv); } -#endif /* NEWINIT */ /* * scrub_env() * * We only accept the environment variables listed below. */ - void -scrub_env() +void +scrub_env(void) { - static const char *reject[] = { + static const char *rej[] = { "TERMCAP=/", NULL }; - static const char *accept[] = { + static const char *acc[] = { "XAUTH=", "XAUTHORITY=", "DISPLAY=", "TERM=", "EDITOR=", "PAGER=", "LOGNAME=", "POSIXLY_CORRECT=", "PRINTER=", NULL }; char **cpp, **cpp2; const char **p; for (cpp2 = cpp = environ; *cpp; cpp++) { int reject_it = 0; - for(p = reject; *p; p++) + for(p = rej; *p; p++) if(strncmp(*cpp, *p, strlen(*p)) == 0) { reject_it = 1; break; } if (reject_it) continue; - for(p = accept; *p; p++) + for(p = acc; *p; p++) if(strncmp(*cpp, *p, strlen(*p)) == 0) break; if(*p != NULL) *cpp2++ = *cpp; } *cpp2 = NULL; } /* * cleanup() * * This is the routine to call when we are all through, to * clean up anything that needs to be cleaned up. */ - /* ARGSUSED */ - void -cleanup(sig) - int sig; +/* ARGSUSED */ +void +cleanup(int sig __unused) { -#ifndef PARENT_DOES_UTMP -# if (BSD > 43) || defined(convex) char *p; p = line + sizeof(_PATH_DEV) - 1; if (logout(p)) logwtmp(p, "", ""); (void)chmod(line, 0666); (void)chown(line, 0, 0); *p = 'p'; (void)chmod(line, 0666); (void)chown(line, 0, 0); (void) shutdown(net, 2); exit(1); -# else - void rmut(); - - rmut(); - vhangup(); /* XXX */ - (void) shutdown(net, 2); - exit(1); -# endif -#else /* PARENT_DOES_UTMP */ -# ifdef NEWINIT - (void) shutdown(net, 2); - exit(1); -# else /* NEWINIT */ - rmut(line); - close(pty); - (void) shutdown(net, 2); - exit(1); -# endif /* NEWINT */ -#endif /* PARENT_DOES_UTMP */ } - -#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) -/* - * _utmp_sig_rcv - * utmp_sig_init - * utmp_sig_wait - * These three functions are used to coordinate the handling of - * the utmp file between the server and the soon-to-be-login shell. - * The server actually creates the utmp structure, the child calls - * utmp_sig_wait(), until the server calls utmp_sig_notify() and - * signals the future-login shell to proceed. - */ -static int caught=0; /* NZ when signal intercepted */ -static void (*func)(); /* address of previous handler */ - - void -_utmp_sig_rcv(sig) - int sig; -{ - caught = 1; - (void) signal(SIGUSR1, func); -} - - void -utmp_sig_init() -{ - /* - * register signal handler for UTMP creation - */ - if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) - fatalperror(net, "telnetd/signal"); -} - - void -utmp_sig_reset() -{ - (void) signal(SIGUSR1, func); /* reset handler to default */ -} - - void -utmp_sig_wait() -{ - /* - * Wait for parent to write our utmp entry. - */ - sigoff(); - while (caught == 0) { - pause(); /* wait until we get a signal (sigon) */ - sigoff(); /* turn off signals while we check caught */ - } - sigon(); /* turn on signals again */ -} - - void -utmp_sig_notify(pid) -{ - kill(pid, SIGUSR1); -} - -#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ - -/* - * rmut() - * - * This is the function called by cleanup() to - * remove the utmp entry for this person. - */ - -#ifdef UTMPX - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - struct utmpx *utxp, utmpx; - - /* - * This updates the utmpx and utmp entries and make a wtmp/x entry - */ - - SCPYN(utmpx.ut_line, line + sizeof(_PATH_DEV) - 1); - utxp = getutxline(&utmpx); - if (utxp) { - utxp->ut_type = DEAD_PROCESS; - utxp->ut_exit.e_termination = 0; - utxp->ut_exit.e_exit = 0; - (void) time(&utmpx.ut_tv.tv_sec); - utmpx.ut_tv.tv_usec = 0; - modutx(utxp); - } - endutxent(); -} /* end of rmut */ -#endif - -#if !defined(UTMPX) && BSD <= 43 - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - f = open(utmpf, O_RDWR); - if (f >= 0) { - (void) fstat(f, &statbf); - utmp = (struct utmp *)malloc((unsigned)statbf.st_size); - if (!utmp) - syslog(LOG_ERR, "utmp malloc failed"); - if (statbf.st_size && utmp) { - nutmp = read(f, (char *)utmp, (int)statbf.st_size); - nutmp /= sizeof(struct utmp); - - for (u = utmp ; u < &utmp[nutmp] ; u++) { - if (SCMPN(u->ut_line, line+5) || - u->ut_name[0]==0) - continue; - (void) lseek(f, ((long)u)-((long)utmp), L_SET); - SCPYN(u->ut_name, ""); - SCPYN(u->ut_host, ""); - (void) time(&u->ut_time); - (void) write(f, (char *)u, sizeof(wtmp)); - found++; - } - } - (void) close(f); - } - if (found) { - f = open(wtmpf, O_WRONLY|O_APPEND); - if (f >= 0) { - SCPYN(wtmp.ut_line, line+5); - SCPYN(wtmp.ut_name, ""); - SCPYN(wtmp.ut_host, ""); - (void) time(&wtmp.ut_time); - (void) write(f, (char *)&wtmp, sizeof(wtmp)); - (void) close(f); - } - } - (void) chmod(line, 0666); - (void) chown(line, 0, 0); - line[strlen(_PATH_DEV)] = 'p'; - (void) chmod(line, 0666); - (void) chown(line, 0, 0); -} /* end of rmut */ -#endif Index: head/crypto/telnet/telnetd/telnetd.8 =================================================================== --- head/crypto/telnet/telnetd/telnetd.8 (revision 87138) +++ head/crypto/telnet/telnetd/telnetd.8 (revision 87139) @@ -1,607 +1,587 @@ .\" Copyright (c) 1983, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)telnetd.8 8.4 (Berkeley) 6/1/94 .\" $FreeBSD$ .\" .Dd January 27, 2000 .Dt TELNETD 8 .Os .Sh NAME .Nm telnetd .Nd DARPA .Tn TELNET protocol server .Sh SYNOPSIS .Nm /usr/libexec/telnetd .Op Fl BUhlkns .Op Fl D Ar debugmode .Op Fl S Ar tos .Op Fl X Ar authtype .Op Fl a Ar authmode .Op Fl edebug .Op Fl p Ar loginprog .Op Fl r Ns Ar lowpty-highpty .Op Fl u Ar len .Op Fl debug Op Ar port .Sh DESCRIPTION The .Nm command is a server which supports the .Tn DARPA standard .Tn TELNET virtual terminal protocol. .Nm Telnetd is normally invoked by the internet server (see .Xr inetd 8 ) for requests to connect to the .Tn TELNET port as indicated by the .Pa /etc/services file (see .Xr services 5 ) . The .Fl debug option may be used to start up .Nm manually, instead of through .Xr inetd 8 . If started up this way, .Ar port may be specified to run .Nm on an alternate .Tn TCP port number. .Pp The .Nm command accepts the following options: .Bl -tag -width indent .It Fl a Ar authmode This option may be used for specifying what mode should be used for authentication. Note that this option is only useful if .Nm has been compiled with support for the .Dv AUTHENTICATION option. There are several valid values for .Ar authmode : .Bl -tag -width debug .It Cm debug Turn on authentication debugging code. .It Cm user Only allow connections when the remote user can provide valid authentication information to identify the remote user, and is allowed access to the specified account without providing a password. .It Cm valid Only allow connections when the remote user can provide valid authentication information to identify the remote user. The .Xr login 1 command will provide any additional user verification needed if the remote user is not allowed automatic access to the specified account. .It Cm other Only allow connections that supply some authentication information. This option is currently not supported by any of the existing authentication mechanisms, and is thus the same as specifying .Fl a .Cm valid . .It Cm none This is the default state. Authentication information is not required. If no or insufficient authentication information is provided, then the .Xr login 1 program will provide the necessary user verification. .It Cm off Disable the authentication code. All user verification will happen through the .Xr login 1 program. .El .It Fl B Specify bftp server mode. In this mode, .Nm causes login to start a .Xr bftp 1 session rather than the user's normal shell. In bftp daemon mode normal logins are not supported, and it must be used on a port other than the normal .Tn TELNET port. .It Fl D Ar debugmode This option may be used for debugging purposes. This allows .Nm to print out debugging information to the connection, allowing the user to see what .Nm is doing. There are several possible values for .Ar debugmode : .Bl -tag -width exercise .It Cm options Print information about the negotiation of .Tn TELNET options. .It Cm report Print the .Cm options information, plus some additional information about what processing is going on. .It Cm netdata Display the data stream received by .Nm . .It Cm ptydata Display data written to the pty. .It Cm exercise Has not been implemented yet. .El .It Fl debug Enable debugging on each socket created by .Nm (see .Dv SO_DEBUG in .Xr socket 2 ) . .It Fl edebug If .Nm has been compiled with support for data encryption, then the .Fl edebug option may be used to enable encryption debugging code. .It Fl p Ar loginprog Specify an alternate .Xr login 1 command to run to complete the login. The alternate command must understand the same command arguments as the standard login. .It Fl h Disable the printing of host-specific information before login has been completed. .It Fl k This option is only useful if .Nm has been compiled with both linemode and kludge linemode support. If the .Fl k option is specified, then if the remote client does not support the .Dv LINEMODE option, then .Nm will operate in character at a time mode. It will still support kludge linemode, but will only go into kludge linemode if the remote client requests it. (This is done by the client sending .Dv DONT SUPPRESS-GO-AHEAD and .Dv DONT ECHO . ) The .Fl k option is most useful when there are remote clients that do not support kludge linemode, but pass the heuristic (if they respond with .Dv WILL TIMING-MARK in response to a .Dv DO TIMING-MARK ) for kludge linemode support. .It Fl l Specify line mode. Try to force clients to use line- at-a-time mode. If the .Dv LINEMODE option is not supported, it will go into kludge linemode. .It Fl n Disable .Dv TCP keep-alives. Normally .Nm enables the .Tn TCP keep-alive mechanism to probe connections that have been idle for some period of time to determine if the client is still there, so that idle connections from machines that have crashed or can no longer be reached may be cleaned up. -.It Fl s -This option is only enabled if -.Nm -is compiled with support for -.Tn SecurID -cards. -It causes the -.Fl s -option to be passed on to -.Xr login 1 , -and thus is only useful if -.Xr login 1 -supports the -.Fl s -flag to indicate that only -.Tn SecurID -validated logins are allowed, and is -usually useful for controlling remote logins -from outside of a firewall. -.It Fl S Ar tos .It Fl u Ar len This option is used to specify the size of the field in the .Dv utmp structure that holds the remote host name. If the resolved host name is longer than .Ar len , the dotted decimal value will be used instead. This allows hosts with very long host names that overflow this field to still be uniquely identified. Specifying .Fl u0 indicates that only dotted decimal addresses should be put into the .Pa utmp file. .It Fl U This option causes .Nm to refuse connections from addresses that cannot be mapped back into a symbolic name via the .Xr gethostbyaddr 3 routine. .It Fl X Ar authtype This option is only valid if .Nm has been built with support for the authentication option. It disables the use of .Ar authtype authentication, and can be used to temporarily disable a specific authentication type without having to recompile .Nm . .El .Pp .Nm Telnetd operates by allocating a pseudo-terminal device (see .Xr pty 4 ) for a client, then creating a login process which has the slave side of the pseudo-terminal as .Dv stdin , .Dv stdout and .Dv stderr . .Nm Telnetd manipulates the master side of the pseudo-terminal, implementing the .Tn TELNET protocol and passing characters between the remote client and the login process. .Pp When a .Tn TELNET session is started up, .Nm sends .Tn TELNET options to the client side indicating a willingness to do the following .Tn TELNET options, which are described in more detail below: .Bd -literal -offset indent DO AUTHENTICATION WILL ENCRYPT DO TERMINAL TYPE DO TSPEED DO XDISPLOC DO NEW-ENVIRON DO ENVIRON WILL SUPPRESS GO AHEAD DO ECHO DO LINEMODE DO NAWS WILL STATUS DO LFLOW DO TIMING-MARK .Ed .Pp The pseudo-terminal allocated to the client is configured to operate in .Dq cooked mode, and with .Dv XTABS and .Dv CRMOD enabled (see .Xr tty 4 ) . .Pp .Nm Telnetd has support for enabling locally the following .Tn TELNET options: .Bl -tag -width "DO AUTHENTICATION" .It "WILL ECHO" When the .Dv LINEMODE option is enabled, a .Dv WILL ECHO or .Dv WONT ECHO will be sent to the client to indicate the current state of terminal echoing. When terminal echo is not desired, a .Dv WILL ECHO is sent to indicate that .Nm will take care of echoing any data that needs to be echoed to the terminal, and then nothing is echoed. When terminal echo is desired, a .Dv WONT ECHO is sent to indicate that .Nm will not be doing any terminal echoing, so the client should do any terminal echoing that is needed. .It "WILL BINARY" Indicate that the client is willing to send a 8 bits of data, rather than the normal 7 bits of the Network Virtual Terminal. .It "WILL SGA" Indicate that it will not be sending .Dv IAC GA , go ahead, commands. .It "WILL STATUS" Indicate a willingness to send the client, upon request, of the current status of all .Tn TELNET options. .It "WILL TIMING-MARK" Whenever a .Dv DO TIMING-MARK command is received, it is always responded to with a .Dv WILL TIMING-MARK . .It "WILL LOGOUT" When a .Dv DO LOGOUT is received, a .Dv WILL LOGOUT is sent in response, and the .Tn TELNET session is shut down. .It "WILL ENCRYPT" Only sent if .Nm is compiled with support for data encryption, and indicates a willingness to decrypt the data stream. .El .Pp .Nm Telnetd has support for enabling remotely the following .Tn TELNET options: .Bl -tag -width "DO AUTHENTICATION" .It "DO BINARY" Sent to indicate that .Nm is willing to receive an 8 bit data stream. .It "DO LFLOW" Requests that the client handle flow control characters remotely. .It "DO ECHO" This is not really supported, but is sent to identify a .Bx 4.2 .Xr telnet 1 client, which will improperly respond with .Dv WILL ECHO . If a .Dv WILL ECHO is received, a .Dv DONT ECHO will be sent in response. .It "DO TERMINAL-TYPE" Indicate a desire to be able to request the name of the type of terminal that is attached to the client side of the connection. .It "DO SGA" Indicate that it does not need to receive .Dv IAC GA , the go ahead command. .It "DO NAWS" Requests that the client inform the server when the window (display) size changes. .It "DO TERMINAL-SPEED" Indicate a desire to be able to request information about the speed of the serial line to which the client is attached. .It "DO XDISPLOC" Indicate a desire to be able to request the name of the X Window System display that is associated with the telnet client. .It "DO NEW-ENVIRON" Indicate a desire to be able to request environment variable information, as described in RFC 1572. .It "DO ENVIRON" Indicate a desire to be able to request environment variable information, as described in RFC 1408. .It "DO LINEMODE" Only sent if .Nm is compiled with support for linemode, and requests that the client do line by line processing. .It "DO TIMING-MARK" Only sent if .Nm is compiled with support for both linemode and kludge linemode, and the client responded with .Dv WONT LINEMODE . If the client responds with .Dv WILL TM , the it is assumed that the client supports kludge linemode. Note that the .Op Fl k option can be used to disable this. .It "DO AUTHENTICATION" Only sent if .Nm is compiled with support for authentication, and indicates a willingness to receive authentication information for automatic login. .It "DO ENCRYPT" Only sent if .Nm is compiled with support for data encryption, and indicates a willingness to decrypt the data stream. .El .Sh NOTES By default .Nm will read the .Em \&he , .Em \&hn , and .Em \&im capabilities from .Pa /etc/gettytab and use that information (if present) to determine what to display before the login: prompt. You can also use a System V style .Pa /etc/issue file by using the .Em \&if capability, which will override .Em \&im . The information specified in either .Em \&im or .Em \&if will be displayed to both console and remote logins. .\" .Sh ENVIRONMENT .Sh FILES .Bl -tag -width /usr/ucb/bftp -compact .It Pa /etc/services .It Pa /etc/gettytab .It Pa /etc/iptos (if supported) .It Pa /usr/ucb/bftp (if supported) .El .Sh "SEE ALSO" .Xr bftp 1 , .Xr login 1 , .Xr gettytab 5 , .Xr telnet 1 (if supported) .Sh STANDARDS .Bl -tag -compact -width RFC-1572 .It Cm RFC-854 .Tn TELNET PROTOCOL SPECIFICATION .It Cm RFC-855 TELNET OPTION SPECIFICATIONS .It Cm RFC-856 TELNET BINARY TRANSMISSION .It Cm RFC-857 TELNET ECHO OPTION .It Cm RFC-858 TELNET SUPPRESS GO AHEAD OPTION .It Cm RFC-859 TELNET STATUS OPTION .It Cm RFC-860 TELNET TIMING MARK OPTION .It Cm RFC-861 TELNET EXTENDED OPTIONS - LIST OPTION .It Cm RFC-885 TELNET END OF RECORD OPTION .It Cm RFC-1073 Telnet Window Size Option .It Cm RFC-1079 Telnet Terminal Speed Option .It Cm RFC-1091 Telnet Terminal-Type Option .It Cm RFC-1096 Telnet X Display Location Option .It Cm RFC-1123 Requirements for Internet Hosts -- Application and Support .It Cm RFC-1184 Telnet Linemode Option .It Cm RFC-1372 Telnet Remote Flow Control Option .It Cm RFC-1416 Telnet Authentication Option .It Cm RFC-1411 Telnet Authentication: Kerberos Version 4 .It Cm RFC-1412 Telnet Authentication: SPX .It Cm RFC-1571 Telnet Environment Option Interoperability Issues .It Cm RFC-1572 Telnet Environment Option .El .Sh BUGS Some .Tn TELNET commands are only partially implemented. .Pp Because of bugs in the original .Bx 4.2 .Xr telnet 1 , .Nm performs some dubious protocol exchanges to try to discover if the remote client is, in fact, a .Bx 4.2 .Xr telnet 1 . .Pp Binary mode has no common interpretation except between similar operating systems (Unix in this case). .Pp The terminal type name received from the remote client is converted to lower case. .Pp .Nm Telnetd never sends .Tn TELNET .Dv IAC GA (go ahead) commands. .Sh HISTORY IPv6 support was added by WIDE/KAME project. Index: head/crypto/telnet/telnetd/telnetd.c =================================================================== --- head/crypto/telnet/telnetd/telnetd.c (revision 87138) +++ head/crypto/telnet/telnetd/telnetd.c (revision 87139) @@ -1,1371 +1,1226 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include "telnetd.h" #include "pathnames.h" -#include -#include - #include +#include #include #include +#include #include -#if defined(AUTHENTICATION) +#include + +#ifdef AUTHENTICATION #include int auth_level = 0; #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif #include -#if defined(SecurID) -int require_SecurID = 0; -#endif char remote_hostname[MAXHOSTNAMELEN]; -int utmp_len = sizeof(remote_hostname) - 1; +size_t utmp_len = sizeof(remote_hostname) - 1; int registerd_host_only = 0; -#ifdef STREAMSPTY -# include -# include -/* make sure we don't get the bsd version */ -# include "/usr/include/sys/tty.h" -# include /* - * Because of the way ptyibuf is used with streams messages, we need - * ptyibuf+1 to be on a full-word boundary. The following weirdness - * is simply to make that happen. - */ -long ptyibufbuf[BUFSIZ/sizeof(long)+1]; -char *ptyibuf = ((char *)&ptyibufbuf[1])-1; -char *ptyip = ((char *)&ptyibufbuf[1])-1; -char ptyibuf2[BUFSIZ]; -unsigned char ctlbuf[BUFSIZ]; -struct strbuf strbufc, strbufd; - -#else /* ! STREAMPTY */ - -/* * I/O data buffers, * pointers, and counters. */ char ptyibuf[BUFSIZ], *ptyip = ptyibuf; char ptyibuf2[BUFSIZ]; -# include +int readstream(int, char *, int); +void doit(struct sockaddr *); +int terminaltypeok(char *); -int readstream(int p, char *ibuf, int bufsize); -void doit(struct sockaddr *who); -int terminaltypeok(char *s); -void startslave(char *host, int autologin, char *autoname); - -#endif /* ! STREAMPTY */ - int hostinfo = 1; /* do we print login banner? */ int debug = 0; int keepalive = 1; -char *altlogin; +const char *altlogin; void doit __P((struct sockaddr *)); int terminaltypeok __P((char *)); void startslave __P((char *, int, char *)); extern void usage P((void)); +static void _gettermname __P((void)); /* * The string to pass to getopt(). We do it this way so * that only the actual options that we support will be * passed off to getopt(). */ char valid_opts[] = { 'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U', '4', '6', #ifdef AUTHENTICATION 'a', ':', 'X', ':', #endif #ifdef BFTPDAEMON 'B', #endif #ifdef DIAGNOSTICS 'D', ':', #endif #ifdef ENCRYPTION 'e', ':', #endif #ifdef LINEMODE 'l', #endif -#ifdef SecurID - 's', -#endif '\0' }; int family = AF_INET; +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif /* MAXHOSTNAMELEN */ + +char *hostname; +char host_name[MAXHOSTNAMELEN]; + +extern void telnet P((int, int, char *)); + +int level; +char user_name[256]; + int -main(argc, argv) - char *argv[]; +main(int argc, char *argv[]) { struct sockaddr_storage from; int on = 1, fromlen; - register int ch; + int ch; #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; #ifdef ENCRYPTION nclearto = 0; #endif /* ENCRYPTION */ /* * This initialization causes linemode to default to a configuration * that works on all telnet clients, including the FreeBSD client. * This is not quite the same as the telnet client issuing a "mode * character" command, but has most of the same benefits, and is * preferable since some clients (like usofts) don't have the * mode character command anyway and linemode breaks things. * The most notable symptom of fix is that csh "set filec" operations * like (filename completion) and ^D (choices) keys now work * in telnet sessions and can be used more than once on the same line. * CR/LF handling is also corrected in some termio modes. This * change resolves problem reports bin/771 and bin/1037. */ linemode=1; /*Default to mode that works on bulk of clients*/ while ((ch = getopt(argc, argv, valid_opts)) != -1) { switch(ch) { #ifdef AUTHENTICATION case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { warnx("unknown authorization level for -a"); } break; #endif /* AUTHENTICATION */ #ifdef BFTPDAEMON case 'B': bftpd++; break; #endif /* BFTPDAEMON */ case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ #ifdef ENCRYPTION case 'e': if (strcmp(optarg, "debug") == 0) { extern int encrypt_debug_mode; encrypt_debug_mode = 1; break; } usage(); /* NOTREACHED */ break; #endif /* ENCRYPTION */ case 'h': hostinfo = 0; break; #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'k': #if defined(LINEMODE) && defined(KLUDGELINEMODE) lmodetype = NO_AUTOKLUDGE; #else /* ignore -k option if built without kludge linemode */ #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ break; case 'n': keepalive = 0; break; case 'p': altlogin = optarg; break; -#ifdef SecurID - case 's': - /* SecurID required */ - require_SecurID = 1; - break; -#endif /* SecurID */ case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) warnx("%s%s%s", "bad TOS argument '", optarg, "'; will try to use default TOS"); #else warnx("TOS option unavailable; -S flag not supported"); #endif break; case 'u': - utmp_len = atoi(optarg); - if (utmp_len < 0) - utmp_len = -utmp_len; + utmp_len = (size_t)atoi(optarg); if (utmp_len >= sizeof(remote_hostname)) utmp_len = sizeof(remote_hostname) - 1; break; case 'U': registerd_host_only = 1; break; #ifdef AUTHENTICATION case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif /* AUTHENTICATION */ case '4': family = AF_INET; break; #ifdef INET6 case '6': family = AF_INET6; break; #endif default: warnx("%c: unknown option", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debug) { int s, ns, foo, error; - char *service = "telnet"; + const char *service = "telnet"; struct addrinfo hints, *res; if (argc > 1) { usage(); /* NOT REACHED */ } else if (argc == 1) service = *argv; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; error = getaddrinfo(NULL, service, &hints, &res); if (error) { errx(1, "tcp/%s: %s\n", service, gai_strerror(error)); if (error == EAI_SYSTEM) errx(1, "tcp/%s: %s\n", service, strerror(errno)); usage(); } s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) err(1, "socket"); (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); if (bind(s, res->ai_addr, res->ai_addrlen) < 0) err(1, "bind"); if (listen(s, 1) < 0) err(1, "listen"); foo = res->ai_addrlen; ns = accept(s, res->ai_addr, &foo); if (ns < 0) err(1, "accept"); (void) dup2(ns, 0); (void) close(ns); (void) close(s); #ifdef convex } else if (argc == 1) { ; /* VOID*/ /* Just ignore the host/port name */ #endif } else if (argc > 0) { usage(); /* NOT REACHED */ } openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { warn("getpeername"); _exit(1); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof (on)) < 0) { syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } #if defined(IPPROTO_IP) && defined(IP_TOS) if (from.ss_family == AF_INET) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = 0; doit((struct sockaddr *)&from); /* NOTREACHED */ return(0); } /* end of main */ void usage() { fprintf(stderr, "usage: telnetd"); #ifdef AUTHENTICATION fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); #endif #ifdef BFTPDAEMON fprintf(stderr, " [-B]"); #endif fprintf(stderr, " [-debug]"); #ifdef DIAGNOSTICS fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); #endif #ifdef AUTHENTICATION fprintf(stderr, " [-edebug]"); #endif fprintf(stderr, " [-h]"); #if defined(LINEMODE) && defined(KLUDGELINEMODE) fprintf(stderr, " [-k]"); #endif #ifdef LINEMODE fprintf(stderr, " [-l]"); #endif fprintf(stderr, " [-n]"); fprintf(stderr, "\n\t"); -#ifdef SecurID - fprintf(stderr, " [-s]"); -#endif #ifdef HAS_GETTOS fprintf(stderr, " [-S tos]"); #endif #ifdef AUTHENTICATION fprintf(stderr, " [-X auth-type]"); #endif fprintf(stderr, " [-u utmp_hostname_length] [-U]"); fprintf(stderr, " [port]\n"); exit(1); } /* * getterminaltype * * Ask the other end to send along its terminal type and speed. * Output is the variable terminaltype filled in. */ static unsigned char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE }; - int -getterminaltype(name) - char *name; + +#ifndef AUTHENTICATION +#define undef2 __unused +#else +#define undef2 +#endif + +static int +getterminaltype(char *name undef2) { int retval = -1; - void _gettermname(); settimer(baseline); -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION /* * Handle the Authentication option before we do anything else. */ send_do(TELOPT_AUTHENTICATION, 1); while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) ttloop(); if (his_state_is_will(TELOPT_AUTHENTICATION)) { retval = auth_wait(name); } #endif #ifdef ENCRYPTION send_will(TELOPT_ENCRYPT, 1); #endif /* ENCRYPTION */ send_do(TELOPT_TTYPE, 1); send_do(TELOPT_TSPEED, 1); send_do(TELOPT_XDISPLOC, 1); send_do(TELOPT_NEW_ENVIRON, 1); send_do(TELOPT_OLD_ENVIRON, 1); while ( #ifdef ENCRYPTION his_do_dont_is_changing(TELOPT_ENCRYPT) || #endif /* ENCRYPTION */ his_will_wont_is_changing(TELOPT_TTYPE) || his_will_wont_is_changing(TELOPT_TSPEED) || his_will_wont_is_changing(TELOPT_XDISPLOC) || his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { ttloop(); } #ifdef ENCRYPTION /* * Wait for the negotiation of what type of encryption we can * send with. If autoencrypt is not set, this will just return. */ if (his_state_is_will(TELOPT_ENCRYPT)) { encrypt_wait(); } #endif /* ENCRYPTION */ if (his_state_is_will(TELOPT_TSPEED)) { static unsigned char sb[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_XDISPLOC)) { static unsigned char sb[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_NEW_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; output_datalen(sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_TTYPE)) { output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, sizeof ttytype_sbbuf - 2);); } if (his_state_is_will(TELOPT_TSPEED)) { while (sequenceIs(tspeedsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_XDISPLOC)) { while (sequenceIs(xdisplocsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_NEW_ENVIRON)) { while (sequenceIs(environsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_OLD_ENVIRON)) { while (sequenceIs(oenvironsubopt, baseline)) ttloop(); } if (his_state_is_will(TELOPT_TTYPE)) { char first[256], last[256]; while (sequenceIs(ttypesubopt, baseline)) ttloop(); /* * If the other side has already disabled the option, then * we have to just go with what we (might) have already gotten. */ if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { (void) strncpy(first, terminaltype, sizeof(first)-1); first[sizeof(first)-1] = '\0'; for(;;) { /* * Save the unknown name, and request the next name. */ (void) strncpy(last, terminaltype, sizeof(last)-1); last[sizeof(last)-1] = '\0'; _gettermname(); if (terminaltypeok(terminaltype)) break; if ((strncmp(last, terminaltype, sizeof(last)) == 0) || his_state_is_wont(TELOPT_TTYPE)) { /* * We've hit the end. If this is the same as * the first name, just go with it. */ if (strncmp(first, terminaltype, sizeof(first)) == 0) break; /* * Get the terminal name one more time, so that * RFC1091 compliant telnets will cycle back to * the start of the list. */ _gettermname(); if (strncmp(first, terminaltype, sizeof(first)) != 0) { (void) strncpy(terminaltype, first, sizeof(terminaltype)-1); terminaltype[sizeof(terminaltype)-1] = '\0'; } break; } } } } return(retval); } /* end of getterminaltype */ - void -_gettermname() +static void +_gettermname(void) { /* * If the client turned off the option, * we can't send another request, so we * just return. */ if (his_state_is_wont(TELOPT_TTYPE)) return; settimer(baseline); output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, sizeof ttytype_sbbuf - 2);); while (sequenceIs(ttypesubopt, baseline)) ttloop(); } - int -terminaltypeok(s) - char *s; +int +terminaltypeok(char *s) { char buf[1024]; if (terminaltype == NULL) return(1); /* * tgetent() will return 1 if the type is known, and * 0 if it is not known. If it returns -1, it couldn't * open the database. But if we can't open the database, * it won't help to say we failed, because we won't be * able to verify anything else. So, we treat -1 like 1. */ if (tgetent(buf, s) == 0) return(0); return(1); } -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 256 -#endif /* MAXHOSTNAMELEN */ - -char *hostname; -char host_name[MAXHOSTNAMELEN]; - -extern void telnet P((int, int, char *)); - -int level; -char user_name[256]; /* * Get a pty, scan input lines. */ - void -doit(who) - struct sockaddr *who; +void +doit(struct sockaddr *who) { - int err; + int err_; /* XXX */ int ptynum; /* * Find an available pty to use. */ #ifndef convex pty = getpty(&ptynum); if (pty < 0) fatal(net, "All network ports in use"); #else for (;;) { char *lp; if ((lp = getpty()) == NULL) fatal(net, "Out of ptys"); if ((pty = open(lp, 2)) >= 0) { strlcpy(line,lp,sizeof(line)); line[5] = 't'; break; } } #endif /* get name of connected client */ if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1, who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only) fatal(net, "Couldn't resolve your address into a host name.\r\n\ Please contact your net administrator"); remote_hostname[sizeof(remote_hostname) - 1] = '\0'; trimdomain(remote_hostname, UT_HOSTSIZE); if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len) - err = getnameinfo(who, who->sa_len, remote_hostname, + err_ = getnameinfo(who, who->sa_len, remote_hostname, sizeof(remote_hostname), NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID); - /* XXX: do 'err' check */ + /* XXX: do 'err_' check */ (void) gethostname(host_name, sizeof(host_name) - 1); host_name[sizeof(host_name) - 1] = '\0'; hostname = host_name; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#ifdef AUTHENTICATION +#ifdef ENCRYPTION +/* The above #ifdefs should actually be "or"'ed, not "and"'ed. + * This is a byproduct of needing "#ifdef" and not "#if defined()" + * for unifdef. XXX MarkM + */ auth_encrypt_init(hostname, remote_hostname, "TELNETD", 1); #endif +#endif init_env(); /* * get terminal type. */ *user_name = 0; level = getterminaltype(user_name); setenv("TERM", terminaltype ? terminaltype : "network", 1); telnet(net, pty, remote_hostname); /* begin server process */ /*NOTREACHED*/ } /* end of doit */ /* * Main loop. Select from pty and network, and * hand data to telnet receiver finite state machine. */ - void -telnet(f, p, host) - int f, p; - char *host; +void +telnet(int f, int p, char *host) { int on = 1; #define TABBUFSIZ 512 char defent[TABBUFSIZ]; char defstrs[TABBUFSIZ]; #undef TABBUFSIZ char *HE; char *HN; char *IM; int nfd; /* * Initialize the slc mapping table. */ get_slc_defaults(); /* * Do some tests where it is desireable to wait for a response. * Rather than doing them slowly, one at a time, do them all * at once. */ if (my_state_is_wont(TELOPT_SGA)) send_will(TELOPT_SGA, 1); /* * Is the client side a 4.2 (NOT 4.3) system? We need to know this * because 4.2 clients are unable to deal with TCP urgent data. * * To find out, we send out a "DO ECHO". If the remote system * answers "WILL ECHO" it is probably a 4.2 client, and we note * that fact ("WILL ECHO" ==> that the client will echo what * WE, the server, sends it; it does NOT mean that the client will * echo the terminal input). */ send_do(TELOPT_ECHO, 1); #ifdef LINEMODE if (his_state_is_wont(TELOPT_LINEMODE)) { /* Query the peer for linemode support by trying to negotiate * the linemode option. */ linemode = 0; editmode = 0; send_do(TELOPT_LINEMODE, 1); /* send do linemode */ } #endif /* LINEMODE */ /* * Send along a couple of other options that we wish to negotiate. */ send_do(TELOPT_NAWS, 1); send_will(TELOPT_STATUS, 1); flowmode = 1; /* default flow control state */ restartany = -1; /* uninitialized... */ send_do(TELOPT_LFLOW, 1); /* * Spin, waiting for a response from the DO ECHO. However, * some REALLY DUMB telnets out there might not respond * to the DO ECHO. So, we spin looking for NAWS, (most dumb * telnets so far seem to respond with WONT for a DO that * they don't understand...) because by the time we get the * response, it will already have processed the DO ECHO. * Kludge upon kludge. */ while (his_will_wont_is_changing(TELOPT_NAWS)) ttloop(); /* * But... * The client might have sent a WILL NAWS as part of its * startup code; if so, we'll be here before we get the * response to the DO ECHO. We'll make the assumption * that any implementation that understands about NAWS * is a modern enough implementation that it will respond * to our DO ECHO request; hence we'll do another spin * waiting for the ECHO option to settle down, which is * what we wanted to do in the first place... */ if (his_want_state_is_will(TELOPT_ECHO) && his_state_is_will(TELOPT_NAWS)) { while (his_will_wont_is_changing(TELOPT_ECHO)) ttloop(); } /* * On the off chance that the telnet client is broken and does not * respond to the DO ECHO we sent, (after all, we did send the * DO NAWS negotiation after the DO ECHO, and we won't get here * until a response to the DO NAWS comes back) simulate the * receipt of a will echo. This will also send a WONT ECHO * to the client, since we assume that the client failed to * respond because it believes that it is already in DO ECHO * mode, which we do not want. */ if (his_want_state_is_will(TELOPT_ECHO)) { DIAG(TD_OPTIONS, output_data("td: simulating recv\r\n")); willoption(TELOPT_ECHO); } /* * Finally, to clean things up, we turn on our echo. This * will break stupid 4.2 telnets out of local terminal echo. */ if (my_state_is_wont(TELOPT_ECHO)) send_will(TELOPT_ECHO, 1); -#ifndef STREAMSPTY /* * Turn on packet mode */ (void) ioctl(p, TIOCPKT, (char *)&on); -#endif #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * Continuing line mode support. If client does not support * real linemode, attempt to negotiate kludge linemode by sending * the do timing mark sequence. */ if (lmodetype < REAL_LINEMODE) send_do(TELOPT_TM, 1); #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ /* * Call telrcv() once to pick up anything received during * terminal type negotiation, 4.2/4.3 determination, and * linemode negotiation. */ telrcv(); (void) ioctl(f, FIONBIO, (char *)&on); (void) ioctl(p, FIONBIO, (char *)&on); #if defined(SO_OOBINLINE) (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof on); #endif /* defined(SO_OOBINLINE) */ #ifdef SIGTSTP (void) signal(SIGTSTP, SIG_IGN); #endif #ifdef SIGTTOU /* * Ignoring SIGTTOU keeps the kernel from blocking us * in ttioct() in /sys/tty.c. */ (void) signal(SIGTTOU, SIG_IGN); #endif (void) signal(SIGCHLD, cleanup); #ifdef TIOCNOTTY { - register int t; + int t; t = open(_PATH_TTY, O_RDWR); if (t >= 0) { (void) ioctl(t, TIOCNOTTY, (char *)0); (void) close(t); } } #endif /* * Show banner that getty never gave. * * We put the banner in the pty input buffer. This way, it * gets carriage return null processing, etc., just like all * other pty --> client data. */ if (getent(defent, "default") == 1) { - char *Getstr(); char *cp=defstrs; HE = Getstr("he", &cp); HN = Getstr("hn", &cp); IM = Getstr("im", &cp); if (HN && *HN) (void) strlcpy(host_name, HN, sizeof(host_name)); if (IM == 0) - IM = ""; + IM = strdup(""); } else { - IM = DEFAULT_IM; + IM = strdup(DEFAULT_IM); HE = 0; } edithost(HE, host_name); if (hostinfo && *IM) putf(IM, ptyibuf2); if (pcc) (void) strncat(ptyibuf2, ptyip, pcc+1); ptyip = ptyibuf2; pcc = strlen(ptyip); #ifdef LINEMODE /* * Last check to make sure all our states are correct. */ init_termbuf(); localstat(); #endif /* LINEMODE */ DIAG(TD_REPORT, output_data("td: Entering processing loop\r\n")); /* * Startup the login process on the slave side of the terminal * now. We delay this until here to insure option negotiation * is complete. */ startslave(host, level, user_name); nfd = ((f > p) ? f : p) + 1; for (;;) { fd_set ibits, obits, xbits; - register int c; + int c; if (ncc < 0 && pcc < 0) break; FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&xbits); /* * Never look for input if there's still * stuff in the corresponding output buffer */ if (nfrontp - nbackp || pcc > 0) { FD_SET(f, &obits); } else { FD_SET(p, &ibits); } if (pfrontp - pbackp || ncc > 0) { FD_SET(p, &obits); } else { FD_SET(f, &ibits); } if (!SYNCHing) { FD_SET(f, &xbits); } if ((c = select(nfd, &ibits, &obits, &xbits, (struct timeval *)0)) < 1) { if (c == -1) { if (errno == EINTR) { continue; } } sleep(5); continue; } /* * Any urgent data? */ if (FD_ISSET(net, &xbits)) { SYNCHing = 1; } /* * Something to read from the network... */ if (FD_ISSET(net, &ibits)) { #if !defined(SO_OOBINLINE) /* * In 4.2 (and 4.3 beta) systems, the * OOB indication and data handling in the kernel * is such that if two separate TCP Urgent requests * come in, one byte of TCP data will be overlaid. * This is fatal for Telnet, but we try to live * with it. * * In addition, in 4.2 (and...), a special protocol * is needed to pick up the TCP Urgent data in * the correct sequence. * * What we do is: if we think we are in urgent * mode, we look to see if we are "at the mark". * If we are, we do an OOB receive. If we run * this twice, we will do the OOB receive twice, * but the second will fail, since the second * time we were "at the mark", but there wasn't * any data there (the kernel doesn't reset * "at the mark" until we do a normal read). * Once we've read the OOB data, we go ahead * and do normal reads. * * There is also another problem, which is that * since the OOB byte we read doesn't put us * out of OOB state, and since that byte is most * likely the TELNET DM (data mark), we would * stay in the TELNET SYNCH (SYNCHing) state. * So, clocks to the rescue. If we've "just" * received a DM, then we test for the * presence of OOB data when the receive OOB * fails (and AFTER we did the normal mode read * to clear "at the mark"). */ if (SYNCHing) { int atmark; (void) ioctl(net, SIOCATMARK, (char *)&atmark); if (atmark) { ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); if ((ncc == -1) && (errno == EINVAL)) { ncc = read(net, netibuf, sizeof (netibuf)); if (sequenceIs(didnetreceive, gotDM)) { SYNCHing = stilloob(net); } } } else { ncc = read(net, netibuf, sizeof (netibuf)); } } else { ncc = read(net, netibuf, sizeof (netibuf)); } settimer(didnetreceive); #else /* !defined(SO_OOBINLINE)) */ ncc = read(net, netibuf, sizeof (netibuf)); #endif /* !defined(SO_OOBINLINE)) */ if (ncc < 0 && errno == EWOULDBLOCK) ncc = 0; else { if (ncc <= 0) { break; } netip = netibuf; } DIAG((TD_REPORT | TD_NETDATA), output_data("td: netread %d chars\r\n", ncc)); DIAG(TD_NETDATA, printdata("nd", netip, ncc)); } /* * Something to read from the pty... */ if (FD_ISSET(p, &ibits)) { -#ifndef STREAMSPTY pcc = read(p, ptyibuf, BUFSIZ); -#else - pcc = readstream(p, ptyibuf, BUFSIZ); -#endif /* * On some systems, if we try to read something * off the master side before the slave side is * opened, we get EIO. */ if (pcc < 0 && (errno == EWOULDBLOCK || #ifdef EAGAIN errno == EAGAIN || #endif errno == EIO)) { pcc = 0; } else { if (pcc <= 0) break; #ifdef LINEMODE /* * If ioctl from pty, pass it through net */ if (ptyibuf[0] & TIOCPKT_IOCTL) { copy_termbuf(ptyibuf+1, pcc-1); localstat(); pcc = 1; } #endif /* LINEMODE */ if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { netclear(); /* clear buffer back */ #ifndef NO_URGENT /* * There are client telnets on some * operating systems get screwed up * royally if we send them urgent * mode data. */ output_data("%c%c", IAC, DM); neturg = nfrontp-1; /* off by one XXX */ DIAG(TD_OPTIONS, printoption("td: send IAC", DM)); #endif } if (his_state_is_will(TELOPT_LFLOW) && (ptyibuf[0] & (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { int newflow = ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; if (newflow != flowmode) { flowmode = newflow; output_data("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, flowmode ? LFLOW_ON : LFLOW_OFF, IAC, SE); DIAG(TD_OPTIONS, printsub('>', (unsigned char *)nfrontp-4, 4);); } } pcc--; ptyip = ptyibuf+1; } } while (pcc > 0) { if ((&netobuf[BUFSIZ] - nfrontp) < 2) break; c = *ptyip++ & 0377, pcc--; if (c == IAC) output_data("%c", c); output_data("%c", c); if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { if (pcc > 0 && ((*ptyip & 0377) == '\n')) { output_data("%c", *ptyip++ & 0377); pcc--; } else output_data("%c", '\0'); } } if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) netflush(); if (ncc > 0) telrcv(); if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) ptyflush(); } cleanup(0); } /* end of telnet */ #ifndef TCSIG # ifdef TIOCSIG # define TCSIG TIOCSIG # endif #endif -#ifdef STREAMSPTY - -int flowison = -1; /* current state of flow: -1 is unknown */ - -int readstream(p, ibuf, bufsize) - int p; - char *ibuf; - int bufsize; -{ - int flags = 0; - int ret = 0; - struct termios *tsp; - struct termio *tp; - struct iocblk *ip; - char vstop, vstart; - int ixon; - int newflow; - - strbufc.maxlen = BUFSIZ; - strbufc.buf = (char *)ctlbuf; - strbufd.maxlen = bufsize-1; - strbufd.len = 0; - strbufd.buf = ibuf+1; - ibuf[0] = 0; - - ret = getmsg(p, &strbufc, &strbufd, &flags); - if (ret < 0) /* error of some sort -- probably EAGAIN */ - return(-1); - - if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { - /* data message */ - if (strbufd.len > 0) { /* real data */ - return(strbufd.len + 1); /* count header char */ - } else { - /* nothing there */ - errno = EAGAIN; - return(-1); - } - } - - /* - * It's a control message. Return 1, to look at the flag we set - */ - - switch (ctlbuf[0]) { - case M_FLUSH: - if (ibuf[1] & FLUSHW) - ibuf[0] = TIOCPKT_FLUSHWRITE; - return(1); - - case M_IOCTL: - ip = (struct iocblk *) (ibuf+1); - - switch (ip->ioc_cmd) { - case TCSETS: - case TCSETSW: - case TCSETSF: - tsp = (struct termios *) - (ibuf+1 + sizeof(struct iocblk)); - vstop = tsp->c_cc[VSTOP]; - vstart = tsp->c_cc[VSTART]; - ixon = tsp->c_iflag & IXON; - break; - case TCSETA: - case TCSETAW: - case TCSETAF: - tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); - vstop = tp->c_cc[VSTOP]; - vstart = tp->c_cc[VSTART]; - ixon = tp->c_iflag & IXON; - break; - default: - errno = EAGAIN; - return(-1); - } - - newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; - if (newflow != flowison) { /* it's a change */ - flowison = newflow; - ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; - return(1); - } - } - - /* nothing worth doing anything about */ - errno = EAGAIN; - return(-1); -} -#endif /* STREAMSPTY */ - /* * Send interrupt to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write intr char. */ - void -interrupt() +void +interrupt(void) { ptyflush(); /* half-hearted */ -#if defined(STREAMSPTY) && defined(TIOCSIGNAL) - /* Streams PTY style ioctl to post a signal */ - { - int sig = SIGINT; - (void) ioctl(pty, TIOCSIGNAL, &sig); - (void) ioctl(pty, I_FLUSH, FLUSHR); - } -#else #ifdef TCSIG (void) ioctl(pty, TCSIG, (char *)SIGINT); #else /* TCSIG */ init_termbuf(); *pfrontp++ = slctab[SLC_IP].sptr ? (unsigned char)*slctab[SLC_IP].sptr : '\177'; #endif /* TCSIG */ -#endif } /* * Send quit to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write quit char. */ - void -sendbrk() +void +sendbrk(void) { ptyflush(); /* half-hearted */ #ifdef TCSIG (void) ioctl(pty, TCSIG, (char *)SIGQUIT); #else /* TCSIG */ init_termbuf(); *pfrontp++ = slctab[SLC_ABORT].sptr ? (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; #endif /* TCSIG */ } - void -sendsusp() +void +sendsusp(void) { #ifdef SIGTSTP ptyflush(); /* half-hearted */ # ifdef TCSIG (void) ioctl(pty, TCSIG, (char *)SIGTSTP); # else /* TCSIG */ *pfrontp++ = slctab[SLC_SUSP].sptr ? (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; # endif /* TCSIG */ #endif /* SIGTSTP */ } /* * When we get an AYT, if ^T is enabled, use that. Otherwise, * just send back "[Yes]". */ - void -recv_ayt() +void +recv_ayt(void) { #if defined(SIGINFO) && defined(TCSIG) if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { (void) ioctl(pty, TCSIG, (char *)SIGINFO); return; } #endif output_data("\r\n[Yes]\r\n"); } - void -doeof() +void +doeof(void) { init_termbuf(); #if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) if (!tty_isediting()) { extern char oldeofc; *pfrontp++ = oldeofc; return; } #endif *pfrontp++ = slctab[SLC_EOF].sptr ? (unsigned char)*slctab[SLC_EOF].sptr : '\004'; } Index: head/crypto/telnet/telnetd/telnetd.h =================================================================== --- head/crypto/telnet/telnetd/telnetd.h (revision 87138) +++ head/crypto/telnet/telnetd/telnetd.h (revision 87139) @@ -1,49 +1,49 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)telnetd.h 8.1 (Berkeley) 6/4/93 + * $FreeBSD$ */ #include "defs.h" #include "ext.h" #ifdef DIAGNOSTICS #define DIAG(a,b) if (diagnostic & (a)) b #else #define DIAG(a,b) #endif /* other external variables */ extern char **environ; -extern int errno; - +extern const char *altlogin; Index: head/crypto/telnet/telnetd/termstat.c =================================================================== --- head/crypto/telnet/telnetd/termstat.c (revision 87138) +++ head/crypto/telnet/telnetd/termstat.c (revision 87139) @@ -1,633 +1,632 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include + +__FBSDID("$FreeBSD$"); + #ifndef lint -#if 0 static const char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ #include "telnetd.h" -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif /* * local variables */ int def_tspeed = -1, def_rspeed = -1; #ifdef TIOCSWINSZ int def_row = 0, def_col = 0; #endif #ifdef LINEMODE static int _terminit = 0; #endif /* LINEMODE */ #ifdef LINEMODE /* * localstat * * This function handles all management of linemode. * * Linemode allows the client to do the local editing of data * and send only complete lines to the server. Linemode state is * based on the state of the pty driver. If the pty is set for * external processing, then we can use linemode. Further, if we * can use real linemode, then we can look at the edit control bits * in the pty to determine what editing the client should do. * * Linemode support uses the following state flags to keep track of * current and desired linemode state. * alwayslinemode : true if -l was specified on the telnetd * command line. It means to have linemode on as much as * possible. * * lmodetype: signifies whether the client can * handle real linemode, or if use of kludgeomatic linemode * is preferred. It will be set to one of the following: * REAL_LINEMODE : use linemode option * NO_KLUDGE : don't initiate kludge linemode. * KLUDGE_LINEMODE : use kludge linemode * NO_LINEMODE : client is ignorant of linemode * * linemode, uselinemode : linemode is true if linemode * is currently on, uselinemode is the state that we wish * to be in. If another function wishes to turn linemode * on or off, it sets or clears uselinemode. * * editmode, useeditmode : like linemode/uselinemode, but * these contain the edit mode states (edit and trapsig). * * The state variables correspond to some of the state information * in the pty. * linemode: * In real linemode, this corresponds to whether the pty * expects external processing of incoming data. * In kludge linemode, this more closely corresponds to the * whether normal processing is on or not. (ICANON in * system V, or COOKED mode in BSD.) * If the -l option was specified (alwayslinemode), then * an attempt is made to force external processing on at * all times. * * The following heuristics are applied to determine linemode * handling within the server. * 1) Early on in starting up the server, an attempt is made * to negotiate the linemode option. If this succeeds * then lmodetype is set to REAL_LINEMODE and all linemode * processing occurs in the context of the linemode option. * 2) If the attempt to negotiate the linemode option failed, * and the "-k" (don't initiate kludge linemode) isn't set, * then we try to use kludge linemode. We test for this * capability by sending "do Timing Mark". If a positive * response comes back, then we assume that the client * understands kludge linemode (ech!) and the * lmodetype flag is set to KLUDGE_LINEMODE. * 3) Otherwise, linemode is not supported at all and * lmodetype remains set to NO_LINEMODE (which happens * to be 0 for convenience). * 4) At any time a command arrives that implies a higher * state of linemode support in the client, we move to that * linemode support. * * A short explanation of kludge linemode is in order here. * 1) The heuristic to determine support for kludge linemode * is to send a do timing mark. We assume that a client * that supports timing marks also supports kludge linemode. * A risky proposition at best. * 2) Further negotiation of linemode is done by changing the * the server's state regarding SGA. If server will SGA, * then linemode is off, if server won't SGA, then linemode * is on. */ - void -localstat() +void +localstat(void) { int need_will_echo = 0; /* * Check for changes to flow control if client supports it. */ flowstat(); /* * Check linemode on/off state */ uselinemode = tty_linemode(); /* * If alwayslinemode is on, and pty is changing to turn it off, then * force linemode back on. */ if (alwayslinemode && linemode && !uselinemode) { uselinemode = 1; tty_setlinemode(uselinemode); } if (uselinemode) { /* * Check for state of BINARY options. * * We only need to do the binary dance if we are actually going * to use linemode. As this confuses some telnet clients * that don't support linemode, and doesn't gain us * anything, we don't do it unless we're doing linemode. * -Crh (henrich@msu.edu) */ if (tty_isbinaryin()) { if (his_want_state_is_wont(TELOPT_BINARY)) send_do(TELOPT_BINARY, 1); } else { if (his_want_state_is_will(TELOPT_BINARY)) send_dont(TELOPT_BINARY, 1); } if (tty_isbinaryout()) { if (my_want_state_is_wont(TELOPT_BINARY)) send_will(TELOPT_BINARY, 1); } else { if (my_want_state_is_will(TELOPT_BINARY)) send_wont(TELOPT_BINARY, 1); } } #ifdef ENCRYPTION /* * If the terminal is not echoing, but editing is enabled, * something like password input is going to happen, so * if we the other side is not currently sending encrypted * data, ask the other side to start encrypting. */ if (his_state_is_will(TELOPT_ENCRYPT)) { static int enc_passwd = 0; if (uselinemode && !tty_isecho() && tty_isediting() && (enc_passwd == 0) && !decrypt_input) { encrypt_send_request_start(); enc_passwd = 1; } else if (enc_passwd) { encrypt_send_request_end(); enc_passwd = 0; } } #endif /* ENCRYPTION */ /* * Do echo mode handling as soon as we know what the * linemode is going to be. * If the pty has echo turned off, then tell the client that * the server will echo. If echo is on, then the server * will echo if in character mode, but in linemode the * client should do local echoing. The state machine will * not send anything if it is unnecessary, so don't worry * about that here. * * If we need to send the WILL ECHO (because echo is off), * then delay that until after we have changed the MODE. * This way, when the user is turning off both editing * and echo, the client will get editing turned off first. * This keeps the client from going into encryption mode * and then right back out if it is doing auto-encryption * when passwords are being typed. */ if (uselinemode) { if (tty_isecho()) send_wont(TELOPT_ECHO, 1); else need_will_echo = 1; #ifdef KLUDGELINEMODE if (lmodetype == KLUDGE_OK) lmodetype = KLUDGE_LINEMODE; #endif } /* * If linemode is being turned off, send appropriate * command and then we're all done. */ if (!uselinemode && linemode) { # ifdef KLUDGELINEMODE if (lmodetype == REAL_LINEMODE) { # endif /* KLUDGELINEMODE */ send_dont(TELOPT_LINEMODE, 1); # ifdef KLUDGELINEMODE } else if (lmodetype == KLUDGE_LINEMODE) send_will(TELOPT_SGA, 1); # endif /* KLUDGELINEMODE */ send_will(TELOPT_ECHO, 1); linemode = uselinemode; goto done; } # ifdef KLUDGELINEMODE /* * If using real linemode check edit modes for possible later use. * If we are in kludge linemode, do the SGA negotiation. */ if (lmodetype == REAL_LINEMODE) { # endif /* KLUDGELINEMODE */ useeditmode = 0; if (tty_isediting()) useeditmode |= MODE_EDIT; if (tty_istrapsig()) useeditmode |= MODE_TRAPSIG; if (tty_issofttab()) useeditmode |= MODE_SOFT_TAB; if (tty_islitecho()) useeditmode |= MODE_LIT_ECHO; # ifdef KLUDGELINEMODE } else if (lmodetype == KLUDGE_LINEMODE) { if (tty_isediting() && uselinemode) send_wont(TELOPT_SGA, 1); else send_will(TELOPT_SGA, 1); } # endif /* KLUDGELINEMODE */ /* * Negotiate linemode on if pty state has changed to turn it on. * Send appropriate command and send along edit mode, then all done. */ if (uselinemode && !linemode) { # ifdef KLUDGELINEMODE if (lmodetype == KLUDGE_LINEMODE) { send_wont(TELOPT_SGA, 1); } else if (lmodetype == REAL_LINEMODE) { # endif /* KLUDGELINEMODE */ send_do(TELOPT_LINEMODE, 1); /* send along edit modes */ output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode, IAC, SE); editmode = useeditmode; # ifdef KLUDGELINEMODE } # endif /* KLUDGELINEMODE */ linemode = uselinemode; goto done; } # ifdef KLUDGELINEMODE /* * None of what follows is of any value if not using * real linemode. */ if (lmodetype < REAL_LINEMODE) goto done; # endif /* KLUDGELINEMODE */ if (linemode && his_state_is_will(TELOPT_LINEMODE)) { /* * If edit mode changed, send edit mode. */ if (useeditmode != editmode) { /* * Send along appropriate edit mode mask. */ output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode, IAC, SE); editmode = useeditmode; } /* * Check for changes to special characters in use. */ start_slc(0); check_slc(); (void) end_slc(0); } done: if (need_will_echo) send_will(TELOPT_ECHO, 1); /* * Some things should be deferred until after the pty state has * been set by the local process. Do those things that have been * deferred now. This only happens once. */ if (_terminit == 0) { _terminit = 1; defer_terminit(); } netflush(); set_termbuf(); return; } /* end of localstat */ #endif /* LINEMODE */ /* * flowstat * * Check for changes to flow control */ - void -flowstat() +void +flowstat(void) { if (his_state_is_will(TELOPT_LFLOW)) { if (tty_flowmode() != flowmode) { flowmode = tty_flowmode(); output_data("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, flowmode ? LFLOW_ON : LFLOW_OFF, IAC, SE); } if (tty_restartany() != restartany) { restartany = tty_restartany(); output_data("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, restartany ? LFLOW_RESTART_ANY : LFLOW_RESTART_XON, IAC, SE); } } } /* * clientstat * * Process linemode related requests from the client. * Client can request a change to only one of linemode, editmode or slc's * at a time, and if using kludge linemode, then only linemode may be * affected. */ - void -clientstat(code, parm1, parm2) - register int code, parm1, parm2; +void +clientstat(int code, int parm1, int parm2) { /* * Get a copy of terminal characteristics. */ init_termbuf(); /* * Process request from client. code tells what it is. */ switch (code) { #ifdef LINEMODE case TELOPT_LINEMODE: /* * Don't do anything unless client is asking us to change * modes. */ uselinemode = (parm1 == WILL); if (uselinemode != linemode) { # ifdef KLUDGELINEMODE /* * If using kludge linemode, make sure that * we can do what the client asks. * We can not turn off linemode if alwayslinemode * and the ICANON bit is set. */ if (lmodetype == KLUDGE_LINEMODE) { if (alwayslinemode && tty_isediting()) { uselinemode = 1; } } /* * Quit now if we can't do it. */ if (uselinemode == linemode) return; /* * If using real linemode and linemode is being * turned on, send along the edit mode mask. */ if (lmodetype == REAL_LINEMODE && uselinemode) # else /* KLUDGELINEMODE */ if (uselinemode) # endif /* KLUDGELINEMODE */ { useeditmode = 0; if (tty_isediting()) useeditmode |= MODE_EDIT; if (tty_istrapsig) useeditmode |= MODE_TRAPSIG; if (tty_issofttab()) useeditmode |= MODE_SOFT_TAB; if (tty_islitecho()) useeditmode |= MODE_LIT_ECHO; output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode, IAC, SE); editmode = useeditmode; } tty_setlinemode(uselinemode); linemode = uselinemode; if (!linemode) send_will(TELOPT_ECHO, 1); } break; case LM_MODE: { - register int ack, changed; + int ack, changed; /* * Client has sent along a mode mask. If it agrees with * what we are currently doing, ignore it; if not, it could * be viewed as a request to change. Note that the server * will change to the modes in an ack if it is different from * what we currently have, but we will not ack the ack. */ useeditmode &= MODE_MASK; ack = (useeditmode & MODE_ACK); useeditmode &= ~MODE_ACK; if ((changed = (useeditmode ^ editmode))) { /* * This check is for a timing problem. If the * state of the tty has changed (due to the user * application) we need to process that info * before we write in the state contained in the * ack!!! This gets out the new MODE request, * and when the ack to that command comes back * we'll set it and be in the right mode. */ if (ack) localstat(); if (changed & MODE_EDIT) tty_setedit(useeditmode & MODE_EDIT); if (changed & MODE_TRAPSIG) tty_setsig(useeditmode & MODE_TRAPSIG); if (changed & MODE_SOFT_TAB) tty_setsofttab(useeditmode & MODE_SOFT_TAB); if (changed & MODE_LIT_ECHO) tty_setlitecho(useeditmode & MODE_LIT_ECHO); set_termbuf(); if (!ack) { output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode|MODE_ACK, IAC, SE); } editmode = useeditmode; } break; } /* end of case LM_MODE */ #endif /* LINEMODE */ case TELOPT_NAWS: #ifdef TIOCSWINSZ { struct winsize ws; def_col = parm1; def_row = parm2; #ifdef LINEMODE /* * Defer changing window size until after terminal is * initialized. */ if (terminit() == 0) return; #endif /* LINEMODE */ /* * Change window size as requested by client. */ ws.ws_col = parm1; ws.ws_row = parm2; (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); } #endif /* TIOCSWINSZ */ break; case TELOPT_TSPEED: { def_tspeed = parm1; def_rspeed = parm2; #ifdef LINEMODE /* * Defer changing the terminal speed. */ if (terminit() == 0) return; #endif /* LINEMODE */ /* * Change terminal speed as requested by client. * We set the receive speed first, so that if we can't * store separate receive and transmit speeds, the transmit * speed will take precedence. */ tty_rspeed(parm2); tty_tspeed(parm1); set_termbuf(); break; } /* end of case TELOPT_TSPEED */ default: /* What? */ break; } /* end of switch */ netflush(); } /* end of clientstat */ #ifdef LINEMODE /* * defer_terminit * * Some things should not be done until after the login process has started * and all the pty modes are set to what they are supposed to be. This * function is called when the pty state has been processed for the first time. * It calls other functions that do things that were deferred in each module. */ - void -defer_terminit() +void +defer_terminit(void) { /* * local stuff that got deferred. */ if (def_tspeed != -1) { clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed); def_tspeed = def_rspeed = 0; } #ifdef TIOCSWINSZ if (def_col || def_row) { struct winsize ws; memset((char *)&ws, 0, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); } #endif /* * The only other module that currently defers anything. */ deferslc(); } /* end of defer_terminit */ /* * terminit * * Returns true if the pty state has been processed yet. */ - int -terminit() +int +terminit(void) { return(_terminit); } /* end of terminit */ #endif /* LINEMODE */ Index: head/crypto/telnet/telnetd/utility.c =================================================================== --- head/crypto/telnet/telnetd/utility.c (revision 87138) +++ head/crypto/telnet/telnetd/utility.c (revision 87139) @@ -1,1107 +1,1081 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static const char sccsid[] = "@(#)utility.c 8.4 (Berkeley) 5/30/95"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #ifdef __FreeBSD__ #include #include #endif #include #define PRINTOPTIONS #include "telnetd.h" -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION #include #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION #include #endif /* * utility functions performing io related tasks */ /* * ttloop * * A small subroutine to flush the network output buffer, get some data * from the network, and pass it through the telnet state machine. We * also flush the pty input buffer (by dropping its data) if it becomes * too full. */ void ttloop() { DIAG(TD_REPORT, output_data("td: ttloop\r\n")); if (nfrontp - nbackp > 0) { netflush(); } ncc = read(net, netibuf, sizeof netibuf); if (ncc < 0) { syslog(LOG_INFO, "ttloop: read: %m"); exit(1); } else if (ncc == 0) { syslog(LOG_INFO, "ttloop: peer died: %m"); exit(1); } DIAG(TD_REPORT, output_data("td: ttloop read %d chars\r\n", ncc)); netip = netibuf; telrcv(); /* state machine */ if (ncc > 0) { pfrontp = pbackp = ptyobuf; telrcv(); } } /* end of ttloop */ /* * Check a descriptor to see if out of band data exists on it. */ - int -stilloob(s) - int s; /* socket number */ +int +stilloob(int s) { - static struct timeval timeout = { 0 }; + static struct timeval timeout = { 0, 0 }; fd_set excepts; int value; do { FD_ZERO(&excepts); FD_SET(s, &excepts); memset((char *)&timeout, 0, sizeof timeout); value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); } while ((value == -1) && (errno == EINTR)); if (value < 0) { fatalperror(pty, "select"); } if (FD_ISSET(s, &excepts)) { return 1; } else { return 0; } } - void -ptyflush() +void +ptyflush(void) { int n; if ((n = pfrontp - pbackp) > 0) { DIAG(TD_REPORT | TD_PTYDATA, output_data("td: ptyflush %d chars\r\n", n)); DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); n = write(pty, pbackp, n); } if (n < 0) { if (errno == EWOULDBLOCK || errno == EINTR) return; cleanup(0); } pbackp += n; if (pbackp == pfrontp) pbackp = pfrontp = ptyobuf; } /* * nextitem() * * Return the address of the next "item" in the TELNET data * stream. This will be the address of the next character if * the current address is a user data character, or it will * be the address of the character following the TELNET command * if the current address is a TELNET IAC ("I Am a Command") * character. */ - char * -nextitem(current) - char *current; +static char * +nextitem(char *current) { if ((*current&0xff) != IAC) { return current+1; } switch (*(current+1)&0xff) { case DO: case DONT: case WILL: case WONT: return current+3; case SB: /* loop forever looking for the SE */ { - register char *look = current+2; + char *look = current+2; for (;;) { if ((*look++&0xff) == IAC) { if ((*look++&0xff) == SE) { return look; } } } } default: return current+2; } } /* end of nextitem */ - /* * netclear() * * We are about to do a TELNET SYNCH operation. Clear * the path to the network. * * Things are a bit tricky since we may have sent the first * byte or so of a previous TELNET command into the network. * So, we have to scan the network buffer from the beginning * until we are up to where we want to be. * * A side effect of what we do, just to keep things * simple, is to clear the urgent data pointer. The principal * caller should be setting the urgent data pointer AFTER calling * us in any case. */ - void -netclear() +void +netclear(void) { - register char *thisitem, *next; + char *thisitem, *next; char *good; #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) #ifdef ENCRYPTION thisitem = nclearto > netobuf ? nclearto : netobuf; #else /* ENCRYPTION */ thisitem = netobuf; #endif /* ENCRYPTION */ while ((next = nextitem(thisitem)) <= nbackp) { thisitem = next; } /* Now, thisitem is first before/at boundary. */ #ifdef ENCRYPTION good = nclearto > netobuf ? nclearto : netobuf; #else /* ENCRYPTION */ good = netobuf; /* where the good bytes go */ #endif /* ENCRYPTION */ while (nfrontp > thisitem) { if (wewant(thisitem)) { int length; next = thisitem; do { next = nextitem(next); } while (wewant(next) && (nfrontp > next)); length = next-thisitem; memmove(good, thisitem, length); good += length; thisitem = next; } else { thisitem = nextitem(thisitem); } } nbackp = netobuf; nfrontp = good; /* next byte to be sent */ neturg = 0; } /* end of netclear */ /* * netflush * Send as much data as possible to the network, * handling requests for urgent data. */ - void -netflush() +void +netflush(void) { int n; extern int not42; while ((n = nfrontp - nbackp) > 0) { #if 0 /* XXX This causes output_data() to recurse and die */ DIAG(TD_REPORT, { n += output_data("td: netflush %d chars\r\n", n); }); #endif #ifdef ENCRYPTION if (encrypt_output) { char *s = nclearto ? nclearto : nbackp; if (nfrontp - s > 0) { (*encrypt_output)((unsigned char *)s, nfrontp-s); nclearto = nfrontp; } } #endif /* ENCRYPTION */ /* * if no urgent data, or if the other side appears to be an * old 4.2 client (and thus unable to survive TCP urgent data), * write the entire buffer in non-OOB mode. */ if ((neturg == 0) || (not42 == 0)) { n = write(net, nbackp, n); /* normal write */ } else { n = neturg - nbackp; /* * In 4.2 (and 4.3) systems, there is some question about * what byte in a sendOOB operation is the "OOB" data. * To make ourselves compatible, we only send ONE byte * out of band, the one WE THINK should be OOB (though * we really have more the TCP philosophy of urgent data * rather than the Unix philosophy of OOB data). */ if (n > 1) { n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ } else { n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ } } if (n == -1) { if (errno == EWOULDBLOCK || errno == EINTR) continue; cleanup(0); /* NOTREACHED */ } nbackp += n; #ifdef ENCRYPTION if (nbackp > nclearto) nclearto = 0; #endif /* ENCRYPTION */ if (nbackp >= neturg) { neturg = 0; } if (nbackp == nfrontp) { nbackp = nfrontp = netobuf; #ifdef ENCRYPTION nclearto = 0; #endif /* ENCRYPTION */ } } return; } /* end of netflush */ /* * miscellaneous functions doing a variety of little jobs follow ... */ - void -fatal(f, msg) - int f; - char *msg; +void +fatal(int f, const char *msg) { char buf[BUFSIZ]; (void) snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg); #ifdef ENCRYPTION if (encrypt_output) { /* * Better turn off encryption first.... * Hope it flushes... */ encrypt_send_end(); netflush(); } #endif /* ENCRYPTION */ (void) write(f, buf, (int)strlen(buf)); sleep(1); /*XXX*/ exit(1); } - void -fatalperror(f, msg) - int f; - char *msg; +void +fatalperror(int f, const char *msg) { - char buf[BUFSIZ], *strerror(); + char buf[BUFSIZ]; (void) snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno)); fatal(f, buf); } char editedhost[32]; - void -edithost(pat, host) - register char *pat; - register char *host; +void +edithost(char *pat, char *host) { - register char *res = editedhost; + char *res = editedhost; if (!pat) - pat = ""; + pat = strdup(""); while (*pat) { switch (*pat) { case '#': if (*host) host++; break; case '@': if (*host) *res++ = *host++; break; default: *res++ = *pat; break; } if (res == &editedhost[sizeof editedhost - 1]) { *res = '\0'; return; } pat++; } if (*host) (void) strncpy(res, host, sizeof editedhost - (res - editedhost) -1); else *res = '\0'; editedhost[sizeof editedhost - 1] = '\0'; } static char *putlocation; - void -putstr(s) - register char *s; +static void +putstr(const char *s) { while (*s) putchr(*s++); } - void -putchr(cc) - int cc; +void +putchr(int cc) { *putlocation++ = cc; } #ifdef __FreeBSD__ static char fmtstr[] = { "%+" }; #else -/* - * This is split on two lines so that SCCS will not see the M - * between two % signs and expand it... - */ -static char fmtstr[] = { "%l:%M\ -%P on %A, %d %B %Y" }; +static char fmtstr[] = { "%l:%M%P on %A, %d %B %Y" }; #endif - void -putf(cp, where) - register char *cp; - char *where; +void +putf(char *cp, char *where) { char *slash; time_t t; char db[100]; #ifdef __FreeBSD__ static struct utsname kerninfo; if (!*kerninfo.sysname) uname(&kerninfo); #endif putlocation = where; while (*cp) { if (*cp =='\n') { putstr("\r\n"); cp++; continue; } else if (*cp != '%') { putchr(*cp++); continue; } switch (*++cp) { case 't': #ifdef STREAMSPTY /* names are like /dev/pts/2 -- we want pts/2 */ slash = strchr(line+1, '/'); #else slash = strrchr(line, '/'); #endif if (slash == (char *) 0) putstr(line); else putstr(&slash[1]); break; case 'h': putstr(editedhost); break; case 'd': #ifdef __FreeBSD__ setlocale(LC_TIME, ""); #endif (void)time(&t); (void)strftime(db, sizeof(db), fmtstr, localtime(&t)); putstr(db); break; #ifdef __FreeBSD__ case 's': putstr(kerninfo.sysname); break; case 'm': putstr(kerninfo.machine); break; case 'r': putstr(kerninfo.release); break; case 'v': putstr(kerninfo.version); break; #endif case '%': putchr('%'); break; } cp++; } } #ifdef DIAGNOSTICS /* * Print telnet options and commands in plain text, if possible. */ - void -printoption(fmt, option) - register char *fmt; - register int option; +void +printoption(const char *fmt, int option) { if (TELOPT_OK(option)) output_data("%s %s\r\n", fmt, TELOPT(option)); else if (TELCMD_OK(option)) output_data("%s %s\r\n", fmt, TELCMD(option)); else output_data("%s %d\r\n", fmt, option); return; } - void -printsub(direction, pointer, length) - char direction; /* '<' or '>' */ - unsigned char *pointer; /* where suboption data sits */ - int length; /* length of suboption data */ +void +printsub(char direction, unsigned char *pointer, int length) { - register int i = 0; + int i = 0; if (!(diagnostic & TD_OPTIONS)) return; if (direction) { output_data("td: %s suboption ", direction == '<' ? "recv" : "send"); if (length >= 3) { - register int j; + int j; i = pointer[length-2]; j = pointer[length-1]; if (i != IAC || j != SE) { output_data("(terminated by "); if (TELOPT_OK(i)) output_data("%s ", TELOPT(i)); else if (TELCMD_OK(i)) output_data("%s ", TELCMD(i)); else output_data("%d ", i); if (TELOPT_OK(j)) output_data("%s", TELOPT(j)); else if (TELCMD_OK(j)) output_data("%s", TELCMD(j)); else output_data("%d", j); output_data(", not IAC SE!) "); } } length -= 2; } if (length < 1) { output_data("(Empty suboption??\?)"); return; } switch (pointer[0]) { case TELOPT_TTYPE: output_data("TERMINAL-TYPE "); switch (pointer[1]) { case TELQUAL_IS: output_data("IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: output_data("SEND"); break; default: output_data( "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_TSPEED: output_data("TERMINAL-SPEED"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_IS: output_data(" IS %.*s", length-2, (char *)pointer+2); break; default: if (pointer[1] == 1) output_data(" SEND"); else output_data(" %d (unknown)", pointer[1]); for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; } break; case TELOPT_LFLOW: output_data("TOGGLE-FLOW-CONTROL"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case LFLOW_OFF: output_data(" OFF"); break; case LFLOW_ON: output_data(" ON"); break; case LFLOW_RESTART_ANY: output_data(" RESTART-ANY"); break; case LFLOW_RESTART_XON: output_data(" RESTART-XON"); break; default: output_data(" %d (unknown)", pointer[1]); } for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case TELOPT_NAWS: output_data("NAWS"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } if (length == 2) { output_data(" ?%d?", pointer[1]); break; } output_data(" %d %d (%d)", pointer[1], pointer[2], (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); if (length == 4) { output_data(" ?%d?", pointer[3]); break; } output_data(" %d %d (%d)", pointer[3], pointer[4], (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); for (i = 5; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case TELOPT_LINEMODE: output_data("LINEMODE "); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case WILL: output_data("WILL "); goto common; case WONT: output_data("WONT "); goto common; case DO: output_data("DO "); goto common; case DONT: output_data("DONT "); common: if (length < 3) { output_data("(no option??\?)"); break; } switch (pointer[2]) { case LM_FORWARDMASK: output_data("Forward Mask"); for (i = 3; i < length; i++) { output_data(" %x", pointer[i]); } break; default: output_data("%d (unknown)", pointer[2]); for (i = 3; i < length; i++) { output_data(" %d", pointer[i]); } break; } break; case LM_SLC: output_data("SLC"); for (i = 2; i < length - 2; i += 3) { if (SLC_NAME_OK(pointer[i+SLC_FUNC])) output_data(" %s", SLC_NAME(pointer[i+SLC_FUNC])); else output_data(" %d", pointer[i+SLC_FUNC]); switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { case SLC_NOSUPPORT: output_data(" NOSUPPORT"); break; case SLC_CANTCHANGE: output_data(" CANTCHANGE"); break; case SLC_VARIABLE: output_data(" VARIABLE"); break; case SLC_DEFAULT: output_data(" DEFAULT"); break; } output_data("%s%s%s", pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| SLC_FLUSHOUT| SLC_LEVELBITS)) { output_data("(0x%x)", pointer[i+SLC_FLAGS]); } output_data(" %d;", pointer[i+SLC_VALUE]); if ((pointer[i+SLC_VALUE] == IAC) && (pointer[i+SLC_VALUE+1] == IAC)) i++; } for (; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case LM_MODE: output_data("MODE "); if (length < 3) { output_data("(no mode??\?)"); break; } { char tbuf[32]; sprintf(tbuf, "%s%s%s%s%s", pointer[2]&MODE_EDIT ? "|EDIT" : "", pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", pointer[2]&MODE_ACK ? "|ACK" : ""); output_data("%s", tbuf[1] ? &tbuf[1] : "0"); } if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { output_data(" (0x%x)", pointer[2]); } for (i = 3; i < length; i++) { output_data(" ?0x%x?", pointer[i]); } break; default: output_data("%d (unknown)", pointer[1]); for (i = 2; i < length; i++) { output_data(" %d", pointer[i]); } } break; case TELOPT_STATUS: { - register char *cp; - register int j, k; + const char *cp; + int j, k; output_data("STATUS"); switch (pointer[1]) { default: if (pointer[1] == TELQUAL_SEND) output_data(" SEND"); else output_data(" %d (unknown)", pointer[1]); for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; case TELQUAL_IS: output_data(" IS\r\n"); for (i = 2; i < length; i++) { switch(pointer[i]) { case DO: cp = "DO"; goto common2; case DONT: cp = "DONT"; goto common2; case WILL: cp = "WILL"; goto common2; case WONT: cp = "WONT"; goto common2; common2: i++; if (TELOPT_OK(pointer[i])) output_data(" %s %s", cp, TELOPT(pointer[i])); else output_data(" %s %d", cp, pointer[i]); output_data("\r\n"); break; case SB: output_data(" SB "); i++; j = k = i; while (j < length) { if (pointer[j] == SE) { if (j+1 == length) break; if (pointer[j+1] == SE) j++; else break; } pointer[k++] = pointer[j++]; } printsub(0, &pointer[i], k - i); if (i < length) { output_data(" SE"); i = j; } else i = j - 1; output_data("\r\n"); break; default: output_data(" %d", pointer[i]); break; } } break; } break; } case TELOPT_XDISPLOC: output_data("X-DISPLAY-LOCATION "); switch (pointer[1]) { case TELQUAL_IS: output_data("IS \"%.*s\"", length-2, (char *)pointer+2); break; case TELQUAL_SEND: output_data("SEND"); break; default: output_data("- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_NEW_ENVIRON: output_data("NEW-ENVIRON "); goto env_common1; case TELOPT_OLD_ENVIRON: output_data("OLD-ENVIRON"); env_common1: switch (pointer[1]) { case TELQUAL_IS: output_data("IS "); goto env_common; case TELQUAL_SEND: output_data("SEND "); goto env_common; case TELQUAL_INFO: output_data("INFO "); env_common: { - register int noquote = 2; + int noquote = 2; for (i = 2; i < length; i++ ) { switch (pointer[i]) { case NEW_ENV_VAR: output_data("\" VAR " + noquote); noquote = 2; break; case NEW_ENV_VALUE: output_data("\" VALUE " + noquote); noquote = 2; break; case ENV_ESC: output_data("\" ESC " + noquote); noquote = 2; break; case ENV_USERVAR: output_data("\" USERVAR " + noquote); noquote = 2; break; default: if (isprint(pointer[i]) && pointer[i] != '"') { if (noquote) { output_data("\""); noquote = 0; } output_data("%c", pointer[i]); } else { output_data("\" %03o " + noquote, pointer[i]); noquote = 2; } break; } } if (!noquote) output_data("\""); break; } } break; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: output_data("AUTHENTICATION"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_REPLY: case TELQUAL_IS: output_data(" %s ", (pointer[1] == TELQUAL_IS) ? "IS" : "REPLY"); if (AUTHTYPE_NAME_OK(pointer[2])) output_data("%s ", AUTHTYPE_NAME(pointer[2])); else output_data("%d ", pointer[2]); if (length < 3) { output_data("(partial suboption??\?)"); break; } output_data("%s|%s", ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); { char buf[512]; auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); output_data("%s", buf); } break; case TELQUAL_SEND: i = 2; output_data(" SEND "); while (i < length) { if (AUTHTYPE_NAME_OK(pointer[i])) output_data("%s ", AUTHTYPE_NAME(pointer[i])); else output_data("%d ", pointer[i]); if (++i >= length) { output_data("(partial suboption??\?)"); break; } output_data("%s|%s ", ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); ++i; } break; case TELQUAL_NAME: output_data(" NAME \"%.*s\"", length - 2, pointer + 2); break; default: for (i = 2; i < length; i++) { output_data(" ?%d?", pointer[i]); } break; } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: output_data("ENCRYPT"); if (length < 2) { output_data(" (empty suboption??\?)"); break; } switch (pointer[1]) { case ENCRYPT_START: output_data(" START"); break; case ENCRYPT_END: output_data(" END"); break; case ENCRYPT_REQSTART: output_data(" REQUEST-START"); break; case ENCRYPT_REQEND: output_data(" REQUEST-END"); break; case ENCRYPT_IS: case ENCRYPT_REPLY: output_data(" %s ", (pointer[1] == ENCRYPT_IS) ? "IS" : "REPLY"); if (length < 3) { output_data(" (partial suboption??\?)"); break; } if (ENCTYPE_NAME_OK(pointer[2])) output_data("%s ", ENCTYPE_NAME(pointer[2])); else output_data(" %d (unknown)", pointer[2]); { char buf[512]; encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); output_data("%s", buf); } break; case ENCRYPT_SUPPORT: i = 2; output_data(" SUPPORT "); while (i < length) { if (ENCTYPE_NAME_OK(pointer[i])) output_data("%s ", ENCTYPE_NAME(pointer[i])); else output_data("%d ", pointer[i]); i++; } break; case ENCRYPT_ENC_KEYID: output_data(" ENC_KEYID"); goto encommon; case ENCRYPT_DEC_KEYID: output_data(" DEC_KEYID"); goto encommon; default: output_data(" %d (unknown)", pointer[1]); encommon: for (i = 2; i < length; i++) { output_data(" %d", pointer[i]); } break; } break; #endif /* ENCRYPTION */ default: if (TELOPT_OK(pointer[0])) output_data("%s (unknown)", TELOPT(pointer[0])); else output_data("%d (unknown)", pointer[i]); for (i = 1; i < length; i++) { output_data(" %d", pointer[i]); } break; } output_data("\r\n"); } /* * Dump a data buffer in hex and ascii to the output data stream. */ - void -printdata(tag, ptr, cnt) - register char *tag; - register char *ptr; - register int cnt; +void +printdata(const char *tag, char *ptr, int cnt) { - register int i; + int i; char xbuf[30]; while (cnt) { /* flush net output buffer if no room for new data) */ if ((&netobuf[BUFSIZ] - nfrontp) < 80) { netflush(); } /* add a line of output */ output_data("%s: ", tag); for (i = 0; i < 20 && cnt; i++) { output_data("%02x", *ptr); if (isprint(*ptr)) { xbuf[i] = *ptr; } else { xbuf[i] = '.'; } if (i % 2) { output_data(" "); } cnt--; ptr++; } xbuf[i] = '\0'; output_data(" %s\r\n", xbuf ); } } #endif /* DIAGNOSTICS */