Import NetBSD telnetd(8)
Change-Id: Ie1ae80e8a4945f6f4ccce8f468c1b04a8d89cf43
This commit is contained in:
parent
7348b5c52b
commit
e044bafaad
@ -1000,6 +1000,7 @@
|
||||
./usr/libexec/ld.elf_so minix-base
|
||||
./usr/libexec/makewhatis minix-base
|
||||
./usr/libexec/rshd minix-base
|
||||
./usr/libexec/telnetd minix-base
|
||||
./usr/libexec/virecover minix-base
|
||||
./usr/log minix-base
|
||||
./usr/log/messages minix-base
|
||||
|
@ -591,6 +591,7 @@
|
||||
./usr/libdata/debug/usr/libexec/lto1.debug minix-debug gcc=5,gcccmds,debug
|
||||
./usr/libdata/debug/usr/libexec/makewhatis.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/libexec/rshd.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/libexec/telnetd.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/mdec minix-debug
|
||||
./usr/libdata/debug/usr/sbin minix-debug
|
||||
./usr/libdata/debug/usr/sbin/arp.debug minix-debug debug
|
||||
|
@ -3476,6 +3476,7 @@
|
||||
./usr/man/man8/sysctl.8 minix-man
|
||||
./usr/man/man8/syslogd.8 minix-man
|
||||
./usr/man/man8/tcpd.8 minix-man obsolete
|
||||
./usr/man/man8/telnetd.8 minix-man
|
||||
./usr/man/man8/traceroute.8 minix-man
|
||||
./usr/man/man8/traceroute6.8 minix-man use_inet6
|
||||
./usr/man/man8/uds.8 minix-man obsolete
|
||||
|
@ -7,9 +7,7 @@ SUBDIR= \
|
||||
fingerd ftpd getty \
|
||||
ld.elf_so \
|
||||
rshd \
|
||||
|
||||
|
||||
|
||||
telnetd
|
||||
|
||||
.if defined(__MINIX)
|
||||
SUBDIR+= makewhatis
|
||||
|
43
libexec/telnetd/Makefile
Normal file
43
libexec/telnetd/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
# $NetBSD: Makefile,v 1.49 2012/01/09 16:36:48 christos Exp $
|
||||
# from: @(#)Makefile 8.2 (Berkeley) 12/15/93
|
||||
|
||||
WARNS?= 4 # XXX: const issues in sys_term.c
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
MAN= telnetd.8
|
||||
|
||||
PROG= telnetd
|
||||
.if defined(__MINIX)
|
||||
CPPFLAGS+=-DDIAGNOSTICS
|
||||
.else # !defined(__MINIX)
|
||||
CPPFLAGS+=-DLINEMODE -DKLUDGELINEMODE -DDIAGNOSTICS
|
||||
.endif # !defined(__MINIX)
|
||||
CPPFLAGS+=-DOLD_ENVIRON -DENV_HACK -DSECURELOGIN -DSUPPORT_UTMP -DSUPPORT_UTMPX
|
||||
SRCS= authenc.c global.c slc.c state.c sys_term.c telnetd.c \
|
||||
termstat.c utility.c
|
||||
DPADD= ${LIBTELNETDIR}/libtelnet.a ${LIBTERMINFO} ${LIBUTIL}
|
||||
LDADD+= ${LIBTELNETDIR}/libtelnet.a -lterminfo -lutil
|
||||
|
||||
CPPFLAGS+=-I${NETBSDSRCDIR}/lib
|
||||
CPPFLAGS+=-I${.CURDIR}
|
||||
|
||||
LIBTELNETDIR!= cd ${.CURDIR}/../../lib/libtelnet; ${PRINTOBJDIR}
|
||||
|
||||
.if (${USE_KERBEROS} != "no")
|
||||
CPPFLAGS+=-DKRB5 -DAUTHENTICATION -DENCRYPTION
|
||||
LDADD+= -lkrb5 -lasn1 -lcom_err -lroken
|
||||
DPADD+= ${LIBKRB5} ${LIBASN1} ${LIBCOM_ERR} ${LIBROKEN}
|
||||
.endif
|
||||
|
||||
.if (${MKCRYPTO} != "no")
|
||||
LDADD+=-ldes -lcrypto -lcrypt
|
||||
DPADD+=${LIBDES} ${LIBCRYPTO} ${LIBCRYPT}
|
||||
.endif
|
||||
|
||||
.if (${USE_PAM} != "no")
|
||||
LDADD+= -lpam ${PAM_STATIC_LDADD}
|
||||
DPADD+= ${LIBPAM} ${PAM_STATIC_DPADD}
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
85
libexec/telnetd/authenc.c
Normal file
85
libexec/telnetd/authenc.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* $NetBSD: authenc.c,v 1.12 2005/02/06 05:58:20 perry Exp $ */
|
||||
|
||||
/*-
|
||||
* 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. 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 <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)authenc.c 8.2 (Berkeley) 5/30/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: authenc.c,v 1.12 2005/02/06 05:58:20 perry Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#if defined(AUTHENTICATION) || defined(ENCRYPTION)
|
||||
#include "telnetd.h"
|
||||
#include <libtelnet/misc.h>
|
||||
|
||||
int
|
||||
telnet_net_write(unsigned char *str, int len)
|
||||
{
|
||||
if (nfrontp + len < netobuf + BUFSIZ) {
|
||||
output_datalen((const char *)str, len);
|
||||
return(len);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
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(void)
|
||||
{
|
||||
ttloop();
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *
|
||||
telnet_getenv(char *val)
|
||||
{
|
||||
return(getenv(val));
|
||||
}
|
||||
|
||||
char *
|
||||
telnet_gets(char *prompt, char *result, int length, int echo)
|
||||
{
|
||||
return((char *)0);
|
||||
}
|
||||
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
|
200
libexec/telnetd/defs.h
Normal file
200
libexec/telnetd/defs.h
Normal file
@ -0,0 +1,200 @@
|
||||
/* $NetBSD: defs.h,v 1.16 2007/02/21 21:14:07 hubertf Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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.
|
||||
*
|
||||
* from: @(#)defs.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Telnet server defines
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS)
|
||||
#define TELOPTS
|
||||
#define TELCMDS
|
||||
#define SLC_NAMES
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <arpa/telnet.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* I/O data buffers defines
|
||||
*/
|
||||
#define NETSLOP 64
|
||||
|
||||
#define NIACCUM(c) do { \
|
||||
*netip++ = c; \
|
||||
ncc++; \
|
||||
} while (0)
|
||||
|
||||
/* clock manipulations */
|
||||
#define settimer(x) (clocks.x = ++clocks.system)
|
||||
#define sequenceIs(x,y) (clocks.x < clocks.y)
|
||||
|
||||
/*
|
||||
* Linemode support states, in decreasing order of importance
|
||||
*/
|
||||
#define REAL_LINEMODE 0x04
|
||||
#define KLUDGE_OK 0x03
|
||||
#define NO_AUTOKLUDGE 0x02
|
||||
#define KLUDGE_LINEMODE 0x01
|
||||
#define NO_LINEMODE 0x00
|
||||
|
||||
/*
|
||||
* Structures of information for each special character function.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char flag; /* the flags for this function */
|
||||
cc_t val; /* the value of the special character */
|
||||
} slcent, *Slcent;
|
||||
|
||||
typedef struct {
|
||||
slcent defset; /* the default settings */
|
||||
slcent current; /* the current settings */
|
||||
cc_t *sptr; /* a pointer to the char in */
|
||||
/* system data structures */
|
||||
} slcfun, *Slcfun;
|
||||
|
||||
#ifdef DIAGNOSTICS
|
||||
/*
|
||||
* Diagnostics capabilities
|
||||
*/
|
||||
#define TD_REPORT 0x01 /* Report operations to client */
|
||||
#define TD_EXERCISE 0x02 /* Exercise client's implementation */
|
||||
#define TD_NETDATA 0x04 /* Display received data stream */
|
||||
#define TD_PTYDATA 0x08 /* Display data passed to pty */
|
||||
#define TD_OPTIONS 0x10 /* Report just telnet options */
|
||||
#endif /* DIAGNOSTICS */
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
/*
|
||||
* Tricky code here. What we want to know is if the MY_STATE_WILL
|
||||
* and MY_WANT_STATE_WILL bits have the same value. Since the two
|
||||
* bits are adjacent, a little arithmetic will show that by adding
|
||||
* in the lower bit, the upper bit will be set if the two bits were
|
||||
* different, and clear if they were the same.
|
||||
*/
|
||||
#define my_will_wont_is_changing(opt) \
|
||||
((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL)
|
||||
|
||||
#define my_do_dont_is_changing(opt) \
|
||||
((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO)
|
||||
|
||||
/*
|
||||
* Make everything symmetrical
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
#define his_will_wont_is_changing my_do_dont_is_changing
|
||||
#define his_do_dont_is_changing my_will_wont_is_changing
|
||||
|
||||
/*
|
||||
* Initialization buffer for tty device [16 characters long]
|
||||
*/
|
||||
#define NULL16STR "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
207
libexec/telnetd/ext.h
Normal file
207
libexec/telnetd/ext.h
Normal file
@ -0,0 +1,207 @@
|
||||
/* $NetBSD: ext.h,v 1.22 2012/01/10 23:39:11 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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.
|
||||
*
|
||||
* from: @(#)ext.h 8.2 (Berkeley) 12/15/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
# ifdef KLUDGELINEMODE
|
||||
extern int lmodetype; /* Client support for linemode */
|
||||
# endif /* KLUDGELINEMODE */
|
||||
#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 SECURELOGIN
|
||||
extern int require_secure_login;
|
||||
#endif
|
||||
#ifdef AUTHENTICATION
|
||||
extern int auth_level;
|
||||
#endif
|
||||
|
||||
extern slcfun slctab[NSLC + 1]; /* slc mapping table */
|
||||
extern char terminaltype[41];
|
||||
|
||||
/*
|
||||
* I/O data buffers, pointers, and counters.
|
||||
*/
|
||||
extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
|
||||
extern char netibuf[BUFSIZ], *netip;
|
||||
extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
|
||||
extern char *neturg; /* one past last bye of urgent data */
|
||||
extern int pcc, ncc;
|
||||
extern int pty, net;
|
||||
extern char *line;
|
||||
extern int SYNCHing; /* we are in TELNET SYNCH mode */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
extern void
|
||||
_termstat(void),
|
||||
add_slc(char, char, cc_t),
|
||||
check_slc(void),
|
||||
change_slc(int, int, cc_t),
|
||||
cleanup(int) __dead,
|
||||
clientstat(int, int, int),
|
||||
copy_termbuf(char *, int),
|
||||
deferslc(void),
|
||||
defer_terminit(void),
|
||||
do_opt_slc(unsigned char *, int),
|
||||
doeof(void),
|
||||
dooption(int),
|
||||
dontoption(int),
|
||||
edithost(const char *, const char *),
|
||||
fatal(int, const char *) __dead,
|
||||
fatalperror(int, const char *) __dead,
|
||||
get_slc_defaults(void),
|
||||
init_env(void),
|
||||
init_termbuf(void),
|
||||
interrupt(void),
|
||||
localstat(void),
|
||||
flowstat(void),
|
||||
netclear(void),
|
||||
netflush(void),
|
||||
#ifdef DIAGNOSTICS
|
||||
printoption(const char *, int),
|
||||
printdata(const char *, char *, int),
|
||||
#ifndef ENCRYPTION
|
||||
printsub(int, unsigned char *, int),
|
||||
#endif
|
||||
#endif
|
||||
ptyflush(void),
|
||||
putchr(int),
|
||||
recv_ayt(void),
|
||||
send_do(int, int),
|
||||
send_dont(int, int),
|
||||
send_slc(void),
|
||||
send_status(void),
|
||||
send_will(int, int),
|
||||
send_wont(int, int),
|
||||
sendbrk(void),
|
||||
sendsusp(void),
|
||||
set_termbuf(void),
|
||||
start_login(char *, int, char *) __dead,
|
||||
start_slc(int),
|
||||
startslave(char *, int, char *),
|
||||
suboption(void),
|
||||
telrcv(void),
|
||||
ttloop(void),
|
||||
tty_binaryin(int),
|
||||
tty_binaryout(int);
|
||||
|
||||
extern char *
|
||||
putf(const char *, char *);
|
||||
|
||||
extern int
|
||||
end_slc(unsigned char **),
|
||||
getnpty(void),
|
||||
getpty(int *),
|
||||
spcset(int, cc_t *, cc_t **),
|
||||
stilloob(int),
|
||||
terminit(void),
|
||||
termstat(void),
|
||||
tty_flowmode(void),
|
||||
tty_restartany(void),
|
||||
tty_isbinaryin(void),
|
||||
tty_isbinaryout(void),
|
||||
tty_iscrnl(void),
|
||||
tty_isecho(void),
|
||||
tty_isediting(void),
|
||||
tty_islitecho(void),
|
||||
tty_isnewmap(void),
|
||||
tty_israw(void),
|
||||
tty_issofttab(void),
|
||||
tty_istrapsig(void),
|
||||
tty_linemode(void);
|
||||
|
||||
extern void
|
||||
tty_rspeed(int),
|
||||
tty_setecho(int),
|
||||
tty_setedit(int),
|
||||
tty_setlinemode(int),
|
||||
tty_setlitecho(int),
|
||||
tty_setsig(int),
|
||||
tty_setsofttab(int),
|
||||
tty_tspeed(int),
|
||||
willoption(int),
|
||||
wontoption(int),
|
||||
writenet(unsigned char *, int);
|
||||
|
||||
extern int output_data(const char *, ...)
|
||||
__attribute__((__format__(__printf__, 1, 2)));
|
||||
extern int output_datalen(const char *, size_t);
|
||||
|
||||
#ifdef ENCRYPTION
|
||||
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
|
||||
# define DEFAULT_IM "\r\n\r\n4.4 BSD UNIX (%h) (%t)\r\n\r\r\n\r"
|
||||
#endif
|
||||
|
||||
#ifdef AUTHENTICATION
|
||||
#include <libtelnet/auth.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENCRYPTION
|
||||
#include <libtelnet/encrypt.h>
|
||||
#endif
|
51
libexec/telnetd/global.c
Normal file
51
libexec/telnetd/global.c
Normal file
@ -0,0 +1,51 @@
|
||||
/* $NetBSD: global.c,v 1.8 2003/08/07 09:46:51 agc Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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 <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)global.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: global.c,v 1.8 2003/08/07 09:46:51 agc Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Allocate global variables. We do this
|
||||
* by including the header file that defines
|
||||
* them all as externs, but first we define
|
||||
* the keyword "extern" to be nothing, so that
|
||||
* we will actually allocate the space.
|
||||
*/
|
||||
|
||||
#include <defs.h>
|
||||
#define extern
|
||||
#include <ext.h>
|
38
libexec/telnetd/pathnames.h
Normal file
38
libexec/telnetd/pathnames.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* $NetBSD: pathnames.h,v 1.7 2003/08/07 09:46:51 agc Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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.
|
||||
*
|
||||
* from: @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#include <paths.h>
|
||||
|
||||
#ifndef _PATH_LOGIN
|
||||
# define _PATH_LOGIN "/usr/bin/login"
|
||||
#endif
|
488
libexec/telnetd/slc.c
Normal file
488
libexec/telnetd/slc.c
Normal file
@ -0,0 +1,488 @@
|
||||
/* $NetBSD: slc.c,v 1.15 2006/11/24 19:46:58 christos Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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 <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)slc.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: slc.c,v 1.15 2006/11/24 19:46:58 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include "telnetd.h"
|
||||
|
||||
#ifdef LINEMODE
|
||||
/*
|
||||
* local varibles
|
||||
*/
|
||||
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 */
|
||||
|
||||
void default_slc(void);
|
||||
void process_slc(u_int, u_int, cc_t);
|
||||
|
||||
/*
|
||||
* send_slc
|
||||
*
|
||||
* Write out the current special characters to the client.
|
||||
*/
|
||||
void
|
||||
send_slc(void)
|
||||
{
|
||||
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(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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(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(int getit)
|
||||
{
|
||||
|
||||
slcchange = 0;
|
||||
if (getit)
|
||||
init_termbuf();
|
||||
(void)snprintf((char *)slcbuf, sizeof 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(unsigned char **bufp)
|
||||
{
|
||||
int len;
|
||||
|
||||
/*
|
||||
* If a change has occurred, 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) snprintf((char *)slcptr,
|
||||
sizeof(slcbuf) - (slcptr - slcbuf), "%c%c",
|
||||
IAC, SE);
|
||||
slcptr += 2;
|
||||
len = slcptr - slcbuf;
|
||||
writenet(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(u_int func, u_int flag, cc_t val)
|
||||
{
|
||||
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(int func, int flag, cc_t val)
|
||||
{
|
||||
int hislevel, mylevel;
|
||||
|
||||
hislevel = flag & SLC_LEVELBITS;
|
||||
mylevel = slctab[func].defset.flag & SLC_LEVELBITS;
|
||||
/*
|
||||
* If client is setting a function to NOSUPPORT
|
||||
* or DEFAULT, then we can easily and directly
|
||||
* accommodate the request.
|
||||
*/
|
||||
if (hislevel == SLC_NOSUPPORT) {
|
||||
slctab[func].current.flag = flag;
|
||||
slctab[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[func].current.flag = SLC_NOSUPPORT;
|
||||
} else {
|
||||
slctab[func].current.flag = slctab[func].defset.flag;
|
||||
}
|
||||
slctab[func].current.val = slctab[func].defset.val;
|
||||
add_slc(func, slctab[func].current.flag,
|
||||
slctab[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[func].sptr) {
|
||||
/*
|
||||
* We can change this one.
|
||||
*/
|
||||
slctab[func].current.val = val;
|
||||
*(slctab[func].sptr) = val;
|
||||
slctab[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[func].current.flag = flag;
|
||||
slctab[func].current.val = val;
|
||||
flag |= SLC_ACK;
|
||||
} else if (hislevel == SLC_CANTCHANGE &&
|
||||
mylevel == SLC_CANTCHANGE) {
|
||||
flag &= ~SLC_LEVELBITS;
|
||||
flag |= SLC_NOSUPPORT;
|
||||
slctab[func].current.flag = flag;
|
||||
} else {
|
||||
flag &= ~SLC_LEVELBITS;
|
||||
flag |= mylevel;
|
||||
slctab[func].current.flag = flag;
|
||||
if (mylevel == SLC_CANTCHANGE) {
|
||||
slctab[func].current.val =
|
||||
slctab[func].defset.val;
|
||||
val = slctab[func].current.val;
|
||||
}
|
||||
}
|
||||
add_slc(func, flag, val);
|
||||
}
|
||||
|
||||
} /* end of change_slc */
|
||||
|
||||
#if 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)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= NSLC; i++) {
|
||||
#if 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 /* VEOF == VMIN */
|
||||
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(unsigned char *ptr, int len)
|
||||
{
|
||||
unsigned char func, flag;
|
||||
cc_t val;
|
||||
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((u_int)func, (u_int)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 */
|
||||
memcpy(def_slcbuf, ptr, len);
|
||||
}
|
||||
}
|
||||
|
||||
} /* end of do_opt_slc */
|
||||
|
||||
/*
|
||||
* deferslc
|
||||
*
|
||||
* Do slc stuff that was deferred.
|
||||
*/
|
||||
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 */
|
1680
libexec/telnetd/state.c
Normal file
1680
libexec/telnetd/state.c
Normal file
File diff suppressed because it is too large
Load Diff
798
libexec/telnetd/sys_term.c
Normal file
798
libexec/telnetd/sys_term.c
Normal file
@ -0,0 +1,798 @@
|
||||
/* $NetBSD: sys_term.c,v 1.47 2013/06/28 15:48:02 christos Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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 <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: sys_term.c,v 1.47 2013/06/28 15:48:02 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include "telnetd.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
#include <util.h>
|
||||
#include <vis.h>
|
||||
|
||||
#ifdef SUPPORT_UTMP
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMPX
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
|
||||
#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
|
||||
#define SCMPN(a, b) strncmp(a, b, sizeof(a))
|
||||
|
||||
struct termios termbuf, termbuf2; /* pty control structure */
|
||||
|
||||
void getptyslave(void);
|
||||
int cleanopen(char *);
|
||||
char **addarg(char **, const char *);
|
||||
void scrub_env(void);
|
||||
int getent(char *, char *);
|
||||
char *getstr(const char *, char **);
|
||||
#ifdef KRB5
|
||||
extern void kerberos5_cleanup(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
(void) tcgetattr(pty, &termbuf);
|
||||
termbuf2 = termbuf;
|
||||
}
|
||||
|
||||
#if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
|
||||
void
|
||||
copy_termbuf(char *cp, int len)
|
||||
{
|
||||
if ((size_t)len > sizeof(termbuf))
|
||||
len = sizeof(termbuf);
|
||||
memmove((char *)&termbuf, cp, len);
|
||||
termbuf2 = termbuf;
|
||||
}
|
||||
#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
|
||||
|
||||
void
|
||||
set_termbuf(void)
|
||||
{
|
||||
/*
|
||||
* Only make the necessary changes.
|
||||
*/
|
||||
if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
|
||||
(void) tcsetattr(pty, TCSANOW, &termbuf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
spcset(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);
|
||||
|
||||
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:
|
||||
setval(VSTART, SLC_VARIABLE);
|
||||
case SLC_XOFF:
|
||||
setval(VSTOP, SLC_VARIABLE);
|
||||
case SLC_EW:
|
||||
setval(VWERASE, SLC_VARIABLE);
|
||||
case SLC_RP:
|
||||
setval(VREPRINT, SLC_VARIABLE);
|
||||
case SLC_LNEXT:
|
||||
setval(VLNEXT, SLC_VARIABLE);
|
||||
case SLC_AO:
|
||||
setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
|
||||
case SLC_SUSP:
|
||||
setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
|
||||
case SLC_FORW1:
|
||||
setval(VEOL, SLC_VARIABLE);
|
||||
case SLC_FORW2:
|
||||
setval(VEOL2, SLC_VARIABLE);
|
||||
case SLC_AYT:
|
||||
setval(VSTATUS, SLC_VARIABLE);
|
||||
|
||||
case SLC_BRK:
|
||||
case SLC_SYNCH:
|
||||
case SLC_EOR:
|
||||
defval(0);
|
||||
|
||||
default:
|
||||
*valp = 0;
|
||||
*valpp = 0;
|
||||
return(SLC_NOSUPPORT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __GNUC__
|
||||
char *line = NULL16STR;
|
||||
#else
|
||||
static char Xline[] = NULL16STR;
|
||||
char *line = Xline;
|
||||
#endif
|
||||
|
||||
|
||||
static int ptyslavefd; /* for cleanopen() */
|
||||
|
||||
int
|
||||
getpty(int *ptynum)
|
||||
{
|
||||
int ptyfd;
|
||||
|
||||
ptyfd = openpty(ptynum, &ptyslavefd, line, NULL, NULL);
|
||||
if (ptyfd == 0)
|
||||
return *ptynum;
|
||||
ptyslavefd = -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
tty_linemode(void)
|
||||
{
|
||||
return(termbuf.c_lflag & EXTPROC);
|
||||
}
|
||||
|
||||
void
|
||||
tty_setlinemode(int on)
|
||||
{
|
||||
set_termbuf();
|
||||
(void) ioctl(pty, TIOCEXT, (char *)&on);
|
||||
init_termbuf();
|
||||
}
|
||||
#endif /* LINEMODE */
|
||||
|
||||
int
|
||||
tty_isecho(void)
|
||||
{
|
||||
return (termbuf.c_lflag & ECHO);
|
||||
}
|
||||
|
||||
int
|
||||
tty_flowmode(void)
|
||||
{
|
||||
return((termbuf.c_iflag & IXON) ? 1 : 0);
|
||||
}
|
||||
|
||||
int
|
||||
tty_restartany(void)
|
||||
{
|
||||
return((termbuf.c_iflag & IXANY) ? 1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
tty_setecho(int on)
|
||||
{
|
||||
if (on)
|
||||
termbuf.c_lflag |= ECHO;
|
||||
else
|
||||
termbuf.c_lflag &= ~ECHO;
|
||||
}
|
||||
|
||||
int
|
||||
tty_israw(void)
|
||||
{
|
||||
return(!(termbuf.c_lflag & ICANON));
|
||||
}
|
||||
|
||||
void
|
||||
tty_binaryin(int on)
|
||||
{
|
||||
if (on) {
|
||||
termbuf.c_iflag &= ~ISTRIP;
|
||||
} else {
|
||||
termbuf.c_iflag |= ISTRIP;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tty_binaryout(int on)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tty_isbinaryin(void)
|
||||
{
|
||||
return(!(termbuf.c_iflag & ISTRIP));
|
||||
}
|
||||
|
||||
int
|
||||
tty_isbinaryout(void)
|
||||
{
|
||||
return(!(termbuf.c_oflag&OPOST));
|
||||
}
|
||||
|
||||
#ifdef LINEMODE
|
||||
int
|
||||
tty_isediting(void)
|
||||
{
|
||||
return(termbuf.c_lflag & ICANON);
|
||||
}
|
||||
|
||||
int
|
||||
tty_istrapsig(void)
|
||||
{
|
||||
return(termbuf.c_lflag & ISIG);
|
||||
}
|
||||
|
||||
void
|
||||
tty_setedit(int on)
|
||||
{
|
||||
if (on)
|
||||
termbuf.c_lflag |= ICANON;
|
||||
else
|
||||
termbuf.c_lflag &= ~ICANON;
|
||||
}
|
||||
|
||||
void
|
||||
tty_setsig(int on)
|
||||
{
|
||||
if (on)
|
||||
termbuf.c_lflag |= ISIG;
|
||||
else
|
||||
termbuf.c_lflag &= ~ISIG;
|
||||
}
|
||||
#endif /* LINEMODE */
|
||||
|
||||
int
|
||||
tty_issofttab(void)
|
||||
{
|
||||
# ifdef OXTABS
|
||||
return (termbuf.c_oflag & OXTABS);
|
||||
# endif
|
||||
# ifdef TABDLY
|
||||
return ((termbuf.c_oflag & TABDLY) == TAB3);
|
||||
# endif
|
||||
}
|
||||
|
||||
void
|
||||
tty_setsofttab(int on)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tty_islitecho(void)
|
||||
{
|
||||
# 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
|
||||
}
|
||||
|
||||
void
|
||||
tty_setlitecho(int on)
|
||||
{
|
||||
# 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
|
||||
}
|
||||
|
||||
int
|
||||
tty_iscrnl(void)
|
||||
{
|
||||
return (termbuf.c_iflag & ICRNL);
|
||||
}
|
||||
|
||||
void
|
||||
tty_tspeed(int val)
|
||||
{
|
||||
cfsetospeed(&termbuf, val);
|
||||
}
|
||||
|
||||
void
|
||||
tty_rspeed(int val)
|
||||
{
|
||||
cfsetispeed(&termbuf, val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* getptyslave()
|
||||
*
|
||||
* Open the slave side of the pty, and do any initialization
|
||||
* that is necessary. The return value is a file descriptor
|
||||
* for the slave side.
|
||||
*/
|
||||
extern int def_tspeed, def_rspeed;
|
||||
extern int def_row, def_col;
|
||||
|
||||
void
|
||||
getptyslave(void)
|
||||
{
|
||||
int t = -1;
|
||||
|
||||
#ifdef LINEMODE
|
||||
int waslm;
|
||||
#endif
|
||||
struct winsize ws;
|
||||
/*
|
||||
* 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
|
||||
* so that we can re-set them if we need to.
|
||||
*/
|
||||
#ifdef LINEMODE
|
||||
waslm = tty_linemode();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure that we don't have a controlling tty, and
|
||||
* that we are the session (process group) leader.
|
||||
*/
|
||||
t = open(_PATH_TTY, O_RDWR);
|
||||
if (t >= 0) {
|
||||
(void) ioctl(t, TIOCNOTTY, (char *)0);
|
||||
(void) close(t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
t = cleanopen(line);
|
||||
if (t < 0)
|
||||
fatalperror(net, line);
|
||||
|
||||
|
||||
/*
|
||||
* set up the tty modes as we like them to be.
|
||||
*/
|
||||
init_termbuf();
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Settings for sgtty based systems
|
||||
*/
|
||||
|
||||
/*
|
||||
* Settings for all other termios/termio based
|
||||
* systems, other than 4.4BSD. In 4.4BSD the
|
||||
* kernel does the initial terminal setup.
|
||||
*/
|
||||
tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
|
||||
tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
|
||||
#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 (pty > 2) {
|
||||
(void) close(pty);
|
||||
pty = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the specified slave side of the pty,
|
||||
* making sure that we have a clean tty.
|
||||
*/
|
||||
int
|
||||
cleanopen(char *ttyline)
|
||||
{
|
||||
return ptyslavefd;
|
||||
}
|
||||
|
||||
/*
|
||||
* startslave(host)
|
||||
*
|
||||
* Given a hostname, do whatever
|
||||
* is necessary to startup the login process on the slave side of the pty.
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
startslave(char *host, int autologin, char *autoname)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef AUTHENTICATION
|
||||
if (!autoname || !autoname[0])
|
||||
autologin = 0;
|
||||
|
||||
if (autologin < auth_level) {
|
||||
fatal(net, "Authorization failed");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if ((i = fork()) < 0)
|
||||
fatalperror(net, "fork");
|
||||
if (i) {
|
||||
} else {
|
||||
getptyslave();
|
||||
start_login(host, autologin, autoname);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
char *envinit[3];
|
||||
|
||||
void
|
||||
init_env(void)
|
||||
{
|
||||
char **envp;
|
||||
|
||||
envp = envinit;
|
||||
if ((*envp = getenv("TZ")))
|
||||
*envp++ -= 3;
|
||||
*envp = 0;
|
||||
environ = envinit;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* start_login(host)
|
||||
*
|
||||
* Assuming that we are now running as a child processes, this
|
||||
* function will turn us into the login process.
|
||||
*/
|
||||
extern char *gettyname;
|
||||
|
||||
void
|
||||
start_login(char *host, int autologin, char *name)
|
||||
{
|
||||
char **argv;
|
||||
#define TABBUFSIZ 512
|
||||
char defent[TABBUFSIZ];
|
||||
char defstrs[TABBUFSIZ];
|
||||
#undef TABBUFSIZ
|
||||
const char *loginprog = NULL;
|
||||
extern struct sockaddr_storage from;
|
||||
char buf[sizeof(from) * 4 + 1];
|
||||
|
||||
scrub_env();
|
||||
|
||||
/*
|
||||
* -a : pass on the address of the host.
|
||||
* -h : pass on name of host.
|
||||
* WARNING: -h and -a are 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");
|
||||
|
||||
argv = addarg(argv, "-a");
|
||||
(void)strvisx(buf, (const char *)(const void *)&from, sizeof(from),
|
||||
VIS_WHITE);
|
||||
argv = addarg(argv, buf);
|
||||
|
||||
argv = addarg(argv, "-h");
|
||||
argv = addarg(argv, host);
|
||||
|
||||
argv = addarg(argv, "-p");
|
||||
#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 SECURELOGIN
|
||||
/*
|
||||
* don't worry about the -f that might get sent.
|
||||
* A -s is supposed to override it anyhow.
|
||||
*/
|
||||
if (require_secure_login)
|
||||
argv = addarg(argv, "-s");
|
||||
#endif
|
||||
#ifdef AUTHENTICATION
|
||||
if (auth_level >= 0 && autologin == AUTH_VALID) {
|
||||
argv = addarg(argv, "-f");
|
||||
argv = addarg(argv, "--");
|
||||
argv = addarg(argv, name);
|
||||
} else
|
||||
#endif
|
||||
if (getenv("USER")) {
|
||||
argv = addarg(argv, "--");
|
||||
argv = addarg(argv, getenv("USER"));
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
if (getent(defent, gettyname) == 1) {
|
||||
char *cp = defstrs;
|
||||
|
||||
loginprog = getstr("lo", &cp);
|
||||
}
|
||||
if (loginprog == NULL)
|
||||
loginprog = _PATH_LOGIN;
|
||||
closelog();
|
||||
/*
|
||||
* This sleep(1) is in here so that telnetd can
|
||||
* finish up with the tty. There's a race condition
|
||||
* the login banner message gets lost...
|
||||
*/
|
||||
sleep(1);
|
||||
execv(loginprog, argv);
|
||||
|
||||
syslog(LOG_ERR, "%s: %m", loginprog);
|
||||
fatalperror(net, loginprog);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
char **
|
||||
addarg(char **argv, const char *val)
|
||||
{
|
||||
char **cpp;
|
||||
char **nargv;
|
||||
|
||||
if (argv == NULL) {
|
||||
/*
|
||||
* 10 entries, a leading length, and a null
|
||||
*/
|
||||
argv = malloc(sizeof(*argv) * 12);
|
||||
if (argv == NULL)
|
||||
return(NULL);
|
||||
*argv++ = (char *)10;
|
||||
*argv = (char *)0;
|
||||
}
|
||||
for (cpp = argv; *cpp; cpp++)
|
||||
;
|
||||
if (cpp == &argv[(long)argv[-1]]) {
|
||||
--argv;
|
||||
nargv = realloc(argv, sizeof(*argv) * ((long)(*argv) + 10 + 2));
|
||||
if (nargv == NULL) {
|
||||
fatal(net, "not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
argv = nargv;
|
||||
*argv = (char *)((long)(*argv) + 10);
|
||||
argv++;
|
||||
cpp = &argv[(long)argv[-1] - 10];
|
||||
}
|
||||
*cpp++ = __UNCONST(val);
|
||||
*cpp = 0;
|
||||
return(argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* scrub_env()
|
||||
*
|
||||
* We only accept the environment variables listed below.
|
||||
*/
|
||||
|
||||
void
|
||||
scrub_env(void)
|
||||
{
|
||||
static const char *reject[] = {
|
||||
"TERMCAP=/",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *acceptstr[] = {
|
||||
"XAUTH=", "XAUTHORITY=", "DISPLAY=",
|
||||
"TERM=",
|
||||
"EDITOR=",
|
||||
"PAGER=",
|
||||
"LOGNAME=",
|
||||
"POSIXLY_CORRECT=",
|
||||
"TERMCAP=",
|
||||
"PRINTER=",
|
||||
NULL
|
||||
};
|
||||
|
||||
char **cpp, **cpp2;
|
||||
const char **p;
|
||||
|
||||
for (cpp2 = cpp = environ; *cpp; cpp++) {
|
||||
int reject_it = 0;
|
||||
|
||||
for(p = reject; *p; p++)
|
||||
if(strncmp(*cpp, *p, strlen(*p)) == 0) {
|
||||
reject_it = 1;
|
||||
break;
|
||||
}
|
||||
if (reject_it)
|
||||
continue;
|
||||
|
||||
for(p = acceptstr; *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(int sig)
|
||||
{
|
||||
char *p, c;
|
||||
|
||||
p = line + sizeof(_PATH_DEV) - 1;
|
||||
#ifdef SUPPORT_UTMP
|
||||
if (logout(p))
|
||||
logwtmp(p, "", "");
|
||||
#endif
|
||||
#ifdef SUPPORT_UTMPX
|
||||
if (logoutx(p, 0, DEAD_PROCESS))
|
||||
logwtmpx(p, "", "", 0, DEAD_PROCESS);
|
||||
#endif
|
||||
(void)chmod(line, 0666);
|
||||
(void)chown(line, 0, 0);
|
||||
c = *p; *p = 'p';
|
||||
(void)chmod(line, 0666);
|
||||
(void)chown(line, 0, 0);
|
||||
*p = c;
|
||||
if (ttyaction(line, "telnetd", "root"))
|
||||
syslog(LOG_ERR, "%s: ttyaction failed", line);
|
||||
(void) shutdown(net, 2);
|
||||
exit(1);
|
||||
}
|
591
libexec/telnetd/telnetd.8
Normal file
591
libexec/telnetd/telnetd.8
Normal file
@ -0,0 +1,591 @@
|
||||
.\" $NetBSD: telnetd.8,v 1.31 2009/04/08 13:36:32 joerg Exp $
|
||||
.\"
|
||||
.\" 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. 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.
|
||||
.\"
|
||||
.\" from: @(#)telnetd.8 8.3 (Berkeley) 3/1/94
|
||||
.\"
|
||||
.Dd July 17, 2004
|
||||
.Dt TELNETD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm telnetd
|
||||
.Nd DARPA
|
||||
.Tn TELNET
|
||||
protocol server
|
||||
.Sh SYNOPSIS
|
||||
.Nm /usr/libexec/telnetd
|
||||
.Op Fl Uhlkns46
|
||||
.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 g Ar gettyent
|
||||
.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
|
||||
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 "-a authmode"
|
||||
.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 debug
|
||||
Turns on authentication debugging code.
|
||||
.It 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 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 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 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 off
|
||||
This disables the authentication code.
|
||||
All user verification will happen through the
|
||||
.Xr login 1
|
||||
program.
|
||||
.El
|
||||
.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
|
||||
Prints information about the negotiation of
|
||||
.Tn TELNET
|
||||
options.
|
||||
.It Cm report
|
||||
Prints the
|
||||
.Cm options
|
||||
information, plus some additional information
|
||||
about what processing is going on.
|
||||
.It Cm netdata
|
||||
Displays the data stream received by
|
||||
.Nm .
|
||||
.It Cm ptydata
|
||||
Displays data written to the pty.
|
||||
.It Cm exercise
|
||||
Has not been implemented yet.
|
||||
.El
|
||||
.It Fl debug
|
||||
Enables 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 g Ar gettyent
|
||||
Specifies which entry from
|
||||
.Pa /etc/gettytab
|
||||
should be used to get banner strings, login program and
|
||||
other information.
|
||||
The default entry is
|
||||
.Dv default .
|
||||
.It Fl h
|
||||
Disables 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 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
|
||||
Specifies line mode.
|
||||
Tries 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 secure logins.
|
||||
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 Kerberos or S/Key
|
||||
validated logins are allowed, and is
|
||||
usually useful for controlling remote logins
|
||||
from outside of a firewall.
|
||||
.It Fl S Ar tos
|
||||
This option sets the IP Type-of Service (TOS) option
|
||||
on the connection to the value tos, which may be a
|
||||
numeric TOS value or a symbolic TOS name found in the
|
||||
.Pa /etc/iptos
|
||||
file.
|
||||
This option has no effect on
|
||||
.Nx .
|
||||
.\"The option has no effect on systems that do not
|
||||
.\"support
|
||||
.\".Xr parsetos 3
|
||||
.\"routine and the
|
||||
.\".Pa /etc/iptos
|
||||
.\"file.
|
||||
.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 getnameinfo 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 .
|
||||
.It Fl 4
|
||||
.It Fl 6
|
||||
Specifies address family to be used on
|
||||
.Fl debug
|
||||
mode.
|
||||
During normal operation
|
||||
.Po
|
||||
called from
|
||||
.Xr inetd 8
|
||||
.Pc
|
||||
.Nm
|
||||
will use the file descriptor passed from
|
||||
.Xr inetd 8 .
|
||||
.El
|
||||
.Pp
|
||||
.Nm
|
||||
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
|
||||
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 \*(lqcooked\*(rq mode, and with
|
||||
.Dv XTABS and
|
||||
.Dv CRMOD
|
||||
enabled (see
|
||||
.Xr tty 4 ) .
|
||||
.Pp
|
||||
.Nm
|
||||
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
|
||||
.Tn telnetd
|
||||
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
|
||||
.Tn telnetd
|
||||
will not be doing any terminal echoing, so the
|
||||
client should do any terminal echoing that is needed.
|
||||
.It "WILL BINARY"
|
||||
Indicates 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"
|
||||
Indicates that it will not be sending
|
||||
.Dv IAC GA ,
|
||||
go ahead, commands.
|
||||
.It "WILL STATUS"
|
||||
Indicates 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
|
||||
has support for enabling remotely the following
|
||||
.Tn TELNET
|
||||
options:
|
||||
.Bl -tag -width "DO AUTHENTICATION"
|
||||
.It "DO BINARY"
|
||||
Sent to indicate that
|
||||
.Tn telnetd
|
||||
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"
|
||||
Indicates 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"
|
||||
Indicates 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"
|
||||
Indicates a desire to be able to request information
|
||||
about the speed of the serial line to which
|
||||
the client is attached.
|
||||
.It "DO XDISPLOC"
|
||||
Indicates a desire to be able to request the name
|
||||
of the X windows display that is associated with
|
||||
the telnet client.
|
||||
.It "DO NEW-ENVIRON"
|
||||
Indicates a desire to be able to request environment
|
||||
variable information, as described in RFC 1572.
|
||||
.It "DO ENVIRON"
|
||||
Indicates 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
|
||||
.Pp
|
||||
At the end of a login session,
|
||||
.Nm
|
||||
invokes the
|
||||
.Xr ttyaction 3
|
||||
facility with an action of "telnetd" and user "root"
|
||||
to execute site-specific commands.
|
||||
.Sh FILES
|
||||
.Bl -item -compact
|
||||
.It
|
||||
.Pa /etc/services
|
||||
.It
|
||||
.Pa /etc/iptos
|
||||
(if supported)
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr login 1 ,
|
||||
.Xr skey 1 ,
|
||||
.Xr telnet 1 ,
|
||||
.Xr ttyaction 3
|
||||
.Sh STANDARDS
|
||||
.Bl -tag -compact -width "RFC 1572 "
|
||||
.It RFC 854
|
||||
.Tn TELNET
|
||||
PROTOCOL SPECIFICATION
|
||||
.It RFC 855
|
||||
TELNET OPTION SPECIFICATIONS
|
||||
.It RFC 856
|
||||
TELNET BINARY TRANSMISSION
|
||||
.It RFC 857
|
||||
TELNET ECHO OPTION
|
||||
.It RFC 858
|
||||
TELNET SUPPRESS GO AHEAD OPTION
|
||||
.It RFC 859
|
||||
TELNET STATUS OPTION
|
||||
.It RFC 860
|
||||
TELNET TIMING MARK OPTION
|
||||
.It RFC 861
|
||||
TELNET EXTENDED OPTIONS - LIST OPTION
|
||||
.It RFC 885
|
||||
TELNET END OF RECORD OPTION
|
||||
.It RFC 1073
|
||||
Telnet Window Size Option
|
||||
.It RFC 1079
|
||||
Telnet Terminal Speed Option
|
||||
.It RFC 1091
|
||||
Telnet Terminal-Type Option
|
||||
.It RFC 1096
|
||||
Telnet X Display Location Option
|
||||
.It RFC 1123
|
||||
Requirements for Internet Hosts -- Application and Support
|
||||
.It RFC 1184
|
||||
Telnet Linemode Option
|
||||
.It RFC 1372
|
||||
Telnet Remote Flow Control Option
|
||||
.It RFC 1416
|
||||
Telnet Authentication Option
|
||||
.It RFC 1411
|
||||
Telnet Authentication: Kerberos Version 4
|
||||
.It RFC 1412
|
||||
Telnet Authentication: SPX
|
||||
.It RFC 1571
|
||||
Telnet Environment Option Interoperability Issues
|
||||
.It 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
|
||||
.Po
|
||||
.Ux
|
||||
in this case
|
||||
.Pc .
|
||||
.Pp
|
||||
The terminal type name received from the remote client is converted to
|
||||
lower case.
|
||||
.Pp
|
||||
.Nm
|
||||
never sends
|
||||
.Tn TELNET
|
||||
.Dv IAC GA
|
||||
(go ahead) commands.
|
1159
libexec/telnetd/telnetd.c
Normal file
1159
libexec/telnetd/telnetd.c
Normal file
File diff suppressed because it is too large
Load Diff
45
libexec/telnetd/telnetd.h
Normal file
45
libexec/telnetd/telnetd.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* $NetBSD: telnetd.h,v 1.8 2003/08/07 09:46:52 agc Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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.
|
||||
*
|
||||
* from: @(#)telnetd.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
|
||||
#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;
|
620
libexec/telnetd/termstat.c
Normal file
620
libexec/telnetd/termstat.c
Normal file
@ -0,0 +1,620 @@
|
||||
/* $NetBSD: termstat.c,v 1.14 2005/02/06 05:58:21 perry Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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 <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: termstat.c,v 1.14 2005/02/06 05:58:21 perry Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include "telnetd.h"
|
||||
|
||||
#ifdef ENCRYPTION
|
||||
#include <libtelnet/encrypt.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* local variables
|
||||
*/
|
||||
int def_tspeed = -1, def_rspeed = -1;
|
||||
int def_row = 0, def_col = 0;
|
||||
#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)
|
||||
{
|
||||
int need_will_echo = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Check for state of BINARY options.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
#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 */
|
||||
(void) 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.
|
||||
*/
|
||||
(void) 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)
|
||||
{
|
||||
if (his_state_is_will(TELOPT_LFLOW)) {
|
||||
if (tty_flowmode() != flowmode) {
|
||||
flowmode = tty_flowmode();
|
||||
(void) 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();
|
||||
(void) 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(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;
|
||||
(void) 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:
|
||||
{
|
||||
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) {
|
||||
(void) 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:
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
/*
|
||||
* local stuff that got deferred.
|
||||
*/
|
||||
if (def_tspeed != -1) {
|
||||
clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed);
|
||||
def_tspeed = def_rspeed = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(void)
|
||||
{
|
||||
return(_terminit);
|
||||
|
||||
} /* end of terminit */
|
||||
#endif /* LINEMODE */
|
1077
libexec/telnetd/utility.c
Normal file
1077
libexec/telnetd/utility.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user