* Ported libtelnet.a and telnetd from FreeBSD.
* The subdirectory is called "libtelnet" instead of "telnet" (as usual), since telnetd expects some headers to be found in libtelnet/ (which I could have changed as well, just in case you very much prefer telnet/). * I needed to disable some stuff to make it compile, and it's absolutely not tested, so it might as well not work yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19488 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -7,4 +7,5 @@ SubInclude HAIKU_TOP src bin network ifconfig ;
|
|||||||
#SubInclude HAIKU_TOP src bin network ppp_up ;
|
#SubInclude HAIKU_TOP src bin network ppp_up ;
|
||||||
SubInclude HAIKU_TOP src bin network ping ;
|
SubInclude HAIKU_TOP src bin network ping ;
|
||||||
SubInclude HAIKU_TOP src bin network route ;
|
SubInclude HAIKU_TOP src bin network route ;
|
||||||
|
SubInclude HAIKU_TOP src bin network telnetd ;
|
||||||
SubInclude HAIKU_TOP src bin network traceroute ;
|
SubInclude HAIKU_TOP src bin network traceroute ;
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
SubDir HAIKU_TOP src bin network telnetd ;
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src libs ] : true ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src libs libtelnet ] : false ;
|
||||||
|
|
||||||
|
local defines = [ FDefines USE_TERMIO=1 ] ;
|
||||||
|
|
||||||
|
SubDirCcFlags $(defines) ;
|
||||||
|
SubDirC++Flags $(defines) ;
|
||||||
|
|
||||||
|
BinCommand telnetd :
|
||||||
|
authenc.c
|
||||||
|
global.c
|
||||||
|
slc.c
|
||||||
|
state.c
|
||||||
|
sys_term.c
|
||||||
|
telnetd.c
|
||||||
|
termstat.c
|
||||||
|
utility.c
|
||||||
|
: libtermcap.a libtelnet.a libutil.a libbsd.so $(NETWORK_LIBS)
|
||||||
|
;
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static const char sccsid[] = "@(#)authenc.c 8.2 (Berkeley) 5/30/95";
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/telnetd/authenc.c,v 1.8 2003/05/04 02:54:49 obrien Exp $");
|
||||||
|
|
||||||
|
#ifdef AUTHENTICATION
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
/* Above "#ifdef"s actually "or"'ed together. XXX MarkM
|
||||||
|
*/
|
||||||
|
#include "telnetd.h"
|
||||||
|
#include <libtelnet/misc.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
net_write(unsigned char *str, int len)
|
||||||
|
{
|
||||||
|
if (nfrontp + len < netobuf + BUFSIZ) {
|
||||||
|
output_datalen(str, len);
|
||||||
|
return(len);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_encrypt(void)
|
||||||
|
{
|
||||||
|
#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(const char *prompt __unused, char *result __unused, int length __unused, int echo __unused)
|
||||||
|
{
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
#endif /* AUTHENTICATION */
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)defs.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/telnetd/defs.h,v 1.2 2001/08/29 14:16:15 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Telnet server defines
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#ifndef BSD
|
||||||
|
# define BSD 43
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS)
|
||||||
|
#define TELOPTS
|
||||||
|
#define TELCMDS
|
||||||
|
#define SLC_NAMES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SYSV_TERMIO) && !defined(USE_TERMIO)
|
||||||
|
# define USE_TERMIO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
//#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#ifndef FILIO_H
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#else
|
||||||
|
#include <sys/filio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef __STDC__
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#ifndef LOG_DAEMON
|
||||||
|
#define LOG_DAEMON 0
|
||||||
|
#endif
|
||||||
|
#ifndef LOG_ODELAY
|
||||||
|
#define LOG_ODELAY 0
|
||||||
|
#endif
|
||||||
|
#include <ctype.h>
|
||||||
|
#ifndef NO_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#else
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_TERMIO
|
||||||
|
#include <sgtty.h>
|
||||||
|
#else
|
||||||
|
# ifdef SYSV_TERMIO
|
||||||
|
# include <termio.h>
|
||||||
|
# else
|
||||||
|
# include <termios.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_TERMIO) || defined(NO_CC_T)
|
||||||
|
typedef unsigned char cc_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _POSIX_VDISABLE
|
||||||
|
# ifdef VDISABLE
|
||||||
|
# define _POSIX_VDISABLE VDISABLE
|
||||||
|
# else
|
||||||
|
# define _POSIX_VDISABLE ((unsigned char)'\377')
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(TIOCSCTTY) && defined(TCSETCTTY)
|
||||||
|
# define TIOCSCTTY TCSETCTTY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FD_SET
|
||||||
|
#ifndef HAVE_fd_set
|
||||||
|
typedef struct fd_set { int fds_bits[1]; } fd_set;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n)))
|
||||||
|
#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n)))
|
||||||
|
#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n)))
|
||||||
|
#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
|
||||||
|
#endif /* FD_SET */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O data buffers defines
|
||||||
|
*/
|
||||||
|
#define NETSLOP 64
|
||||||
|
|
||||||
|
#define NIACCUM(c) { *netip++ = c; \
|
||||||
|
ncc++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 arithmatic 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 symetrical
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HIS_STATE_WILL MY_STATE_DO
|
||||||
|
#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO
|
||||||
|
#define HIS_STATE_DO MY_STATE_WILL
|
||||||
|
#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL
|
||||||
|
|
||||||
|
#define his_state_is_do my_state_is_will
|
||||||
|
#define his_state_is_will my_state_is_do
|
||||||
|
#define his_want_state_is_do my_want_state_is_will
|
||||||
|
#define his_want_state_is_will my_want_state_is_do
|
||||||
|
|
||||||
|
#define his_state_is_dont my_state_is_wont
|
||||||
|
#define his_state_is_wont my_state_is_dont
|
||||||
|
#define his_want_state_is_dont my_want_state_is_wont
|
||||||
|
#define his_want_state_is_wont my_want_state_is_dont
|
||||||
|
|
||||||
|
#define set_his_state_do set_my_state_will
|
||||||
|
#define set_his_state_will set_my_state_do
|
||||||
|
#define set_his_want_state_do set_my_want_state_will
|
||||||
|
#define set_his_want_state_will set_my_want_state_do
|
||||||
|
|
||||||
|
#define set_his_state_dont set_my_state_wont
|
||||||
|
#define set_his_state_wont set_my_state_dont
|
||||||
|
#define set_his_want_state_dont set_my_want_state_wont
|
||||||
|
#define set_his_want_state_wont set_my_want_state_dont
|
||||||
|
|
||||||
|
#define his_will_wont_is_changing my_do_dont_is_changing
|
||||||
|
#define his_do_dont_is_changing my_will_wont_is_changing
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)ext.h 8.2 (Berkeley) 12/15/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/telnetd/ext.h,v 1.11 2001/11/30 22:28:07 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Telnet server variable declarations
|
||||||
|
*/
|
||||||
|
extern char options[256];
|
||||||
|
extern char do_dont_resp[256];
|
||||||
|
extern char will_wont_resp[256];
|
||||||
|
extern int linemode; /* linemode on/off */
|
||||||
|
#ifdef LINEMODE
|
||||||
|
extern int uselinemode; /* what linemode to use (on/off) */
|
||||||
|
extern int editmode; /* edit modes in use */
|
||||||
|
extern int useeditmode; /* edit modes to use */
|
||||||
|
extern int alwayslinemode; /* command line option */
|
||||||
|
extern int lmodetype; /* Client support for linemode */
|
||||||
|
#endif /* LINEMODE */
|
||||||
|
extern int flowmode; /* current flow control state */
|
||||||
|
extern int restartany; /* restart output on any character state */
|
||||||
|
#ifdef DIAGNOSTICS
|
||||||
|
extern int diagnostic; /* telnet diagnostic capabilities */
|
||||||
|
#endif /* DIAGNOSTICS */
|
||||||
|
#ifdef BFTPDAEMON
|
||||||
|
extern int bftpd; /* behave as bftp daemon */
|
||||||
|
#endif /* BFTPDAEMON */
|
||||||
|
#ifdef AUTHENTICATION
|
||||||
|
extern int auth_level;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern slcfun slctab[NSLC + 1]; /* slc mapping table */
|
||||||
|
|
||||||
|
char *terminaltype;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O data buffers, pointers, and counters.
|
||||||
|
*/
|
||||||
|
extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
|
||||||
|
|
||||||
|
extern char netibuf[BUFSIZ], *netip;
|
||||||
|
|
||||||
|
extern char netobuf[BUFSIZ], *nfrontp, *nbackp;
|
||||||
|
extern char *neturg; /* one past last bye of urgent data */
|
||||||
|
|
||||||
|
extern int pcc, ncc;
|
||||||
|
|
||||||
|
extern int pty, net;
|
||||||
|
extern char line[16];
|
||||||
|
extern int SYNCHing; /* we are in TELNET SYNCH mode */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_termstat(void),
|
||||||
|
add_slc(char, char, cc_t),
|
||||||
|
check_slc(void),
|
||||||
|
change_slc(char, char, cc_t),
|
||||||
|
cleanup(int),
|
||||||
|
clientstat(int, int, int),
|
||||||
|
copy_termbuf(char *, size_t),
|
||||||
|
deferslc(void),
|
||||||
|
defer_terminit(void),
|
||||||
|
do_opt_slc(unsigned char *, int),
|
||||||
|
doeof(void),
|
||||||
|
dooption(int),
|
||||||
|
dontoption(int),
|
||||||
|
edithost(char *, char *),
|
||||||
|
fatal(int, const char *),
|
||||||
|
fatalperror(int, const char *),
|
||||||
|
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),
|
||||||
|
printsub(char, unsigned char *, int),
|
||||||
|
#endif
|
||||||
|
process_slc(unsigned char, unsigned char, cc_t),
|
||||||
|
ptyflush(void),
|
||||||
|
putchr(int),
|
||||||
|
putf(char *, char *),
|
||||||
|
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 *),
|
||||||
|
start_slc(int),
|
||||||
|
#ifdef AUTHENTICATION
|
||||||
|
start_slave(char *),
|
||||||
|
#else
|
||||||
|
start_slave(char *, int, char *),
|
||||||
|
#endif
|
||||||
|
suboption(void),
|
||||||
|
telrcv(void),
|
||||||
|
ttloop(void),
|
||||||
|
tty_binaryin(int),
|
||||||
|
tty_binaryout(int);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
end_slc(unsigned char **),
|
||||||
|
getnpty(void),
|
||||||
|
#ifndef convex
|
||||||
|
getpty(int *),
|
||||||
|
#endif
|
||||||
|
login_tty(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);
|
||||||
|
|
||||||
|
int output_data(const char *, ...) __printflike(1, 2);
|
||||||
|
void output_datalen(const char *, int);
|
||||||
|
void startslave(char *, int, char *);
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
extern void (*encrypt_output)(unsigned char *, int);
|
||||||
|
extern int (*decrypt_input)(int);
|
||||||
|
extern char *nclearto;
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following are some clocks used to decide how to interpret
|
||||||
|
* the relationship between various variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern struct {
|
||||||
|
int
|
||||||
|
system, /* what the current time is */
|
||||||
|
echotoggle, /* last time user entered echo character */
|
||||||
|
modenegotiated, /* last time operating mode negotiated */
|
||||||
|
didnetreceive, /* last time we read data from network */
|
||||||
|
ttypesubopt, /* ttype subopt is received */
|
||||||
|
tspeedsubopt, /* tspeed subopt is received */
|
||||||
|
environsubopt, /* environ subopt is received */
|
||||||
|
oenvironsubopt, /* old environ subopt is received */
|
||||||
|
xdisplocsubopt, /* xdisploc subopt is received */
|
||||||
|
baseline, /* time started to do timed action */
|
||||||
|
gotDM; /* when did we last see a data mark */
|
||||||
|
} clocks;
|
||||||
|
|
||||||
|
#ifndef DEFAULT_IM
|
||||||
|
# ifdef ultrix
|
||||||
|
# define DEFAULT_IM "\r\n\r\nULTRIX (%h) (%t)\r\n\r\r\n\r"
|
||||||
|
# else
|
||||||
|
# ifdef __FreeBSD__
|
||||||
|
# define DEFAULT_IM "\r\n\r\nFreeBSD (%h) (%t)\r\n\r\r\n\r"
|
||||||
|
# else
|
||||||
|
# define DEFAULT_IM "\r\n\r\n4.4 BSD UNIX (%h) (%t)\r\n\r\r\n\r"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static const char sccsid[] = "@(#)global.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#endif /* not lint */
|
||||||
|
#endif
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/telnetd/global.c,v 1.6 2003/05/04 02:54:49 obrien Exp $");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/telnetd/pathnames.h,v 1.3 2001/08/20 12:28:40 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <paths.h>
|
||||||
|
|
||||||
|
#define _PATH_TTY "/dev/tty"
|
||||||
|
#ifndef _PATH_LOGIN
|
||||||
|
# define _PATH_LOGIN "/bin/login"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BFTPDAEMON
|
||||||
|
#define BFTPPATH "/usr/ucb/bftp"
|
||||||
|
#endif /* BFTPDAEMON */
|
||||||
@@ -0,0 +1,484 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static const char sccsid[] = "@(#)slc.c 8.2 (Berkeley) 5/30/95";
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/telnetd/slc.c,v 1.9 2003/05/04 02:54:49 obrien Exp $");
|
||||||
|
|
||||||
|
#include "telnetd.h"
|
||||||
|
|
||||||
|
#ifdef LINEMODE
|
||||||
|
/*
|
||||||
|
* local variables
|
||||||
|
*/
|
||||||
|
static unsigned char *def_slcbuf = (unsigned char *)0;
|
||||||
|
static int def_slclen = 0;
|
||||||
|
static int slcchange; /* change to slc is requested */
|
||||||
|
static unsigned char *slcptr; /* pointer into slc buffer */
|
||||||
|
static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send_slc
|
||||||
|
*
|
||||||
|
* Write out the current special characters to the client.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
send_slc(void)
|
||||||
|
{
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
static 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) sprintf((char *)slcbuf, "%c%c%c%c",
|
||||||
|
IAC, SB, TELOPT_LINEMODE, LM_SLC);
|
||||||
|
slcptr = slcbuf + 4;
|
||||||
|
|
||||||
|
} /* end of start_slc */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* end_slc
|
||||||
|
*
|
||||||
|
* Finish up the slc negotiation. If something to send, then send it.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
end_slc(unsigned char **bufp)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a change has occured, store the new terminal control
|
||||||
|
* structures back to the terminal driver.
|
||||||
|
*/
|
||||||
|
if (slcchange) {
|
||||||
|
set_termbuf();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the pty state has not yet been fully processed and there is a
|
||||||
|
* deferred slc request from the client, then do not send any
|
||||||
|
* sort of slc negotiation now. We will respond to the client's
|
||||||
|
* request very soon.
|
||||||
|
*/
|
||||||
|
if (def_slcbuf && (terminit() == 0)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slcptr > (slcbuf + 4)) {
|
||||||
|
if (bufp) {
|
||||||
|
*bufp = &slcbuf[4];
|
||||||
|
return(slcptr - slcbuf - 4);
|
||||||
|
} else {
|
||||||
|
(void) sprintf((char *)slcptr, "%c%c", IAC, SE);
|
||||||
|
slcptr += 2;
|
||||||
|
len = slcptr - slcbuf;
|
||||||
|
output_datalen(slcbuf, len);
|
||||||
|
netflush(); /* force it out immediately */
|
||||||
|
DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2););
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
} /* end of end_slc */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process_slc
|
||||||
|
*
|
||||||
|
* Figure out what to do about the client's slc
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
process_slc(unsigned char func, unsigned char 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(char func, char flag, cc_t val)
|
||||||
|
{
|
||||||
|
int hislevel, mylevel;
|
||||||
|
|
||||||
|
hislevel = flag & SLC_LEVELBITS;
|
||||||
|
mylevel = slctab[(int)func].defset.flag & SLC_LEVELBITS;
|
||||||
|
/*
|
||||||
|
* If client is setting a function to NOSUPPORT
|
||||||
|
* or DEFAULT, then we can easily and directly
|
||||||
|
* accomodate the request.
|
||||||
|
*/
|
||||||
|
if (hislevel == SLC_NOSUPPORT) {
|
||||||
|
slctab[(int)func].current.flag = flag;
|
||||||
|
slctab[(int)func].current.val = (cc_t)_POSIX_VDISABLE;
|
||||||
|
flag |= SLC_ACK;
|
||||||
|
add_slc(func, flag, val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (hislevel == SLC_DEFAULT) {
|
||||||
|
/*
|
||||||
|
* Special case here. If client tells us to use
|
||||||
|
* the default on a function we don't support, then
|
||||||
|
* return NOSUPPORT instead of what we may have as a
|
||||||
|
* default level of DEFAULT.
|
||||||
|
*/
|
||||||
|
if (mylevel == SLC_DEFAULT) {
|
||||||
|
slctab[(int)func].current.flag = SLC_NOSUPPORT;
|
||||||
|
} else {
|
||||||
|
slctab[(int)func].current.flag = slctab[(int)func].defset.flag;
|
||||||
|
}
|
||||||
|
slctab[(int)func].current.val = slctab[(int)func].defset.val;
|
||||||
|
add_slc(func, slctab[(int)func].current.flag,
|
||||||
|
slctab[(int)func].current.val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Client wants us to change to a new value or he
|
||||||
|
* is telling us that he can't change to our value.
|
||||||
|
* Some of the slc's we support and can change,
|
||||||
|
* some we do support but can't change,
|
||||||
|
* and others we don't support at all.
|
||||||
|
* If we can change it then we have a pointer to
|
||||||
|
* the place to put the new value, so change it,
|
||||||
|
* otherwise, continue the negotiation.
|
||||||
|
*/
|
||||||
|
if (slctab[(int)func].sptr) {
|
||||||
|
/*
|
||||||
|
* We can change this one.
|
||||||
|
*/
|
||||||
|
slctab[(int)func].current.val = val;
|
||||||
|
*(slctab[(int)func].sptr) = val;
|
||||||
|
slctab[(int)func].current.flag = flag;
|
||||||
|
flag |= SLC_ACK;
|
||||||
|
slcchange = 1;
|
||||||
|
add_slc(func, flag, val);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* It is not possible for us to support this
|
||||||
|
* request as he asks.
|
||||||
|
*
|
||||||
|
* If our level is DEFAULT, then just ack whatever was
|
||||||
|
* sent.
|
||||||
|
*
|
||||||
|
* If he can't change and we can't change,
|
||||||
|
* then degenerate to NOSUPPORT.
|
||||||
|
*
|
||||||
|
* Otherwise we send our level back to him, (CANTCHANGE
|
||||||
|
* or NOSUPPORT) and if CANTCHANGE, send
|
||||||
|
* our value as well.
|
||||||
|
*/
|
||||||
|
if (mylevel == SLC_DEFAULT) {
|
||||||
|
slctab[(int)func].current.flag = flag;
|
||||||
|
slctab[(int)func].current.val = val;
|
||||||
|
flag |= SLC_ACK;
|
||||||
|
} else if (hislevel == SLC_CANTCHANGE &&
|
||||||
|
mylevel == SLC_CANTCHANGE) {
|
||||||
|
flag &= ~SLC_LEVELBITS;
|
||||||
|
flag |= SLC_NOSUPPORT;
|
||||||
|
slctab[(int)func].current.flag = flag;
|
||||||
|
} else {
|
||||||
|
flag &= ~SLC_LEVELBITS;
|
||||||
|
flag |= mylevel;
|
||||||
|
slctab[(int)func].current.flag = flag;
|
||||||
|
if (mylevel == SLC_CANTCHANGE) {
|
||||||
|
slctab[(int)func].current.val =
|
||||||
|
slctab[(int)func].defset.val;
|
||||||
|
val = slctab[(int)func].current.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_slc(func, flag, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end of change_slc */
|
||||||
|
|
||||||
|
#if defined(USE_TERMIO) && (VEOF == VMIN)
|
||||||
|
cc_t oldeofc = '\004';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check_slc
|
||||||
|
*
|
||||||
|
* Check the special characters in use and notify the client if any have
|
||||||
|
* changed. Only those characters that are capable of being changed are
|
||||||
|
* likely to have changed. If a local change occurs, kick the support level
|
||||||
|
* and flags up to the defaults.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
check_slc(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i <= NSLC; i++) {
|
||||||
|
#if defined(USE_TERMIO) && (VEOF == VMIN)
|
||||||
|
/*
|
||||||
|
* In a perfect world this would be a neat little
|
||||||
|
* function. But in this world, we should not notify
|
||||||
|
* client of changes to the VEOF char when
|
||||||
|
* ICANON is off, because it is not representing
|
||||||
|
* a special character.
|
||||||
|
*/
|
||||||
|
if (i == SLC_EOF) {
|
||||||
|
if (!tty_isediting())
|
||||||
|
continue;
|
||||||
|
else if (slctab[i].sptr)
|
||||||
|
oldeofc = *(slctab[i].sptr);
|
||||||
|
}
|
||||||
|
#endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */
|
||||||
|
if (slctab[i].sptr &&
|
||||||
|
(*(slctab[i].sptr) != slctab[i].current.val)) {
|
||||||
|
slctab[i].current.val = *(slctab[i].sptr);
|
||||||
|
if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE)
|
||||||
|
slctab[i].current.flag = SLC_NOSUPPORT;
|
||||||
|
else
|
||||||
|
slctab[i].current.flag = slctab[i].defset.flag;
|
||||||
|
add_slc((unsigned char)i, slctab[i].current.flag,
|
||||||
|
slctab[i].current.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* check_slc */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_opt_slc
|
||||||
|
*
|
||||||
|
* Process an slc option buffer. Defer processing of incoming slc's
|
||||||
|
* until after the terminal state has been processed. Save the first slc
|
||||||
|
* request that comes along, but discard all others.
|
||||||
|
*
|
||||||
|
* ptr points to the beginning of the buffer, len is the length.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
do_opt_slc(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(func, flag, val);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* save this slc buffer if it is the first, otherwise dump
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
|
if (def_slcbuf == (unsigned char *)0) {
|
||||||
|
def_slclen = len;
|
||||||
|
def_slcbuf = (unsigned char *)malloc((unsigned)len);
|
||||||
|
if (def_slcbuf == (unsigned char *)0)
|
||||||
|
return; /* too bad */
|
||||||
|
memmove(def_slcbuf, ptr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end of do_opt_slc */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* deferslc
|
||||||
|
*
|
||||||
|
* Do slc stuff that was deferred.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
deferslc(void)
|
||||||
|
{
|
||||||
|
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 */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)telnetd.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/telnetd/telnetd.h,v 1.2 2001/11/30 21:06:38 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
#include "ext.h"
|
||||||
|
|
||||||
|
#ifdef DIAGNOSTICS
|
||||||
|
#define DIAG(a,b) if (diagnostic & (a)) b
|
||||||
|
#else
|
||||||
|
#define DIAG(a,b)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* other external variables */
|
||||||
|
extern char **environ;
|
||||||
|
extern const char *altlogin;
|
||||||
@@ -0,0 +1,632 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static const char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95";
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/telnetd/termstat.c,v 1.13 2004/07/28 05:37:18 kan Exp $");
|
||||||
|
|
||||||
|
#include "telnetd.h"
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
#include <libtelnet/encrypt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* local variables
|
||||||
|
*/
|
||||||
|
int def_tspeed = -1, def_rspeed = -1;
|
||||||
|
#ifdef TIOCSWINSZ
|
||||||
|
int def_row = 0, def_col = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef LINEMODE
|
||||||
|
static int _terminit = 0;
|
||||||
|
#endif /* LINEMODE */
|
||||||
|
|
||||||
|
#ifdef LINEMODE
|
||||||
|
/*
|
||||||
|
* localstat
|
||||||
|
*
|
||||||
|
* This function handles all management of linemode.
|
||||||
|
*
|
||||||
|
* Linemode allows the client to do the local editing of data
|
||||||
|
* and send only complete lines to the server. Linemode state is
|
||||||
|
* based on the state of the pty driver. If the pty is set for
|
||||||
|
* external processing, then we can use linemode. Further, if we
|
||||||
|
* can use real linemode, then we can look at the edit control bits
|
||||||
|
* in the pty to determine what editing the client should do.
|
||||||
|
*
|
||||||
|
* Linemode support uses the following state flags to keep track of
|
||||||
|
* current and desired linemode state.
|
||||||
|
* alwayslinemode : true if -l was specified on the telnetd
|
||||||
|
* command line. It means to have linemode on as much as
|
||||||
|
* possible.
|
||||||
|
*
|
||||||
|
* lmodetype: signifies whether the client can
|
||||||
|
* handle real linemode, or if use of kludgeomatic linemode
|
||||||
|
* is preferred. It will be set to one of the following:
|
||||||
|
* REAL_LINEMODE : use linemode option
|
||||||
|
* NO_KLUDGE : don't initiate kludge linemode.
|
||||||
|
* KLUDGE_LINEMODE : use kludge linemode
|
||||||
|
* NO_LINEMODE : client is ignorant of linemode
|
||||||
|
*
|
||||||
|
* linemode, uselinemode : linemode is true if linemode
|
||||||
|
* is currently on, uselinemode is the state that we wish
|
||||||
|
* to be in. If another function wishes to turn linemode
|
||||||
|
* on or off, it sets or clears uselinemode.
|
||||||
|
*
|
||||||
|
* editmode, useeditmode : like linemode/uselinemode, but
|
||||||
|
* these contain the edit mode states (edit and trapsig).
|
||||||
|
*
|
||||||
|
* The state variables correspond to some of the state information
|
||||||
|
* in the pty.
|
||||||
|
* linemode:
|
||||||
|
* In real linemode, this corresponds to whether the pty
|
||||||
|
* expects external processing of incoming data.
|
||||||
|
* In kludge linemode, this more closely corresponds to the
|
||||||
|
* whether normal processing is on or not. (ICANON in
|
||||||
|
* system V, or COOKED mode in BSD.)
|
||||||
|
* If the -l option was specified (alwayslinemode), then
|
||||||
|
* an attempt is made to force external processing on at
|
||||||
|
* all times.
|
||||||
|
*
|
||||||
|
* The following heuristics are applied to determine linemode
|
||||||
|
* handling within the server.
|
||||||
|
* 1) Early on in starting up the server, an attempt is made
|
||||||
|
* to negotiate the linemode option. If this succeeds
|
||||||
|
* then lmodetype is set to REAL_LINEMODE and all linemode
|
||||||
|
* processing occurs in the context of the linemode option.
|
||||||
|
* 2) If the attempt to negotiate the linemode option failed,
|
||||||
|
* and the "-k" (don't initiate kludge linemode) isn't set,
|
||||||
|
* then we try to use kludge linemode. We test for this
|
||||||
|
* capability by sending "do Timing Mark". If a positive
|
||||||
|
* response comes back, then we assume that the client
|
||||||
|
* understands kludge linemode (ech!) and the
|
||||||
|
* lmodetype flag is set to KLUDGE_LINEMODE.
|
||||||
|
* 3) Otherwise, linemode is not supported at all and
|
||||||
|
* lmodetype remains set to NO_LINEMODE (which happens
|
||||||
|
* to be 0 for convenience).
|
||||||
|
* 4) At any time a command arrives that implies a higher
|
||||||
|
* state of linemode support in the client, we move to that
|
||||||
|
* linemode support.
|
||||||
|
*
|
||||||
|
* A short explanation of kludge linemode is in order here.
|
||||||
|
* 1) The heuristic to determine support for kludge linemode
|
||||||
|
* is to send a do timing mark. We assume that a client
|
||||||
|
* that supports timing marks also supports kludge linemode.
|
||||||
|
* A risky proposition at best.
|
||||||
|
* 2) Further negotiation of linemode is done by changing the
|
||||||
|
* the server's state regarding SGA. If server will SGA,
|
||||||
|
* then linemode is off, if server won't SGA, then linemode
|
||||||
|
* is on.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
localstat(void)
|
||||||
|
{
|
||||||
|
int need_will_echo = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for changes to flow control if client supports it.
|
||||||
|
*/
|
||||||
|
flowstat();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check linemode on/off state
|
||||||
|
*/
|
||||||
|
uselinemode = tty_linemode();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If alwayslinemode is on, and pty is changing to turn it off, then
|
||||||
|
* force linemode back on.
|
||||||
|
*/
|
||||||
|
if (alwayslinemode && linemode && !uselinemode) {
|
||||||
|
uselinemode = 1;
|
||||||
|
tty_setlinemode(uselinemode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uselinemode) {
|
||||||
|
/*
|
||||||
|
* Check for state of BINARY options.
|
||||||
|
*
|
||||||
|
* We only need to do the binary dance if we are actually going
|
||||||
|
* to use linemode. As this confuses some telnet clients
|
||||||
|
* that don't support linemode, and doesn't gain us
|
||||||
|
* anything, we don't do it unless we're doing linemode.
|
||||||
|
* -Crh ([email protected])
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tty_isbinaryin()) {
|
||||||
|
if (his_want_state_is_wont(TELOPT_BINARY))
|
||||||
|
send_do(TELOPT_BINARY, 1);
|
||||||
|
} else {
|
||||||
|
if (his_want_state_is_will(TELOPT_BINARY))
|
||||||
|
send_dont(TELOPT_BINARY, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tty_isbinaryout()) {
|
||||||
|
if (my_want_state_is_wont(TELOPT_BINARY))
|
||||||
|
send_will(TELOPT_BINARY, 1);
|
||||||
|
} else {
|
||||||
|
if (my_want_state_is_will(TELOPT_BINARY))
|
||||||
|
send_wont(TELOPT_BINARY, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
/*
|
||||||
|
* If the terminal is not echoing, but editing is enabled,
|
||||||
|
* something like password input is going to happen, so
|
||||||
|
* if we the other side is not currently sending encrypted
|
||||||
|
* data, ask the other side to start encrypting.
|
||||||
|
*/
|
||||||
|
if (his_state_is_will(TELOPT_ENCRYPT)) {
|
||||||
|
static int enc_passwd = 0;
|
||||||
|
if (uselinemode && !tty_isecho() && tty_isediting()
|
||||||
|
&& (enc_passwd == 0) && !decrypt_input) {
|
||||||
|
encrypt_send_request_start();
|
||||||
|
enc_passwd = 1;
|
||||||
|
} else if (enc_passwd) {
|
||||||
|
encrypt_send_request_end();
|
||||||
|
enc_passwd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do echo mode handling as soon as we know what the
|
||||||
|
* linemode is going to be.
|
||||||
|
* If the pty has echo turned off, then tell the client that
|
||||||
|
* the server will echo. If echo is on, then the server
|
||||||
|
* will echo if in character mode, but in linemode the
|
||||||
|
* client should do local echoing. The state machine will
|
||||||
|
* not send anything if it is unnecessary, so don't worry
|
||||||
|
* about that here.
|
||||||
|
*
|
||||||
|
* If we need to send the WILL ECHO (because echo is off),
|
||||||
|
* then delay that until after we have changed the MODE.
|
||||||
|
* This way, when the user is turning off both editing
|
||||||
|
* and echo, the client will get editing turned off first.
|
||||||
|
* This keeps the client from going into encryption mode
|
||||||
|
* and then right back out if it is doing auto-encryption
|
||||||
|
* when passwords are being typed.
|
||||||
|
*/
|
||||||
|
if (uselinemode) {
|
||||||
|
if (tty_isecho())
|
||||||
|
send_wont(TELOPT_ECHO, 1);
|
||||||
|
else
|
||||||
|
need_will_echo = 1;
|
||||||
|
#ifdef KLUDGELINEMODE
|
||||||
|
if (lmodetype == KLUDGE_OK)
|
||||||
|
lmodetype = KLUDGE_LINEMODE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If linemode is being turned off, send appropriate
|
||||||
|
* command and then we're all done.
|
||||||
|
*/
|
||||||
|
if (!uselinemode && linemode) {
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
if (lmodetype == REAL_LINEMODE) {
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
send_dont(TELOPT_LINEMODE, 1);
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
} else if (lmodetype == KLUDGE_LINEMODE)
|
||||||
|
send_will(TELOPT_SGA, 1);
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
send_will(TELOPT_ECHO, 1);
|
||||||
|
linemode = uselinemode;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
/*
|
||||||
|
* If using real linemode check edit modes for possible later use.
|
||||||
|
* If we are in kludge linemode, do the SGA negotiation.
|
||||||
|
*/
|
||||||
|
if (lmodetype == REAL_LINEMODE) {
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
useeditmode = 0;
|
||||||
|
if (tty_isediting())
|
||||||
|
useeditmode |= MODE_EDIT;
|
||||||
|
if (tty_istrapsig())
|
||||||
|
useeditmode |= MODE_TRAPSIG;
|
||||||
|
if (tty_issofttab())
|
||||||
|
useeditmode |= MODE_SOFT_TAB;
|
||||||
|
if (tty_islitecho())
|
||||||
|
useeditmode |= MODE_LIT_ECHO;
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
} else if (lmodetype == KLUDGE_LINEMODE) {
|
||||||
|
if (tty_isediting() && uselinemode)
|
||||||
|
send_wont(TELOPT_SGA, 1);
|
||||||
|
else
|
||||||
|
send_will(TELOPT_SGA, 1);
|
||||||
|
}
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Negotiate linemode on if pty state has changed to turn it on.
|
||||||
|
* Send appropriate command and send along edit mode, then all done.
|
||||||
|
*/
|
||||||
|
if (uselinemode && !linemode) {
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
if (lmodetype == KLUDGE_LINEMODE) {
|
||||||
|
send_wont(TELOPT_SGA, 1);
|
||||||
|
} else if (lmodetype == REAL_LINEMODE) {
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
send_do(TELOPT_LINEMODE, 1);
|
||||||
|
/* send along edit modes */
|
||||||
|
output_data("%c%c%c%c%c%c%c", IAC, SB,
|
||||||
|
TELOPT_LINEMODE, LM_MODE, useeditmode,
|
||||||
|
IAC, SE);
|
||||||
|
editmode = useeditmode;
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
}
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
linemode = uselinemode;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
/*
|
||||||
|
* None of what follows is of any value if not using
|
||||||
|
* real linemode.
|
||||||
|
*/
|
||||||
|
if (lmodetype < REAL_LINEMODE)
|
||||||
|
goto done;
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
|
||||||
|
if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
|
||||||
|
/*
|
||||||
|
* If edit mode changed, send edit mode.
|
||||||
|
*/
|
||||||
|
if (useeditmode != editmode) {
|
||||||
|
/*
|
||||||
|
* Send along appropriate edit mode mask.
|
||||||
|
*/
|
||||||
|
output_data("%c%c%c%c%c%c%c", IAC, SB,
|
||||||
|
TELOPT_LINEMODE, LM_MODE, useeditmode,
|
||||||
|
IAC, SE);
|
||||||
|
editmode = useeditmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for changes to special characters in use.
|
||||||
|
*/
|
||||||
|
start_slc(0);
|
||||||
|
check_slc();
|
||||||
|
(void) end_slc(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (need_will_echo)
|
||||||
|
send_will(TELOPT_ECHO, 1);
|
||||||
|
/*
|
||||||
|
* Some things should be deferred until after the pty state has
|
||||||
|
* been set by the local process. Do those things that have been
|
||||||
|
* deferred now. This only happens once.
|
||||||
|
*/
|
||||||
|
if (_terminit == 0) {
|
||||||
|
_terminit = 1;
|
||||||
|
defer_terminit();
|
||||||
|
}
|
||||||
|
|
||||||
|
netflush();
|
||||||
|
set_termbuf();
|
||||||
|
return;
|
||||||
|
|
||||||
|
} /* end of localstat */
|
||||||
|
#endif /* LINEMODE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flowstat
|
||||||
|
*
|
||||||
|
* Check for changes to flow control
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
flowstat(void)
|
||||||
|
{
|
||||||
|
if (his_state_is_will(TELOPT_LFLOW)) {
|
||||||
|
if (tty_flowmode() != flowmode) {
|
||||||
|
flowmode = tty_flowmode();
|
||||||
|
output_data("%c%c%c%c%c%c",
|
||||||
|
IAC, SB, TELOPT_LFLOW,
|
||||||
|
flowmode ? LFLOW_ON : LFLOW_OFF,
|
||||||
|
IAC, SE);
|
||||||
|
}
|
||||||
|
if (tty_restartany() != restartany) {
|
||||||
|
restartany = tty_restartany();
|
||||||
|
output_data("%c%c%c%c%c%c",
|
||||||
|
IAC, SB, TELOPT_LFLOW,
|
||||||
|
restartany ? LFLOW_RESTART_ANY
|
||||||
|
: LFLOW_RESTART_XON,
|
||||||
|
IAC, SE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clientstat
|
||||||
|
*
|
||||||
|
* Process linemode related requests from the client.
|
||||||
|
* Client can request a change to only one of linemode, editmode or slc's
|
||||||
|
* at a time, and if using kludge linemode, then only linemode may be
|
||||||
|
* affected.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clientstat(int code, int parm1, int parm2)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a copy of terminal characteristics.
|
||||||
|
*/
|
||||||
|
init_termbuf();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process request from client. code tells what it is.
|
||||||
|
*/
|
||||||
|
switch (code) {
|
||||||
|
#ifdef LINEMODE
|
||||||
|
case TELOPT_LINEMODE:
|
||||||
|
/*
|
||||||
|
* Don't do anything unless client is asking us to change
|
||||||
|
* modes.
|
||||||
|
*/
|
||||||
|
uselinemode = (parm1 == WILL);
|
||||||
|
if (uselinemode != linemode) {
|
||||||
|
# ifdef KLUDGELINEMODE
|
||||||
|
/*
|
||||||
|
* If using kludge linemode, make sure that
|
||||||
|
* we can do what the client asks.
|
||||||
|
* We can not turn off linemode if alwayslinemode
|
||||||
|
* and the ICANON bit is set.
|
||||||
|
*/
|
||||||
|
if (lmodetype == KLUDGE_LINEMODE) {
|
||||||
|
if (alwayslinemode && tty_isediting()) {
|
||||||
|
uselinemode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quit now if we can't do it.
|
||||||
|
*/
|
||||||
|
if (uselinemode == linemode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If using real linemode and linemode is being
|
||||||
|
* turned on, send along the edit mode mask.
|
||||||
|
*/
|
||||||
|
if (lmodetype == REAL_LINEMODE && uselinemode)
|
||||||
|
# else /* KLUDGELINEMODE */
|
||||||
|
if (uselinemode)
|
||||||
|
# endif /* KLUDGELINEMODE */
|
||||||
|
{
|
||||||
|
useeditmode = 0;
|
||||||
|
if (tty_isediting())
|
||||||
|
useeditmode |= MODE_EDIT;
|
||||||
|
if (tty_istrapsig())
|
||||||
|
useeditmode |= MODE_TRAPSIG;
|
||||||
|
if (tty_issofttab())
|
||||||
|
useeditmode |= MODE_SOFT_TAB;
|
||||||
|
if (tty_islitecho())
|
||||||
|
useeditmode |= MODE_LIT_ECHO;
|
||||||
|
output_data("%c%c%c%c%c%c%c", IAC,
|
||||||
|
SB, TELOPT_LINEMODE, LM_MODE,
|
||||||
|
useeditmode, IAC, SE);
|
||||||
|
editmode = useeditmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tty_setlinemode(uselinemode);
|
||||||
|
|
||||||
|
linemode = uselinemode;
|
||||||
|
|
||||||
|
if (!linemode)
|
||||||
|
send_will(TELOPT_ECHO, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LM_MODE:
|
||||||
|
{
|
||||||
|
int ack, changed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Client has sent along a mode mask. If it agrees with
|
||||||
|
* what we are currently doing, ignore it; if not, it could
|
||||||
|
* be viewed as a request to change. Note that the server
|
||||||
|
* will change to the modes in an ack if it is different from
|
||||||
|
* what we currently have, but we will not ack the ack.
|
||||||
|
*/
|
||||||
|
useeditmode &= MODE_MASK;
|
||||||
|
ack = (useeditmode & MODE_ACK);
|
||||||
|
useeditmode &= ~MODE_ACK;
|
||||||
|
|
||||||
|
if ((changed = (useeditmode ^ editmode))) {
|
||||||
|
/*
|
||||||
|
* This check is for a timing problem. If the
|
||||||
|
* state of the tty has changed (due to the user
|
||||||
|
* application) we need to process that info
|
||||||
|
* before we write in the state contained in the
|
||||||
|
* ack!!! This gets out the new MODE request,
|
||||||
|
* and when the ack to that command comes back
|
||||||
|
* we'll set it and be in the right mode.
|
||||||
|
*/
|
||||||
|
if (ack)
|
||||||
|
localstat();
|
||||||
|
if (changed & MODE_EDIT)
|
||||||
|
tty_setedit(useeditmode & MODE_EDIT);
|
||||||
|
|
||||||
|
if (changed & MODE_TRAPSIG)
|
||||||
|
tty_setsig(useeditmode & MODE_TRAPSIG);
|
||||||
|
|
||||||
|
if (changed & MODE_SOFT_TAB)
|
||||||
|
tty_setsofttab(useeditmode & MODE_SOFT_TAB);
|
||||||
|
|
||||||
|
if (changed & MODE_LIT_ECHO)
|
||||||
|
tty_setlitecho(useeditmode & MODE_LIT_ECHO);
|
||||||
|
|
||||||
|
set_termbuf();
|
||||||
|
|
||||||
|
if (!ack) {
|
||||||
|
output_data("%c%c%c%c%c%c%c", IAC,
|
||||||
|
SB, TELOPT_LINEMODE, LM_MODE,
|
||||||
|
useeditmode|MODE_ACK,
|
||||||
|
IAC, SE);
|
||||||
|
}
|
||||||
|
|
||||||
|
editmode = useeditmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
} /* end of case LM_MODE */
|
||||||
|
#endif /* LINEMODE */
|
||||||
|
|
||||||
|
case TELOPT_NAWS:
|
||||||
|
#ifdef TIOCSWINSZ
|
||||||
|
{
|
||||||
|
struct winsize ws;
|
||||||
|
|
||||||
|
def_col = parm1;
|
||||||
|
def_row = parm2;
|
||||||
|
#ifdef LINEMODE
|
||||||
|
/*
|
||||||
|
* Defer changing window size until after terminal is
|
||||||
|
* initialized.
|
||||||
|
*/
|
||||||
|
if (terminit() == 0)
|
||||||
|
return;
|
||||||
|
#endif /* LINEMODE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change window size as requested by client.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ws.ws_col = parm1;
|
||||||
|
ws.ws_row = parm2;
|
||||||
|
(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
|
||||||
|
}
|
||||||
|
#endif /* TIOCSWINSZ */
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TELOPT_TSPEED:
|
||||||
|
{
|
||||||
|
def_tspeed = parm1;
|
||||||
|
def_rspeed = parm2;
|
||||||
|
#ifdef LINEMODE
|
||||||
|
/*
|
||||||
|
* Defer changing the terminal speed.
|
||||||
|
*/
|
||||||
|
if (terminit() == 0)
|
||||||
|
return;
|
||||||
|
#endif /* LINEMODE */
|
||||||
|
/*
|
||||||
|
* Change terminal speed as requested by client.
|
||||||
|
* We set the receive speed first, so that if we can't
|
||||||
|
* store separate receive and transmit speeds, the transmit
|
||||||
|
* speed will take precedence.
|
||||||
|
*/
|
||||||
|
tty_rspeed(parm2);
|
||||||
|
tty_tspeed(parm1);
|
||||||
|
set_termbuf();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
} /* end of case TELOPT_TSPEED */
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* What? */
|
||||||
|
break;
|
||||||
|
} /* end of switch */
|
||||||
|
|
||||||
|
netflush();
|
||||||
|
|
||||||
|
} /* end of clientstat */
|
||||||
|
|
||||||
|
#ifdef LINEMODE
|
||||||
|
/*
|
||||||
|
* defer_terminit
|
||||||
|
*
|
||||||
|
* Some things should not be done until after the login process has started
|
||||||
|
* and all the pty modes are set to what they are supposed to be. This
|
||||||
|
* function is called when the pty state has been processed for the first time.
|
||||||
|
* It calls other functions that do things that were deferred in each module.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
defer_terminit(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* local stuff that got deferred.
|
||||||
|
*/
|
||||||
|
if (def_tspeed != -1) {
|
||||||
|
clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed);
|
||||||
|
def_tspeed = def_rspeed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TIOCSWINSZ
|
||||||
|
if (def_col || def_row) {
|
||||||
|
struct winsize ws;
|
||||||
|
|
||||||
|
memset((char *)&ws, 0, sizeof(ws));
|
||||||
|
ws.ws_col = def_col;
|
||||||
|
ws.ws_row = def_row;
|
||||||
|
(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The only other module that currently defers anything.
|
||||||
|
*/
|
||||||
|
deferslc();
|
||||||
|
|
||||||
|
} /* end of defer_terminit */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* terminit
|
||||||
|
*
|
||||||
|
* Returns true if the pty state has been processed yet.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
terminit(void)
|
||||||
|
{
|
||||||
|
return(_terminit);
|
||||||
|
|
||||||
|
} /* end of terminit */
|
||||||
|
#endif /* LINEMODE */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ SubInclude HAIKU_TOP src libs expat ;
|
|||||||
SubInclude HAIKU_TOP src libs fluidsynth ;
|
SubInclude HAIKU_TOP src libs fluidsynth ;
|
||||||
SubInclude HAIKU_TOP src libs freetype2 ;
|
SubInclude HAIKU_TOP src libs freetype2 ;
|
||||||
SubInclude HAIKU_TOP src libs icon ;
|
SubInclude HAIKU_TOP src libs icon ;
|
||||||
|
SubInclude HAIKU_TOP src libs libtelnet ;
|
||||||
SubInclude HAIKU_TOP src libs ncurses ;
|
SubInclude HAIKU_TOP src libs ncurses ;
|
||||||
SubInclude HAIKU_TOP src libs pdflib ;
|
SubInclude HAIKU_TOP src libs pdflib ;
|
||||||
SubInclude HAIKU_TOP src libs png ;
|
SubInclude HAIKU_TOP src libs png ;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
SubDir HAIKU_TOP src libs libtelnet ;
|
||||||
|
|
||||||
|
SetSubDirSupportedPlatforms $(HAIKU_BONE_COMPATIBLE_PLATFORMS) ;
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ;
|
||||||
|
|
||||||
|
SharedLibrary libtelnet.a :
|
||||||
|
auth.c
|
||||||
|
enc_des.c
|
||||||
|
encrypt.c
|
||||||
|
genget.c
|
||||||
|
getent.c
|
||||||
|
kerberos.c
|
||||||
|
kerberos5.c
|
||||||
|
misc.c
|
||||||
|
#pk.c
|
||||||
|
read_password.c
|
||||||
|
rsaencpwd.c
|
||||||
|
sra.c
|
||||||
|
;
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)auth-proto.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/libtelnet/auth-proto.h,v 1.7 2001/11/30 22:28:07 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef AUTHENTICATION
|
||||||
|
|
||||||
|
Authenticator *findauthenticator(int, int);
|
||||||
|
|
||||||
|
void auth_init(const char *, int);
|
||||||
|
int auth_cmd(int, char **);
|
||||||
|
void auth_request(void);
|
||||||
|
void auth_send(unsigned char *, int);
|
||||||
|
void auth_send_retry(void);
|
||||||
|
void auth_is(unsigned char *, int);
|
||||||
|
void auth_reply(unsigned char *, int);
|
||||||
|
void auth_finished(Authenticator *, int);
|
||||||
|
int auth_wait(char *);
|
||||||
|
void auth_disable_name(char *);
|
||||||
|
void auth_gen_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
void auth_name(unsigned char *, int);
|
||||||
|
void auth_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
int auth_sendname(unsigned char *, int);
|
||||||
|
void auth_encrypt_user(char *);
|
||||||
|
int auth_disable(char *);
|
||||||
|
int auth_enable(char *);
|
||||||
|
int auth_togdebug(int);
|
||||||
|
int auth_status(void);
|
||||||
|
|
||||||
|
int getauthmask(char *, int *);
|
||||||
|
|
||||||
|
#ifdef KRB4
|
||||||
|
int kerberos4_init(Authenticator *, int);
|
||||||
|
int kerberos4_send(Authenticator *);
|
||||||
|
void kerberos4_is(Authenticator *, unsigned char *, int);
|
||||||
|
void kerberos4_reply(Authenticator *, unsigned char *, int);
|
||||||
|
int kerberos4_status(Authenticator *, char *, int);
|
||||||
|
void kerberos4_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef KRB5
|
||||||
|
int kerberos5_init(Authenticator *, int);
|
||||||
|
int kerberos5_send_mutual(Authenticator *);
|
||||||
|
int kerberos5_send_oneway(Authenticator *);
|
||||||
|
void kerberos5_is(Authenticator *, unsigned char *, int);
|
||||||
|
void kerberos5_reply(Authenticator *, unsigned char *, int);
|
||||||
|
int kerberos5_status(Authenticator *, char *, int level);
|
||||||
|
void kerberos5_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SRA
|
||||||
|
int sra_init(Authenticator *, int);
|
||||||
|
int sra_send(Authenticator *);
|
||||||
|
void sra_is(Authenticator *, unsigned char *, int);
|
||||||
|
void sra_reply(Authenticator *, unsigned char *, int);
|
||||||
|
int sra_status(Authenticator *, char *, int);
|
||||||
|
void sra_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,623 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static const char sccsid[] = "@(#)auth.c 8.3 (Berkeley) 5/30/95";
|
||||||
|
#endif /* not lint */
|
||||||
|
#endif
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/auth.c,v 1.10 2003/05/04 02:54:48 obrien Exp $");
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef AUTHENTICATION
|
||||||
|
#define AUTH_NAMES
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "misc-proto.h"
|
||||||
|
#include "auth-proto.h"
|
||||||
|
|
||||||
|
#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0)
|
||||||
|
|
||||||
|
#ifdef KRB4_ENCPWD
|
||||||
|
extern krb4encpwd_init();
|
||||||
|
extern krb4encpwd_send();
|
||||||
|
extern krb4encpwd_is();
|
||||||
|
extern krb4encpwd_reply();
|
||||||
|
extern krb4encpwd_status();
|
||||||
|
extern krb4encpwd_printsub();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RSA_ENCPWD
|
||||||
|
extern rsaencpwd_init();
|
||||||
|
extern rsaencpwd_send();
|
||||||
|
extern rsaencpwd_is();
|
||||||
|
extern rsaencpwd_reply();
|
||||||
|
extern rsaencpwd_status();
|
||||||
|
extern rsaencpwd_printsub();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int auth_debug_mode = 0;
|
||||||
|
static const char *Name = "Noname";
|
||||||
|
static int Server = 0;
|
||||||
|
static Authenticator *authenticated = 0;
|
||||||
|
static int authenticating = 0;
|
||||||
|
static int validuser = 0;
|
||||||
|
static unsigned char _auth_send_data[256];
|
||||||
|
static unsigned char *auth_send_data;
|
||||||
|
static int auth_send_cnt = 0;
|
||||||
|
|
||||||
|
int auth_onoff(char *type, int on);
|
||||||
|
void auth_encrypt_user(char *name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authentication types supported. Plese note that these are stored
|
||||||
|
* in priority order, i.e. try the first one first.
|
||||||
|
*/
|
||||||
|
Authenticator authenticators[] = {
|
||||||
|
#ifdef KRB5
|
||||||
|
# ifdef ENCRYPTION
|
||||||
|
{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
|
||||||
|
kerberos5_init,
|
||||||
|
kerberos5_send_mutual,
|
||||||
|
kerberos5_is,
|
||||||
|
kerberos5_reply,
|
||||||
|
kerberos5_status,
|
||||||
|
kerberos5_printsub },
|
||||||
|
# endif /* ENCRYPTION */
|
||||||
|
{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
|
||||||
|
kerberos5_init,
|
||||||
|
kerberos5_send_oneway,
|
||||||
|
kerberos5_is,
|
||||||
|
kerberos5_reply,
|
||||||
|
kerberos5_status,
|
||||||
|
kerberos5_printsub },
|
||||||
|
#endif
|
||||||
|
#ifdef KRB4
|
||||||
|
# ifdef ENCRYPTION
|
||||||
|
{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
|
||||||
|
kerberos4_init,
|
||||||
|
kerberos4_send,
|
||||||
|
kerberos4_is,
|
||||||
|
kerberos4_reply,
|
||||||
|
kerberos4_status,
|
||||||
|
kerberos4_printsub },
|
||||||
|
# endif /* ENCRYPTION */
|
||||||
|
{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
|
||||||
|
kerberos4_init,
|
||||||
|
kerberos4_send,
|
||||||
|
kerberos4_is,
|
||||||
|
kerberos4_reply,
|
||||||
|
kerberos4_status,
|
||||||
|
kerberos4_printsub },
|
||||||
|
#endif
|
||||||
|
#ifdef KRB4_ENCPWD
|
||||||
|
{ AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
|
||||||
|
krb4encpwd_init,
|
||||||
|
krb4encpwd_send,
|
||||||
|
krb4encpwd_is,
|
||||||
|
krb4encpwd_reply,
|
||||||
|
krb4encpwd_status,
|
||||||
|
krb4encpwd_printsub },
|
||||||
|
#endif
|
||||||
|
#ifdef RSA_ENCPWD
|
||||||
|
{ AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
|
||||||
|
rsaencpwd_init,
|
||||||
|
rsaencpwd_send,
|
||||||
|
rsaencpwd_is,
|
||||||
|
rsaencpwd_reply,
|
||||||
|
rsaencpwd_status,
|
||||||
|
rsaencpwd_printsub },
|
||||||
|
#endif
|
||||||
|
#ifdef SRA
|
||||||
|
{ AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
|
||||||
|
sra_init,
|
||||||
|
sra_send,
|
||||||
|
sra_is,
|
||||||
|
sra_reply,
|
||||||
|
sra_status,
|
||||||
|
sra_printsub },
|
||||||
|
|
||||||
|
#endif
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static Authenticator NoAuth = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
static int i_support = 0;
|
||||||
|
static int i_wont_support = 0;
|
||||||
|
|
||||||
|
Authenticator *
|
||||||
|
findauthenticator(int type, int way)
|
||||||
|
{
|
||||||
|
Authenticator *ap = authenticators;
|
||||||
|
|
||||||
|
while (ap->type && (ap->type != type || ap->way != way))
|
||||||
|
++ap;
|
||||||
|
return(ap->type ? ap : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_init(const char *name, int server)
|
||||||
|
{
|
||||||
|
Authenticator *ap = authenticators;
|
||||||
|
|
||||||
|
Server = server;
|
||||||
|
Name = name;
|
||||||
|
|
||||||
|
i_support = 0;
|
||||||
|
authenticated = 0;
|
||||||
|
authenticating = 0;
|
||||||
|
while (ap->type) {
|
||||||
|
if (!ap->init || (*ap->init)(ap, server)) {
|
||||||
|
i_support |= typemask(ap->type);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: I support auth type %d %d\r\n",
|
||||||
|
Name,
|
||||||
|
ap->type, ap->way);
|
||||||
|
}
|
||||||
|
else if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Init failed: auth type %d %d\r\n",
|
||||||
|
Name, ap->type, ap->way);
|
||||||
|
++ap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_disable_name(char *name)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < AUTHTYPE_CNT; ++x) {
|
||||||
|
if (AUTHTYPE_NAME(x) && !strcasecmp(name, AUTHTYPE_NAME(x))) {
|
||||||
|
i_wont_support |= typemask(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getauthmask(char *type, int *maskp)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
if (AUTHTYPE_NAME(0) && !strcasecmp(type, AUTHTYPE_NAME(0))) {
|
||||||
|
*maskp = -1;
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = 1; x < AUTHTYPE_CNT; ++x) {
|
||||||
|
if (AUTHTYPE_NAME(x) && !strcasecmp(type, AUTHTYPE_NAME(x))) {
|
||||||
|
*maskp = typemask(x);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_enable(char *type)
|
||||||
|
{
|
||||||
|
return(auth_onoff(type, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_disable(char *type)
|
||||||
|
{
|
||||||
|
return(auth_onoff(type, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_onoff(char *type, int on)
|
||||||
|
{
|
||||||
|
int i, mask = -1;
|
||||||
|
Authenticator *ap;
|
||||||
|
|
||||||
|
if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
|
||||||
|
printf("auth %s 'type'\n", on ? "enable" : "disable");
|
||||||
|
printf("Where 'type' is one of:\n");
|
||||||
|
printf("\t%s\n", AUTHTYPE_NAME(0));
|
||||||
|
mask = 0;
|
||||||
|
for (ap = authenticators; ap->type; ap++) {
|
||||||
|
if ((mask & (i = typemask(ap->type))) != 0)
|
||||||
|
continue;
|
||||||
|
mask |= i;
|
||||||
|
printf("\t%s\n", AUTHTYPE_NAME(ap->type));
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!getauthmask(type, &mask)) {
|
||||||
|
printf("%s: invalid authentication type\n", type);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (on)
|
||||||
|
i_wont_support &= ~mask;
|
||||||
|
else
|
||||||
|
i_wont_support |= mask;
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_togdebug(int on)
|
||||||
|
{
|
||||||
|
if (on < 0)
|
||||||
|
auth_debug_mode ^= 1;
|
||||||
|
else
|
||||||
|
auth_debug_mode = on;
|
||||||
|
printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_status(void)
|
||||||
|
{
|
||||||
|
Authenticator *ap;
|
||||||
|
int i, mask;
|
||||||
|
|
||||||
|
if (i_wont_support == -1)
|
||||||
|
printf("Authentication disabled\n");
|
||||||
|
else
|
||||||
|
printf("Authentication enabled\n");
|
||||||
|
|
||||||
|
mask = 0;
|
||||||
|
for (ap = authenticators; ap->type; ap++) {
|
||||||
|
if ((mask & (i = typemask(ap->type))) != 0)
|
||||||
|
continue;
|
||||||
|
mask |= i;
|
||||||
|
printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
|
||||||
|
(i_wont_support & typemask(ap->type)) ?
|
||||||
|
"disabled" : "enabled");
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine is called by the server to start authentication
|
||||||
|
* negotiation.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
auth_request(void)
|
||||||
|
{
|
||||||
|
static unsigned char str_request[64] = { IAC, SB,
|
||||||
|
TELOPT_AUTHENTICATION,
|
||||||
|
TELQUAL_SEND, };
|
||||||
|
Authenticator *ap = authenticators;
|
||||||
|
unsigned char *e = str_request + 4;
|
||||||
|
|
||||||
|
if (!authenticating) {
|
||||||
|
authenticating = 1;
|
||||||
|
while (ap->type) {
|
||||||
|
if (i_support & ~i_wont_support & typemask(ap->type)) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf(">>>%s: Sending type %d %d\r\n",
|
||||||
|
Name, ap->type, ap->way);
|
||||||
|
}
|
||||||
|
*e++ = ap->type;
|
||||||
|
*e++ = ap->way;
|
||||||
|
}
|
||||||
|
++ap;
|
||||||
|
}
|
||||||
|
*e++ = IAC;
|
||||||
|
*e++ = SE;
|
||||||
|
net_write(str_request, e - str_request);
|
||||||
|
printsub('>', &str_request[2], e - str_request - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is called when an AUTH SEND is received.
|
||||||
|
* It should never arrive on the server side (as only the server can
|
||||||
|
* send an AUTH SEND).
|
||||||
|
* You should probably respond to it if you can...
|
||||||
|
*
|
||||||
|
* If you want to respond to the types out of order (i.e. even
|
||||||
|
* if he sends LOGIN KERBEROS and you support both, you respond
|
||||||
|
* with KERBEROS instead of LOGIN (which is against what the
|
||||||
|
* protocol says)) you will have to hack this code...
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
auth_send(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
Authenticator *ap;
|
||||||
|
static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
|
||||||
|
TELQUAL_IS, AUTHTYPE_NULL, 0,
|
||||||
|
IAC, SE };
|
||||||
|
if (Server) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf(">>>%s: auth_send called!\r\n", Name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf(">>>%s: auth_send got:", Name);
|
||||||
|
printd(data, cnt); printf("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the data, if it is new, so that we can continue looking
|
||||||
|
* at it if the authorization we try doesn't work
|
||||||
|
*/
|
||||||
|
if (data < _auth_send_data ||
|
||||||
|
data > _auth_send_data + sizeof(_auth_send_data)) {
|
||||||
|
auth_send_cnt = (size_t)cnt > sizeof(_auth_send_data)
|
||||||
|
? sizeof(_auth_send_data)
|
||||||
|
: cnt;
|
||||||
|
memmove((void *)_auth_send_data, (void *)data, auth_send_cnt);
|
||||||
|
auth_send_data = _auth_send_data;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This is probably a no-op, but we just make sure
|
||||||
|
*/
|
||||||
|
auth_send_data = data;
|
||||||
|
auth_send_cnt = cnt;
|
||||||
|
}
|
||||||
|
while ((auth_send_cnt -= 2) >= 0) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: He supports %d\r\n",
|
||||||
|
Name, *auth_send_data);
|
||||||
|
if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
|
||||||
|
ap = findauthenticator(auth_send_data[0],
|
||||||
|
auth_send_data[1]);
|
||||||
|
if (ap && ap->send) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Trying %d %d\r\n",
|
||||||
|
Name, auth_send_data[0],
|
||||||
|
auth_send_data[1]);
|
||||||
|
if ((*ap->send)(ap)) {
|
||||||
|
/*
|
||||||
|
* Okay, we found one we like
|
||||||
|
* and did it.
|
||||||
|
* we can go home now.
|
||||||
|
*/
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Using type %d\r\n",
|
||||||
|
Name, *auth_send_data);
|
||||||
|
auth_send_data += 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* else
|
||||||
|
* just continue on and look for the
|
||||||
|
* next one if we didn't do anything.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
auth_send_data += 2;
|
||||||
|
}
|
||||||
|
net_write(str_none, sizeof(str_none));
|
||||||
|
printsub('>', &str_none[2], sizeof(str_none) - 2);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Sent failure message\r\n", Name);
|
||||||
|
auth_finished(0, AUTH_REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_send_retry(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* if auth_send_cnt <= 0 then auth_send will end up rejecting
|
||||||
|
* the authentication and informing the other side of this.
|
||||||
|
*/
|
||||||
|
auth_send(auth_send_data, auth_send_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_is(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
Authenticator *ap;
|
||||||
|
|
||||||
|
if (cnt < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data[0] == AUTHTYPE_NULL) {
|
||||||
|
auth_finished(0, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ap = findauthenticator(data[0], data[1]))) {
|
||||||
|
if (ap->is)
|
||||||
|
(*ap->is)(ap, data+2, cnt-2);
|
||||||
|
} else if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Invalid authentication in IS: %d\r\n",
|
||||||
|
Name, *data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_reply(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
Authenticator *ap;
|
||||||
|
|
||||||
|
if (cnt < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((ap = findauthenticator(data[0], data[1]))) {
|
||||||
|
if (ap->reply)
|
||||||
|
(*ap->reply)(ap, data+2, cnt-2);
|
||||||
|
} else if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Invalid authentication in SEND: %d\r\n",
|
||||||
|
Name, *data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_name(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
unsigned char savename[256];
|
||||||
|
|
||||||
|
if (cnt < 1) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Empty name in NAME\r\n", Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((size_t)cnt > sizeof(savename) - 1) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
|
||||||
|
Name, cnt, (u_int)sizeof(savename)-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove((void *)savename, (void *)data, cnt);
|
||||||
|
savename[cnt] = '\0'; /* Null terminate */
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
|
||||||
|
auth_encrypt_user(savename);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_sendname(unsigned char *cp, int len)
|
||||||
|
{
|
||||||
|
static unsigned char str_request[256+6]
|
||||||
|
= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
|
||||||
|
unsigned char *e = str_request + 4;
|
||||||
|
unsigned char *ee = &str_request[sizeof(str_request)-2];
|
||||||
|
|
||||||
|
while (--len >= 0) {
|
||||||
|
if ((*e++ = *cp++) == IAC)
|
||||||
|
*e++ = IAC;
|
||||||
|
if (e >= ee)
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
*e++ = IAC;
|
||||||
|
*e++ = SE;
|
||||||
|
net_write(str_request, e - str_request);
|
||||||
|
printsub('>', &str_request[2], e - &str_request[2]);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_finished(Authenticator *ap, int result)
|
||||||
|
{
|
||||||
|
if (!(authenticated = ap))
|
||||||
|
authenticated = &NoAuth;
|
||||||
|
validuser = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
static void
|
||||||
|
auth_intr(int sig __unused)
|
||||||
|
{
|
||||||
|
auth_finished(0, AUTH_REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_wait(char *name)
|
||||||
|
{
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf(">>>%s: in auth_wait.\r\n", Name);
|
||||||
|
|
||||||
|
if (Server && !authenticating)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
(void) signal(SIGALRM, auth_intr);
|
||||||
|
alarm(30);
|
||||||
|
while (!authenticated)
|
||||||
|
if (telnet_spin())
|
||||||
|
break;
|
||||||
|
alarm(0);
|
||||||
|
(void) signal(SIGALRM, SIG_DFL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now check to see if the user is valid or not
|
||||||
|
*/
|
||||||
|
if (!authenticated || authenticated == &NoAuth)
|
||||||
|
return(AUTH_REJECT);
|
||||||
|
|
||||||
|
if (validuser == AUTH_VALID)
|
||||||
|
validuser = AUTH_USER;
|
||||||
|
|
||||||
|
if (authenticated->status)
|
||||||
|
validuser = (*authenticated->status)(authenticated,
|
||||||
|
name, validuser);
|
||||||
|
return(validuser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
Authenticator *ap;
|
||||||
|
|
||||||
|
if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
|
||||||
|
(*ap->printsub)(data, cnt, buf, buflen);
|
||||||
|
else
|
||||||
|
auth_gen_printsub(data, cnt, buf, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
unsigned char *cp;
|
||||||
|
unsigned char tbuf[16];
|
||||||
|
|
||||||
|
cnt -= 3;
|
||||||
|
data += 3;
|
||||||
|
buf[buflen-1] = '\0';
|
||||||
|
buf[buflen-2] = '*';
|
||||||
|
buflen -= 2;
|
||||||
|
for (; cnt > 0; cnt--, data++) {
|
||||||
|
sprintf((char *)tbuf, " %d", *data);
|
||||||
|
for (cp = tbuf; *cp && buflen > 0; --buflen)
|
||||||
|
*buf++ = *cp++;
|
||||||
|
if (buflen <= 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*buf = '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)auth.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/libtelnet/auth.h,v 1.3 2001/11/30 21:06:34 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUTH__
|
||||||
|
#define __AUTH__
|
||||||
|
|
||||||
|
#define AUTH_REJECT 0 /* Rejected */
|
||||||
|
#define AUTH_UNKNOWN 1 /* We don't know who he is, but he's okay */
|
||||||
|
#define AUTH_OTHER 2 /* We know him, but not his name */
|
||||||
|
#define AUTH_USER 3 /* We know he name */
|
||||||
|
#define AUTH_VALID 4 /* We know him, and he needs no password */
|
||||||
|
|
||||||
|
typedef struct XauthP {
|
||||||
|
int type;
|
||||||
|
int way;
|
||||||
|
int (*init)(struct XauthP *, int);
|
||||||
|
int (*send)(struct XauthP *);
|
||||||
|
void (*is)(struct XauthP *, unsigned char *, int);
|
||||||
|
void (*reply)(struct XauthP *, unsigned char *, int);
|
||||||
|
int (*status)(struct XauthP *, char *, int);
|
||||||
|
void (*printsub)(unsigned char *, int, unsigned char *, int);
|
||||||
|
} Authenticator;
|
||||||
|
|
||||||
|
#include "auth-proto.h"
|
||||||
|
|
||||||
|
extern int auth_debug_mode;
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)enc-proto.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/libtelnet/enc-proto.h,v 1.7 2001/11/30 22:28:07 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
void encrypt_init(const char *, int);
|
||||||
|
Encryptions *findencryption(int);
|
||||||
|
void encrypt_send_supprt(void);
|
||||||
|
void encrypt_auto(int);
|
||||||
|
void decrypt_auto(int);
|
||||||
|
void encrypt_is(unsigned char *, int);
|
||||||
|
void encrypt_reply(unsigned char *, int);
|
||||||
|
void encrypt_start_input(int);
|
||||||
|
void encrypt_session_key(Session_Key *, int);
|
||||||
|
void encrypt_end_input(void);
|
||||||
|
void encrypt_start_output(int);
|
||||||
|
void encrypt_end_output(void);
|
||||||
|
void encrypt_send_request_start(void);
|
||||||
|
void encrypt_send_request_end(void);
|
||||||
|
void encrypt_send_end(void);
|
||||||
|
void encrypt_wait(void);
|
||||||
|
void encrypt_send_support(void);
|
||||||
|
void encrypt_send_keyid(int, const char *, int, int);
|
||||||
|
void encrypt_start(unsigned char *, int);
|
||||||
|
void encrypt_end(void);
|
||||||
|
void encrypt_support(unsigned char *, int);
|
||||||
|
void encrypt_request_start(unsigned char *, int);
|
||||||
|
void encrypt_request_end(void);
|
||||||
|
void encrypt_enc_keyid(unsigned char *, int);
|
||||||
|
void encrypt_dec_keyid(unsigned char *, int);
|
||||||
|
void encrypt_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
void encrypt_gen_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
void encrypt_display(void);
|
||||||
|
|
||||||
|
void fb64_printsub(unsigned char *, int, unsigned char *, int, const char *);
|
||||||
|
|
||||||
|
int EncryptEnable(char *, char *);
|
||||||
|
int EncryptDisable(char *, char *);
|
||||||
|
int EncryptStatus(void);
|
||||||
|
int EncryptDebug(int);
|
||||||
|
int EncryptVerbose(int);
|
||||||
|
int EncryptAutoEnc(int);
|
||||||
|
int EncryptAutoDec(int);
|
||||||
|
|
||||||
|
void krbdes_encrypt(unsigned char *, int);
|
||||||
|
int krbdes_decrypt(int);
|
||||||
|
int krbdes_is(unsigned char *, int);
|
||||||
|
int krbdes_reply(unsigned char *, int);
|
||||||
|
void krbdes_init(int);
|
||||||
|
int krbdes_start(int, int);
|
||||||
|
void krbdes_session(Session_Key *, int);
|
||||||
|
void krbdes_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
|
||||||
|
void cfb64_encrypt(unsigned char *, int);
|
||||||
|
int cfb64_decrypt(int);
|
||||||
|
void cfb64_init(int);
|
||||||
|
int cfb64_start(int, int);
|
||||||
|
int cfb64_is(unsigned char *, int);
|
||||||
|
int cfb64_reply(unsigned char *, int);
|
||||||
|
void cfb64_session(Session_Key *, int);
|
||||||
|
int cfb64_keyid(int, unsigned char *, int *);
|
||||||
|
void cfb64_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
|
||||||
|
void ofb64_encrypt(unsigned char *, int);
|
||||||
|
int ofb64_decrypt(int);
|
||||||
|
void ofb64_init(int);
|
||||||
|
int ofb64_start(int, int);
|
||||||
|
int ofb64_is(unsigned char *, int);
|
||||||
|
int ofb64_reply(unsigned char *, int);
|
||||||
|
void ofb64_session(Session_Key *, int);
|
||||||
|
int ofb64_keyid(int, unsigned char *, int *);
|
||||||
|
void ofb64_printsub(unsigned char *, int, unsigned char *, int);
|
||||||
|
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
@@ -0,0 +1,662 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95";
|
||||||
|
#endif /* not lint */
|
||||||
|
#endif
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/enc_des.c,v 1.10 2003/05/04 02:54:48 obrien Exp $");
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
# ifdef AUTHENTICATION
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
#include <openssl/des.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "key-proto.h"
|
||||||
|
#include "misc-proto.h"
|
||||||
|
|
||||||
|
extern int encrypt_debug_mode;
|
||||||
|
|
||||||
|
#define CFB 0
|
||||||
|
#define OFB 1
|
||||||
|
|
||||||
|
#define NO_SEND_IV 1
|
||||||
|
#define NO_RECV_IV 2
|
||||||
|
#define NO_KEYID 4
|
||||||
|
#define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID)
|
||||||
|
#define SUCCESS 0
|
||||||
|
#define FAILED -1
|
||||||
|
|
||||||
|
|
||||||
|
struct fb {
|
||||||
|
Block krbdes_key;
|
||||||
|
Schedule krbdes_sched;
|
||||||
|
Block temp_feed;
|
||||||
|
unsigned char fb_feed[64];
|
||||||
|
int need_start;
|
||||||
|
int state[2];
|
||||||
|
int keyid[2];
|
||||||
|
struct stinfo {
|
||||||
|
Block str_output;
|
||||||
|
Block str_feed;
|
||||||
|
Block str_iv;
|
||||||
|
Block str_ikey;
|
||||||
|
Schedule str_sched;
|
||||||
|
int str_index;
|
||||||
|
int str_flagshift;
|
||||||
|
} streams[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct fb fb[2];
|
||||||
|
|
||||||
|
struct keyidlist {
|
||||||
|
const char *keyid;
|
||||||
|
int keyidlen;
|
||||||
|
char *key;
|
||||||
|
int keylen;
|
||||||
|
int flags;
|
||||||
|
} keyidlist [] = {
|
||||||
|
{ "\0", 1, 0, 0, 0 }, /* default key of zero */
|
||||||
|
{ 0, 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define KEYFLAG_MASK 03
|
||||||
|
|
||||||
|
#define KEYFLAG_NOINIT 00
|
||||||
|
#define KEYFLAG_INIT 01
|
||||||
|
#define KEYFLAG_OK 02
|
||||||
|
#define KEYFLAG_BAD 03
|
||||||
|
|
||||||
|
#define KEYFLAG_SHIFT 2
|
||||||
|
|
||||||
|
#define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2)))
|
||||||
|
|
||||||
|
#define FB64_IV 1
|
||||||
|
#define FB64_IV_OK 2
|
||||||
|
#define FB64_IV_BAD 3
|
||||||
|
|
||||||
|
|
||||||
|
void fb64_stream_iv(Block, struct stinfo *);
|
||||||
|
void fb64_init(struct fb *);
|
||||||
|
static int fb64_start(struct fb *, int, int);
|
||||||
|
int fb64_is(unsigned char *, int, struct fb *);
|
||||||
|
int fb64_reply(unsigned char *, int, struct fb *);
|
||||||
|
static void fb64_session(Session_Key *, int, struct fb *);
|
||||||
|
void fb64_stream_key(Block, struct stinfo *);
|
||||||
|
int fb64_keyid(int, unsigned char *, int *, struct fb *);
|
||||||
|
|
||||||
|
void
|
||||||
|
cfb64_init(int server __unused)
|
||||||
|
{
|
||||||
|
fb64_init(&fb[CFB]);
|
||||||
|
fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
|
||||||
|
fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
|
||||||
|
fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ofb64_init(int server __unused)
|
||||||
|
{
|
||||||
|
fb64_init(&fb[OFB]);
|
||||||
|
fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
|
||||||
|
fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
|
||||||
|
fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fb64_init(struct fb *fbp)
|
||||||
|
{
|
||||||
|
memset((void *)fbp, 0, sizeof(*fbp));
|
||||||
|
fbp->state[0] = fbp->state[1] = FAILED;
|
||||||
|
fbp->fb_feed[0] = IAC;
|
||||||
|
fbp->fb_feed[1] = SB;
|
||||||
|
fbp->fb_feed[2] = TELOPT_ENCRYPT;
|
||||||
|
fbp->fb_feed[3] = ENCRYPT_IS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns:
|
||||||
|
* -1: some error. Negotiation is done, encryption not ready.
|
||||||
|
* 0: Successful, initial negotiation all done.
|
||||||
|
* 1: successful, negotiation not done yet.
|
||||||
|
* 2: Not yet. Other things (like getting the key from
|
||||||
|
* Kerberos) have to happen before we can continue.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cfb64_start(int dir, int server)
|
||||||
|
{
|
||||||
|
return(fb64_start(&fb[CFB], dir, server));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ofb64_start(int dir, int server)
|
||||||
|
{
|
||||||
|
return(fb64_start(&fb[OFB], dir, server));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fb64_start(struct fb *fbp, int dir, int server __unused)
|
||||||
|
{
|
||||||
|
size_t x;
|
||||||
|
unsigned char *p;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
switch (dir) {
|
||||||
|
case DIR_DECRYPT:
|
||||||
|
/*
|
||||||
|
* This is simply a request to have the other side
|
||||||
|
* start output (our input). He will negotiate an
|
||||||
|
* IV so we need not look for it.
|
||||||
|
*/
|
||||||
|
state = fbp->state[dir-1];
|
||||||
|
if (state == FAILED)
|
||||||
|
state = IN_PROGRESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIR_ENCRYPT:
|
||||||
|
state = fbp->state[dir-1];
|
||||||
|
if (state == FAILED)
|
||||||
|
state = IN_PROGRESS;
|
||||||
|
else if ((state & NO_SEND_IV) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!VALIDKEY(fbp->krbdes_key)) {
|
||||||
|
fbp->need_start = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state &= ~NO_SEND_IV;
|
||||||
|
state |= NO_RECV_IV;
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf("Creating new feed\r\n");
|
||||||
|
/*
|
||||||
|
* Create a random feed and send it over.
|
||||||
|
*/
|
||||||
|
des_random_key((Block *)fbp->temp_feed);
|
||||||
|
des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed,
|
||||||
|
fbp->krbdes_sched, 1);
|
||||||
|
p = fbp->fb_feed + 3;
|
||||||
|
*p++ = ENCRYPT_IS;
|
||||||
|
p++;
|
||||||
|
*p++ = FB64_IV;
|
||||||
|
for (x = 0; x < sizeof(Block); ++x) {
|
||||||
|
if ((*p++ = fbp->temp_feed[x]) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
|
||||||
|
net_write(fbp->fb_feed, p - fbp->fb_feed);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return(FAILED);
|
||||||
|
}
|
||||||
|
return(fbp->state[dir-1] = state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns:
|
||||||
|
* -1: some error. Negotiation is done, encryption not ready.
|
||||||
|
* 0: Successful, initial negotiation all done.
|
||||||
|
* 1: successful, negotiation not done yet.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cfb64_is(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
return(fb64_is(data, cnt, &fb[CFB]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ofb64_is(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
return(fb64_is(data, cnt, &fb[OFB]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fb64_is(unsigned char *data, int cnt, struct fb *fbp)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
int state = fbp->state[DIR_DECRYPT-1];
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
switch (*data++) {
|
||||||
|
case FB64_IV:
|
||||||
|
if (cnt != sizeof(Block)) {
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf("CFB64: initial vector failed on size\r\n");
|
||||||
|
state = FAILED;
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf("CFB64: initial vector received\r\n");
|
||||||
|
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf("Initializing Decrypt stream\r\n");
|
||||||
|
|
||||||
|
fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]);
|
||||||
|
|
||||||
|
p = fbp->fb_feed + 3;
|
||||||
|
*p++ = ENCRYPT_REPLY;
|
||||||
|
p++;
|
||||||
|
*p++ = FB64_IV_OK;
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
|
||||||
|
net_write(fbp->fb_feed, p - fbp->fb_feed);
|
||||||
|
|
||||||
|
state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (encrypt_debug_mode) {
|
||||||
|
printf("Unknown option type: %d\r\n", *(data-1));
|
||||||
|
printd(data, cnt);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
/* FALL THROUGH */
|
||||||
|
failure:
|
||||||
|
/*
|
||||||
|
* We failed. Send an FB64_IV_BAD option
|
||||||
|
* to the other side so it will know that
|
||||||
|
* things failed.
|
||||||
|
*/
|
||||||
|
p = fbp->fb_feed + 3;
|
||||||
|
*p++ = ENCRYPT_REPLY;
|
||||||
|
p++;
|
||||||
|
*p++ = FB64_IV_BAD;
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
|
||||||
|
net_write(fbp->fb_feed, p - fbp->fb_feed);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(fbp->state[DIR_DECRYPT-1] = state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns:
|
||||||
|
* -1: some error. Negotiation is done, encryption not ready.
|
||||||
|
* 0: Successful, initial negotiation all done.
|
||||||
|
* 1: successful, negotiation not done yet.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cfb64_reply(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
return(fb64_reply(data, cnt, &fb[CFB]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ofb64_reply(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
return(fb64_reply(data, cnt, &fb[OFB]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fb64_reply(unsigned char *data, int cnt, struct fb *fbp)
|
||||||
|
{
|
||||||
|
int state = fbp->state[DIR_ENCRYPT-1];
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
switch (*data++) {
|
||||||
|
case FB64_IV_OK:
|
||||||
|
fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
|
||||||
|
if (state == FAILED)
|
||||||
|
state = IN_PROGRESS;
|
||||||
|
state &= ~NO_RECV_IV;
|
||||||
|
encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FB64_IV_BAD:
|
||||||
|
memset(fbp->temp_feed, 0, sizeof(Block));
|
||||||
|
fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
|
||||||
|
state = FAILED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (encrypt_debug_mode) {
|
||||||
|
printf("Unknown option type: %d\r\n", data[-1]);
|
||||||
|
printd(data, cnt);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
/* FALL THROUGH */
|
||||||
|
failure:
|
||||||
|
state = FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(fbp->state[DIR_ENCRYPT-1] = state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cfb64_session(Session_Key *key, int server)
|
||||||
|
{
|
||||||
|
fb64_session(key, server, &fb[CFB]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ofb64_session(Session_Key *key, int server)
|
||||||
|
{
|
||||||
|
fb64_session(key, server, &fb[OFB]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fb64_session(Session_Key *key, int server, struct fb *fbp)
|
||||||
|
{
|
||||||
|
if (!key || key->type != SK_DES) {
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf("Can't set krbdes's session key (%d != %d)\r\n",
|
||||||
|
key ? key->type : -1, SK_DES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
|
||||||
|
|
||||||
|
fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
|
||||||
|
fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
|
||||||
|
|
||||||
|
des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched);
|
||||||
|
/*
|
||||||
|
* Now look to see if krbdes_start() was was waiting for
|
||||||
|
* the key to show up. If so, go ahead an call it now
|
||||||
|
* that we have the key.
|
||||||
|
*/
|
||||||
|
if (fbp->need_start) {
|
||||||
|
fbp->need_start = 0;
|
||||||
|
fb64_start(fbp, DIR_ENCRYPT, server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We only accept a keyid of 0. If we get a keyid of
|
||||||
|
* 0, then mark the state as SUCCESS.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cfb64_keyid(int dir, unsigned char *kp, int *lenp)
|
||||||
|
{
|
||||||
|
return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ofb64_keyid(int dir, unsigned char *kp, int *lenp)
|
||||||
|
{
|
||||||
|
return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp)
|
||||||
|
{
|
||||||
|
int state = fbp->state[dir-1];
|
||||||
|
|
||||||
|
if (*lenp != 1 || (*kp != '\0')) {
|
||||||
|
*lenp = 0;
|
||||||
|
return(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == FAILED)
|
||||||
|
state = IN_PROGRESS;
|
||||||
|
|
||||||
|
state &= ~NO_KEYID;
|
||||||
|
|
||||||
|
return(fbp->state[dir-1] = state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type)
|
||||||
|
{
|
||||||
|
char lbuf[32];
|
||||||
|
int i;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
buf[buflen-1] = '\0'; /* make sure it's NULL terminated */
|
||||||
|
buflen -= 1;
|
||||||
|
|
||||||
|
switch(data[2]) {
|
||||||
|
case FB64_IV:
|
||||||
|
sprintf(lbuf, "%s_IV", type);
|
||||||
|
cp = lbuf;
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case FB64_IV_OK:
|
||||||
|
sprintf(lbuf, "%s_IV_OK", type);
|
||||||
|
cp = lbuf;
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case FB64_IV_BAD:
|
||||||
|
sprintf(lbuf, "%s_IV_BAD", type);
|
||||||
|
cp = lbuf;
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(lbuf, " %d (unknown)", data[2]);
|
||||||
|
cp = lbuf;
|
||||||
|
common:
|
||||||
|
for (; (buflen > 0) && (*buf = *cp++); buf++)
|
||||||
|
buflen--;
|
||||||
|
for (i = 3; i < cnt; i++) {
|
||||||
|
sprintf(lbuf, " %d", data[i]);
|
||||||
|
for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
|
||||||
|
buflen--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
fb64_printsub(data, cnt, buf, buflen, "CFB64");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
fb64_printsub(data, cnt, buf, buflen, "OFB64");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fb64_stream_iv(Block seed, struct stinfo *stp)
|
||||||
|
{
|
||||||
|
|
||||||
|
memmove((void *)stp->str_iv, (void *)seed, sizeof(Block));
|
||||||
|
memmove((void *)stp->str_output, (void *)seed, sizeof(Block));
|
||||||
|
|
||||||
|
des_key_sched((Block *)stp->str_ikey, stp->str_sched);
|
||||||
|
|
||||||
|
stp->str_index = sizeof(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fb64_stream_key(Block key, struct stinfo *stp)
|
||||||
|
{
|
||||||
|
memmove((void *)stp->str_ikey, (void *)key, sizeof(Block));
|
||||||
|
des_key_sched((Block *)key, stp->str_sched);
|
||||||
|
|
||||||
|
memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
|
||||||
|
|
||||||
|
stp->str_index = sizeof(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DES 64 bit Cipher Feedback
|
||||||
|
*
|
||||||
|
* key --->+-----+
|
||||||
|
* +->| DES |--+
|
||||||
|
* | +-----+ |
|
||||||
|
* | v
|
||||||
|
* INPUT --(--------->(+)+---> DATA
|
||||||
|
* | |
|
||||||
|
* +-------------+
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Given:
|
||||||
|
* iV: Initial vector, 64 bits (8 bytes) long.
|
||||||
|
* Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
|
||||||
|
* On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
|
||||||
|
*
|
||||||
|
* V0 = DES(iV, key)
|
||||||
|
* On = Dn ^ Vn
|
||||||
|
* V(n+1) = DES(On, key)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
cfb64_encrypt(unsigned char *s, int c)
|
||||||
|
{
|
||||||
|
struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1];
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = stp->str_index;
|
||||||
|
while (c-- > 0) {
|
||||||
|
if (idx == sizeof(Block)) {
|
||||||
|
Block b;
|
||||||
|
des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
|
||||||
|
memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On encryption, we store (feed ^ data) which is cypher */
|
||||||
|
*s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s);
|
||||||
|
s++;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
stp->str_index = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfb64_decrypt(int data)
|
||||||
|
{
|
||||||
|
struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if (data == -1) {
|
||||||
|
/*
|
||||||
|
* Back up one byte. It is assumed that we will
|
||||||
|
* never back up more than one byte. If we do, this
|
||||||
|
* may or may not work.
|
||||||
|
*/
|
||||||
|
if (stp->str_index)
|
||||||
|
--stp->str_index;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = stp->str_index++;
|
||||||
|
if (idx == sizeof(Block)) {
|
||||||
|
Block b;
|
||||||
|
des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
|
||||||
|
memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
|
||||||
|
stp->str_index = 1; /* Next time will be 1 */
|
||||||
|
idx = 0; /* But now use 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On decryption we store (data) which is cypher. */
|
||||||
|
stp->str_output[idx] = data;
|
||||||
|
return(data ^ stp->str_feed[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DES 64 bit Output Feedback
|
||||||
|
*
|
||||||
|
* key --->+-----+
|
||||||
|
* +->| DES |--+
|
||||||
|
* | +-----+ |
|
||||||
|
* +-----------+
|
||||||
|
* v
|
||||||
|
* INPUT -------->(+) ----> DATA
|
||||||
|
*
|
||||||
|
* Given:
|
||||||
|
* iV: Initial vector, 64 bits (8 bytes) long.
|
||||||
|
* Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
|
||||||
|
* On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
|
||||||
|
*
|
||||||
|
* V0 = DES(iV, key)
|
||||||
|
* V(n+1) = DES(Vn, key)
|
||||||
|
* On = Dn ^ Vn
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ofb64_encrypt(unsigned char *s, int c)
|
||||||
|
{
|
||||||
|
struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1];
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = stp->str_index;
|
||||||
|
while (c-- > 0) {
|
||||||
|
if (idx == sizeof(Block)) {
|
||||||
|
Block b;
|
||||||
|
des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
|
||||||
|
memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
*s++ ^= stp->str_feed[idx];
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
stp->str_index = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ofb64_decrypt(int data)
|
||||||
|
{
|
||||||
|
struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if (data == -1) {
|
||||||
|
/*
|
||||||
|
* Back up one byte. It is assumed that we will
|
||||||
|
* never back up more than one byte. If we do, this
|
||||||
|
* may or may not work.
|
||||||
|
*/
|
||||||
|
if (stp->str_index)
|
||||||
|
--stp->str_index;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = stp->str_index++;
|
||||||
|
if (idx == sizeof(Block)) {
|
||||||
|
Block b;
|
||||||
|
des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
|
||||||
|
memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
|
||||||
|
stp->str_index = 1; /* Next time will be 1 */
|
||||||
|
idx = 0; /* But now use 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return(data ^ stp->str_feed[idx]);
|
||||||
|
}
|
||||||
|
# endif /* AUTHENTICATION */
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
@@ -0,0 +1,953 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/encrypt.c,v 1.9 2002/06/26 17:06:14 markm Exp $");
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static const char sccsid[] = "@(#)encrypt.c 8.2 (Berkeley) 5/30/95";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#define ENCRYPT_NAMES
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions pointers point to the current routines
|
||||||
|
* for encrypting and decrypting data.
|
||||||
|
*/
|
||||||
|
void (*encrypt_output)(unsigned char *, int);
|
||||||
|
int (*decrypt_input)(int);
|
||||||
|
|
||||||
|
int EncryptType(char *type, char *mode);
|
||||||
|
int EncryptStart(char *mode);
|
||||||
|
int EncryptStop(char *mode);
|
||||||
|
int EncryptStartInput(void);
|
||||||
|
int EncryptStartOutput(void);
|
||||||
|
int EncryptStopInput(void);
|
||||||
|
int EncryptStopOutput(void);
|
||||||
|
|
||||||
|
int encrypt_debug_mode = 0;
|
||||||
|
static int decrypt_mode = 0;
|
||||||
|
static int encrypt_mode = 0;
|
||||||
|
static int encrypt_verbose = 0;
|
||||||
|
static int autoencrypt = 0;
|
||||||
|
static int autodecrypt = 0;
|
||||||
|
static int havesessionkey = 0;
|
||||||
|
static int Server = 0;
|
||||||
|
static const char *Name = "Noname";
|
||||||
|
|
||||||
|
#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0)
|
||||||
|
|
||||||
|
static u_long i_support_encrypt = 0
|
||||||
|
| typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
|
||||||
|
|0;
|
||||||
|
static u_long i_support_decrypt = 0
|
||||||
|
| typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
|
||||||
|
|0;
|
||||||
|
|
||||||
|
static u_long i_wont_support_encrypt = 0;
|
||||||
|
static u_long i_wont_support_decrypt = 0;
|
||||||
|
#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt)
|
||||||
|
#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt)
|
||||||
|
|
||||||
|
static u_long remote_supports_encrypt = 0;
|
||||||
|
static u_long remote_supports_decrypt = 0;
|
||||||
|
|
||||||
|
static Encryptions encryptions[] = {
|
||||||
|
{ "DES_CFB64", ENCTYPE_DES_CFB64,
|
||||||
|
cfb64_encrypt,
|
||||||
|
cfb64_decrypt,
|
||||||
|
cfb64_init,
|
||||||
|
cfb64_start,
|
||||||
|
cfb64_is,
|
||||||
|
cfb64_reply,
|
||||||
|
cfb64_session,
|
||||||
|
cfb64_keyid,
|
||||||
|
cfb64_printsub },
|
||||||
|
{ "DES_OFB64", ENCTYPE_DES_OFB64,
|
||||||
|
ofb64_encrypt,
|
||||||
|
ofb64_decrypt,
|
||||||
|
ofb64_init,
|
||||||
|
ofb64_start,
|
||||||
|
ofb64_is,
|
||||||
|
ofb64_reply,
|
||||||
|
ofb64_session,
|
||||||
|
ofb64_keyid,
|
||||||
|
ofb64_printsub },
|
||||||
|
{ NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
|
||||||
|
ENCRYPT_SUPPORT };
|
||||||
|
static unsigned char str_suplen = 0;
|
||||||
|
static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
|
||||||
|
static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
|
||||||
|
|
||||||
|
Encryptions *
|
||||||
|
findencryption(int type)
|
||||||
|
{
|
||||||
|
Encryptions *ep = encryptions;
|
||||||
|
|
||||||
|
if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & (unsigned)typemask(type)))
|
||||||
|
return(0);
|
||||||
|
while (ep->type && ep->type != type)
|
||||||
|
++ep;
|
||||||
|
return(ep->type ? ep : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Encryptions *
|
||||||
|
finddecryption(int type)
|
||||||
|
{
|
||||||
|
Encryptions *ep = encryptions;
|
||||||
|
|
||||||
|
if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)typemask(type)))
|
||||||
|
return(0);
|
||||||
|
while (ep->type && ep->type != type)
|
||||||
|
++ep;
|
||||||
|
return(ep->type ? ep : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAXKEYLEN 64
|
||||||
|
|
||||||
|
static struct key_info {
|
||||||
|
unsigned char keyid[MAXKEYLEN];
|
||||||
|
int keylen;
|
||||||
|
int dir;
|
||||||
|
int *modep;
|
||||||
|
Encryptions *(*getcrypt)(int);
|
||||||
|
} ki[2] = {
|
||||||
|
{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
|
||||||
|
{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len);
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_init(const char *name, int server)
|
||||||
|
{
|
||||||
|
Encryptions *ep = encryptions;
|
||||||
|
|
||||||
|
Name = name;
|
||||||
|
Server = server;
|
||||||
|
i_support_encrypt = i_support_decrypt = 0;
|
||||||
|
remote_supports_encrypt = remote_supports_decrypt = 0;
|
||||||
|
encrypt_mode = 0;
|
||||||
|
decrypt_mode = 0;
|
||||||
|
encrypt_output = 0;
|
||||||
|
decrypt_input = 0;
|
||||||
|
|
||||||
|
str_suplen = 4;
|
||||||
|
|
||||||
|
while (ep->type) {
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: I will support %s\r\n",
|
||||||
|
Name, ENCTYPE_NAME(ep->type));
|
||||||
|
i_support_encrypt |= typemask(ep->type);
|
||||||
|
i_support_decrypt |= typemask(ep->type);
|
||||||
|
if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
|
||||||
|
if ((str_send[str_suplen++] = ep->type) == IAC)
|
||||||
|
str_send[str_suplen++] = IAC;
|
||||||
|
if (ep->init)
|
||||||
|
(*ep->init)(Server);
|
||||||
|
++ep;
|
||||||
|
}
|
||||||
|
str_send[str_suplen++] = IAC;
|
||||||
|
str_send[str_suplen++] = SE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
encrypt_list_types(void)
|
||||||
|
{
|
||||||
|
Encryptions *ep = encryptions;
|
||||||
|
|
||||||
|
printf("Valid encryption types:\n");
|
||||||
|
while (ep->type) {
|
||||||
|
printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
|
||||||
|
++ep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptEnable(char *type, char *mode)
|
||||||
|
{
|
||||||
|
if (isprefix(type, "help") || isprefix(type, "?")) {
|
||||||
|
printf("Usage: encrypt enable <type> [input|output]\n");
|
||||||
|
encrypt_list_types();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (EncryptType(type, mode))
|
||||||
|
return(EncryptStart(mode));
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptDisable(char *type, char *mode)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (isprefix(type, "help") || isprefix(type, "?")) {
|
||||||
|
printf("Usage: encrypt disable <type> [input|output]\n");
|
||||||
|
encrypt_list_types();
|
||||||
|
} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
|
||||||
|
sizeof(Encryptions))) == 0) {
|
||||||
|
printf("%s: invalid encryption type\n", type);
|
||||||
|
} else if (Ambiguous((char **)ep)) {
|
||||||
|
printf("Ambiguous type '%s'\n", type);
|
||||||
|
} else {
|
||||||
|
if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
|
||||||
|
if (decrypt_mode == ep->type)
|
||||||
|
EncryptStopInput();
|
||||||
|
i_wont_support_decrypt |= typemask(ep->type);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
if ((mode == 0) || (isprefix(mode, "output"))) {
|
||||||
|
if (encrypt_mode == ep->type)
|
||||||
|
EncryptStopOutput();
|
||||||
|
i_wont_support_encrypt |= typemask(ep->type);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
if (ret == 0)
|
||||||
|
printf("%s: invalid encryption mode\n", mode);
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptType(char *type, char *mode)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (isprefix(type, "help") || isprefix(type, "?")) {
|
||||||
|
printf("Usage: encrypt type <type> [input|output]\n");
|
||||||
|
encrypt_list_types();
|
||||||
|
} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
|
||||||
|
sizeof(Encryptions))) == 0) {
|
||||||
|
printf("%s: invalid encryption type\n", type);
|
||||||
|
} else if (Ambiguous((char **)ep)) {
|
||||||
|
printf("Ambiguous type '%s'\n", type);
|
||||||
|
} else {
|
||||||
|
if ((mode == 0) || isprefix(mode, "input")) {
|
||||||
|
decrypt_mode = ep->type;
|
||||||
|
i_wont_support_decrypt &= ~typemask(ep->type);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
if ((mode == 0) || isprefix(mode, "output")) {
|
||||||
|
encrypt_mode = ep->type;
|
||||||
|
i_wont_support_encrypt &= ~typemask(ep->type);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
if (ret == 0)
|
||||||
|
printf("%s: invalid encryption mode\n", mode);
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptStart(char *mode)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if (mode) {
|
||||||
|
if (isprefix(mode, "input"))
|
||||||
|
return(EncryptStartInput());
|
||||||
|
if (isprefix(mode, "output"))
|
||||||
|
return(EncryptStartOutput());
|
||||||
|
if (isprefix(mode, "help") || isprefix(mode, "?")) {
|
||||||
|
printf("Usage: encrypt start [input|output]\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
ret += EncryptStartInput();
|
||||||
|
ret += EncryptStartOutput();
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptStartInput(void)
|
||||||
|
{
|
||||||
|
if (decrypt_mode) {
|
||||||
|
encrypt_send_request_start();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
printf("No previous decryption mode, decryption not enabled\r\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptStartOutput(void)
|
||||||
|
{
|
||||||
|
if (encrypt_mode) {
|
||||||
|
encrypt_start_output(encrypt_mode);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
printf("No previous encryption mode, encryption not enabled\r\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptStop(char *mode)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if (mode) {
|
||||||
|
if (isprefix(mode, "input"))
|
||||||
|
return(EncryptStopInput());
|
||||||
|
if (isprefix(mode, "output"))
|
||||||
|
return(EncryptStopOutput());
|
||||||
|
if (isprefix(mode, "help") || isprefix(mode, "?")) {
|
||||||
|
printf("Usage: encrypt stop [input|output]\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
ret += EncryptStopInput();
|
||||||
|
ret += EncryptStopOutput();
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptStopInput(void)
|
||||||
|
{
|
||||||
|
encrypt_send_request_end();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptStopOutput(void)
|
||||||
|
{
|
||||||
|
encrypt_send_end();
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_display(void)
|
||||||
|
{
|
||||||
|
if (encrypt_output)
|
||||||
|
printf("Currently encrypting output with %s\r\n",
|
||||||
|
ENCTYPE_NAME(encrypt_mode));
|
||||||
|
if (decrypt_input)
|
||||||
|
printf("Currently decrypting input with %s\r\n",
|
||||||
|
ENCTYPE_NAME(decrypt_mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptStatus(void)
|
||||||
|
{
|
||||||
|
if (encrypt_output)
|
||||||
|
printf("Currently encrypting output with %s\r\n",
|
||||||
|
ENCTYPE_NAME(encrypt_mode));
|
||||||
|
else if (encrypt_mode) {
|
||||||
|
printf("Currently output is clear text.\r\n");
|
||||||
|
printf("Last encryption mode was %s\r\n",
|
||||||
|
ENCTYPE_NAME(encrypt_mode));
|
||||||
|
}
|
||||||
|
if (decrypt_input) {
|
||||||
|
printf("Currently decrypting input with %s\r\n",
|
||||||
|
ENCTYPE_NAME(decrypt_mode));
|
||||||
|
} else if (decrypt_mode) {
|
||||||
|
printf("Currently input is clear text.\r\n");
|
||||||
|
printf("Last decryption mode was %s\r\n",
|
||||||
|
ENCTYPE_NAME(decrypt_mode));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_send_support(void)
|
||||||
|
{
|
||||||
|
if (str_suplen) {
|
||||||
|
/*
|
||||||
|
* If the user has requested that decryption start
|
||||||
|
* immediatly, then send a "REQUEST START" before
|
||||||
|
* we negotiate the type.
|
||||||
|
*/
|
||||||
|
if (!Server && autodecrypt)
|
||||||
|
encrypt_send_request_start();
|
||||||
|
net_write(str_send, str_suplen);
|
||||||
|
printsub('>', &str_send[2], str_suplen - 2);
|
||||||
|
str_suplen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptDebug(int on)
|
||||||
|
{
|
||||||
|
if (on < 0)
|
||||||
|
encrypt_debug_mode ^= 1;
|
||||||
|
else
|
||||||
|
encrypt_debug_mode = on;
|
||||||
|
printf("Encryption debugging %s\r\n",
|
||||||
|
encrypt_debug_mode ? "enabled" : "disabled");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptVerbose(int on)
|
||||||
|
{
|
||||||
|
if (on < 0)
|
||||||
|
encrypt_verbose ^= 1;
|
||||||
|
else
|
||||||
|
encrypt_verbose = on;
|
||||||
|
printf("Encryption %s verbose\r\n",
|
||||||
|
encrypt_verbose ? "is" : "is not");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptAutoEnc(int on)
|
||||||
|
{
|
||||||
|
encrypt_auto(on);
|
||||||
|
printf("Automatic encryption of output is %s\r\n",
|
||||||
|
autoencrypt ? "enabled" : "disabled");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
EncryptAutoDec(int on)
|
||||||
|
{
|
||||||
|
decrypt_auto(on);
|
||||||
|
printf("Automatic decryption of input is %s\r\n",
|
||||||
|
autodecrypt ? "enabled" : "disabled");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when ENCRYPT SUPPORT is received.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
encrypt_support(unsigned char *typelist, int cnt)
|
||||||
|
{
|
||||||
|
int type, use_type = 0;
|
||||||
|
Encryptions *ep;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forget anything the other side has previously told us.
|
||||||
|
*/
|
||||||
|
remote_supports_decrypt = 0;
|
||||||
|
|
||||||
|
while (cnt-- > 0) {
|
||||||
|
type = *typelist++;
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: He is supporting %s (%d)\r\n",
|
||||||
|
Name,
|
||||||
|
ENCTYPE_NAME(type), type);
|
||||||
|
if ((type < ENCTYPE_CNT) &&
|
||||||
|
(I_SUPPORT_ENCRYPT & typemask(type))) {
|
||||||
|
remote_supports_decrypt |= typemask(type);
|
||||||
|
if (use_type == 0)
|
||||||
|
use_type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (use_type) {
|
||||||
|
ep = findencryption(use_type);
|
||||||
|
if (!ep)
|
||||||
|
return;
|
||||||
|
type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: (*ep->start)() returned %d\r\n",
|
||||||
|
Name, type);
|
||||||
|
if (type < 0)
|
||||||
|
return;
|
||||||
|
encrypt_mode = use_type;
|
||||||
|
if (type == 0)
|
||||||
|
encrypt_start_output(use_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_is(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
int type, ret;
|
||||||
|
|
||||||
|
if (--cnt < 0)
|
||||||
|
return;
|
||||||
|
type = *data++;
|
||||||
|
if (type < ENCTYPE_CNT)
|
||||||
|
remote_supports_encrypt |= typemask(type);
|
||||||
|
if (!(ep = finddecryption(type))) {
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
|
||||||
|
Name,
|
||||||
|
ENCTYPE_NAME_OK(type)
|
||||||
|
? ENCTYPE_NAME(type) : "(unknown)",
|
||||||
|
type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ep->is) {
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
|
||||||
|
Name,
|
||||||
|
ENCTYPE_NAME_OK(type)
|
||||||
|
? ENCTYPE_NAME(type) : "(unknown)",
|
||||||
|
type);
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
ret = (*ep->is)(data, cnt);
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
|
||||||
|
(ret < 0) ? "FAIL " :
|
||||||
|
(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
autodecrypt = 0;
|
||||||
|
} else {
|
||||||
|
decrypt_mode = type;
|
||||||
|
if (ret == 0 && autodecrypt)
|
||||||
|
encrypt_send_request_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_reply(unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
int ret, type;
|
||||||
|
|
||||||
|
if (--cnt < 0)
|
||||||
|
return;
|
||||||
|
type = *data++;
|
||||||
|
if (!(ep = findencryption(type))) {
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
|
||||||
|
Name,
|
||||||
|
ENCTYPE_NAME_OK(type)
|
||||||
|
? ENCTYPE_NAME(type) : "(unknown)",
|
||||||
|
type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ep->reply) {
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
|
||||||
|
Name,
|
||||||
|
ENCTYPE_NAME_OK(type)
|
||||||
|
? ENCTYPE_NAME(type) : "(unknown)",
|
||||||
|
type);
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
ret = (*ep->reply)(data, cnt);
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
|
||||||
|
data, cnt,
|
||||||
|
(ret < 0) ? "FAIL " :
|
||||||
|
(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
|
||||||
|
}
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
|
||||||
|
if (ret < 0) {
|
||||||
|
autoencrypt = 0;
|
||||||
|
} else {
|
||||||
|
encrypt_mode = type;
|
||||||
|
if (ret == 0 && autoencrypt)
|
||||||
|
encrypt_start_output(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when a ENCRYPT START command is received.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
encrypt_start(unsigned char *data __unused, int cnt __unused)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
|
||||||
|
if (!decrypt_mode) {
|
||||||
|
/*
|
||||||
|
* Something is wrong. We should not get a START
|
||||||
|
* command without having already picked our
|
||||||
|
* decryption scheme. Send a REQUEST-END to
|
||||||
|
* attempt to clear the channel...
|
||||||
|
*/
|
||||||
|
printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
|
||||||
|
encrypt_send_request_end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ep = finddecryption(decrypt_mode))) {
|
||||||
|
decrypt_input = ep->input;
|
||||||
|
if (encrypt_verbose)
|
||||||
|
printf("[ Input is now decrypted with type %s ]\r\n",
|
||||||
|
ENCTYPE_NAME(decrypt_mode));
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Start to decrypt input with type %s\r\n",
|
||||||
|
Name, ENCTYPE_NAME(decrypt_mode));
|
||||||
|
} else {
|
||||||
|
printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
|
||||||
|
Name,
|
||||||
|
ENCTYPE_NAME_OK(decrypt_mode)
|
||||||
|
? ENCTYPE_NAME(decrypt_mode)
|
||||||
|
: "(unknown)",
|
||||||
|
decrypt_mode);
|
||||||
|
encrypt_send_request_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_session_key( Session_Key *key, int server)
|
||||||
|
{
|
||||||
|
Encryptions *ep = encryptions;
|
||||||
|
|
||||||
|
havesessionkey = 1;
|
||||||
|
|
||||||
|
while (ep->type) {
|
||||||
|
if (ep->session)
|
||||||
|
(*ep->session)(key, server);
|
||||||
|
++ep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when ENCRYPT END is received.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
encrypt_end(void)
|
||||||
|
{
|
||||||
|
decrypt_input = 0;
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Input is back to clear text\r\n", Name);
|
||||||
|
if (encrypt_verbose)
|
||||||
|
printf("[ Input is now clear text ]\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when ENCRYPT REQUEST-END is received.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
encrypt_request_end(void)
|
||||||
|
{
|
||||||
|
encrypt_send_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when ENCRYPT REQUEST-START is received. If we receive
|
||||||
|
* this before a type is picked, then that indicates that the
|
||||||
|
* other side wants us to start encrypting data as soon as we
|
||||||
|
* can.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
encrypt_request_start(unsigned char *data __unused, int cnt __unused)
|
||||||
|
{
|
||||||
|
if (encrypt_mode == 0) {
|
||||||
|
if (Server)
|
||||||
|
autoencrypt = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
encrypt_start_output(encrypt_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_enc_keyid(unsigned char *keyid, int len)
|
||||||
|
{
|
||||||
|
encrypt_keyid(&ki[1], keyid, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_dec_keyid(unsigned char *keyid, int len)
|
||||||
|
{
|
||||||
|
encrypt_keyid(&ki[0], keyid, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
int dir = kp->dir;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!(ep = (*kp->getcrypt)(*kp->modep))) {
|
||||||
|
if (len == 0)
|
||||||
|
return;
|
||||||
|
kp->keylen = 0;
|
||||||
|
} else if (len == 0) {
|
||||||
|
/*
|
||||||
|
* Empty option, indicates a failure.
|
||||||
|
*/
|
||||||
|
if (kp->keylen == 0)
|
||||||
|
return;
|
||||||
|
kp->keylen = 0;
|
||||||
|
if (ep->keyid)
|
||||||
|
(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
|
||||||
|
|
||||||
|
} else if ((len != kp->keylen) ||
|
||||||
|
(memcmp(keyid, kp->keyid, len) != 0)) {
|
||||||
|
/*
|
||||||
|
* Length or contents are different
|
||||||
|
*/
|
||||||
|
kp->keylen = len;
|
||||||
|
memmove(kp->keyid, keyid, len);
|
||||||
|
if (ep->keyid)
|
||||||
|
(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
|
||||||
|
} else {
|
||||||
|
if (ep->keyid)
|
||||||
|
ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
|
||||||
|
if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
|
||||||
|
encrypt_start_output(*kp->modep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_send_keyid(int dir, const char *keyid, int keylen, int saveit)
|
||||||
|
{
|
||||||
|
unsigned char *strp;
|
||||||
|
|
||||||
|
str_keyid[3] = (dir == DIR_ENCRYPT)
|
||||||
|
? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
|
||||||
|
if (saveit) {
|
||||||
|
struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
|
||||||
|
memmove(kp->keyid, keyid, keylen);
|
||||||
|
kp->keylen = keylen;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (strp = &str_keyid[4]; keylen > 0; --keylen) {
|
||||||
|
if ((*strp++ = *keyid++) == IAC)
|
||||||
|
*strp++ = IAC;
|
||||||
|
}
|
||||||
|
*strp++ = IAC;
|
||||||
|
*strp++ = SE;
|
||||||
|
net_write(str_keyid, strp - str_keyid);
|
||||||
|
printsub('>', &str_keyid[2], strp - str_keyid - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_auto(int on)
|
||||||
|
{
|
||||||
|
if (on < 0)
|
||||||
|
autoencrypt ^= 1;
|
||||||
|
else
|
||||||
|
autoencrypt = on ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
decrypt_auto(int on)
|
||||||
|
{
|
||||||
|
if (on < 0)
|
||||||
|
autodecrypt ^= 1;
|
||||||
|
else
|
||||||
|
autodecrypt = on ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_start_output(int type)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
unsigned char *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!(ep = findencryption(type))) {
|
||||||
|
if (encrypt_debug_mode) {
|
||||||
|
printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
|
||||||
|
Name,
|
||||||
|
ENCTYPE_NAME_OK(type)
|
||||||
|
? ENCTYPE_NAME(type) : "(unknown)",
|
||||||
|
type);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ep->start) {
|
||||||
|
i = (*ep->start)(DIR_ENCRYPT, Server);
|
||||||
|
if (encrypt_debug_mode) {
|
||||||
|
printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
|
||||||
|
Name,
|
||||||
|
(i < 0) ? "failed" :
|
||||||
|
"initial negotiation in progress",
|
||||||
|
i, ENCTYPE_NAME(type));
|
||||||
|
}
|
||||||
|
if (i)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p = str_start + 3;
|
||||||
|
*p++ = ENCRYPT_START;
|
||||||
|
for (i = 0; i < ki[0].keylen; ++i) {
|
||||||
|
if ((*p++ = ki[0].keyid[i]) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
net_write(str_start, p - str_start);
|
||||||
|
net_encrypt();
|
||||||
|
printsub('>', &str_start[2], p - &str_start[2]);
|
||||||
|
/*
|
||||||
|
* If we are already encrypting in some mode, then
|
||||||
|
* encrypt the ring (which includes our request) in
|
||||||
|
* the old mode, mark it all as "clear text" and then
|
||||||
|
* switch to the new mode.
|
||||||
|
*/
|
||||||
|
encrypt_output = ep->output;
|
||||||
|
encrypt_mode = type;
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Started to encrypt output with type %s\r\n",
|
||||||
|
Name, ENCTYPE_NAME(type));
|
||||||
|
if (encrypt_verbose)
|
||||||
|
printf("[ Output is now encrypted with type %s ]\r\n",
|
||||||
|
ENCTYPE_NAME(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_send_end(void)
|
||||||
|
{
|
||||||
|
if (!encrypt_output)
|
||||||
|
return;
|
||||||
|
|
||||||
|
str_end[3] = ENCRYPT_END;
|
||||||
|
net_write(str_end, sizeof(str_end));
|
||||||
|
net_encrypt();
|
||||||
|
printsub('>', &str_end[2], sizeof(str_end) - 2);
|
||||||
|
/*
|
||||||
|
* Encrypt the output buffer now because it will not be done by
|
||||||
|
* netflush...
|
||||||
|
*/
|
||||||
|
encrypt_output = 0;
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Output is back to clear text\r\n", Name);
|
||||||
|
if (encrypt_verbose)
|
||||||
|
printf("[ Output is now clear text ]\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_send_request_start(void)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
p = &str_start[3];
|
||||||
|
*p++ = ENCRYPT_REQSTART;
|
||||||
|
for (i = 0; i < ki[1].keylen; ++i) {
|
||||||
|
if ((*p++ = ki[1].keyid[i]) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
net_write(str_start, p - str_start);
|
||||||
|
printsub('>', &str_start[2], p - &str_start[2]);
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Request input to be encrypted\r\n", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_send_request_end(void)
|
||||||
|
{
|
||||||
|
str_end[3] = ENCRYPT_REQEND;
|
||||||
|
net_write(str_end, sizeof(str_end));
|
||||||
|
printsub('>', &str_end[2], sizeof(str_end) - 2);
|
||||||
|
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: Request input to be clear text\r\n", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_wait(void)
|
||||||
|
{
|
||||||
|
if (encrypt_debug_mode)
|
||||||
|
printf(">>>%s: in encrypt_wait\r\n", Name);
|
||||||
|
if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
|
||||||
|
return;
|
||||||
|
while (autoencrypt && !encrypt_output)
|
||||||
|
if (telnet_spin())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
char tbuf[16], *cp;
|
||||||
|
|
||||||
|
cnt -= 2;
|
||||||
|
data += 2;
|
||||||
|
buf[buflen-1] = '\0';
|
||||||
|
buf[buflen-2] = '*';
|
||||||
|
buflen -= 2;;
|
||||||
|
for (; cnt > 0; cnt--, data++) {
|
||||||
|
sprintf(tbuf, " %d", *data);
|
||||||
|
for (cp = tbuf; *cp && buflen > 0; --buflen)
|
||||||
|
*buf++ = *cp++;
|
||||||
|
if (buflen <= 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*buf = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
Encryptions *ep;
|
||||||
|
int type = data[1];
|
||||||
|
|
||||||
|
for (ep = encryptions; ep->type && ep->type != type; ep++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (ep->printsub)
|
||||||
|
(*ep->printsub)(data, cnt, buf, buflen);
|
||||||
|
else
|
||||||
|
encrypt_gen_printsub(data, cnt, buf, buflen);
|
||||||
|
}
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)encrypt.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/libtelnet/encrypt.h,v 1.6 2001/11/30 21:06:34 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
# ifndef __ENCRYPTION__
|
||||||
|
# define __ENCRYPTION__
|
||||||
|
|
||||||
|
#define DIR_DECRYPT 1
|
||||||
|
#define DIR_ENCRYPT 2
|
||||||
|
|
||||||
|
#include <openssl/des.h>
|
||||||
|
typedef unsigned char Block[8];
|
||||||
|
typedef unsigned char *BlockT;
|
||||||
|
#if 0
|
||||||
|
typedef struct { Block __; } Schedule[16];
|
||||||
|
#else
|
||||||
|
#define Schedule des_key_schedule
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \
|
||||||
|
key[4] | key[5] | key[6] | key[7])
|
||||||
|
|
||||||
|
#define SAMEKEY(k1, k2) (!bcmp((void *)k1, (void *)k2, sizeof(Block)))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short type;
|
||||||
|
int length;
|
||||||
|
unsigned char *data;
|
||||||
|
} Session_Key;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
int type;
|
||||||
|
void (*output)(unsigned char *, int);
|
||||||
|
int (*input)(int);
|
||||||
|
void (*init)(int);
|
||||||
|
int (*start)(int, int);
|
||||||
|
int (*is)(unsigned char *, int);
|
||||||
|
int (*reply)(unsigned char *, int);
|
||||||
|
void (*session)(Session_Key *, int);
|
||||||
|
int (*keyid)(int, unsigned char *, int *);
|
||||||
|
void (*printsub)(unsigned char *, int, unsigned char *, int);
|
||||||
|
} Encryptions;
|
||||||
|
|
||||||
|
#define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */
|
||||||
|
|
||||||
|
#include "enc-proto.h"
|
||||||
|
|
||||||
|
extern int encrypt_debug_mode;
|
||||||
|
extern int (*decrypt_input)(int);
|
||||||
|
extern void (*encrypt_output)(unsigned char *, int);
|
||||||
|
# endif /* __ENCRYPTION__ */
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/genget.c,v 1.7 2001/11/30 21:06:34 markm Exp $");
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static const char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "misc-proto.h"
|
||||||
|
|
||||||
|
#define LOWER(x) (isupper(x) ? tolower(x) : (x))
|
||||||
|
/*
|
||||||
|
* The prefix function returns 0 if *s1 is not a prefix
|
||||||
|
* of *s2. If *s1 exactly matches *s2, the negative of
|
||||||
|
* the length is returned. If *s1 is a prefix of *s2,
|
||||||
|
* the length of *s1 is returned.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
isprefix(char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
char *os1;
|
||||||
|
char c1, c2;
|
||||||
|
|
||||||
|
if (*s1 == '\0')
|
||||||
|
return(-1);
|
||||||
|
os1 = s1;
|
||||||
|
c1 = *s1;
|
||||||
|
c2 = *s2;
|
||||||
|
while (LOWER(c1) == LOWER(c2)) {
|
||||||
|
if (c1 == '\0')
|
||||||
|
break;
|
||||||
|
c1 = *++s1;
|
||||||
|
c2 = *++s2;
|
||||||
|
}
|
||||||
|
return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *ambiguous; /* special return value for command routines */
|
||||||
|
|
||||||
|
char **
|
||||||
|
genget(char *name, char **table, int stlen)
|
||||||
|
{
|
||||||
|
char **c, **found;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (name == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
found = 0;
|
||||||
|
for (c = table; *c != 0; c = (char **)((char *)c + stlen)) {
|
||||||
|
if ((n = isprefix(name, *c)) == 0)
|
||||||
|
continue;
|
||||||
|
if (n < 0) /* exact match */
|
||||||
|
return(c);
|
||||||
|
if (found)
|
||||||
|
return(&ambiguous);
|
||||||
|
found = c;
|
||||||
|
}
|
||||||
|
return(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function call version of Ambiguous()
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
Ambiguous(char **s)
|
||||||
|
{
|
||||||
|
return(s == &ambiguous);
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/getent.c,v 1.7 2001/11/30 21:06:34 markm Exp $");
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "misc-proto.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static char *area;
|
||||||
|
static char gettytab[] = "/etc/gettytab";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
getent(char *cp __unused, const char *name)
|
||||||
|
{
|
||||||
|
printf("cgetent() not implemented, name = %s\n", name);
|
||||||
|
return -1;
|
||||||
|
#if 0
|
||||||
|
int retval;
|
||||||
|
char *tempnam, *dba[2] = { gettytab, NULL };
|
||||||
|
|
||||||
|
tempnam = strdup(name);
|
||||||
|
retval = cgetent(&area, dba, tempnam) == 0 ? 1 : 0;
|
||||||
|
free(tempnam);
|
||||||
|
return(retval);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
char *
|
||||||
|
Getstr(const char *id, char **cpp __unused)
|
||||||
|
{
|
||||||
|
printf("cgetstr() not implemented, id = %s\n", id);
|
||||||
|
return NULL;
|
||||||
|
#if 0
|
||||||
|
int retval;
|
||||||
|
char *answer, *tempid;
|
||||||
|
|
||||||
|
tempid = strdup(id);
|
||||||
|
retval = cgetstr(area, tempid, &answer);
|
||||||
|
free(tempid);
|
||||||
|
return((retval > 0) ? answer : NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,506 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/kerberos.c,v 1.8 2003/01/29 18:14:28 nectar Exp $");
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
static const char sccsid[] = "@(#)kerberos.c 8.3 (Berkeley) 5/30/95";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef KRB4
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
#include <openssl/des.h> /* BSD wont include this in krb.h, so we do it here */
|
||||||
|
#include <krb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
int kerberos4_cksum(unsigned char *, int);
|
||||||
|
int kuserok(AUTH_DAT *, char *);
|
||||||
|
|
||||||
|
extern int auth_debug_mode;
|
||||||
|
|
||||||
|
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
|
||||||
|
AUTHTYPE_KERBEROS_V4, };
|
||||||
|
|
||||||
|
#define KRB_AUTH 0 /* Authentication data follows */
|
||||||
|
#define KRB_REJECT 1 /* Rejected (reason might follow) */
|
||||||
|
#define KRB_ACCEPT 2 /* Accepted */
|
||||||
|
#define KRB_CHALLENGE 3 /* Challenge for mutual auth. */
|
||||||
|
#define KRB_RESPONSE 4 /* Response for mutual auth. */
|
||||||
|
|
||||||
|
static KTEXT_ST auth;
|
||||||
|
static char name[ANAME_SZ];
|
||||||
|
static AUTH_DAT adat = { 0, "", "", "", 0, {}, 0, 0, 0, { 0, "", 0 } };
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
static Block session_key = { 0 };
|
||||||
|
static des_key_schedule sched;
|
||||||
|
static Block challenge = { 0 };
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
|
||||||
|
static char krb_service_name[] = "rcmd";
|
||||||
|
static char empty[] = "";
|
||||||
|
|
||||||
|
static int
|
||||||
|
Data(Authenticator *ap, int type, const unsigned char *d, int c)
|
||||||
|
{
|
||||||
|
unsigned char *p = str_data + 4;
|
||||||
|
const unsigned char *cd = d;
|
||||||
|
|
||||||
|
if (c == -1)
|
||||||
|
c = strlen(cd);
|
||||||
|
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("%s:%d: [%d] (%d)",
|
||||||
|
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
|
||||||
|
str_data[3],
|
||||||
|
type, c);
|
||||||
|
printd(d, c);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
*p++ = ap->type;
|
||||||
|
*p++ = ap->way;
|
||||||
|
*p++ = type;
|
||||||
|
while (c-- > 0) {
|
||||||
|
if ((*p++ = *cd++) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
if (str_data[3] == TELQUAL_IS)
|
||||||
|
printsub('>', &str_data[2], p - (&str_data[2]));
|
||||||
|
return(net_write(str_data, p - str_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos4_init(Authenticator *ap __unused, int server)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (server) {
|
||||||
|
str_data[3] = TELQUAL_REPLY;
|
||||||
|
if ((fp = fopen(KEYFILE, "r")) == NULL)
|
||||||
|
return(0);
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
str_data[3] = TELQUAL_IS;
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
|
||||||
|
int dst_realm_sz = REALM_SZ;
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos4_send(Authenticator *ap)
|
||||||
|
{
|
||||||
|
KTEXT_ST lauth;
|
||||||
|
char instance[INST_SZ];
|
||||||
|
char *realm;
|
||||||
|
CREDENTIALS cred;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
printf("[ Trying KERBEROS4 ... ]\n");
|
||||||
|
if (!UserNameRequested) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("Kerberos V4: no user name supplied\r\n");
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(instance, 0, sizeof(instance));
|
||||||
|
|
||||||
|
if ((realm = krb_get_phost(RemoteHostName)))
|
||||||
|
strncpy(instance, realm, sizeof(instance));
|
||||||
|
|
||||||
|
instance[sizeof(instance)-1] = '\0';
|
||||||
|
|
||||||
|
realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
|
||||||
|
|
||||||
|
if (!realm) {
|
||||||
|
printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if ((r = krb_mk_req(&lauth, krb_service_name, instance, realm, 0L))) {
|
||||||
|
printf("mk_req failed: %s\r\n", krb_err_txt[r]);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if ((r = krb_get_cred(krb_service_name, instance, realm, &cred))) {
|
||||||
|
printf("get_cred failed: %s\r\n", krb_err_txt[r]);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room for user name\r\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Sent %d bytes of authentication data\r\n", lauth.length);
|
||||||
|
if (!Data(ap, KRB_AUTH, (void *)lauth.dat, lauth.length)) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room for authentication data\r\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
/*
|
||||||
|
* If we are doing mutual authentication, get set up to send
|
||||||
|
* the challenge, and verify it when the response comes back.
|
||||||
|
*/
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
des_key_sched(&cred.session, sched);
|
||||||
|
des_random_key(&session_key);
|
||||||
|
des_ecb_encrypt(&session_key, &session_key, sched, 0);
|
||||||
|
des_ecb_encrypt(&session_key, &challenge, sched, 0);
|
||||||
|
/*
|
||||||
|
* Increment the challenge by 1, and encrypt it for
|
||||||
|
* later comparison.
|
||||||
|
*/
|
||||||
|
for (i = 7; i >= 0; --i) {
|
||||||
|
register int x;
|
||||||
|
x = (unsigned int)challenge[i] + 1;
|
||||||
|
challenge[i] = x; /* ignore overflow */
|
||||||
|
if (x < 256) /* if no overflow, all done */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
des_ecb_encrypt(&challenge, &challenge, sched, 1);
|
||||||
|
}
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("CK: %d:", kerberos4_cksum(lauth.dat, lauth.length));
|
||||||
|
printd(lauth.dat, lauth.length);
|
||||||
|
printf("\r\n");
|
||||||
|
printf("Sent Kerberos V4 credentials to server\r\n");
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
Session_Key skey;
|
||||||
|
Block datablock;
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
char realm[REALM_SZ];
|
||||||
|
char instance[INST_SZ];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
case KRB_AUTH:
|
||||||
|
if (krb_get_lrealm(realm, 1) != KSUCCESS) {
|
||||||
|
Data(ap, KRB_REJECT, "No local V4 Realm.", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("No local realm\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove((void *)auth.dat, (void *)data, auth.length = cnt);
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("Got %d bytes of authentication data\r\n", cnt);
|
||||||
|
printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
|
||||||
|
printd(auth.dat, auth.length);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
instance[0] = '*'; instance[1] = 0;
|
||||||
|
if ((r = krb_rd_req(&auth, krb_service_name,
|
||||||
|
instance, 0, &adat, empty))) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos failed him as %s\r\n", name);
|
||||||
|
Data(ap, KRB_REJECT, krb_err_txt[r], -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
memmove((void *)session_key, (void *)adat.session, sizeof(Block));
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
krb_kntoln(&adat, name);
|
||||||
|
|
||||||
|
if (UserNameRequested && !kuserok(&adat, UserNameRequested))
|
||||||
|
Data(ap, KRB_ACCEPT, NULL, 0);
|
||||||
|
else
|
||||||
|
Data(ap, KRB_REJECT, "user is not authorized", -1);
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KRB_CHALLENGE:
|
||||||
|
#ifndef ENCRYPTION
|
||||||
|
Data(ap, KRB_RESPONSE, NULL, 0);
|
||||||
|
#else /* ENCRYPTION */
|
||||||
|
if (!VALIDKEY(session_key)) {
|
||||||
|
/*
|
||||||
|
* We don't have a valid session key, so just
|
||||||
|
* send back a response with an empty session
|
||||||
|
* key.
|
||||||
|
*/
|
||||||
|
Data(ap, KRB_RESPONSE, NULL, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
des_key_sched(&session_key, sched);
|
||||||
|
memmove((void *)datablock, (void *)data, sizeof(Block));
|
||||||
|
/*
|
||||||
|
* Take the received encrypted challenge, and encrypt
|
||||||
|
* it again to get a unique session_key for the
|
||||||
|
* ENCRYPT option.
|
||||||
|
*/
|
||||||
|
des_ecb_encrypt(&datablock, &session_key, sched, 1);
|
||||||
|
skey.type = SK_DES;
|
||||||
|
skey.length = 8;
|
||||||
|
skey.data = session_key;
|
||||||
|
encrypt_session_key(&skey, 1);
|
||||||
|
/*
|
||||||
|
* Now decrypt the received encrypted challenge,
|
||||||
|
* increment by one, re-encrypt it and send it back.
|
||||||
|
*/
|
||||||
|
des_ecb_encrypt(&datablock, &challenge, sched, 0);
|
||||||
|
for (r = 7; r >= 0; r--) {
|
||||||
|
register int t;
|
||||||
|
t = (unsigned int)challenge[r] + 1;
|
||||||
|
challenge[r] = t; /* ignore overflow */
|
||||||
|
if (t < 256) /* if no overflow, all done */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
des_ecb_encrypt(&challenge, &challenge, sched, 1);
|
||||||
|
Data(ap, KRB_RESPONSE, challenge, sizeof(challenge));
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Unknown Kerberos option %d\r\n", data[-1]);
|
||||||
|
Data(ap, KRB_REJECT, NULL, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
Session_Key skey;
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
case KRB_REJECT:
|
||||||
|
if (cnt > 0) {
|
||||||
|
printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n",
|
||||||
|
cnt, data);
|
||||||
|
} else
|
||||||
|
printf("[ Kerberos V4 refuses authentication ]\r\n");
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
case KRB_ACCEPT:
|
||||||
|
printf("[ Kerberos V4 accepts you ]\n");
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
|
||||||
|
/*
|
||||||
|
* Send over the encrypted challenge.
|
||||||
|
*/
|
||||||
|
#ifndef ENCRYPTION
|
||||||
|
Data(ap, KRB_CHALLENGE, NULL, 0);
|
||||||
|
#else /* ENCRYPTION */
|
||||||
|
Data(ap, KRB_CHALLENGE, session_key,
|
||||||
|
sizeof(session_key));
|
||||||
|
des_ecb_encrypt(&session_key, &session_key, sched, 1);
|
||||||
|
skey.type = SK_DES;
|
||||||
|
skey.length = 8;
|
||||||
|
skey.data = session_key;
|
||||||
|
encrypt_session_key(&skey, 0);
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
return;
|
||||||
|
case KRB_RESPONSE:
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
/*
|
||||||
|
* Verify that the response to the challenge is correct.
|
||||||
|
*/
|
||||||
|
if ((cnt != sizeof(Block)) ||
|
||||||
|
(0 != memcmp((void *)data, (void *)challenge,
|
||||||
|
sizeof(challenge))))
|
||||||
|
{
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
printf("[ Kerberos V4 challenge failed!!! ]\r\n");
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
}
|
||||||
|
printf("[ Kerberos V4 challenge successful ]\r\n");
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Unknown Kerberos option %d\r\n", data[-1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos4_status(Authenticator *ap __unused, char *nam, int level)
|
||||||
|
{
|
||||||
|
if (level < AUTH_USER)
|
||||||
|
return(level);
|
||||||
|
|
||||||
|
if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
|
||||||
|
strcpy(nam, UserNameRequested);
|
||||||
|
return(AUTH_VALID);
|
||||||
|
} else
|
||||||
|
return(AUTH_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
|
||||||
|
#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
|
||||||
|
|
||||||
|
void
|
||||||
|
kerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
char lbuf[32];
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
buf[buflen-1] = '\0'; /* make sure its NULL terminated */
|
||||||
|
buflen -= 1;
|
||||||
|
|
||||||
|
switch(data[3]) {
|
||||||
|
case KRB_REJECT: /* Rejected (reason might follow) */
|
||||||
|
strncpy((char *)buf, " REJECT ", buflen);
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case KRB_ACCEPT: /* Accepted (name might follow) */
|
||||||
|
strncpy((char *)buf, " ACCEPT ", buflen);
|
||||||
|
common:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
if (cnt <= 4)
|
||||||
|
break;
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
for (i = 4; i < cnt; i++)
|
||||||
|
ADDC(buf, buflen, data[i]);
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
ADDC(buf, buflen, '\0');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KRB_AUTH: /* Authentication data follows */
|
||||||
|
strncpy((char *)buf, " AUTH", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB_CHALLENGE:
|
||||||
|
strncpy((char *)buf, " CHALLENGE", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB_RESPONSE:
|
||||||
|
strncpy((char *)buf, " RESPONSE", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(lbuf, " %d (unknown)", data[3]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
common2:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
for (i = 4; i < cnt; i++) {
|
||||||
|
sprintf(lbuf, " %d", data[i]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos4_cksum(unsigned char *d, int n)
|
||||||
|
{
|
||||||
|
int ck = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A comment is probably needed here for those not
|
||||||
|
* well versed in the "C" language. Yes, this is
|
||||||
|
* supposed to be a "switch" with the body of the
|
||||||
|
* "switch" being a "while" statement. The whole
|
||||||
|
* purpose of the switch is to allow us to jump into
|
||||||
|
* the middle of the while() loop, and then not have
|
||||||
|
* to do any more switch()s.
|
||||||
|
*
|
||||||
|
* Some compilers will spit out a warning message
|
||||||
|
* about the loop not being entered at the top.
|
||||||
|
*/
|
||||||
|
switch (n&03)
|
||||||
|
while (n > 0) {
|
||||||
|
case 0:
|
||||||
|
ck ^= (int)*d++ << 24;
|
||||||
|
--n;
|
||||||
|
case 3:
|
||||||
|
ck ^= (int)*d++ << 16;
|
||||||
|
--n;
|
||||||
|
case 2:
|
||||||
|
ck ^= (int)*d++ << 8;
|
||||||
|
--n;
|
||||||
|
case 1:
|
||||||
|
ck ^= (int)*d++;
|
||||||
|
--n;
|
||||||
|
}
|
||||||
|
return(ck);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,825 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America may
|
||||||
|
* require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/kerberos5.c,v 1.7 2003/03/06 13:41:53 nectar Exp $");
|
||||||
|
|
||||||
|
#ifdef KRB5
|
||||||
|
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#define Authenticator k5_Authenticator
|
||||||
|
#include <krb5.h>
|
||||||
|
#undef Authenticator
|
||||||
|
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
|
||||||
|
|
||||||
|
/* These values need to be the same as those defined in telnet/main.c. */
|
||||||
|
/* Either define them in both places, or put in some common header file. */
|
||||||
|
#define OPTS_FORWARD_CREDS 0x00000002
|
||||||
|
#define OPTS_FORWARDABLE_CREDS 0x00000001
|
||||||
|
|
||||||
|
void kerberos5_forward (Authenticator *);
|
||||||
|
|
||||||
|
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
|
||||||
|
AUTHTYPE_KERBEROS_V5, };
|
||||||
|
|
||||||
|
#define KRB_AUTH 0 /* Authentication data follows */
|
||||||
|
#define KRB_REJECT 1 /* Rejected (reason might follow) */
|
||||||
|
#define KRB_ACCEPT 2 /* Accepted */
|
||||||
|
#define KRB_RESPONSE 3 /* Response for mutual auth. */
|
||||||
|
|
||||||
|
#define KRB_FORWARD 4 /* Forwarded credentials follow */
|
||||||
|
#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */
|
||||||
|
#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */
|
||||||
|
|
||||||
|
static krb5_data auth;
|
||||||
|
static krb5_ticket *ticket;
|
||||||
|
|
||||||
|
static krb5_context context;
|
||||||
|
static krb5_auth_context auth_context;
|
||||||
|
|
||||||
|
static int
|
||||||
|
Data(Authenticator *ap, int type, const char *d, int c)
|
||||||
|
{
|
||||||
|
unsigned char *p = str_data + 4;
|
||||||
|
const unsigned char *cd = d;
|
||||||
|
|
||||||
|
if (c == -1)
|
||||||
|
c = strlen(cd);
|
||||||
|
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("%s:%d: [%d] (%d)",
|
||||||
|
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
|
||||||
|
str_data[3],
|
||||||
|
type, c);
|
||||||
|
printd(d, c);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
*p++ = ap->type;
|
||||||
|
*p++ = ap->way;
|
||||||
|
*p++ = type;
|
||||||
|
while (c-- > 0) {
|
||||||
|
if ((*p++ = *cd++) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
if (str_data[3] == TELQUAL_IS)
|
||||||
|
printsub('>', &str_data[2], p - &str_data[2]);
|
||||||
|
return(net_write(str_data, p - str_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos5_init(Authenticator *ap __unused, int server)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
|
||||||
|
ret = krb5_init_context(&context);
|
||||||
|
if (ret)
|
||||||
|
return 0;
|
||||||
|
if (server) {
|
||||||
|
krb5_keytab kt;
|
||||||
|
krb5_kt_cursor cursor;
|
||||||
|
|
||||||
|
ret = krb5_kt_default(context, &kt);
|
||||||
|
if (ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = krb5_kt_start_seq_get (context, kt, &cursor);
|
||||||
|
if (ret) {
|
||||||
|
krb5_kt_close (context, kt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
krb5_kt_end_seq_get (context, kt, &cursor);
|
||||||
|
krb5_kt_close (context, kt);
|
||||||
|
|
||||||
|
str_data[3] = TELQUAL_REPLY;
|
||||||
|
} else
|
||||||
|
str_data[3] = TELQUAL_IS;
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int net;
|
||||||
|
|
||||||
|
static int
|
||||||
|
kerberos5_send(const char *name, Authenticator *ap)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_ccache ccache;
|
||||||
|
int ap_opts;
|
||||||
|
krb5_data cksum_data;
|
||||||
|
char foo[2];
|
||||||
|
|
||||||
|
if (!UserNameRequested) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("Kerberos V5: no user name supplied\r\n");
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_cc_default(context, &ccache);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("Kerberos V5: could not get default ccache: %s\r\n",
|
||||||
|
krb5_get_err_text (context, ret));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
|
||||||
|
ap_opts = AP_OPTS_MUTUAL_REQUIRED;
|
||||||
|
else
|
||||||
|
ap_opts = 0;
|
||||||
|
ap_opts |= AP_OPTS_USE_SUBKEY;
|
||||||
|
|
||||||
|
ret = krb5_auth_con_init (context, &auth_context);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_auth_con_setaddrs_from_fd (context,
|
||||||
|
auth_context,
|
||||||
|
&net);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf ("Kerberos V5:"
|
||||||
|
" krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_auth_con_setkeytype (context, auth_context, KEYTYPE_DES);
|
||||||
|
|
||||||
|
foo[0] = ap->type;
|
||||||
|
foo[1] = ap->way;
|
||||||
|
|
||||||
|
cksum_data.length = sizeof(foo);
|
||||||
|
cksum_data.data = foo;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
krb5_principal service;
|
||||||
|
char sname[128];
|
||||||
|
|
||||||
|
|
||||||
|
ret = krb5_sname_to_principal (context,
|
||||||
|
RemoteHostName,
|
||||||
|
NULL,
|
||||||
|
KRB5_NT_SRV_HST,
|
||||||
|
&service);
|
||||||
|
if(ret) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf ("Kerberos V5:"
|
||||||
|
" krb5_sname_to_principal(%s) failed (%s)\r\n",
|
||||||
|
RemoteHostName, krb5_get_err_text(context, ret));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname));
|
||||||
|
if(ret) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf ("Kerberos V5:"
|
||||||
|
" krb5_unparse_name_fixed failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("[ Trying %s (%s)... ]\r\n", name, sname);
|
||||||
|
ret = krb5_mk_req_exact(context, &auth_context, ap_opts,
|
||||||
|
service,
|
||||||
|
&cksum_data, ccache, &auth);
|
||||||
|
krb5_free_principal (context, service);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
if (1 || auth_debug_mode) {
|
||||||
|
printf("Kerberos V5: mk_req failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!auth_sendname((unsigned char *)UserNameRequested,
|
||||||
|
strlen(UserNameRequested))) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room for user name\r\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room for authentication data\r\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("Sent Kerberos V5 credentials to server\r\n");
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos5_send_mutual(Authenticator *ap)
|
||||||
|
{
|
||||||
|
return kerberos5_send("mutual KERBEROS5", ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos5_send_oneway(Authenticator *ap)
|
||||||
|
{
|
||||||
|
return kerberos5_send("KERBEROS5", ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kerberos5_is(Authenticator *ap, unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_data outbuf;
|
||||||
|
krb5_keyblock *key_block;
|
||||||
|
char *name;
|
||||||
|
krb5_principal server;
|
||||||
|
int zero = 0;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
case KRB_AUTH:
|
||||||
|
auth.data = (char *)data;
|
||||||
|
auth.length = cnt;
|
||||||
|
|
||||||
|
auth_context = NULL;
|
||||||
|
|
||||||
|
ret = krb5_auth_con_init (context, &auth_context);
|
||||||
|
if (ret) {
|
||||||
|
Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_auth_con_setaddrs_from_fd (context,
|
||||||
|
auth_context,
|
||||||
|
&zero);
|
||||||
|
if (ret) {
|
||||||
|
Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos V5: "
|
||||||
|
"krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_sock_to_principal (context,
|
||||||
|
0,
|
||||||
|
"host",
|
||||||
|
KRB5_NT_SRV_HST,
|
||||||
|
&server);
|
||||||
|
if (ret) {
|
||||||
|
Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos V5: "
|
||||||
|
"krb5_sock_to_principal failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_rd_req(context,
|
||||||
|
&auth_context,
|
||||||
|
&auth,
|
||||||
|
server,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&ticket);
|
||||||
|
|
||||||
|
krb5_free_principal (context, server);
|
||||||
|
if (ret) {
|
||||||
|
char *errbuf;
|
||||||
|
|
||||||
|
asprintf(&errbuf,
|
||||||
|
"Read req failed: %s",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
Data(ap, KRB_REJECT, errbuf, -1);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("%s\r\n", errbuf);
|
||||||
|
free (errbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char foo[2];
|
||||||
|
|
||||||
|
foo[0] = ap->type;
|
||||||
|
foo[1] = ap->way;
|
||||||
|
|
||||||
|
ret = krb5_verify_authenticator_checksum(context,
|
||||||
|
auth_context,
|
||||||
|
foo,
|
||||||
|
sizeof(foo));
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
char *errbuf;
|
||||||
|
asprintf(&errbuf, "Bad checksum: %s",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
Data(ap, KRB_REJECT, errbuf, -1);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf ("%s\r\n", errbuf);
|
||||||
|
free(errbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = krb5_auth_con_getremotesubkey (context,
|
||||||
|
auth_context,
|
||||||
|
&key_block);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos V5: "
|
||||||
|
"krb5_auth_con_getremotesubkey failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_block == NULL) {
|
||||||
|
ret = krb5_auth_con_getkey(context,
|
||||||
|
auth_context,
|
||||||
|
&key_block);
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos V5: "
|
||||||
|
"krb5_auth_con_getkey failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (key_block == NULL) {
|
||||||
|
Data(ap, KRB_REJECT, "no subkey received", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos V5: "
|
||||||
|
"krb5_auth_con_getremotesubkey returned NULL key\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
|
||||||
|
ret = krb5_mk_rep(context, auth_context, &outbuf);
|
||||||
|
if (ret) {
|
||||||
|
Data(ap, KRB_REJECT,
|
||||||
|
"krb5_mk_rep failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Kerberos V5: "
|
||||||
|
"krb5_mk_rep failed (%s)\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
|
||||||
|
}
|
||||||
|
if (krb5_unparse_name(context, ticket->client, &name))
|
||||||
|
name = 0;
|
||||||
|
|
||||||
|
if(UserNameRequested && krb5_kuserok(context,
|
||||||
|
ticket->client,
|
||||||
|
UserNameRequested)) {
|
||||||
|
Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("Kerberos5 identifies him as ``%s''\r\n",
|
||||||
|
name ? name : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key_block->keytype == ETYPE_DES_CBC_MD5 ||
|
||||||
|
key_block->keytype == ETYPE_DES_CBC_MD4 ||
|
||||||
|
key_block->keytype == ETYPE_DES_CBC_CRC) {
|
||||||
|
Session_Key skey;
|
||||||
|
|
||||||
|
skey.type = SK_DES;
|
||||||
|
skey.length = 8;
|
||||||
|
skey.data = key_block->keyvalue.data;
|
||||||
|
encrypt_session_key(&skey, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
char *msg;
|
||||||
|
|
||||||
|
asprintf (&msg, "user `%s' is not authorized to "
|
||||||
|
"login as `%s'",
|
||||||
|
name ? name : "<unknown>",
|
||||||
|
UserNameRequested ? UserNameRequested : "<nobody>");
|
||||||
|
if (msg == NULL)
|
||||||
|
Data(ap, KRB_REJECT, NULL, 0);
|
||||||
|
else {
|
||||||
|
Data(ap, KRB_REJECT, (void *)msg, -1);
|
||||||
|
free(msg);
|
||||||
|
}
|
||||||
|
auth_finished (ap, AUTH_REJECT);
|
||||||
|
krb5_free_keyblock_contents(context, key_block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
krb5_free_keyblock_contents(context, key_block);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case KRB_FORWARD: {
|
||||||
|
struct passwd *pwd;
|
||||||
|
char ccname[1024]; /* XXX */
|
||||||
|
krb5_data inbuf;
|
||||||
|
krb5_ccache ccache;
|
||||||
|
inbuf.data = (char *)data;
|
||||||
|
inbuf.length = cnt;
|
||||||
|
|
||||||
|
pwd = getpwnam (UserNameRequested);
|
||||||
|
if (pwd == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
snprintf (ccname, sizeof(ccname),
|
||||||
|
"FILE:/tmp/krb5cc_%u", pwd->pw_uid);
|
||||||
|
|
||||||
|
ret = krb5_cc_resolve (context, ccname, &ccache);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf ("Kerberos V5: could not get ccache: %s\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_cc_initialize (context,
|
||||||
|
ccache,
|
||||||
|
ticket->client);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf ("Kerberos V5: could not init ccache: %s\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(DCE)
|
||||||
|
esetenv("KRB5CCNAME", ccname, 1);
|
||||||
|
#endif
|
||||||
|
ret = krb5_rd_cred2 (context,
|
||||||
|
auth_context,
|
||||||
|
ccache,
|
||||||
|
&inbuf);
|
||||||
|
if(ret) {
|
||||||
|
char *errbuf;
|
||||||
|
|
||||||
|
asprintf (&errbuf,
|
||||||
|
"Read forwarded creds failed: %s",
|
||||||
|
krb5_get_err_text (context, ret));
|
||||||
|
if(errbuf == NULL)
|
||||||
|
Data(ap, KRB_FORWARD_REJECT, NULL, 0);
|
||||||
|
else
|
||||||
|
Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Could not read forwarded credentials: %s\r\n",
|
||||||
|
errbuf);
|
||||||
|
free (errbuf);
|
||||||
|
} else {
|
||||||
|
Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
|
||||||
|
#if defined(DCE)
|
||||||
|
dfsfwd = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
chown (ccname + 5, pwd->pw_uid, -1);
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Forwarded credentials obtained\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Unknown Kerberos option %d\r\n", data[-1]);
|
||||||
|
Data(ap, KRB_REJECT, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
static int mutual_complete = 0;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
case KRB_REJECT:
|
||||||
|
if (cnt > 0) {
|
||||||
|
printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
|
||||||
|
cnt, data);
|
||||||
|
} else
|
||||||
|
printf("[ Kerberos V5 refuses authentication ]\r\n");
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
case KRB_ACCEPT: {
|
||||||
|
krb5_error_code ret;
|
||||||
|
Session_Key skey;
|
||||||
|
krb5_keyblock *keyblock;
|
||||||
|
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
|
||||||
|
!mutual_complete) {
|
||||||
|
printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cnt)
|
||||||
|
printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
|
||||||
|
else
|
||||||
|
printf("[ Kerberos V5 accepts you ]\r\n");
|
||||||
|
|
||||||
|
ret = krb5_auth_con_getlocalsubkey (context,
|
||||||
|
auth_context,
|
||||||
|
&keyblock);
|
||||||
|
if (ret)
|
||||||
|
ret = krb5_auth_con_getkey (context,
|
||||||
|
auth_context,
|
||||||
|
&keyblock);
|
||||||
|
if(ret) {
|
||||||
|
printf("[ krb5_auth_con_getkey: %s ]\r\n",
|
||||||
|
krb5_get_err_text(context, ret));
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
skey.type = SK_DES;
|
||||||
|
skey.length = 8;
|
||||||
|
skey.data = keyblock->keyvalue.data;
|
||||||
|
encrypt_session_key(&skey, 0);
|
||||||
|
krb5_free_keyblock_contents (context, keyblock);
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
if (forward_flags & OPTS_FORWARD_CREDS)
|
||||||
|
kerberos5_forward(ap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KRB_RESPONSE:
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
|
||||||
|
/* the rest of the reply should contain a krb_ap_rep */
|
||||||
|
krb5_ap_rep_enc_part *reply;
|
||||||
|
krb5_data inbuf;
|
||||||
|
krb5_error_code ret;
|
||||||
|
|
||||||
|
inbuf.length = cnt;
|
||||||
|
inbuf.data = (char *)data;
|
||||||
|
|
||||||
|
ret = krb5_rd_rep(context, auth_context, &inbuf, &reply);
|
||||||
|
if (ret) {
|
||||||
|
printf("[ Mutual authentication failed: %s ]\r\n",
|
||||||
|
krb5_get_err_text (context, ret));
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
krb5_free_ap_rep_enc_part(context, reply);
|
||||||
|
mutual_complete = 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case KRB_FORWARD_ACCEPT:
|
||||||
|
printf("[ Kerberos V5 accepted forwarded credentials ]\r\n");
|
||||||
|
return;
|
||||||
|
case KRB_FORWARD_REJECT:
|
||||||
|
printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
|
||||||
|
cnt, data);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Unknown Kerberos option %d\r\n", data[-1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kerberos5_status(Authenticator *ap __unused, char *name, int level)
|
||||||
|
{
|
||||||
|
if (level < AUTH_USER)
|
||||||
|
return(level);
|
||||||
|
|
||||||
|
if (UserNameRequested &&
|
||||||
|
krb5_kuserok(context,
|
||||||
|
ticket->client,
|
||||||
|
UserNameRequested))
|
||||||
|
{
|
||||||
|
strcpy(name, UserNameRequested);
|
||||||
|
return(AUTH_VALID);
|
||||||
|
} else
|
||||||
|
return(AUTH_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
|
||||||
|
#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
|
||||||
|
|
||||||
|
void
|
||||||
|
kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
buf[buflen-1] = '\0'; /* make sure its NULL terminated */
|
||||||
|
buflen -= 1;
|
||||||
|
|
||||||
|
switch(data[3]) {
|
||||||
|
case KRB_REJECT: /* Rejected (reason might follow) */
|
||||||
|
strlcpy((char *)buf, " REJECT ", buflen);
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case KRB_ACCEPT: /* Accepted (name might follow) */
|
||||||
|
strlcpy((char *)buf, " ACCEPT ", buflen);
|
||||||
|
common:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
if (cnt <= 4)
|
||||||
|
break;
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
for (i = 4; i < cnt; i++)
|
||||||
|
ADDC(buf, buflen, data[i]);
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
ADDC(buf, buflen, '\0');
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case KRB_AUTH: /* Authentication data follows */
|
||||||
|
strlcpy((char *)buf, " AUTH", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB_RESPONSE:
|
||||||
|
strlcpy((char *)buf, " RESPONSE", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB_FORWARD: /* Forwarded credentials follow */
|
||||||
|
strlcpy((char *)buf, " FORWARD", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
|
||||||
|
strlcpy((char *)buf, " FORWARD_ACCEPT", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
|
||||||
|
/* (reason might follow) */
|
||||||
|
strlcpy((char *)buf, " FORWARD_REJECT", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
snprintf(buf, buflen, " %d (unknown)", data[3]);
|
||||||
|
common2:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
for (i = 4; i < cnt; i++) {
|
||||||
|
snprintf(buf, buflen, " %d", data[i]);
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kerberos5_forward(Authenticator *ap)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_ccache ccache;
|
||||||
|
krb5_creds creds;
|
||||||
|
krb5_kdc_flags flags;
|
||||||
|
krb5_data out_data;
|
||||||
|
krb5_principal principal;
|
||||||
|
|
||||||
|
ret = krb5_cc_default (context, &ccache);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf ("KerberosV5: could not get default ccache: %s\r\n",
|
||||||
|
krb5_get_err_text (context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_cc_get_principal (context, ccache, &principal);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf ("KerberosV5: could not get principal: %s\r\n",
|
||||||
|
krb5_get_err_text (context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&creds, 0, sizeof(creds));
|
||||||
|
|
||||||
|
creds.client = principal;
|
||||||
|
|
||||||
|
ret = krb5_build_principal (context,
|
||||||
|
&creds.server,
|
||||||
|
strlen(principal->realm),
|
||||||
|
principal->realm,
|
||||||
|
"krbtgt",
|
||||||
|
principal->realm,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf ("KerberosV5: could not get principal: %s\r\n",
|
||||||
|
krb5_get_err_text (context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
creds.times.endtime = 0;
|
||||||
|
|
||||||
|
flags.i = 0;
|
||||||
|
flags.b.forwarded = 1;
|
||||||
|
if (forward_flags & OPTS_FORWARDABLE_CREDS)
|
||||||
|
flags.b.forwardable = 1;
|
||||||
|
|
||||||
|
ret = krb5_get_forwarded_creds (context,
|
||||||
|
auth_context,
|
||||||
|
ccache,
|
||||||
|
flags.i,
|
||||||
|
RemoteHostName,
|
||||||
|
&creds,
|
||||||
|
&out_data);
|
||||||
|
if (ret) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf ("Kerberos V5: error getting forwarded creds: %s\r\n",
|
||||||
|
krb5_get_err_text (context, ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room for authentication data\r\n");
|
||||||
|
} else {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Forwarded local Kerberos V5 credentials to server\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(DCE)
|
||||||
|
/* if this was a K5 authentication try and join a PAG for the user. */
|
||||||
|
void
|
||||||
|
kerberos5_dfspag(void)
|
||||||
|
{
|
||||||
|
if (dfsk5ok) {
|
||||||
|
dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client,
|
||||||
|
UserNameRequested);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* KRB5 */
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)key-proto.h 8.1 (Berkeley) 6/4/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*
|
||||||
|
* $FreeBSD: src/contrib/telnet/libtelnet/key-proto.h,v 1.2 2001/11/30 21:06:34 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KEY_PROTO__
|
||||||
|
#define __KEY_PROTO__
|
||||||
|
|
||||||
|
int key_file_exists(void);
|
||||||
|
void key_lookup(unsigned char *, Block);
|
||||||
|
void key_stream_init(Block, Block, int);
|
||||||
|
unsigned char key_stream(int, int);
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,428 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1992, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/krb4encpwd.c,v 1.7 2001/11/30 22:28:07 markm Exp $");
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
static char sccsid[] = "@(#)krb4encpwd.c 8.3 (Berkeley) 5/30/95";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef KRB4_ENCPWD
|
||||||
|
/*
|
||||||
|
* COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
|
||||||
|
* ALL RIGHTS RESERVED
|
||||||
|
*
|
||||||
|
* "Digital Equipment Corporation authorizes the reproduction,
|
||||||
|
* distribution and modification of this software subject to the following
|
||||||
|
* restrictions:
|
||||||
|
*
|
||||||
|
* 1. Any partial or whole copy of this software, or any modification
|
||||||
|
* thereof, must include this copyright notice in its entirety.
|
||||||
|
*
|
||||||
|
* 2. This software is supplied "as is" with no warranty of any kind,
|
||||||
|
* expressed or implied, for any purpose, including any warranty of fitness
|
||||||
|
* or merchantibility. DIGITAL assumes no responsibility for the use or
|
||||||
|
* reliability of this software, nor promises to provide any form of
|
||||||
|
* support for it on any basis.
|
||||||
|
*
|
||||||
|
* 3. Distribution of this software is authorized only if no profit or
|
||||||
|
* remuneration of any kind is received in exchange for such distribution.
|
||||||
|
*
|
||||||
|
* 4. This software produces public key authentication certificates
|
||||||
|
* bearing an expiration date established by DIGITAL and RSA Data
|
||||||
|
* Security, Inc. It may cease to generate certificates after the expiration
|
||||||
|
* date. Any modification of this software that changes or defeats
|
||||||
|
* the expiration date or its effect is unauthorized.
|
||||||
|
*
|
||||||
|
* 5. Software that will renew or extend the expiration date of
|
||||||
|
* authentication certificates produced by this software may be obtained
|
||||||
|
* from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
|
||||||
|
* 94065, (415)595-8782, or from DIGITAL"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <openssl/des.h>
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
#include <krb.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
int krb_mk_encpwd_req(KTEXT, char *, char *, char *, char *, char *, char *);
|
||||||
|
int krb_rd_encpwd_req(KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *);
|
||||||
|
|
||||||
|
extern auth_debug_mode;
|
||||||
|
|
||||||
|
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
|
||||||
|
AUTHTYPE_KRB4_ENCPWD, };
|
||||||
|
static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
|
||||||
|
TELQUAL_NAME, };
|
||||||
|
|
||||||
|
#define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */
|
||||||
|
#define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
|
||||||
|
#define KRB4_ENCPWD_ACCEPT 2 /* Accepted */
|
||||||
|
#define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */
|
||||||
|
#define KRB4_ENCPWD_ACK 4 /* Acknowledge */
|
||||||
|
|
||||||
|
#define KRB_SERVICE_NAME "rcmd"
|
||||||
|
|
||||||
|
static KTEXT_ST auth;
|
||||||
|
static char name[ANAME_SZ];
|
||||||
|
static char user_passwd[ANAME_SZ];
|
||||||
|
static AUTH_DAT adat = { 0 };
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
static Block session_key = { 0 };
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
static char challenge[REALM_SZ];
|
||||||
|
|
||||||
|
static int
|
||||||
|
Data(ap, type, d, c)
|
||||||
|
Authenticator *ap;
|
||||||
|
int type;
|
||||||
|
void *d;
|
||||||
|
int c;
|
||||||
|
{
|
||||||
|
unsigned char *p = str_data + 4;
|
||||||
|
unsigned char *cd = (unsigned char *)d;
|
||||||
|
|
||||||
|
if (c == -1)
|
||||||
|
c = strlen((char *)cd);
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
printf("%s:%d: [%d] (%d)",
|
||||||
|
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
|
||||||
|
str_data[3],
|
||||||
|
type, c);
|
||||||
|
printd(d, c);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
*p++ = ap->type;
|
||||||
|
*p++ = ap->way;
|
||||||
|
*p++ = type;
|
||||||
|
while (c-- > 0) {
|
||||||
|
if ((*p++ = *cd++) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
if (str_data[3] == TELQUAL_IS)
|
||||||
|
printsub('>', &str_data[2], p - (&str_data[2]));
|
||||||
|
return(net_write(str_data, p - str_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
krb4encpwd_init(ap, server)
|
||||||
|
Authenticator *ap;
|
||||||
|
int server;
|
||||||
|
{
|
||||||
|
char hostname[80], *cp, *realm;
|
||||||
|
C_Block skey;
|
||||||
|
|
||||||
|
if (server) {
|
||||||
|
str_data[3] = TELQUAL_REPLY;
|
||||||
|
} else {
|
||||||
|
str_data[3] = TELQUAL_IS;
|
||||||
|
gethostname(hostname, sizeof(hostname));
|
||||||
|
realm = krb_realmofhost(hostname);
|
||||||
|
cp = strchr(hostname, '.');
|
||||||
|
if (*cp != NULL) *cp = NULL;
|
||||||
|
if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
|
||||||
|
KEYFILE, (char *)skey)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
krb4encpwd_send(ap)
|
||||||
|
Authenticator *ap;
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("[ Trying KRB4ENCPWD ... ]\n");
|
||||||
|
if (!UserNameRequested) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krb4encpwd_is(ap, data, cnt)
|
||||||
|
Authenticator *ap;
|
||||||
|
unsigned char *data;
|
||||||
|
int cnt;
|
||||||
|
{
|
||||||
|
Session_Key skey;
|
||||||
|
Block datablock;
|
||||||
|
char r_passwd[ANAME_SZ], r_user[ANAME_SZ];
|
||||||
|
char lhostname[ANAME_SZ], *cp;
|
||||||
|
int r;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
case KRB4_ENCPWD_AUTH:
|
||||||
|
memmove((void *)auth.dat, (void *)data, auth.length = cnt);
|
||||||
|
|
||||||
|
gethostname(lhostname, sizeof(lhostname));
|
||||||
|
if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
|
||||||
|
|
||||||
|
if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
|
||||||
|
Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auth_encrypt_userpwd(r_passwd);
|
||||||
|
if (passwdok(UserNameRequested, UserPassword) == 0) {
|
||||||
|
/*
|
||||||
|
* illegal username and password
|
||||||
|
*/
|
||||||
|
Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove((void *)session_key, (void *)adat.session, sizeof(Block));
|
||||||
|
Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0);
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KRB4_ENCPWD_CHALLENGE:
|
||||||
|
/*
|
||||||
|
* Take the received random challenge text and save
|
||||||
|
* for future authentication.
|
||||||
|
*/
|
||||||
|
memmove((void *)challenge, (void *)data, sizeof(Block));
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case KRB4_ENCPWD_ACK:
|
||||||
|
/*
|
||||||
|
* Receive ack, if mutual then send random challenge
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are doing mutual authentication, get set up to send
|
||||||
|
* the challenge, and verify it when the response comes back.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
sprintf(challenge, "%x", now);
|
||||||
|
Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
krb4encpwd_reply(ap, data, cnt)
|
||||||
|
Authenticator *ap;
|
||||||
|
unsigned char *data;
|
||||||
|
int cnt;
|
||||||
|
{
|
||||||
|
Session_Key skey;
|
||||||
|
KTEXT_ST krb_token;
|
||||||
|
Block enckey;
|
||||||
|
CREDENTIALS cred;
|
||||||
|
int r;
|
||||||
|
char randchal[REALM_SZ], instance[ANAME_SZ], *cp;
|
||||||
|
char hostname[80], *realm;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
case KRB4_ENCPWD_REJECT:
|
||||||
|
if (cnt > 0) {
|
||||||
|
printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
|
||||||
|
cnt, data);
|
||||||
|
} else
|
||||||
|
printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
case KRB4_ENCPWD_ACCEPT:
|
||||||
|
printf("[ KRB4_ENCPWD accepts you ]\n");
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
return;
|
||||||
|
case KRB4_ENCPWD_CHALLENGE:
|
||||||
|
/*
|
||||||
|
* Verify that the response to the challenge is correct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
gethostname(hostname, sizeof(hostname));
|
||||||
|
realm = krb_realmofhost(hostname);
|
||||||
|
memmove((void *)challenge, (void *)data, cnt);
|
||||||
|
memset(user_passwd, 0, sizeof(user_passwd));
|
||||||
|
local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
|
||||||
|
UserPassword = user_passwd;
|
||||||
|
Challenge = challenge;
|
||||||
|
strcpy(instance, RemoteHostName);
|
||||||
|
if ((cp = strchr(instance, '.')) != 0) *cp = '\0';
|
||||||
|
|
||||||
|
if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
|
||||||
|
krb_token.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
krb4encpwd_status(ap, name, level)
|
||||||
|
Authenticator *ap;
|
||||||
|
char *name;
|
||||||
|
int level;
|
||||||
|
{
|
||||||
|
|
||||||
|
if (level < AUTH_USER)
|
||||||
|
return(level);
|
||||||
|
|
||||||
|
if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
|
||||||
|
strcpy(name, UserNameRequested);
|
||||||
|
return(AUTH_VALID);
|
||||||
|
} else {
|
||||||
|
return(AUTH_USER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
|
||||||
|
#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
|
||||||
|
|
||||||
|
void
|
||||||
|
krb4encpwd_printsub(data, cnt, buf, buflen)
|
||||||
|
unsigned char *data, *buf;
|
||||||
|
int cnt, buflen;
|
||||||
|
{
|
||||||
|
char lbuf[32];
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
buf[buflen-1] = '\0'; /* make sure its NULL terminated */
|
||||||
|
buflen -= 1;
|
||||||
|
|
||||||
|
switch(data[3]) {
|
||||||
|
case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */
|
||||||
|
strncpy((char *)buf, " REJECT ", buflen);
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */
|
||||||
|
strncpy((char *)buf, " ACCEPT ", buflen);
|
||||||
|
common:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
if (cnt <= 4)
|
||||||
|
break;
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
for (i = 4; i < cnt; i++)
|
||||||
|
ADDC(buf, buflen, data[i]);
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
ADDC(buf, buflen, '\0');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KRB4_ENCPWD_AUTH: /* Authentication data follows */
|
||||||
|
strncpy((char *)buf, " AUTH", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB4_ENCPWD_CHALLENGE:
|
||||||
|
strncpy((char *)buf, " CHALLENGE", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case KRB4_ENCPWD_ACK:
|
||||||
|
strncpy((char *)buf, " ACK", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(lbuf, " %d (unknown)", data[3]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
common2:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
for (i = 4; i < cnt; i++) {
|
||||||
|
sprintf(lbuf, " %d", data[i]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int passwdok(name, passwd)
|
||||||
|
char *name, *passwd;
|
||||||
|
{
|
||||||
|
char *crypt();
|
||||||
|
char *salt, *p;
|
||||||
|
struct passwd *pwd;
|
||||||
|
int passwdok_status = 0;
|
||||||
|
|
||||||
|
if (pwd = getpwnam(name))
|
||||||
|
salt = pwd->pw_passwd;
|
||||||
|
else salt = "xx";
|
||||||
|
|
||||||
|
p = crypt(passwd, salt);
|
||||||
|
|
||||||
|
if (pwd && !strcmp(p, pwd->pw_passwd)) {
|
||||||
|
passwdok_status = 1;
|
||||||
|
} else passwdok_status = 0;
|
||||||
|
return(passwdok_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)misc-proto.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD: src/contrib/telnet/libtelnet/misc-proto.h,v 1.4 2001/11/30 22:28:07 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1990 by the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Export of this software from the United States of America is assumed
|
||||||
|
* to require a specific license from the United States Government.
|
||||||
|
* It is the responsibility of any person or organization contemplating
|
||||||
|
* export to obtain such a license before exporting.
|
||||||
|
*
|
||||||
|
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||||
|
* distribute this software and its documentation for any purpose and
|
||||||
|
* without fee is hereby granted, provided that the above copyright
|
||||||
|
* notice appear in all copies and that both that copyright notice and
|
||||||
|
* this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of M.I.T. not be used in advertising or publicity pertaining
|
||||||
|
* to distribution of the software without specific, written prior
|
||||||
|
* permission. M.I.T. makes no representations about the suitability of
|
||||||
|
* this software for any purpose. It is provided "as is" without express
|
||||||
|
* or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MISC_PROTO__
|
||||||
|
#define __MISC_PROTO__
|
||||||
|
|
||||||
|
void auth_encrypt_init(char *, char *, const char *, int);
|
||||||
|
void auth_encrypt_connect(int);
|
||||||
|
void printd(const unsigned char *, int);
|
||||||
|
|
||||||
|
int isprefix(char *, const char *);
|
||||||
|
char **genget(char *, char **, int);
|
||||||
|
int Ambiguous(char **);
|
||||||
|
|
||||||
|
int getent(char *, const char *);
|
||||||
|
char *Getstr(const char *, char **);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions are imported from the application
|
||||||
|
*/
|
||||||
|
int net_write(unsigned char *, int);
|
||||||
|
void net_encrypt(void);
|
||||||
|
int telnet_spin(void);
|
||||||
|
char *telnet_getenv(char *);
|
||||||
|
char *telnet_gets(const char *, char *, int, int);
|
||||||
|
void printsub(char, unsigned char *, int);
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/misc.c,v 1.8 2002/06/26 17:05:08 markm Exp $");
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#ifdef AUTHENTICATION
|
||||||
|
#include "auth.h"
|
||||||
|
#endif
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
#include "encrypt.h"
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
|
||||||
|
char *RemoteHostName;
|
||||||
|
char *LocalHostName;
|
||||||
|
char *UserNameRequested = 0;
|
||||||
|
int ConnectedCount = 0;
|
||||||
|
|
||||||
|
#ifndef AUTHENTICATION
|
||||||
|
#define undef1 __unused
|
||||||
|
#else
|
||||||
|
#define undef1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_encrypt_init(char *local, char *remote, const char *name undef1, int server undef1)
|
||||||
|
{
|
||||||
|
RemoteHostName = remote;
|
||||||
|
LocalHostName = local;
|
||||||
|
#ifdef AUTHENTICATION
|
||||||
|
auth_init(name, server);
|
||||||
|
#endif
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
encrypt_init(name, server);
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
if (UserNameRequested) {
|
||||||
|
free(UserNameRequested);
|
||||||
|
UserNameRequested = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
void
|
||||||
|
auth_encrypt_user(char *name)
|
||||||
|
{
|
||||||
|
if (UserNameRequested)
|
||||||
|
free(UserNameRequested);
|
||||||
|
UserNameRequested = name ? strdup(name) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
void
|
||||||
|
auth_encrypt_connect(int cnt __unused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
|
||||||
|
void
|
||||||
|
printd(const unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
if (cnt > 16)
|
||||||
|
cnt = 16;
|
||||||
|
while (cnt-- > 0) {
|
||||||
|
printf(" %02x", *data);
|
||||||
|
++data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)misc.h 8.1 (Berkeley) 6/4/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern char *UserNameRequested;
|
||||||
|
extern char *LocalHostName;
|
||||||
|
extern char *RemoteHostName;
|
||||||
|
extern int ConnectedCount;
|
||||||
|
extern int ReservedPort;
|
||||||
|
|
||||||
|
#include "misc-proto.h"
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* Dave Safford. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/pk.c,v 1.10 2002/08/22 06:19:07 nsayer Exp $");
|
||||||
|
|
||||||
|
/* public key routines */
|
||||||
|
/* functions:
|
||||||
|
genkeys(char *public, char *secret)
|
||||||
|
common_key(char *secret, char *public, desData *deskey)
|
||||||
|
pk_encode(char *in, *out, DesData *deskey);
|
||||||
|
pk_decode(char *in, *out, DesData *deskey);
|
||||||
|
where
|
||||||
|
char public[HEXKEYBYTES + 1];
|
||||||
|
char secret[HEXKEYBYTES + 1];
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <openssl/des.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "mp.h"
|
||||||
|
#include "pk.h"
|
||||||
|
|
||||||
|
static void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Choose top 128 bits of the common key to use as our idea key.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
extractideakey(MINT *ck, IdeaData *ideakey)
|
||||||
|
{
|
||||||
|
MINT *a;
|
||||||
|
MINT *z;
|
||||||
|
short r;
|
||||||
|
int i;
|
||||||
|
short base = (1 << 8);
|
||||||
|
char *k;
|
||||||
|
|
||||||
|
z = itom(0);
|
||||||
|
a = itom(0);
|
||||||
|
madd(ck, z, a);
|
||||||
|
for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
|
||||||
|
sdiv(a, base, a, &r);
|
||||||
|
}
|
||||||
|
k = (char *)ideakey;
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
sdiv(a, base, a, &r);
|
||||||
|
*k++ = r;
|
||||||
|
}
|
||||||
|
mfree(z);
|
||||||
|
mfree(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Choose middle 64 bits of the common key to use as our des key, possibly
|
||||||
|
* overwriting the lower order bits by setting parity.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
extractdeskey(MINT *ck, DesData *deskey)
|
||||||
|
{
|
||||||
|
MINT *a;
|
||||||
|
MINT *z;
|
||||||
|
short r;
|
||||||
|
int i;
|
||||||
|
short base = (1 << 8);
|
||||||
|
char *k;
|
||||||
|
|
||||||
|
z = itom(0);
|
||||||
|
a = itom(0);
|
||||||
|
madd(ck, z, a);
|
||||||
|
for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
|
||||||
|
sdiv(a, base, a, &r);
|
||||||
|
}
|
||||||
|
k = (char *)deskey;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
sdiv(a, base, a, &r);
|
||||||
|
*k++ = r;
|
||||||
|
}
|
||||||
|
mfree(z);
|
||||||
|
mfree(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get common key from my secret key and his public key
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
|
||||||
|
{
|
||||||
|
MINT *public;
|
||||||
|
MINT *secret;
|
||||||
|
MINT *common;
|
||||||
|
MINT *modulus = xtom(HEXMODULUS);
|
||||||
|
|
||||||
|
public = xtom(xpublic);
|
||||||
|
secret = xtom(xsecret);
|
||||||
|
common = itom(0);
|
||||||
|
pow(public, secret, modulus, common);
|
||||||
|
extractdeskey(common, deskey);
|
||||||
|
extractideakey(common, ideakey);
|
||||||
|
des_set_odd_parity(deskey);
|
||||||
|
mfree(common);
|
||||||
|
mfree(secret);
|
||||||
|
mfree(public);
|
||||||
|
mfree(modulus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a seed
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
getseed(char *seed, int seedsize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
srandomdev();
|
||||||
|
for (i = 0; i < seedsize; i++) {
|
||||||
|
seed[i] = random() & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a random public/secret key pair
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
genkeys(char *public, char *secret)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
# define BASEBITS (8*sizeof(short) - 1)
|
||||||
|
# define BASE (1 << BASEBITS)
|
||||||
|
|
||||||
|
MINT *pk = itom(0);
|
||||||
|
MINT *sk = itom(0);
|
||||||
|
MINT *tmp;
|
||||||
|
MINT *base = itom(BASE);
|
||||||
|
MINT *root = itom(PROOT);
|
||||||
|
MINT *modulus = xtom(HEXMODULUS);
|
||||||
|
short r;
|
||||||
|
unsigned short seed[KEYSIZE/BASEBITS + 1];
|
||||||
|
char *xkey;
|
||||||
|
|
||||||
|
getseed((char *)seed, sizeof(seed));
|
||||||
|
for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
|
||||||
|
r = seed[i] % BASE;
|
||||||
|
tmp = itom(r);
|
||||||
|
mult(sk, base, sk);
|
||||||
|
madd(sk, tmp, sk);
|
||||||
|
mfree(tmp);
|
||||||
|
}
|
||||||
|
tmp = itom(0);
|
||||||
|
mdiv(sk, modulus, tmp, sk);
|
||||||
|
mfree(tmp);
|
||||||
|
pow(root, sk, modulus, pk);
|
||||||
|
xkey = mtox(sk);
|
||||||
|
adjust(secret, xkey);
|
||||||
|
xkey = mtox(pk);
|
||||||
|
adjust(public, xkey);
|
||||||
|
mfree(sk);
|
||||||
|
mfree(base);
|
||||||
|
mfree(pk);
|
||||||
|
mfree(root);
|
||||||
|
mfree(modulus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust the input key so that it is 0-filled on the left
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
adjust(char keyout[HEXKEYBYTES+1], char *keyin)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
for (p = keyin; *p; p++)
|
||||||
|
;
|
||||||
|
for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
|
||||||
|
*s = *p;
|
||||||
|
}
|
||||||
|
while (s >= keyout) {
|
||||||
|
*s-- = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char hextab[17] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
/* given a DES key, cbc encrypt and translate input to terminated hex */
|
||||||
|
void
|
||||||
|
pk_encode(char *in, char *out, DesData *key)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
DesData i;
|
||||||
|
des_key_schedule k;
|
||||||
|
int l,op,deslen;
|
||||||
|
|
||||||
|
memset(&i,0,sizeof(i));
|
||||||
|
memset(buf,0,sizeof(buf));
|
||||||
|
deslen = ((strlen(in) + 7)/8)*8;
|
||||||
|
des_key_sched(key, k);
|
||||||
|
des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT);
|
||||||
|
for (l=0,op=0;l<deslen;l++) {
|
||||||
|
out[op++] = hextab[(buf[l] & 0xf0) >> 4];
|
||||||
|
out[op++] = hextab[(buf[l] & 0x0f)];
|
||||||
|
}
|
||||||
|
out[op] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* given a DES key, translate input from hex and decrypt */
|
||||||
|
void
|
||||||
|
pk_decode(char *in, char *out, DesData *key)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
DesData i;
|
||||||
|
des_key_schedule k;
|
||||||
|
int n1,n2,op;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
memset(&i,0,sizeof(i));
|
||||||
|
memset(buf,0,sizeof(buf));
|
||||||
|
for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
|
||||||
|
if (in[op] > '9')
|
||||||
|
n1 = in[op] - 'A' + 10;
|
||||||
|
else
|
||||||
|
n1 = in[op] - '0';
|
||||||
|
if (in[op+1] > '9')
|
||||||
|
n2 = in[op+1] - 'A' + 10;
|
||||||
|
else
|
||||||
|
n2 = in[op+1] - '0';
|
||||||
|
buf[l] = n1*16 +n2;
|
||||||
|
}
|
||||||
|
des_key_sched(key, k);
|
||||||
|
des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT);
|
||||||
|
out[strlen(in)/2] = '\0';
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* Dave Safford. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD: src/contrib/telnet/libtelnet/pk.h,v 1.6 2001/11/30 21:06:34 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* header for the des routines that we will use */
|
||||||
|
|
||||||
|
typedef unsigned char byte, DesData[ 8], IdeaData[16];
|
||||||
|
#define DesKeys des_key_schedule
|
||||||
|
|
||||||
|
#define DES_DECRYPT 0
|
||||||
|
#define DES_ENCRYPT 1
|
||||||
|
|
||||||
|
/* public key routines */
|
||||||
|
/* functions:
|
||||||
|
genkeys(char *public, char *secret)
|
||||||
|
common_key(char *secret, char *public, desData *deskey)
|
||||||
|
where
|
||||||
|
char public[HEXKEYBYTES + 1];
|
||||||
|
char secret[HEXKEYBYTES + 1];
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"
|
||||||
|
#define HEXKEYBYTES 48
|
||||||
|
#define KEYSIZE 192
|
||||||
|
#define KEYBYTES 24
|
||||||
|
#define PROOT 3
|
||||||
|
|
||||||
|
extern void genkeys(char *public, char *secret);
|
||||||
|
extern void common_key(char *secret, char *public, IdeaData *common,
|
||||||
|
DesData *deskey);
|
||||||
|
extern void pk_encode(char *in, char *out, DesData *deskey);
|
||||||
|
extern void pk_decode(char *in, char *out, DesData *deskey);
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1992, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/read_password.c,v 1.5 2001/11/30 21:06:34 markm Exp $");
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)read_password.c 8.3 (Berkeley) 5/30/95";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Source: /mit/kerberos/src/lib/des/RCS/read_password.c,v $
|
||||||
|
* $Author: jon $
|
||||||
|
*
|
||||||
|
* Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
|
||||||
|
* of Technology.
|
||||||
|
*
|
||||||
|
* For copying and distribution information, please see the file
|
||||||
|
* <mit-copyright.h>.
|
||||||
|
*
|
||||||
|
* This routine prints the supplied string to standard
|
||||||
|
* output as a prompt, and reads a password string without
|
||||||
|
* echoing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(RSA_ENCPWD) || defined(KRB4_ENCPWD)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
static jmp_buf env;
|
||||||
|
|
||||||
|
/*** Routines ****************************************************** */
|
||||||
|
/*
|
||||||
|
* This version just returns the string, doesn't map to key.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, non-zero on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
local_des_read_pw_string(s,max,prompt,verify)
|
||||||
|
char *s;
|
||||||
|
int max;
|
||||||
|
char *prompt;
|
||||||
|
int verify;
|
||||||
|
{
|
||||||
|
int ok = 0;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
jmp_buf old_env;
|
||||||
|
struct sgttyb tty_state;
|
||||||
|
char key_string[BUFSIZ];
|
||||||
|
|
||||||
|
if (max > BUFSIZ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX assume jmp_buf is typedef'ed to an array */
|
||||||
|
memmove((char *)env, (char *)old_env, sizeof(env));
|
||||||
|
if (setjmp(env))
|
||||||
|
goto lose;
|
||||||
|
|
||||||
|
/* save terminal state*/
|
||||||
|
if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1)
|
||||||
|
return -1;
|
||||||
|
/*
|
||||||
|
push_signals();
|
||||||
|
*/
|
||||||
|
/* Turn off echo */
|
||||||
|
tty_state.sg_flags &= ~ECHO;
|
||||||
|
if (ioctl(0,TIOCSETP,(char *)&tty_state) == -1)
|
||||||
|
return -1;
|
||||||
|
while (!ok) {
|
||||||
|
(void) printf("%s", prompt);
|
||||||
|
(void) fflush(stdout);
|
||||||
|
while (!fgets(s, max, stdin));
|
||||||
|
|
||||||
|
if ((ptr = strchr(s, '\n')))
|
||||||
|
*ptr = '\0';
|
||||||
|
if (verify) {
|
||||||
|
printf("\nVerifying, please re-enter %s",prompt);
|
||||||
|
(void) fflush(stdout);
|
||||||
|
if (!fgets(key_string, sizeof(key_string), stdin)) {
|
||||||
|
clearerr(stdin);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((ptr = strchr(key_string, '\n')))
|
||||||
|
*ptr = '\0';
|
||||||
|
if (strcmp(s,key_string)) {
|
||||||
|
printf("\n\07\07Mismatch - try again\n");
|
||||||
|
(void) fflush(stdout);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lose:
|
||||||
|
if (!ok)
|
||||||
|
memset(s, 0, max);
|
||||||
|
printf("\n");
|
||||||
|
/* turn echo back on */
|
||||||
|
tty_state.sg_flags |= ECHO;
|
||||||
|
if (ioctl(0,TIOCSETP,(char *)&tty_state))
|
||||||
|
ok = 0;
|
||||||
|
/*
|
||||||
|
pop_signals();
|
||||||
|
*/
|
||||||
|
memmove((char *)old_env, (char *)env, sizeof(env));
|
||||||
|
if (verify)
|
||||||
|
memset(key_string, 0, sizeof (key_string));
|
||||||
|
s[max-1] = 0; /* force termination */
|
||||||
|
return !ok; /* return nonzero if not okay */
|
||||||
|
}
|
||||||
|
#endif /* defined(RSA_ENCPWD) || defined(KRB4_ENCPWD) */
|
||||||
@@ -0,0 +1,471 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1992, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/rsaencpwd.c,v 1.3 2001/11/30 21:06:34 markm Exp $");
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RSA_ENCPWD
|
||||||
|
/*
|
||||||
|
* COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
|
||||||
|
* ALL RIGHTS RESERVED
|
||||||
|
*
|
||||||
|
* "Digital Equipment Corporation authorizes the reproduction,
|
||||||
|
* distribution and modification of this software subject to the following
|
||||||
|
* restrictions:
|
||||||
|
*
|
||||||
|
* 1. Any partial or whole copy of this software, or any modification
|
||||||
|
* thereof, must include this copyright notice in its entirety.
|
||||||
|
*
|
||||||
|
* 2. This software is supplied "as is" with no warranty of any kind,
|
||||||
|
* expressed or implied, for any purpose, including any warranty of fitness
|
||||||
|
* or merchantibility. DIGITAL assumes no responsibility for the use or
|
||||||
|
* reliability of this software, nor promises to provide any form of
|
||||||
|
* support for it on any basis.
|
||||||
|
*
|
||||||
|
* 3. Distribution of this software is authorized only if no profit or
|
||||||
|
* remuneration of any kind is received in exchange for such distribution.
|
||||||
|
*
|
||||||
|
* 4. This software produces public key authentication certificates
|
||||||
|
* bearing an expiration date established by DIGITAL and RSA Data
|
||||||
|
* Security, Inc. It may cease to generate certificates after the expiration
|
||||||
|
* date. Any modification of this software that changes or defeats
|
||||||
|
* the expiration date or its effect is unauthorized.
|
||||||
|
*
|
||||||
|
* 5. Software that will renew or extend the expiration date of
|
||||||
|
* authentication certificates produced by this software may be obtained
|
||||||
|
* from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
|
||||||
|
* 94065, (415)595-8782, or from DIGITAL"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "cdc.h"
|
||||||
|
|
||||||
|
extern auth_debug_mode;
|
||||||
|
|
||||||
|
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
|
||||||
|
AUTHTYPE_RSA_ENCPWD, };
|
||||||
|
static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
|
||||||
|
TELQUAL_NAME, };
|
||||||
|
|
||||||
|
#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */
|
||||||
|
#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
|
||||||
|
#define RSA_ENCPWD_ACCEPT 2 /* Accepted */
|
||||||
|
#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */
|
||||||
|
|
||||||
|
#define NAME_SZ 40
|
||||||
|
#define CHAL_SZ 20
|
||||||
|
#define PWD_SZ 40
|
||||||
|
|
||||||
|
static KTEXT_ST auth;
|
||||||
|
static char name[NAME_SZ];
|
||||||
|
static char user_passwd[PWD_SZ];
|
||||||
|
static char key_file[2*NAME_SZ];
|
||||||
|
static char lhostname[NAME_SZ];
|
||||||
|
static char challenge[CHAL_SZ];
|
||||||
|
static int challenge_len;
|
||||||
|
|
||||||
|
static int
|
||||||
|
Data(ap, type, d, c)
|
||||||
|
Authenticator *ap;
|
||||||
|
int type;
|
||||||
|
void *d;
|
||||||
|
int c;
|
||||||
|
{
|
||||||
|
unsigned char *p = str_data + 4;
|
||||||
|
unsigned char *cd = (unsigned char *)d;
|
||||||
|
|
||||||
|
if (c == -1)
|
||||||
|
c = strlen((char *)cd);
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
printf("%s:%d: [%d] (%d)",
|
||||||
|
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
|
||||||
|
str_data[3],
|
||||||
|
type, c);
|
||||||
|
printd(d, c);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
*p++ = ap->type;
|
||||||
|
*p++ = ap->way;
|
||||||
|
if (type != NULL) *p++ = type;
|
||||||
|
while (c-- > 0) {
|
||||||
|
if ((*p++ = *cd++) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
if (str_data[3] == TELQUAL_IS)
|
||||||
|
printsub('>', &str_data[2], p - (&str_data[2]));
|
||||||
|
return(net_write(str_data, p - str_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rsaencpwd_init(ap, server)
|
||||||
|
Authenticator *ap;
|
||||||
|
int server;
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (server) {
|
||||||
|
str_data[3] = TELQUAL_REPLY;
|
||||||
|
memset(key_file, 0, sizeof(key_file));
|
||||||
|
gethostname(lhostname, sizeof(lhostname));
|
||||||
|
if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
|
||||||
|
strcpy(key_file, "/etc/.");
|
||||||
|
strcat(key_file, lhostname);
|
||||||
|
strcat(key_file, "_privkey");
|
||||||
|
if ((fp=fopen(key_file, "r"))==NULL) return(0);
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
str_data[3] = TELQUAL_IS;
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rsaencpwd_send(ap)
|
||||||
|
Authenticator *ap;
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("[ Trying RSAENCPWD ... ]\n");
|
||||||
|
if (!UserNameRequested) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (!Data(ap, NULL, (void *)NULL, 0)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rsaencpwd_is(ap, data, cnt)
|
||||||
|
Authenticator *ap;
|
||||||
|
unsigned char *data;
|
||||||
|
int cnt;
|
||||||
|
{
|
||||||
|
Session_Key skey;
|
||||||
|
Block datablock;
|
||||||
|
char r_passwd[PWD_SZ], r_user[NAME_SZ];
|
||||||
|
char *cp, key[160];
|
||||||
|
char chalkey[160], *ptr;
|
||||||
|
FILE *fp;
|
||||||
|
int r, i, j, chalkey_len, len;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
cnt--;
|
||||||
|
switch (*data++) {
|
||||||
|
case RSA_ENCPWD_AUTH:
|
||||||
|
memmove((void *)auth.dat, (void *)data, auth.length = cnt);
|
||||||
|
|
||||||
|
if ((fp=fopen(key_file, "r"))==NULL) {
|
||||||
|
Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* get privkey
|
||||||
|
*/
|
||||||
|
fscanf(fp, "%x;", &len);
|
||||||
|
for (i=0;i<len;i++) {
|
||||||
|
j = getc(fp); key[i]=j;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
r = accept_rsa_encpwd(&auth, key, challenge,
|
||||||
|
challenge_len, r_passwd);
|
||||||
|
if (r < 0) {
|
||||||
|
Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auth_encrypt_userpwd(r_passwd);
|
||||||
|
if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) {
|
||||||
|
/*
|
||||||
|
* illegal username and password
|
||||||
|
*/
|
||||||
|
Data(ap, RSA_ENCPWD_REJECT, (void *)"Illegal password", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data(ap, RSA_ENCPWD_ACCEPT, (void *)0, 0);
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case IAC:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are doing mutual authentication, get set up to send
|
||||||
|
* the challenge, and verify it when the response comes back.
|
||||||
|
*/
|
||||||
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
if ((now % 2) == 0) {
|
||||||
|
sprintf(challenge, "%x", now);
|
||||||
|
challenge_len = strlen(challenge);
|
||||||
|
} else {
|
||||||
|
strcpy(challenge, "randchal");
|
||||||
|
challenge_len = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fp=fopen(key_file, "r"))==NULL) {
|
||||||
|
Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* skip privkey
|
||||||
|
*/
|
||||||
|
fscanf(fp, "%x;", &len);
|
||||||
|
for (i=0;i<len;i++) {
|
||||||
|
j = getc(fp);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* get pubkey
|
||||||
|
*/
|
||||||
|
fscanf(fp, "%x;", &len);
|
||||||
|
for (i=0;i<len;i++) {
|
||||||
|
j = getc(fp); key[i]=j;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
chalkey[0] = 0x30;
|
||||||
|
ptr = (char *) &chalkey[1];
|
||||||
|
chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len;
|
||||||
|
EncodeLength(ptr, chalkey_len);
|
||||||
|
ptr +=NumEncodeLengthOctets(chalkey_len);
|
||||||
|
*ptr++ = 0x04; /* OCTET STRING */
|
||||||
|
*ptr++ = challenge_len;
|
||||||
|
memmove(ptr, challenge, challenge_len);
|
||||||
|
ptr += challenge_len;
|
||||||
|
*ptr++ = 0x04; /* OCTET STRING */
|
||||||
|
EncodeLength(ptr, i);
|
||||||
|
ptr += NumEncodeLengthOctets(i);
|
||||||
|
memmove(ptr, key, i);
|
||||||
|
chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len;
|
||||||
|
Data(ap, RSA_ENCPWD_CHALLENGEKEY, (void *)chalkey, chalkey_len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Data(ap, RSA_ENCPWD_REJECT, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rsaencpwd_reply(ap, data, cnt)
|
||||||
|
Authenticator *ap;
|
||||||
|
unsigned char *data;
|
||||||
|
int cnt;
|
||||||
|
{
|
||||||
|
Session_Key skey;
|
||||||
|
KTEXT_ST token;
|
||||||
|
Block enckey;
|
||||||
|
int r, pubkey_len;
|
||||||
|
char randchal[CHAL_SZ], *cp;
|
||||||
|
char chalkey[160], pubkey[128], *ptr;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
case RSA_ENCPWD_REJECT:
|
||||||
|
if (cnt > 0) {
|
||||||
|
printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n",
|
||||||
|
cnt, data);
|
||||||
|
} else
|
||||||
|
printf("[ RSA_ENCPWD refuses authentication ]\r\n");
|
||||||
|
auth_send_retry();
|
||||||
|
return;
|
||||||
|
case RSA_ENCPWD_ACCEPT:
|
||||||
|
printf("[ RSA_ENCPWD accepts you ]\n");
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
return;
|
||||||
|
case RSA_ENCPWD_CHALLENGEKEY:
|
||||||
|
/*
|
||||||
|
* Verify that the response to the challenge is correct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memmove((void *)chalkey, (void *)data, cnt);
|
||||||
|
ptr = (char *) &chalkey[0];
|
||||||
|
ptr += DecodeHeaderLength(chalkey);
|
||||||
|
if (*ptr != 0x04) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*ptr++;
|
||||||
|
challenge_len = DecodeValueLength(ptr);
|
||||||
|
ptr += NumEncodeLengthOctets(challenge_len);
|
||||||
|
memmove(challenge, ptr, challenge_len);
|
||||||
|
ptr += challenge_len;
|
||||||
|
if (*ptr != 0x04) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*ptr++;
|
||||||
|
pubkey_len = DecodeValueLength(ptr);
|
||||||
|
ptr += NumEncodeLengthOctets(pubkey_len);
|
||||||
|
memmove(pubkey, ptr, pubkey_len);
|
||||||
|
memset(user_passwd, 0, sizeof(user_passwd));
|
||||||
|
local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
|
||||||
|
UserPassword = user_passwd;
|
||||||
|
Challenge = challenge;
|
||||||
|
r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey);
|
||||||
|
if (r < 0) {
|
||||||
|
token.length = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rsaencpwd_status(ap, name, level)
|
||||||
|
Authenticator *ap;
|
||||||
|
char *name;
|
||||||
|
int level;
|
||||||
|
{
|
||||||
|
|
||||||
|
if (level < AUTH_USER)
|
||||||
|
return(level);
|
||||||
|
|
||||||
|
if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) {
|
||||||
|
strcpy(name, UserNameRequested);
|
||||||
|
return(AUTH_VALID);
|
||||||
|
} else {
|
||||||
|
return(AUTH_USER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
|
||||||
|
#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
|
||||||
|
|
||||||
|
void
|
||||||
|
rsaencpwd_printsub(data, cnt, buf, buflen)
|
||||||
|
unsigned char *data, *buf;
|
||||||
|
int cnt, buflen;
|
||||||
|
{
|
||||||
|
char lbuf[32];
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
buf[buflen-1] = '\0'; /* make sure its NULL terminated */
|
||||||
|
buflen -= 1;
|
||||||
|
|
||||||
|
switch(data[3]) {
|
||||||
|
case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */
|
||||||
|
strncpy((char *)buf, " REJECT ", buflen);
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */
|
||||||
|
strncpy((char *)buf, " ACCEPT ", buflen);
|
||||||
|
common:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
if (cnt <= 4)
|
||||||
|
break;
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
for (i = 4; i < cnt; i++)
|
||||||
|
ADDC(buf, buflen, data[i]);
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
ADDC(buf, buflen, '\0');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RSA_ENCPWD_AUTH: /* Authentication data follows */
|
||||||
|
strncpy((char *)buf, " AUTH", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case RSA_ENCPWD_CHALLENGEKEY:
|
||||||
|
strncpy((char *)buf, " CHALLENGEKEY", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(lbuf, " %d (unknown)", data[3]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
common2:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
for (i = 4; i < cnt; i++) {
|
||||||
|
sprintf(lbuf, " %d", data[i]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rsaencpwd_passwdok(name, passwd)
|
||||||
|
char *name, *passwd;
|
||||||
|
{
|
||||||
|
char *crypt();
|
||||||
|
char *salt, *p;
|
||||||
|
struct passwd *pwd;
|
||||||
|
int passwdok_status = 0;
|
||||||
|
|
||||||
|
if (pwd = getpwnam(name))
|
||||||
|
salt = pwd->pw_passwd;
|
||||||
|
else salt = "xx";
|
||||||
|
|
||||||
|
p = crypt(passwd, salt);
|
||||||
|
|
||||||
|
if (pwd && !strcmp(p, pwd->pw_passwd)) {
|
||||||
|
passwdok_status = 1;
|
||||||
|
} else passwdok_status = 0;
|
||||||
|
return(passwdok_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,602 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* Dave Safford. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/sra.c,v 1.16 2002/05/06 09:48:02 markm Exp $");
|
||||||
|
|
||||||
|
#ifdef SRA
|
||||||
|
#ifdef ENCRYPTION
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/telnet.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <ttyent.h>
|
||||||
|
|
||||||
|
#ifndef NOPAM
|
||||||
|
#include <security/pam_appl.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "auth.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "encrypt.h"
|
||||||
|
#include "pk.h"
|
||||||
|
|
||||||
|
char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
|
||||||
|
char *user, *pass, *xuser, *xpass;
|
||||||
|
DesData ck;
|
||||||
|
IdeaData ik;
|
||||||
|
|
||||||
|
extern int auth_debug_mode;
|
||||||
|
extern char line[];
|
||||||
|
|
||||||
|
static int sra_valid = 0;
|
||||||
|
static int passwd_sent = 0;
|
||||||
|
|
||||||
|
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
|
||||||
|
AUTHTYPE_SRA, };
|
||||||
|
|
||||||
|
#define SRA_KEY 0
|
||||||
|
#define SRA_USER 1
|
||||||
|
#define SRA_CONTINUE 2
|
||||||
|
#define SRA_PASS 3
|
||||||
|
#define SRA_ACCEPT 4
|
||||||
|
#define SRA_REJECT 5
|
||||||
|
|
||||||
|
static int check_user(char *, char *);
|
||||||
|
|
||||||
|
/* support routine to send out authentication message */
|
||||||
|
static int
|
||||||
|
Data(Authenticator *ap, int type, void *d, int c)
|
||||||
|
{
|
||||||
|
unsigned char *p = str_data + 4;
|
||||||
|
unsigned char *cd = (unsigned char *)d;
|
||||||
|
|
||||||
|
if (c == -1)
|
||||||
|
c = strlen((char *)cd);
|
||||||
|
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("%s:%d: [%d] (%d)",
|
||||||
|
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
|
||||||
|
str_data[3],
|
||||||
|
type, c);
|
||||||
|
printd(d, c);
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
*p++ = ap->type;
|
||||||
|
*p++ = ap->way;
|
||||||
|
*p++ = type;
|
||||||
|
while (c-- > 0) {
|
||||||
|
if ((*p++ = *cd++) == IAC)
|
||||||
|
*p++ = IAC;
|
||||||
|
}
|
||||||
|
*p++ = IAC;
|
||||||
|
*p++ = SE;
|
||||||
|
if (str_data[3] == TELQUAL_IS)
|
||||||
|
printsub('>', &str_data[2], p - (&str_data[2]));
|
||||||
|
return(net_write(str_data, p - str_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sra_init(Authenticator *ap __unused, int server)
|
||||||
|
{
|
||||||
|
if (server)
|
||||||
|
str_data[3] = TELQUAL_REPLY;
|
||||||
|
else
|
||||||
|
str_data[3] = TELQUAL_IS;
|
||||||
|
|
||||||
|
user = (char *)malloc(256);
|
||||||
|
xuser = (char *)malloc(513);
|
||||||
|
pass = (char *)malloc(256);
|
||||||
|
xpass = (char *)malloc(513);
|
||||||
|
|
||||||
|
if (user == NULL || xuser == NULL || pass == NULL || xpass ==
|
||||||
|
NULL)
|
||||||
|
return 0; /* malloc failed */
|
||||||
|
|
||||||
|
passwd_sent = 0;
|
||||||
|
|
||||||
|
genkeys(pka,ska);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* client received a go-ahead for sra */
|
||||||
|
int
|
||||||
|
sra_send(Authenticator *ap)
|
||||||
|
{
|
||||||
|
/* send PKA */
|
||||||
|
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Sent PKA to server.\r\n" );
|
||||||
|
printf("Trying SRA secure login:\r\n");
|
||||||
|
if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room for authentication data\r\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* server received an IS -- could be SRA KEY, USER, or PASS */
|
||||||
|
void
|
||||||
|
sra_is(Authenticator *ap, unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
int valid;
|
||||||
|
Session_Key skey;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
goto bad;
|
||||||
|
switch (*data++) {
|
||||||
|
|
||||||
|
case SRA_KEY:
|
||||||
|
if (cnt < HEXKEYBYTES) {
|
||||||
|
Data(ap, SRA_REJECT, (void *)0, 0);
|
||||||
|
auth_finished(ap, AUTH_USER);
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("SRA user rejected for bad PKB\r\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Sent pka\r\n");
|
||||||
|
if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(pkb,data,HEXKEYBYTES);
|
||||||
|
pkb[HEXKEYBYTES] = '\0';
|
||||||
|
common_key(ska,pkb,&ik,&ck);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SRA_USER:
|
||||||
|
/* decode KAB(u) */
|
||||||
|
if (cnt > 512) /* Attempted buffer overflow */
|
||||||
|
break;
|
||||||
|
memcpy(xuser,data,cnt);
|
||||||
|
xuser[cnt] = '\0';
|
||||||
|
pk_decode(xuser,user,&ck);
|
||||||
|
auth_encrypt_user(user);
|
||||||
|
Data(ap, SRA_CONTINUE, (void *)0, 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SRA_PASS:
|
||||||
|
if (cnt > 512) /* Attempted buffer overflow */
|
||||||
|
break;
|
||||||
|
/* decode KAB(P) */
|
||||||
|
memcpy(xpass,data,cnt);
|
||||||
|
xpass[cnt] = '\0';
|
||||||
|
pk_decode(xpass,pass,&ck);
|
||||||
|
|
||||||
|
/* check user's password */
|
||||||
|
valid = check_user(user,pass);
|
||||||
|
|
||||||
|
if(valid) {
|
||||||
|
Data(ap, SRA_ACCEPT, (void *)0, 0);
|
||||||
|
skey.data = ck;
|
||||||
|
skey.type = SK_DES;
|
||||||
|
skey.length = 8;
|
||||||
|
encrypt_session_key(&skey, 1);
|
||||||
|
|
||||||
|
sra_valid = 1;
|
||||||
|
auth_finished(ap, AUTH_VALID);
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("SRA user accepted\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Data(ap, SRA_CONTINUE, (void *)0, 0);
|
||||||
|
/*
|
||||||
|
Data(ap, SRA_REJECT, (void *)0, 0);
|
||||||
|
sra_valid = 0;
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
*/
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("SRA user failed\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Unknown SRA option %d\r\n", data[-1]);
|
||||||
|
}
|
||||||
|
bad:
|
||||||
|
Data(ap, SRA_REJECT, 0, 0);
|
||||||
|
sra_valid = 0;
|
||||||
|
auth_finished(ap, AUTH_REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
|
||||||
|
void
|
||||||
|
sra_reply(Authenticator *ap, unsigned char *data, int cnt)
|
||||||
|
{
|
||||||
|
char uprompt[256],tuser[256];
|
||||||
|
Session_Key skey;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (cnt-- < 1)
|
||||||
|
return;
|
||||||
|
switch (*data++) {
|
||||||
|
|
||||||
|
case SRA_KEY:
|
||||||
|
/* calculate common key */
|
||||||
|
if (cnt < HEXKEYBYTES) {
|
||||||
|
if (auth_debug_mode) {
|
||||||
|
printf("SRA user rejected for bad PKB\r\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(pkb,data,HEXKEYBYTES);
|
||||||
|
pkb[HEXKEYBYTES] = '\0';
|
||||||
|
|
||||||
|
common_key(ska,pkb,&ik,&ck);
|
||||||
|
|
||||||
|
enc_user:
|
||||||
|
|
||||||
|
/* encode user */
|
||||||
|
memset(tuser,0,sizeof(tuser));
|
||||||
|
sprintf(uprompt,"User (%s): ",UserNameRequested);
|
||||||
|
telnet_gets(uprompt,tuser,255,1);
|
||||||
|
if (tuser[0] == '\n' || tuser[0] == '\r' )
|
||||||
|
strcpy(user,UserNameRequested);
|
||||||
|
else {
|
||||||
|
/* telnet_gets leaves the newline on */
|
||||||
|
for(i=0;i<sizeof(tuser);i++) {
|
||||||
|
if (tuser[i] == '\n') {
|
||||||
|
tuser[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcpy(user,tuser);
|
||||||
|
}
|
||||||
|
pk_encode(user,xuser,&ck);
|
||||||
|
|
||||||
|
/* send it off */
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Sent KAB(U)\r\n");
|
||||||
|
if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SRA_CONTINUE:
|
||||||
|
if (passwd_sent) {
|
||||||
|
passwd_sent = 0;
|
||||||
|
printf("[ SRA login failed ]\r\n");
|
||||||
|
goto enc_user;
|
||||||
|
}
|
||||||
|
/* encode password */
|
||||||
|
memset(pass,0,sizeof(pass));
|
||||||
|
telnet_gets("Password: ",pass,255,0);
|
||||||
|
pk_encode(pass,xpass,&ck);
|
||||||
|
/* send it off */
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Sent KAB(P)\r\n");
|
||||||
|
if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Not enough room\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
passwd_sent = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SRA_REJECT:
|
||||||
|
printf("[ SRA refuses authentication ]\r\n");
|
||||||
|
printf("Trying plaintext login:\r\n");
|
||||||
|
auth_finished(0,AUTH_REJECT);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SRA_ACCEPT:
|
||||||
|
printf("[ SRA accepts you ]\r\n");
|
||||||
|
skey.data = ck;
|
||||||
|
skey.type = SK_DES;
|
||||||
|
skey.length = 8;
|
||||||
|
encrypt_session_key(&skey, 0);
|
||||||
|
|
||||||
|
auth_finished(ap, AUTH_VALID);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
if (auth_debug_mode)
|
||||||
|
printf("Unknown SRA option %d\r\n", data[-1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sra_status(Authenticator *ap __unused, char *name, int level)
|
||||||
|
{
|
||||||
|
if (level < AUTH_USER)
|
||||||
|
return(level);
|
||||||
|
if (UserNameRequested && sra_valid) {
|
||||||
|
strcpy(name, UserNameRequested);
|
||||||
|
return(AUTH_VALID);
|
||||||
|
} else
|
||||||
|
return(AUTH_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
|
||||||
|
#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
|
||||||
|
|
||||||
|
void
|
||||||
|
sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
|
||||||
|
{
|
||||||
|
char lbuf[32];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
buf[buflen-1] = '\0'; /* make sure its NULL terminated */
|
||||||
|
buflen -= 1;
|
||||||
|
|
||||||
|
switch(data[3]) {
|
||||||
|
|
||||||
|
case SRA_CONTINUE:
|
||||||
|
strncpy((char *)buf, " CONTINUE ", buflen);
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case SRA_REJECT: /* Rejected (reason might follow) */
|
||||||
|
strncpy((char *)buf, " REJECT ", buflen);
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case SRA_ACCEPT: /* Accepted (name might follow) */
|
||||||
|
strncpy((char *)buf, " ACCEPT ", buflen);
|
||||||
|
|
||||||
|
common:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
if (cnt <= 4)
|
||||||
|
break;
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
for (i = 4; i < cnt; i++)
|
||||||
|
ADDC(buf, buflen, data[i]);
|
||||||
|
ADDC(buf, buflen, '"');
|
||||||
|
ADDC(buf, buflen, '\0');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SRA_KEY: /* Authentication data follows */
|
||||||
|
strncpy((char *)buf, " KEY ", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case SRA_USER:
|
||||||
|
strncpy((char *)buf, " USER ", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
case SRA_PASS:
|
||||||
|
strncpy((char *)buf, " PASS ", buflen);
|
||||||
|
goto common2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(lbuf, " %d (unknown)", data[3]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
common2:
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
for (i = 4; i < cnt; i++) {
|
||||||
|
sprintf(lbuf, " %d", data[i]);
|
||||||
|
strncpy((char *)buf, lbuf, buflen);
|
||||||
|
BUMP(buf, buflen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isroot(const char *usr)
|
||||||
|
{
|
||||||
|
struct passwd *pwd;
|
||||||
|
|
||||||
|
if ((pwd=getpwnam(usr))==NULL)
|
||||||
|
return 0;
|
||||||
|
return (!pwd->pw_uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rootterm(char *ttyn)
|
||||||
|
{
|
||||||
|
struct ttyent *t;
|
||||||
|
|
||||||
|
return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NOPAM
|
||||||
|
static int
|
||||||
|
check_user(char *name, char *cred)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
char *xpasswd, *salt;
|
||||||
|
|
||||||
|
if (isroot(name) && !rootterm(line))
|
||||||
|
{
|
||||||
|
crypt("AA","*"); /* Waste some time to simulate success */
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pw = sgetpwnam(name)) {
|
||||||
|
if (pw->pw_shell == NULL) {
|
||||||
|
pw = (struct passwd *) NULL;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
salt = pw->pw_passwd;
|
||||||
|
xpasswd = crypt(cred, salt);
|
||||||
|
/* The strcmp does not catch null passwords! */
|
||||||
|
if (pw == NULL || *pw->pw_passwd == '\0' ||
|
||||||
|
strcmp(xpasswd, pw->pw_passwd)) {
|
||||||
|
pw = (struct passwd *) NULL;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following is stolen from ftpd, which stole it from the imap-uw
|
||||||
|
* PAM module and login.c. It is needed because we can't really
|
||||||
|
* "converse" with the user, having already gone to the trouble of
|
||||||
|
* getting their username and password through an encrypted channel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define COPY_STRING(s) (s ? strdup(s):NULL)
|
||||||
|
|
||||||
|
struct cred_t {
|
||||||
|
const char *uname;
|
||||||
|
const char *pass;
|
||||||
|
};
|
||||||
|
typedef struct cred_t cred_t;
|
||||||
|
|
||||||
|
static int
|
||||||
|
auth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
cred_t *cred = (cred_t *) appdata;
|
||||||
|
struct pam_response *reply =
|
||||||
|
malloc(sizeof(struct pam_response) * num_msg);
|
||||||
|
|
||||||
|
if (reply == NULL)
|
||||||
|
return PAM_BUF_ERR;
|
||||||
|
|
||||||
|
for (i = 0; i < num_msg; i++) {
|
||||||
|
switch (msg[i]->msg_style) {
|
||||||
|
case PAM_PROMPT_ECHO_ON: /* assume want user name */
|
||||||
|
reply[i].resp_retcode = PAM_SUCCESS;
|
||||||
|
reply[i].resp = COPY_STRING(cred->uname);
|
||||||
|
/* PAM frees resp. */
|
||||||
|
break;
|
||||||
|
case PAM_PROMPT_ECHO_OFF: /* assume want password */
|
||||||
|
reply[i].resp_retcode = PAM_SUCCESS;
|
||||||
|
reply[i].resp = COPY_STRING(cred->pass);
|
||||||
|
/* PAM frees resp. */
|
||||||
|
break;
|
||||||
|
case PAM_TEXT_INFO:
|
||||||
|
case PAM_ERROR_MSG:
|
||||||
|
reply[i].resp_retcode = PAM_SUCCESS;
|
||||||
|
reply[i].resp = NULL;
|
||||||
|
break;
|
||||||
|
default: /* unknown message style */
|
||||||
|
free(reply);
|
||||||
|
return PAM_CONV_ERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*resp = reply;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The PAM version as a side effect may put a new username in *name.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_user(char *name, char *cred)
|
||||||
|
{
|
||||||
|
pam_handle_t *pamh = NULL;
|
||||||
|
const void *item;
|
||||||
|
int rval;
|
||||||
|
int e;
|
||||||
|
cred_t auth_cred = { name, cred };
|
||||||
|
struct pam_conv conv = { &auth_conv, &auth_cred };
|
||||||
|
|
||||||
|
e = pam_start("telnetd", name, &conv, &pamh);
|
||||||
|
if (e != PAM_SUCCESS) {
|
||||||
|
syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /* Where can we find this value? */
|
||||||
|
e = pam_set_item(pamh, PAM_RHOST, remotehost);
|
||||||
|
if (e != PAM_SUCCESS) {
|
||||||
|
syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
|
||||||
|
pam_strerror(pamh, e));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
e = pam_authenticate(pamh, 0);
|
||||||
|
switch (e) {
|
||||||
|
case PAM_SUCCESS:
|
||||||
|
/*
|
||||||
|
* With PAM we support the concept of a "template"
|
||||||
|
* user. The user enters a login name which is
|
||||||
|
* authenticated by PAM, usually via a remote service
|
||||||
|
* such as RADIUS or TACACS+. If authentication
|
||||||
|
* succeeds, a different but related "template" name
|
||||||
|
* is used for setting the credentials, shell, and
|
||||||
|
* home directory. The name the user enters need only
|
||||||
|
* exist on the remote authentication server, but the
|
||||||
|
* template name must be present in the local password
|
||||||
|
* database.
|
||||||
|
*
|
||||||
|
* This is supported by two various mechanisms in the
|
||||||
|
* individual modules. However, from the application's
|
||||||
|
* point of view, the template user is always passed
|
||||||
|
* back as a changed value of the PAM_USER item.
|
||||||
|
*/
|
||||||
|
if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
|
||||||
|
PAM_SUCCESS) {
|
||||||
|
strcpy(name, item);
|
||||||
|
} else
|
||||||
|
syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
|
||||||
|
pam_strerror(pamh, e));
|
||||||
|
if (isroot(name) && !rootterm(line))
|
||||||
|
rval = 0;
|
||||||
|
else
|
||||||
|
rval = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAM_AUTH_ERR:
|
||||||
|
case PAM_USER_UNKNOWN:
|
||||||
|
case PAM_MAXTRIES:
|
||||||
|
rval = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
|
||||||
|
rval = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
|
||||||
|
syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
|
||||||
|
rval = 0;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ENCRYPTION */
|
||||||
|
#endif /* SRA */
|
||||||
Reference in New Issue
Block a user