delete POP3, telnet and rsh/rcp support

This commit is contained in:
Love Hörnquist Åstrand
2014-02-16 09:14:19 -08:00
parent 444f9e6568
commit e55b0d0ca5
107 changed files with 0 additions and 35689 deletions

View File

@@ -15,13 +15,9 @@ SUBDIRS = \
login \
$(dir_otp) \
gssmask \
popper \
push \
rsh \
rcp \
su \
xnlock \
telnet \
test \
kx \
kf \

View File

@@ -1,269 +0,0 @@
2006-11-20 Love Hörnquist Åstrand <lha@it.su.se>
* pop_pass.c: Make krb5_get_init_creds_opt_free take a context
argument.
2006-10-07 Love Hörnquist Åstrand <lha@it.su.se>
* Makefile.am: Add man_MANS to EXTRA_DIST
2006-05-05 Love Hörnquist Åstrand <lha@it.su.se>
* Rename u_intXX_t to uintXX_t
2005-10-22 Love Hörnquist Åstrand <lha@it.su.se>
* pop_dropinfo.c: Check return value from asprintf instead of
string != NULL since it undefined behavior on Linux. From Björn
Sandell
2005-05-29 Love Hörnquist Åstrand <lha@it.su.se>
* pop_user.c: avoid 'unused variable' warnings
2005-05-10 Dave Love <fx@gnu.org>
* pop_pass.c: Include <crypt.h>.
2004-08-27 Johan Danielsson <joda@pdc.kth.se>
* popper.c: add message to NOOP result to appease gcc
2004-06-14 Johan Danielsson <joda@pdc.kth.se>
* Makefile.am: SASL
* pop_auth.[ch], auth_gssapi.c, auth_krb4.c : improved SASL
support
* pop_get_command.c: add SASL hooks
* pop_user.c: if using SASL, don't allow plaintext USER/PASS
* pop_init.c: recognise sasl auth level
* popper.h: add AUTH_SASL flag
2003-12-20 Love Hörnquist Åstrand <lha@it.su.se>
* popper.c (main): avoid warning by sending empty string as
formatstring instead of NULL (even though pop_msg handles that
too)
2003-10-10 Johan Danielsson <joda@pdc.kth.se>
* pop_init.c (pop_init): change call to authentication function,
from a ?: construct (which toubles some versions of gcc) to if;
from Björn Grönvall
2003-09-03 Love Hörnquist Åstrand <lha@it.su.se>
* pop_pass.c: use
krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free
2003-09-02 Love Hörnquist Åstrand <lha@it.su.se>
* popper.c (tgets): avoid be clobbered by `longjmp' or `vfork'
warning
2003-04-16 Love Hörnquist Åstrand <lha@it.su.se>
* popper.8: spelling, from jmc <jmc@prioris.mini.pw.edu.pl>
2002-07-04 Johan Danielsson <joda@pdc.kth.se>
* pop_dropcopy.c: use RESP-CODES
* pop_get_command.c: implement CAPA
* popper.c: don't print our version in the greeting string
* popper.h: add a flags parameter to the pop context
2002-05-02 Johan Danielsson <joda@pdc.kth.se>
* pop_debug.c: revert some accidentally commited code in previous
2002-02-07 Johan Danielsson <joda@pdc.kth.se>
* pop_debug.c: only claim krb5 support if really present
2001-09-10 Johan Danielsson <joda@pdc.kth.se>
* maildir.c: replace MAXDROPLEN with MAXPATHLEN
* popper.h: replace MAXDROPLEN with MAXPATHLEN
2001-08-13 Johan Danielsson <joda@pdc.kth.se>
* popper.8: rewritten man page
2000-12-31 Assar Westerlund <assar@sics.se>
* pop_init.c (pop_init): handle krb5_init_context failure
consistently
* pop_debug.c (doit_v5): handle krb5_init_context failure
consistently
2000-06-10 Assar Westerlund <assar@sics.se>
* pop_init.c (krb4_authenticate): do not exit on failure, just
return
(krb5_authenticate): log errors from krb5_recvauth
2000-04-12 Assar Westerlund <assar@sics.se>
* *.c: replace all erroneous calls to pop_log with POP_FAILURE
with POP_PRIORITY. reported by Janne Johansson <jj@it.kth.se>'
2000-01-27 Assar Westerlund <assar@sics.se>
* pop_debug.c (main): figure out port number
1999-12-20 Assar Westerlund <assar@sics.se>
* pop_init.c (pop_init): use getnameinfo_verified
* pop_debug.c (get_socket): use getaddrinfo
1999-12-03 Johan Danielsson <joda@pdc.kth.se>
* pop_init.c: optionally trace connected addresses to a file
1999-11-02 Assar Westerlund <assar@sics.se>
* pop_debug.c (main): redo the v4/v5 selection for consistency.
-4 -> try only v4 -5 -> try only v5 none, -45 -> try v5, v4
1999-10-16 Johan Danielsson <joda@pdc.kth.se>
* pop_init.c (krb5_authenticate): don't use the principal
associated with the socket for authentication, instead let
krb5_rd_req pick the correct one from the ticket; just check that
it actually was a pop-ticket
1999-08-12 Johan Danielsson <joda@pdc.kth.se>
* pop_init.c (pop_init): don't freehostent if ch == NULL
* pop_dele.c: implement XDELE to delete a range of messages
1999-08-05 Assar Westerlund <assar@sics.se>
* pop_init.c: v6-ify
* pop_debug.c: v6-ify
1999-05-10 Assar Westerlund <assar@sics.se>
* pop_debug.c (doit_v5): call krb5_sendauth with ccache == NULL
1999-04-11 Assar Westerlund <assar@sics.se>
* pop_debug.c (main): use print_version
Thu Apr 8 15:07:11 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* pop_pass.c: remove definition of KRB_VERIFY_USER (moved to
config.h)
Thu Mar 18 12:55:42 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* pop_pass.c: define KRB_VERIFY_SECURE if not defined
* Makefile.am: include Makefile.am.common
Wed Mar 17 23:36:21 1999 Assar Westerlund <assar@sics.se>
* pop_pass.c (krb4_verify_password): use KRB_VERIFY_SECURE instead
of 1
Tue Mar 16 22:28:52 1999 Assar Westerlund <assar@sics.se>
* pop_pass.c: krb_verify_user_multiple -> krb_verify_user
Sat Mar 13 22:17:29 1999 Assar Westerlund <assar@sics.se>
* pop_parse.c (pop_parse): cast when calling is* to get rid of a
warning
Mon Mar 8 11:50:06 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* pop_init.c: use print_version
Fri Mar 5 15:14:29 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* pop_send.c: fix handling of messages w/o body
Sun Nov 22 10:33:29 1998 Assar Westerlund <assar@sics.se>
* pop_pass.c (pop_pass): try to always log
* Makefile.in (WFLAGS): set
Fri Jul 10 01:14:25 1998 Assar Westerlund <assar@sics.se>
* pop_init.c: s/net_read/pop_net_read/
Tue Jun 2 17:33:54 1998 Johan Danielsson <joda@emma.pdc.kth.se>
* pop_send.c: add missing newlines
Sun May 24 20:59:45 1998 Johan Danielsson <joda@emma.pdc.kth.se>
* maildir.c (make_path): fix reversed args
Sat May 16 00:02:18 1998 Assar Westerlund <assar@sics.se>
* Makefile.am: link with DBLIB
Sun Apr 26 11:47:58 1998 Assar Westerlund <assar@sics.se>
* pop_pass.c (pop_pass): check return value from changeuser
* pop_dropcopy.c (changeuser): check that `setuid' and `setgid'
succeeded.
* popper.h: changeuser now returns int
Thu Apr 23 00:54:38 1998 Johan Danielsson <joda@emma.pdc.kth.se>
* Add support for maildir spoolfiles.
* popper.h (MsgInfoList): replace `del_flag' and `retr_flag' with
single `flags'
* pop_dropcopy.c: Fix mismatched parenthesis.
Sat Apr 4 15:13:56 1998 Assar Westerlund <assar@sics.se>
* pop_dropcopy.c (pop_dropcopy): first do mkstemp and then fdopen.
Originally from <map@stacken.kth.se>
* popper.h: include <io.h>
Sat Feb 7 10:07:39 1998 Assar Westerlund <assar@sics.se>
* pop_pass.c(krb4_verify_password: Don't use REALM_SZ + 1, just
REALM_SZ
Mon Dec 29 16:37:26 1997 Assar Westerlund <assar@sics.se>
* pop_updt.c (pop_updt): lseek before ftruncating the file. From
<map@stacken.kth.se>
Sat Nov 22 13:46:39 1997 Johan Danielsson <joda@emma.pdc.kth.se>
* pop_pass.c: Destroy tickets after verification.
Sun Nov 9 09:11:14 1997 Assar Westerlund <assar@sics.se>
* pop_dropinfo.c: be careful with mails without msg-id, subject,
or from
Wed Oct 29 02:09:24 1997 Assar Westerlund <assar@sics.se>
* pop_pass.c: conditionalize OTP-support
* pop_init.c: conditionalize OTP-support

View File

@@ -1,51 +0,0 @@
# $Id$
include $(top_srcdir)/Makefile.am.common
WFLAGS += $(WFLAGS_LITE)
noinst_PROGRAMS = pop_debug
libexec_PROGRAMS = popper
popper_SOURCES = \
pop_auth.c \
pop_auth.h \
pop_dele.c \
pop_dropcopy.c \
pop_dropinfo.c \
pop_get_command.c \
pop_init.c \
pop_last.c \
pop_list.c \
pop_log.c \
pop_msg.c \
pop_parse.c \
pop_pass.c \
pop_quit.c \
pop_rset.c \
pop_send.c \
pop_stat.c \
pop_uidl.c \
pop_updt.c \
pop_user.c \
pop_xover.c \
popper.c \
maildir.c \
auth_gssapi.c \
popper.h \
version.h
LDADD = \
$(LIB_otp) \
$(top_builddir)/lib/gssapi/libgssapi.la \
$(LIB_krb5) \
$(LIB_hcrypto) \
$(LIB_roken) \
$(DBLIB)
man_MANS = popper.8
EXTRA_DIST = NTMakefile pop3.rfc1081 pop3e.rfc1082 \
popper.README.release README-FIRST \
$(man_MANS)

View File

@@ -1,35 +0,0 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT HOLDER 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.
#
RELDIR=appl\popper
!include ../../windows/NTMakefile.w32

View File

@@ -1,381 +0,0 @@
@(#)@(#)README 2.6 2.6 4/2/91
The Post Office Protocol Server: Installation Guide
Introduction
The Post Office Protocol server runs on a variety of Unix[1] computers
to manage electronic mail for Macintosh and MS-DOS computers. The
server was developed at the University of California at Berkeley and
conforms fully to the specifications in RFC 1081[2] and RFC 1082[3].
The Berkeley server also has extensions to send electronic mail on
behalf of a client.
This guide explains how to install the POP server on your Unix
computer. It assumes that you are not only familiar with Unix but also
capable of performing Unix system administration.
How to Obtain the Server
The POP server is available via anonymous ftp from ftp.CC.Berkeley.EDU
(128.32.136.9, 128.32.206.12). It is in two files in the pub directory:
a compressed tar file popper-version.tar.Z and a Macintosh StuffIt archive
in BinHex format called MacPOP.sit.hqx.
Contents of the Distribution
The distribution contains the following:
+ All of the C source necessary to create the server program.
+ A visual representation of how the POP system works.
+ Reprints of RFC 1081 and RFC 1082.
+ A HyperCard stack POP client implementation using MacTCP.
+ A man page for the popper daemon.
+ This guide.
Compatibility
The Berkeley POP server has been successfully tested on the following
Unix operating systems:
+ Berkeley Systems Distribution 4.3
+ Sun Microsystems Operating System versions 3.5 and 4.0
+ Ultrix version 2.3
The following POP clients operate correctly with the Berkeley POP server:
+ The Berkeley HyperMail HyperCard stack for the Apple Macintosh
(distributed with the server).
+ The Stanford University Macintosh Internet Protocol MacMH program.
+ The Stanford University Personal Computer Internet Protocol MH
program.
+ The mh version 6.0 programs for Unix.
Support
The Berkeley POP server is not officially supported and is without any
warranty, explicit or implied. However, we are interested in your
experiences using the server. Bugs, comments and suggestions should be
sent electronically to netinfo@garnet.Berkeley.EDU.
Operational Characteristics
The POP Transaction Cycle
The Berkeley POP server is a single program (called popper) that is
launched by inetd when it gets a service request on the POP TCP port.
(The official port number specified in RFC 1081 for POP version 3 is
port 110. However, some POP3 clients attempt to contact the server at
port 109, the POP version 2 port. Unless you are running both POP2 and
POP3 servers, you can simply define both ports for use by the POP3
server. This is explained in the installation instructions later on.)
The popper program initializes and verifies that the peer IP address is
registered in the local domain, logging a warning message when a
connection is made to a client whose IP address does not have a
canonical name. For systems using BSD 4.3 bind, it also checks to see
if a cannonical name lookup for the client returns the same peer IP
address, logging a warning message if it does not. The the server
enters the authorization state, during which the client must correctly
identify itself by providing a valid Unix userid and password on the
server's host machine. No other exchanges are allowed during this
state (other than a request to quit.) If authentication fails, a
warning message is logged and the session ends. Once the user is
identified, popper changes its user and group ids to match that of the
user and enters the transaction state. The server makes a temporary
copy of the user's maildrop (ordinarily in /usr/spool/mail) which is
used for all subsequent transactions. These include the bulk of POP
commands to retrieve mail, delete mail, undelete mail, and so forth. A
Berkeley extension also allows the user to submit a mail parcel to the
server who mails it using the sendmail program (this extension is
supported in the HyperMail client distributed with the server). When
the client quits, the server enters the final update state during which
the network connection is terminated and the user's maildrop is updated
with the (possibly) modified temporary maildrop.
Logging
The POP server uses syslog to keep a record of its activities. On
systems with BSD 4.3 syslogging, the server logs (by default) to the
"local0" facility at priority "notice" for all messages except
debugging which is logged at priority "debug". The default log file is
/usr/spool/mqueue/POPlog. These can be changed, if desired. On
systems with 4.2 syslogging all messages are logged to the local log
file, usually /usr/spool/mqueue/syslog.
Problems
If the filesystem which holds the /usr/spool/mail fills up users will
experience difficulties. The filesystem must have enough space to hold
(approximately) two copies of the largest mail box. Popper (v1.81 and
above) is designed to be robust in the face of this problem, but you may
end up with a situation where some of the user's mail is in
/usr/spool/mail/.userid.pop
and some of the mail is in
/usr/spool/mail/userid
If this happens the System Administrator should clear enough disk space
so that the filesystem has at least as much free disk as both mailboxes
hold and probably a little more. Then the user should initiate a POP
session, and do nothing but quit. If the POP session ends without an
error the user can then use POP or another mail program to clean up his/her
mailbox.
Alternatively, the System Administrator can combine the two files (but
popper will do this for you if there is enough disk space).
Debugging
The popper program will log debugging information when the -d parameter
is specified after its invocation in the inetd.conf file. Care should
be exercised in using this option since it generates considerable
output in the syslog file. Alternatively, the "-t <file-name>" option
will place debugging information into file "<file-name>" using fprintf
instead of syslog. (To enable debugging, you must edit the Makefile
to add -DDEBUG to the compiler options.)
For SunOS version 3.5, the popper program is launched by inetd from
/etc/servers. This file does not allow you to specify command line
arguments. Therefore, if you want to enable debugging, you can specify
a shell script in /etc/servers to be launched instead of popper and in
this script call popper with the desired arguments.
Installation
1. Examine this file for the latest information, warnings, etc.
2. Check the Makefile for conformity with your system.
3. Issue the make command in the directory containing the popper
source.
4. Issue the make install command in the directory containing the
popper source to copy the program to /usr/etc.
5. Enable syslogging:
+ For systems with 4.3 syslogging:
Add the following line to the /etc/syslog.conf file:
local0.notice;local0.debug /usr/spool/mqueue/POPlog
Create the empty file /usr/spool/mqueue/POPlog.
Kill and restart the syslogd daemon.
+ For systems with 4.2 syslogging:
Be sure that you are logging messages of priority 7 and higher.
For example:
7/usr/spool/mqueue/syslog
9/dev/null
6. Update /etc/services:
Add the following line to the /etc/services file:
pop 110/tcp
Note: This is the official port number for version 3 of the
Post Office Protocol as defined in RFC 1081. However, some
POP3 clients use port 109, the port number for the previous
version (2) of POP. Therefore you may also want to add the
following line to the /etc/services file:
pop2 109/tcp
For Sun systems running yp, also do the following:
+ Change to the /var/yp directory.
+ Issue the make services command.
7. Update the inetd daemon configuration. Include the second line ONLY if you
are running the server at both ports.
+ On BSD 4.3 and SunOS 4.0 systems, add the following line to the
/etc/inetd.conf file:
pop stream tcp nowait root /usr/etc/popper popper
pop2 stream tcp nowait root /usr/etc/popper popper
+ On Ultrix systems, add the following line to the
/etc/inetd.conf file:
pop stream tcp nowait /usr/etc/popper popper
pop2 stream tcp nowait /usr/etc/popper popper
+ On SunOS 3.5 systems, add the following line to the
/etc/servers file:
pop tcp /usr/etc/popper
pop2 tcp /usr/etc/popper
Kill and restart the inetd daemon.
You can confirm that the POP server is running on Unix by telneting to
port 110 (or 109 if you set it up that way). For example:
%telnet myhost 110
Trying...
Connected to myhost.berkeley.edu.
Escape character is '^]'.
+OK UCB Pop server (version 1.6) at myhost starting.
quit
Connection closed by foreign host.
Release Notes
1.83 Make sure that everything we do as root is non-destructive.
1.82 Make the /usr/spool/mail/.userid.pop file owned by the user rather
than owned by root.
1.81 There were two versions of 1.7 floating around, 1.7b4 and 1.7b5.
The difference is that 1.7b5 attempted to save disk space on
/usr/spool/mail by deleting the users permanent maildrop after
making the temporary copy. Unfortunately, if compiled with
-DDEBUG, this version could easily wipe out a users' mail file.
This is now fixed.
This version also fixes a security hole for systems that have
/usr/spool/mail writeable by all users.
With this version we go to all new SCCS IDs for all files. This
is unfortunate, and we hope it is not too much of a problem.
Thanks to Steve Dorner of UIUC for pointing out the major problem.
1.7 Extensive re-write of the maildrop processing code contributed by
Viktor Dukhovni <viktor@math.princeton.edu> that greatly reduces the
possibility that the maildrop can be corrupted as the result of
simultaneous access by two or more processes.
Added "pop_dropcopy" module to create a temporary maildrop from
the existing, standard maildrop as root before the setuid and
setgid for the user is done. This allows the temporary maildrop
to be created in a mail spool area that is not world read-writable.
This version does *not* send the sendmail "From " delimiter line
in response to a TOP or RETR command.
Encased all debugging code in #ifdef DEBUG constructs. This code can
be included by specifying the DEGUG compiler flag. Note: You still
need to use the -d or -t option to obtain debugging output.
1.6 Corrects a bug that causes the server to crash on SunOS
4.0 systems.
Uses varargs and vsprintf (if available) in pop_log and
pop_msg. This is enabled by the "HAVE_VSPRINTF"
compiler flag.
For systems with BSD 4.3 bind, performs a cannonical
name lookup and searches the returned address(es) for
the client's address, logging a warning message if it
is not located. This is enabled by the "BIND43"
comiler flag.
Removed all the includes from popper.h and distributed
them throughout the porgrams files, as needed.
Reformatted the source to convert tabs to spaces and
shorten lines for display on 80-column terminals.
1.5 Creates the temporary maildrop with mode "600" and
immediately unlinks it.
Uses client's IP address in lieu of a canonical name if
the latter cannot be obtained.
Added "-t <file-name>" option. The presence of this
option causes debugging output to be placed in the file
"file-name" using fprintf instead of the system log
file using syslog.
Corrected maildrop parsing problem.
1.4 Copies user's mail into a temporary maildrop on which
all subsequent activity is performed.
Added "pop_log" function and replaced "syslog" calls
throughout the code with it.
1.3 Corrected updating of Status: header line.
Added strncasecmp for systems that do not have one.
Used strncasecmp in all appropriate places. This is
enabled by the STRNCASECMP compiler flag.
1.2 Support for version 4.2 syslogging added. This is
enabled by the SYSLOG42 compiler flag.
1.1 Several bugs fixed.
1.0 Original version.
Limitations
+ The POP server copies the user's entire maildrop to /tmp and
then operates on that copy. If the maildrop is particularly
large, or inadequate space is available in /tmp, then the
server will refuse to continue and terminate the connection.
+ Simultaneous modification of a single maildrop can result in
confusing results. For example, manipulating messages in a
maildrop using the Unix /usr/ucb/mail command while a copy of
it is being processed by the POP server can cause the changes
made by one program to be lost when the other terminates. This
problem is being worked on and will be fixed in a later
release.
Credits
The POP server was written by Edward Moy and Austin Shelton with
contributions from Robert Campbell (U.C. Berkeley) and Viktor Dukhovni
(Princeton University). Edward Moy wrote the HyperMail stack and drew
the POP operation diagram. This installation guide was written by
Austin Shelton.
Footnotes
[1] Copyright (c) 1990 Regents of the University of California.
All rights reserved. The Berkeley software License Agreement
specifies the terms and conditions for redistribution. Unix is
a registered trademark of AT&T corporation. HyperCard and
Macintosh are registered trademarks of Apple Corporation.
[2] M. Rose, Post Office Protocol - Version 3. RFC 1081, NIC,
November 1988.
[3] M. Rose, Post Office Protocol - Version 3 Extended Service
Offerings. RFC 1082, NIC, November 1988.

View File

@@ -1,11 +0,0 @@
This kerberized popper was based on popper-1.831beta
which was later announced as "offical" and not beta.
This program is able to talk both the pop3 and the kpop3 protocol.
Please note that the server principal is pop.hostname and not
rcmd.hostname. I.e an additional entry is needed in your mailhub's
/etc/srvtab. Use ksrvutil to add the extra prinicpal.
The server is usually started from inetd and there is already an entry
for that in inetd.conf.changes.

View File

@@ -1,253 +0,0 @@
/*
* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 <popper.h>
#include <base64.h>
#include <pop_auth.h>
RCSID("$Id$");
#if defined(SASL) && defined(KRB5)
#include <gssapi.h>
extern krb5_context gssapi_krb5_context;
struct gss_state {
gss_ctx_id_t context_hdl;
gss_OID mech_oid;
gss_name_t client_name;
int stage;
};
static void
gss_set_error (struct gss_state *gs, int min_stat)
{
OM_uint32 new_stat;
OM_uint32 msg_ctx = 0;
gss_buffer_desc status_string;
OM_uint32 ret;
do {
char * cstr;
ret = gss_display_status (&new_stat,
min_stat,
GSS_C_MECH_CODE,
gs->mech_oid,
&msg_ctx,
&status_string);
if (asprintf(&cstr, "%.*s", (int)status_string.length,
(const char *)status_string.value) >= 0) {
pop_auth_set_error(cstr);
free(cstr);
} else {
pop_auth_set_error("unknown error");
}
gss_release_buffer (&new_stat, &status_string);
} while (!GSS_ERROR(ret) && msg_ctx != 0);
}
static int
gss_loop(POP *p, void *state,
/* const */ void *input, size_t input_length,
void **output, size_t *output_length)
{
struct gss_state *gs = state;
gss_buffer_desc real_input_token, real_output_token;
gss_buffer_t input_token = &real_input_token,
output_token = &real_output_token;
OM_uint32 maj_stat, min_stat;
gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS;
if(gs->stage == 0) {
/* we require an initial response, so ask for one if not
present */
gs->stage++;
if(input == NULL && input_length == 0) {
/* XXX this could be done better */
fputs("+ \r\n", p->output);
fflush(p->output);
return POP_AUTH_CONTINUE;
}
}
if(gs->stage == 1) {
input_token->value = input;
input_token->length = input_length;
maj_stat =
gss_accept_sec_context (&min_stat,
&gs->context_hdl,
GSS_C_NO_CREDENTIAL,
input_token,
bindings,
&gs->client_name,
&gs->mech_oid,
output_token,
NULL,
NULL,
NULL);
if (GSS_ERROR(maj_stat)) {
gss_set_error(gs, min_stat);
return POP_AUTH_FAILURE;
}
if (output_token->length != 0) {
*output = output_token->value;
*output_length = output_token->length;
}
if(maj_stat == GSS_S_COMPLETE)
gs->stage++;
return POP_AUTH_CONTINUE;
}
if(gs->stage == 2) {
/* send wanted protection levels */
unsigned char x[4] = { 1, 0, 0, 0 };
input_token->value = x;
input_token->length = 4;
maj_stat = gss_wrap(&min_stat,
gs->context_hdl,
FALSE,
GSS_C_QOP_DEFAULT,
input_token,
NULL,
output_token);
if (GSS_ERROR(maj_stat)) {
gss_set_error(gs, min_stat);
return POP_AUTH_FAILURE;
}
*output = output_token->value;
*output_length = output_token->length;
gs->stage++;
return POP_AUTH_CONTINUE;
}
if(gs->stage == 3) {
/* receive protection levels and username */
char *name;
krb5_principal principal;
gss_buffer_desc export_name;
gss_OID oid;
unsigned char *ptr;
input_token->value = input;
input_token->length = input_length;
maj_stat = gss_unwrap (&min_stat,
gs->context_hdl,
input_token,
output_token,
NULL,
NULL);
if (GSS_ERROR(maj_stat)) {
gss_set_error(gs, min_stat);
return POP_AUTH_FAILURE;
}
if(output_token->length < 5) {
pop_auth_set_error("response too short");
return POP_AUTH_FAILURE;
}
ptr = output_token->value;
if(ptr[0] != 1) {
pop_auth_set_error("must use clear text");
return POP_AUTH_FAILURE;
}
memmove(output_token->value, ptr + 4, output_token->length - 4);
ptr[output_token->length - 4] = '\0';
maj_stat = gss_display_name(&min_stat, gs->client_name,
&export_name, &oid);
if(maj_stat != GSS_S_COMPLETE) {
gss_set_error(gs, min_stat);
return POP_AUTH_FAILURE;
}
/* XXX kerberos */
if(oid != GSS_KRB5_NT_PRINCIPAL_NAME) {
pop_auth_set_error("unexpected gss name type");
gss_release_buffer(&min_stat, &export_name);
return POP_AUTH_FAILURE;
}
name = malloc(export_name.length + 1);
if(name == NULL) {
pop_auth_set_error("out of memory");
gss_release_buffer(&min_stat, &export_name);
return POP_AUTH_FAILURE;
}
memcpy(name, export_name.value, export_name.length);
name[export_name.length] = '\0';
gss_release_buffer(&min_stat, &export_name);
krb5_parse_name(gssapi_krb5_context, name, &principal);
if(!krb5_kuserok(gssapi_krb5_context, principal, ptr)) {
pop_auth_set_error("Permission denied");
return POP_AUTH_FAILURE;
}
strlcpy(p->user, ptr, sizeof(p->user));
return POP_AUTH_COMPLETE;
}
return POP_AUTH_FAILURE;
}
static int
gss_init(POP *p, void **state)
{
struct gss_state *gs = malloc(sizeof(*gs));
if(gs == NULL) {
pop_auth_set_error("out of memory");
return POP_AUTH_FAILURE;
}
gs->context_hdl = GSS_C_NO_CONTEXT;
gs->stage = 0;
*state = gs;
return POP_AUTH_CONTINUE;
}
static int
gss_cleanup(POP *p, void *state)
{
OM_uint32 min_stat;
struct gss_state *gs = state;
if(gs->context_hdl != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&min_stat, &gs->context_hdl, GSS_C_NO_BUFFER);
free(state);
return POP_AUTH_CONTINUE;
}
struct auth_mech gssapi_mech = {
"GSSAPI", gss_init, gss_loop, gss_cleanup
};
#endif /* KRB5 */

View File

@@ -1,216 +0,0 @@
/*
* Copyright (c) 1998 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 <popper.h>
#include <dirent.h>
RCSID("$Id$");
static void
make_path(POP *p, MsgInfoList *mp, int new, char *buf, size_t len)
{
snprintf(buf, len, "%s/%s%s%s", p->drop_name,
new ? "new" : "cur", mp ? "/" : "", mp ? mp->name : "");
}
static int
scan_file(POP *p, MsgInfoList *mp)
{
char path[MAXPATHLEN];
FILE *f;
char buf[1024];
int eoh = 0;
make_path(p, mp, mp->flags & NEW_FLAG, path, sizeof(path));
f = fopen(path, "r");
if(f == NULL) {
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG,
"Failed to open message file `%s': %s",
path, strerror(errno));
#endif
return pop_msg (p, POP_FAILURE,
"Failed to open message file `%s'", path);
}
while(fgets(buf, sizeof(buf), f)) {
if(buf[strlen(buf) - 1] == '\n')
mp->lines++;
mp->length += strlen(buf);
if(eoh)
continue;
if(strcmp(buf, "\n") == 0)
eoh = 1;
parse_header(mp, buf);
}
fclose(f);
return add_missing_headers(p, mp);
}
static int
scan_dir(POP *p, int new)
{
char tmp[MAXPATHLEN];
DIR *dir;
struct dirent *dent;
MsgInfoList *mp = p->mlp;
int n_mp = p->msg_count;
int e;
make_path(p, NULL, new, tmp, sizeof(tmp));
mkdir(tmp, 0700);
dir = opendir(tmp);
while((dent = readdir(dir)) != NULL) {
if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
continue;
mp = realloc(mp, (n_mp + 1) * sizeof(*mp));
if(mp == NULL) {
p->msg_count = 0;
return pop_msg (p, POP_FAILURE,
"Can't build message list for '%s': Out of memory",
p->user);
}
memset(mp + n_mp, 0, sizeof(*mp));
mp[n_mp].name = strdup(dent->d_name);
if(mp[n_mp].name == NULL) {
p->msg_count = 0;
return pop_msg (p, POP_FAILURE,
"Can't build message list for '%s': Out of memory",
p->user);
}
mp[n_mp].number = n_mp + 1;
mp[n_mp].flags = 0;
if(new)
mp[n_mp].flags |= NEW_FLAG;
e = scan_file(p, &mp[n_mp]);
if(e != POP_SUCCESS)
return e;
p->drop_size += mp[n_mp].length;
n_mp++;
}
closedir(dir);
p->mlp = mp;
p->msg_count = n_mp;
return POP_SUCCESS;
}
int
pop_maildir_info(POP *p)
{
int e;
p->temp_drop[0] = '\0';
p->mlp = NULL;
p->msg_count = 0;
e = scan_dir(p, 0);
if(e != POP_SUCCESS) return e;
e = scan_dir(p, 1);
if(e != POP_SUCCESS) return e;
return POP_SUCCESS;
}
int
pop_maildir_update(POP *p)
{
int i;
char tmp1[MAXPATHLEN], tmp2[MAXPATHLEN];
for(i = 0; i < p->msg_count; i++) {
make_path(p, &p->mlp[i], p->mlp[i].flags & NEW_FLAG,
tmp1, sizeof(tmp1));
if(p->mlp[i].flags & DEL_FLAG) {
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG, "Removing `%s'", tmp1);
#endif
if(unlink(tmp1) < 0) {
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG, "Failed to remove `%s': %s",
tmp1, strerror(errno));
#endif
/* return failure? */
}
} else if((p->mlp[i].flags & NEW_FLAG) &&
(p->mlp[i].flags & RETR_FLAG)) {
make_path(p, &p->mlp[i], 0, tmp2, sizeof(tmp2));
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG, "Linking `%s' to `%s'", tmp1, tmp2);
#endif
if(link(tmp1, tmp2) == 0) {
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG, "Removing `%s'", tmp1);
#endif
if(unlink(tmp1) < 0) {
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG, "Failed to remove `%s'", tmp1);
#endif
/* return failure? */
}
} else {
if(errno == EXDEV) {
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG, "Trying to rename `%s' to `%s'",
tmp1, tmp2);
#endif
if(rename(tmp1, tmp2) < 0) {
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG, "Failed to rename `%s' to `%s'",
tmp1, tmp2);
#endif
}
}
}
}
}
return(pop_quit(p));
}
int
pop_maildir_open(POP *p, MsgInfoList *mp)
{
char tmp[MAXPATHLEN];
make_path(p, mp, mp->flags & NEW_FLAG, tmp, sizeof(tmp));
if(p->drop)
fclose(p->drop);
p->drop = fopen(tmp, "r");
if(p->drop == NULL)
return pop_msg(p, POP_FAILURE, "Failed to open message file");
return POP_SUCCESS;
}

View File

@@ -1,898 +0,0 @@
Network Working Group M. Rose
Request for Comments: 1081 TWG
November 1988
Post Office Protocol - Version 3
Status of this Memo
This memo suggests a simple method for workstations to dynamically
access mail from a mailbox server. This RFC specifies a proposed
protocol for the Internet community, and requests discussion and
suggestions for improvements. Distribution of this memo is
unlimited.
This memo is based on RFC 918 (since revised as RFC 937). Although
similar in form to the original Post Office Protocol (POP) proposed
for the Internet community, the protocol discussed in this memo is
similar in spirit to the ideas investigated by the MZnet project at
the University of California, Irvine.
Further, substantial work was done on examining POP in a PC-based
environment. This work, which resulted in additional functionality
in this protocol, was performed by the ACIS Networking Systems Group
at Stanford University. The author gratefully acknowledges their
interest.
Introduction
On certain types of smaller nodes in the Internet it is often
impractical to maintain a message transport system (MTS). For
example, a workstation may not have sufficient resources (cycles,
disk space) in order to permit a SMTP server and associated local
mail delivery system to be kept resident and continuously running.
Similarly, it may be expensive (or impossible) to keep a personal
computer interconnected to an IP-style network for long amounts of
time (the node is lacking the resource known as "connectivity").
Despite this, it is often very useful to be able to manage mail on
these smaller nodes, and they often support a user agent (UA) to aid
the tasks of mail handling. To solve this problem, a node which can
support an MTS entity offers a maildrop service to these less endowed
nodes. The Post Office Protocol - Version 3 (POP3) is intended to
permit a workstation to dynamically access a maildrop on a server
host in a useful fashion. Usually, this means that the POP3 is used
to allow a workstation to retrieve mail that the server is holding
for it.
Rose [Page 1]
RFC 1081 POP3 November 1988
For the remainder of this memo, the term "client host" refers to a
host making use of the POP3 service, while the term "server host"
refers to a host which offers the POP3 service.
A Short Digression
This memo does not specify how a client host enters mail into the
transport system, although a method consistent with the philosophy of
this memo is presented here:
When the user agent on a client host wishes to enter a message
into the transport system, it establishes an SMTP connection to
its relay host (this relay host could be, but need not be, the
POP3 server host for the client host).
If this method is followed, then the client host appears to the MTS
as a user agent, and should NOT be regarded as a "trusted" MTS entity
in any sense whatsoever. This concept, along with the role of the
POP3 as a part of a split-UA model is discussed later in this memo.
Initially, the server host starts the POP3 service by listening on
TCP port 110. When a client host wishes to make use of the service,
it establishes a TCP connection with the server host. When the
connection is established, the POP3 server sends a greeting. The
client and POP3 server then exchange commands and responses
(respectively) until the connection is closed or aborted.
Commands in the POP3 consist of a keyword possibly followed by an
argument. All commands are terminated by a CRLF pair.
Responses in the POP3 consist of a success indicator and a keyword
possibly followed by additional information. All responses are
terminated by a CRLF pair. There are currently two success
indicators: positive ("+OK") and negative ("-ERR").
Responses to certain commands are multi-line. In these cases, which
are clearly indicated below, after sending the first line of the
response and a CRLF, any additional lines are sent, each terminated
by a CRLF pair. When all lines of the response have been sent, a
final line is sent, consisting of a termination octet (decimal code
046, ".") and a CRLF pair. If any line of the multi-line response
begins with the termination octet, the line is "byte-stuffed" by
pre-pending the termination octet to that line of the response.
Hence a multi-line response is terminated with the five octets
"CRLF.CRLF". When examining a multi-line response, the client checks
to see if the line begins with the termination octet. If so and if
octets other than CRLF follow, the the first octet of the line (the
termination octet) is stripped away. If so and if CRLF immediately
Rose [Page 2]
RFC 1081 POP3 November 1988
follows the termination character, then the response from the POP
server is ended and the line containing ".CRLF" is not considered
part of the multi-line response.
A POP3 session progresses through a number of states during its
lifetime. Once the TCP connection has been opened and the POP3
server has sent the greeting, the session enters the AUTHORIZATION
state. In this state, the client must identify itself to the POP3
server. Once the client has successfully done this, the server
acquires resources associated with the client's maildrop, and the
session enters the TRANSACTION state. In this state, the client
requests actions on the part of the POP3 server. When the client has
finished its transactions, the session enters the UPDATE state. In
this state, the POP3 server releases any resources acquired during
the TRANSACTION state and says goodbye. The TCP connection is then
closed.
The AUTHORIZATION State
Once the TCP connection has been opened by a POP3 client, the POP3
server issues a one line greeting. This can be any string terminated
by CRLF. An example might be:
S. +OK dewey POP3 server ready (Comments to: PostMaster@UDEL.EDU)
Note that this greeting is a POP3 reply. The POP3 server should
always give a positive response as the greeting.
The POP3 session is now in the AUTHORIZATION state. The client must
now issue the USER command. If the POP3 server responds with a
positive success indicator ("+OK"), then the client may issue either
the PASS command to complete the authorization, or the QUIT command
to terminate the POP3 session. If the POP3 server responds with a
negative success indicator ("-ERR") to the USER command, then the
client may either issue a new USER command or may issue the QUIT
command.
When the client issues the PASS command, the POP3 server uses the
argument pair from the USER and PASS commands to determine if the
client should be given access to the appropriate maildrop. If so,
the POP3 server then acquires an exclusive-access lock on the
maildrop. If the lock is successfully acquired, the POP3 server
parses the maildrop into individual messages (read note below),
determines the last message (if any) present in the maildrop that was
referenced by the RETR command, and responds with a positive success
indicator. The POP3 session now enters the TRANSACTION state. If
the lock can not be acquired or the client should is denied access to
the appropriate maildrop or the maildrop can't be parsed for some
Rose [Page 3]
RFC 1081 POP3 November 1988
reason, the POP3 server responds with a negative success indicator.
(If a lock was acquired but the POP3 server intends to respond with a
negative success indicator, the POP3 server must release the lock
prior to rejecting the command.) At this point, the client may
either issue a new USER command and start again, or the client may
issue the QUIT command.
NOTE: Minimal implementations of the POP3 need only be
able to break a maildrop into its component messages;
they need NOT be able to parse individual messages.
More advanced implementations may wish to have this
capability, for reasons discussed later.
After the POP3 server has parsed the maildrop into individual
messages, it assigns a message-id to each message, and notes the size
of the message in octets. The first message in the maildrop is
assigned a message-id of "1", the second is assigned "2", and so on,
so that the n'th message in a maildrop is assigned a message-id of
"n". In POP3 commands and responses, all message-id's and message
sizes are expressed in base-10 (i.e., decimal).
It sets the "highest number accessed" to be that of the last message
referenced by the RETR command.
Here are summaries for the three POP3 commands discussed thus far:
USER name
Arguments: a server specific user-id (required)
Restrictions: may only be given in the AUTHORIZATION
state after the POP3 greeting or after an
unsuccessful USER or PASS command
Possible Responses:
+OK name is welcome here
-ERR never heard of name
Examples:
C: USER mrose
S: +OK mrose is a real hoopy frood
...
C: USER frated
S: -ERR sorry, frated doesn't get his mail here
PASS string
Arguments: a server/user-id specific password (required)
Restrictions: may only be given in the AUTHORIZATION
state after a successful USER command
Possible Responses:
+OK maildrop locked and ready
-ERR invalid password
Rose [Page 4]
RFC 1081 POP3 November 1988
-ERR unable to lock maildrop
Examples:
C: USER mrose
S: +OK mrose is a real hoopy frood
C: PASS secret
S: +OK mrose's maildrop has 2 messages
(320 octets)
...
C: USER mrose
S: +OK mrose is a real hoopy frood
C: PASS secret
S: -ERR unable to lock mrose's maildrop, file
already locked
QUIT
Arguments: none
Restrictions: none
Possible Responses:
+OK
Examples:
C: QUIT
S: +OK dewey POP3 server signing off
The TRANSACTION State
Once the client has successfully identified itself to the POP3 server
and the POP3 server has locked and burst the appropriate maildrop,
the POP3 session is now in the TRANSACTION state. The client may now
issue any of the following POP3 commands repeatedly. After each
command, the POP3 server issues a response. Eventually, the client
issues the QUIT command and the POP3 session enters the UPDATE state.
Here are the POP3 commands valid in the TRANSACTION state:
STAT
Arguments: none
Restrictions: may only be given in the TRANSACTION state.
Discussion:
The POP3 server issues a positive response with a line
containing information for the maildrop. This line is
called a "drop listing" for that maildrop.
In order to simplify parsing, all POP3 servers are
required to use a certain format for drop listings.
The first octets present must indicate the number of
messages in the maildrop. Following this is the size
Rose [Page 5]
RFC 1081 POP3 November 1988
of the maildrop in octets. This memo makes no
requirement on what follows the maildrop size.
Minimal implementations should just end that line of
the response with a CRLF pair. More advanced
implementations may include other information.
NOTE: This memo STRONGLY discourages
implementations from supplying additional
information in the drop listing. Other,
optional, facilities are discussed later on
which permit the client to parse the messages
in the maildrop.
Note that messages marked as deleted are not counted in
either total.
Possible Responses:
+OK nn mm
Examples:
C: STAT
S: +OK 2 320
LIST [msg]
Arguments: a message-id (optionally) If a message-id is
given, it may NOT refer to a message marked as
deleted.
Restrictions: may only be given in the TRANSACTION state.
Discussion:
If an argument was given and the POP3 server issues a
positive response with a line containing information
for that message. This line is called a "scan listing"
for that message.
If no argument was given and the POP3 server issues a
positive response, then the response given is
multi-line. After the initial +OK, for each message
in the maildrop, the POP3 server responds with a line
containing information for that message. This line
is called a "scan listing" for that message.
In order to simplify parsing, all POP3 servers are
required to use a certain format for scan listings.
The first octets present must be the message-id of
the message. Following the message-id is the size of
the message in octets. This memo makes no requirement
on what follows the message size in the scan listing.
Minimal implementations should just end that line of
Rose [Page 6]
RFC 1081 POP3 November 1988
the response with a CRLF pair. More advanced
implementations may include other information, as
parsed from the message.
NOTE: This memo STRONGLY discourages
implementations from supplying additional
information in the scan listing. Other, optional,
facilities are discussed later on which permit
the client to parse the messages in the maildrop.
Note that messages marked as deleted are not listed.
Possible Responses:
+OK scan listing follows
-ERR no such message
Examples:
C: LIST
S: +OK 2 messages (320 octets)
S: 1 120
S: 2 200
S: .
...
C: LIST 2
S: +OK 2 200
...
C: LIST 3
S: -ERR no such message, only 2 messages in
maildrop
RETR msg
Arguments: a message-id (required) This message-id may
NOT refer to a message marked as deleted.
Restrictions: may only be given in the TRANSACTION state.
Discussion:
If the POP3 server issues a positive response, then the
response given is multi-line. After the initial +OK,
the POP3 server sends the message corresponding to the
given message-id, being careful to byte-stuff the
termination character (as with all multi-line
responses).
If the number associated with this message is higher
than the "highest number accessed" in the maildrop, the
POP3 server updates the "highest number accessed" to
the number associated with this message.
Rose [Page 7]
RFC 1081 POP3 November 1988
Possible Responses:
+OK message follows
-ERR no such message
Examples:
C: RETR 1
S: +OK 120 octets
S: <the POP3 server sends the entire message here>
S: .
DELE msg
Arguments: a message-id (required) This message-id
may NOT refer to a message marked as deleted.
Restrictions: may only be given in the TRANSACTION state.
Discussion:
The POP3 server marks the message as deleted. Any
future reference to the message-id associated with the
message in a POP3 command generates an error. The POP3
server does not actually delete the message until the
POP3 session enters the UPDATE state.
If the number associated with this message is higher
than the "highest number accessed" in the maildrop,
the POP3 server updates the "highest number accessed"
to the number associated with this message.
Possible Responses:
+OK message deleted
-ERR no such message
Examples:
C: DELE 1
S: +OK message 1 deleted
...
C: DELE 2
S: -ERR message 2 already deleted
NOOP
Arguments: none
Restrictions: may only be given in the TRANSACTION state.
Discussion:
The POP3 server does nothing, it merely replies with a
positive response.
Possible Responses:
+OK
Rose [Page 8]
RFC 1081 POP3 November 1988
Examples:
C: NOOP
S: +OK
LAST
Arguments: none
Restrictions: may only be issued in the TRANSACTION state.
Discussion:
The POP3 server issues a positive response with a line
containing the highest message number which accessed.
Zero is returned in case no message in the maildrop has
been accessed during previous transactions. A client
may thereafter infer that messages, if any, numbered
greater than the response to the LAST command are
messages not yet accessed by the client.
Possible Response:
+OK nn
Examples:
C: STAT
S: +OK 4 320
C: LAST
S: +OK 1
C: RETR 3
S: +OK 120 octets
S: <the POP3 server sends the entire message
here>
S: .
C: LAST
S: +OK 3
C: DELE 2
S: +OK message 2 deleted
C: LAST
S: +OK 3
C: RSET
S: +OK
C: LAST
S: +OK 1
RSET
Arguments: none
Restrictions: may only be given in the TRANSACTION
state.
Discussion:
If any messages have been marked as deleted by the POP3
Rose [Page 9]
RFC 1081 POP3 November 1988
server, they are unmarked. The POP3 server then
replies with a positive response. In addition, the
"highest number accessed" is also reset to the value
determined at the beginning of the POP3 session.
Possible Responses:
+OK
Examples:
C: RSET
S: +OK maildrop has 2 messages (320 octets)
The UPDATE State
When the client issues the QUIT command from the TRANSACTION state,
the POP3 session enters the UPDATE state. (Note that if the client
issues the QUIT command from the AUTHORIZATION state, the POP3
session terminates but does NOT enter the UPDATE state.)
QUIT
Arguments: none
Restrictions: none
Discussion:
The POP3 server removes all messages marked as deleted
from the maildrop. It then releases the
exclusive-access lock on the maildrop and replies as
to the success of
these operations. The TCP connection is then closed.
Possible Responses:
+OK
Examples:
C: QUIT
S: +OK dewey POP3 server signing off (maildrop
empty)
...
C: QUIT
S: +OK dewey POP3 server signing off (2 messages
left)
...
Optional POP3 Commands
The POP3 commands discussed above must be supported by all minimal
implementations of POP3 servers.
Rose [Page 10]
RFC 1081 POP3 November 1988
The optional POP3 commands described below permit a POP3 client
greater freedom in message handling, while preserving a simple POP3
server implementation.
NOTE: This memo STRONGLY encourages implementations to
support these commands in lieu of developing augmented
drop and scan listings. In short, the philosophy of
this memo is to put intelligence in the part of the
POP3 client and not the POP3 server.
TOP msg n
Arguments: a message-id (required) and a number. This
message-id may NOT refer to a message marked as
deleted.
Restrictions: may only be given in the TRANSACTION state.
Discussion:
If the POP3 server issues a positive response, then
the response given is multi-line. After the initial
+OK, the POP3 server sends the headers of the message,
the blank line separating the headers from the body,
and then the number of lines indicated message's body,
being careful to byte-stuff the termination character
(as with all multi-line responses).
Note that if the number of lines requested by the POP3
client is greater than than the number of lines in the
body, then the POP3 server sends the entire message.
Possible Responses:
+OK top of message follows
-ERR no such message
Examples:
C: TOP 10
S: +OK
S: <the POP3 server sends the headers of the
message, a blank line, and the first 10 lines
of the body of the message>
S: .
...
C: TOP 100
S: -ERR no such message
RPOP user
Arguments: a client specific user-id (required)
Restrictions: may only be given in the AUTHORIZATION
state after a successful USER command; in addition,
may only be given if the client used a reserved
Rose [Page 11]
RFC 1081 POP3 November 1988
(privileged) TCP port to connect to the server.
Discussion:
The RPOP command may be used instead of the PASS
command to authenticate access to the maildrop. In
order for this command to be successful, the POP3
client must use a reserved TCP port (port < 1024) to
connect tothe server. The POP3 server uses the
argument pair from the USER and RPOP commands to
determine if the client should be given access to
the appropriate maildrop. Unlike the PASS command
however, the POP3 server considers if the remote user
specified by the RPOP command who resides on the POP3
client host is allowed to access the maildrop for the
user specified by the USER command (e.g., on Berkeley
UNIX, the .rhosts mechanism is used). With the
exception of this differing in authentication, this
command is identical to the PASS command.
Note that the use of this feature has allowed much wider
penetration into numerous hosts on local networks (and
sometimes remote networks) by those who gain illegal
access to computers by guessing passwords or otherwise
breaking into the system.
Possible Responses:
+OK maildrop locked and ready
-ERR permission denied
Examples:
C: USER mrose
S: +OK mrose is a real hoopy frood
C: RPOP mrose
S: +OK mrose's maildrop has 2 messages (320
octets)
Minimal POP3 Commands:
USER name valid in the AUTHORIZATION state
PASS string
QUIT
STAT valid in the TRANSACTION state
LIST [msg]
RETR msg
DELE msg
NOOP
LAST
RSET
Rose [Page 12]
RFC 1081 POP3 November 1988
QUIT valid in the UPDATE state
Optional POP3 Commands:
RPOP user valid in the AUTHORIZATION state
TOP msg n valid in the TRANSACTION state
POP3 Replies:
+OK
-ERR
Note that with the exception of the STAT command, the reply given
by the POP3 server to any command is significant only to "+OK"
and "-ERR". Any text occurring after this reply may be ignored
by the client.
Example POP3 Session
S: <wait for connection on TCP port 110>
...
C: <open connection>
S: +OK dewey POP3 server ready (Comments to: PostMaster@UDEL.EDU)
C: USER mrose
S: +OK mrose is a real hoopy frood
C: PASS secret
S: +OK mrose's maildrop has 2 messages (320 octets)
C: STAT
S: +OK 2 320
C: LIST
S: +OK 2 messages (320 octets)
S: 1 120
S: 2 200
S: .
C: RETR 1
S: +OK 120 octets
S: <the POP3 server sends message 1>
S: .
C: DELE 1
S: +OK message 1 deleted
C: RETR 2
S: +OK 200 octets
S: <the POP3 server sends message 2>
S: .
C: DELE 2
S: +OK message 2 deleted
C: QUIT
Rose [Page 13]
RFC 1081 POP3 November 1988
S: +OK dewey POP3 server signing off (maildrop empty)
C: <close connection>
S: <wait for next connection>
Message Format
All messages transmitted during a POP3 session are assumed to conform
to the standard for the format of Internet text messages [RFC822].
It is important to note that the byte count for a message on the
server host may differ from the octet count assigned to that message
due to local conventions for designating end-of-line. Usually,
during the AUTHORIZATION state of the POP3 session, the POP3 client
can calculate the size of each message in octets when it parses the
maildrop into messages. For example, if the POP3 server host
internally represents end-of-line as a single character, then the
POP3 server simply counts each occurrence of this character in a
message as two octets. Note that lines in the message which start
with the termination octet need not be counted twice, since the POP3
client will remove all byte-stuffed termination characters when it
receives a multi-line response.
The POP and the Split-UA model
The underlying paradigm in which the POP3 functions is that of a
split-UA model. The POP3 client host, being a remote PC based
workstation, acts solely as a client to the message transport system.
It does not provide delivery/authentication services to others.
Hence, it is acting as a UA, on behalf of the person using the
workstation. Furthermore, the workstation uses SMTP to enter mail
into the MTS.
In this sense, we have two UA functions which interface to the
message transport system: Posting (SMTP) and Retrieval (POP3). The
entity which supports this type of environment is called a split-UA
(since the user agent is split between two hosts which must
interoperate to provide these functions).
ASIDE: Others might term this a remote-UA instead.
There are arguments supporting the use of both terms.
This memo has explicitly referenced TCP as the underlying transport
agent for the POP3. This need not be the case. In the MZnet split-
UA, for example, personal micro-computer systems are used which do
not have IP-style networking capability. To connect to the POP3
server host, a PC establishes a terminal connection using some simple
protocol (PhoneNet). A program on the PC drives the connection,
first establishing a login session as a normal user. The login shell
Rose [Page 14]
RFC 1081 POP3 November 1988
for this pseudo-user is a program which drives the other half of the
terminal protocol and communicates with one of two servers. Although
MZnet can support several PCs, a single pseudo-user login is present
on the server host. The user-id and password for this pseudo-user
login is known to all members of MZnet. Hence, the first action of
the login shell, after starting the terminal protocol, is to demand a
USER/PASS authorization pair from the PC. This second level of
authorization is used to ascertain who is interacting with the MTS.
Although the server host is deemed to support a "trusted" MTS entity,
PCs in MZnet are not. Naturally, the USER/PASS authorization pair
for a PC is known only to the owner of the PC (in theory, at least).
After successfully verifying the identity of the client, a modified
SMTP server is started, and the PC posts mail with the server host.
After the QUIT command is given to the SMTP server and it terminates,
a modified POP3 server is started, and the PC retrieves mail from the
server host. After the QUIT command is given to the POP3 server and
it terminates, the login shell for the pseudo-user terminates the
terminal protocol and logs the job out. The PC then closes the
terminal connection to the server host.
The SMTP server used by MZnet is modified in the sense that it knows
that it's talking to a user agent and not a "trusted" entity in the
message transport system. Hence, it does performs the validation
activities normally performed by an entity in the MTS when it accepts
a message from a UA.
The POP3 server used by MZnet is modified in the sense that it does
not require a USER/PASS combination before entering the TRANSACTION
state. The reason for this (of course) is that the PC has already
identified itself during the second-level authorization step
described above.
NOTE: Truth in advertising laws require that the author
of this memo state that MZnet has not actually been
fully implemented. The concepts presented and proven
by the project led to the notion of the MZnet
split-slot model. This notion has inspired the
split-UA concept described in this memo, led to the
author's interest in the POP, and heavily influenced
the the description of the POP3 herein.
In fact, some UAs present in the Internet already support the notion
of posting directly to an SMTP server and retrieving mail directly
from a POP server, even if the POP server and client resided on the
same host!
ASIDE: this discussion raises an issue which this memo
Rose [Page 15]
RFC 1081 POP3 November 1988
purposedly avoids: how does SMTP know that it's talking
to a "trusted" MTS entity?
References
[MZnet] Stefferud, E., J. Sweet, and T. Domae, "MZnet: Mail
Service for Personal Micro-Computer Systems",
Proceedings, IFIP 6.5 International Conference on
Computer Message Systems, Nottingham, U.K., May 1984.
[RFC821] Postel, J., "Simple Mail Transfer Protocol",
USC/Information Sciences Institute, August 1982.
[RFC822] Crocker, D., "Standard for the Format of ARPA-Internet
Text Messages", University of Delaware, August 1982.
[RFC937] Butler, M., J. Postel, D. Chase, J. Goldberger, and J.
Reynolds, "Post Office Protocol - Version 2", RFC 937,
USC/Information Sciences Institute, February 1985.
[RFC1010] Reynolds, J., and J. Postel, "Assigned Numbers", RFC
1010, USC/Information Sciences Institute, May 1987.
Author's Address:
Marshall Rose
The Wollongong Group
1129 San Antonio Rd.
Palo Alto, California 94303
Phone: (415) 962-7100
Email: MRose@TWG.COM
Rose [Page 16]

View File

@@ -1,619 +0,0 @@
Network Working Group M. Rose
Request for Comments: 1082 TWG
November 1988
Post Office Protocol - Version 3
Extended Service Offerings
Status of This Memo
This memo suggests a simple method for workstations to dynamically
access mail from a discussion group server, as an extension to an
earlier memo which dealt with dynamically accessing mail from a
mailbox server using the Post Office Protocol - Version 3 (POP3).
This RFC specifies a proposed protocol for the Internet community,
and requests discussion and suggestions for improvements. All of the
extensions described in this memo to the POP3 are OPTIONAL.
Distribution of this memo is unlimited.
Introduction and Motivation
It is assumed that the reader is familiar with RFC 1081 that
discusses the Post Office Protocol - Version 3 (POP3) [RFC1081].
This memo describes extensions to the POP3 which enhance the service
it offers to clients. This additional service permits a client host
to access discussion group mail, which is often kept in a separate
spool area, using the general POP3 facilities.
The next section describes the evolution of discussion groups and the
technologies currently used to implement them. To summarize:
o An exploder is used to map from a single address to
a list of addresses which subscribe to the list, and redirects
any subsequent error reports associated with the delivery of
each message. This has two primary advantages:
- Subscribers need know only a single address
- Responsible parties get the error reports and not
the subscribers
Rose [Page 1]
RFC 1082 POP3 Extended Service November 1988
o Typically, each subscription address is not a person's private
maildrop, but a system-wide maildrop, which can be accessed
by more than one user. This has several advantages:
- Only a single copy of each message need traverse the
net for a given site (which may contain several local
hosts). This conserves bandwidth and cycles.
- Only a single copy of each message need reside on each
subscribing host. This conserves disk space.
- The private maildrop for each user is not cluttered
with discussion group mail.
Despite this optimization of resources, further economy can be
achieved at sites with more than one host. Typically, sites with
more than one host either:
1. Replicate discussion group mail on each host. This
results in literally gigabytes of disk space committed to
unnecessarily store redundant information.
2. Keep discussion group mail on one host and give all users a
login on that host (in addition to any other logins they may
have). This is usually a gross inconvenience for users who
work on other hosts, or a burden to users who are forced to
work on that host.
As discussed in [RFC1081], the problem of giving workstations dynamic
access to mail from a mailbox server has been explored in great
detail (originally there was [RFC918], this prompted the author to
write [RFC1081], independently of this [RFC918] was upgraded to
[RFC937]). A natural solution to the problem outlined above is to
keep discussion group mail on a mailbox server at each site and
permit different hosts at that site to employ the POP3 to access
discussion group mail. If implemented properly, this avoids the
problems of both strategies outlined above.
ASIDE: It might be noted that a good distributed filesystem
could also solve this problem. Sadly, "good"
distributed filesystems, which do not suffer
unacceptable response time for interactive use, are
few and far between these days!
Given this motivation, now let's consider discussion groups, both in
general and from the point of view of a user agent. Following this,
extensions to the POP3 defined in [RFC1081] are presented. Finally,
some additional policy details are discussed along with some initial
experiences.
Rose [Page 2]
RFC 1082 POP3 Extended Service November 1988
What's in a Discussion Group
Since mailers and user agents first crawled out of the primordial
ARPAnet, the value of discussion groups have been appreciated,
(though their implementation has not always been well-understood).
Described simply, a discussion group is composed of a number of
subscribers with a common interest. These subscribers post mail to a
single address, known as a distribution address. From this
distribution address, a copy of the message is sent to each
subscriber. Each group has a moderator, which is the person that
administrates the group. The moderator can usually be reached at a
special address, known as a request address. Usually, the
responsibilities of the moderator are quite simple, since the mail
system handles the distribution to subscribers automatically. In
some cases, the interest group, instead of being distributed directly
to its subscribers, is put into a digest format by the moderator and
then sent to the subscribers. Although this requires more work on
the part of the moderator, such groups tend to be better organized.
Unfortunately, there are a few problems with the scheme outlined
above. First, if two users on the same host subscribe to the same
interest group, two copies of the message get delivered. This is
wasteful of both processor and disk resources.
Second, some of these groups carry a lot of traffic. Although
subscription to an group does indicate interest on the part of a
subscriber, it is usually not interesting to get 50 messages or so
delivered to the user's private maildrop each day, interspersed with
personal mail, that is likely to be of a much more important and
timely nature.
Third, if a subscriber on the distribution list for a group becomes
"bad" somehow, the originator of the message and not the moderator of
the group is notified. It is not uncommon for a large list to have
10 or so bogus addresses present. This results in the originator
being flooded with "error messages" from mailers across the Internet
stating that a given address on the list was bad. Needless to say,
the originator usually could not care less if the bogus addresses got
a copy of the message or not. The originator is merely interested in
posting a message to the group at large. Furthermore, the moderator
of the group does care if there are bogus addresses on the list, but
ironically does not receive notification.
There are various approaches which can be used to solve some or all
of these problems. Usually these involve placing an exploder agent
at the distribution source of the discussion group, which expands the
name of the group into the list of subscription addresses for the
Rose [Page 3]
RFC 1082 POP3 Extended Service November 1988
group. In the process, the exploder will also change the address
that receives error notifications to be the request address or other
responsible party.
A complementary approach, used in order to cut down on resource
utilization of all kinds, replaces all the subscribers at a single
host (or group of hosts under a single administration) with a single
address at that host. This address maps to a file on the host,
usually in a spool area, which all users can access. (Advanced
implementations can also implement private discussion groups this
way, in which a single copy of each message is kept, but is
accessible to only a select number of users on the host.)
The two approaches can be combined to avoid all of the problems
described above.
Finally, a third approach can be taken, which can be used to aid user
agents processing mail for the discussion group: In order to speed
querying of the maildrop which contains the local host's copy of the
discussion group, two other items are usually associated with the
discussion group, on a local basis. These are the maxima and the
last-date. Each time a message is received for the group on the
local host, the maxima is increased by at least one. Furthermore,
when a new maxima is generated, the current date is determined. This
is called the last date. As the message is entered into the local
maildrop, it is given the current maxima and last-date. This permits
the user agent to quickly determine if new messages are present in
the maildrop.
NOTE: The maxima may be characterized as a monotonically
increasing quanity. Although sucessive values of the
maxima need not be consecutive, any maxima assigned
is always greater than any previously assigned value.
Definition of Terms
To formalize these notions somewhat, consider the following 7
parameters which describe a given discussion group from the
perspective of the user agent (the syntax given is from [RFC822]):
Rose [Page 4]
RFC 1082 POP3 Extended Service November 1988
NAME Meaning: the name of the discussion group
Syntax: TOKEN (ALPHA *[ ALPHA / DIGIT / "-" ])
(case-insensitive recognition)
Example: unix-wizards
ALIASES Meaning: alternates names for the group, which
are locally meaningful; these are
typically used to shorten user typein
Syntax: TOKEN (case-insensitive recognition)
Example: uwiz
ADDRESS Meaning: the primary source of the group
Syntax: 822 address
Example: Unix-Wizards@BRL.MIL
REQUEST Meaning: the primary moderator of the group
Syntax: 822 address
Example: Unix-Wizards-Request@BRL.MIL
FLAGS Meaning: locally meaningful flags associated
with the discussion group; this memo
leaves interpretation of this
parameter to each POP3 implementation
Syntax: octal number
Example: 01
MAXIMA Meaning: the magic cookie associated with the
last message locally received for the
group; it is the property of the magic
cookie that it's value NEVER
decreases, and increases by at least
one each time a message is locally
received
Syntax: decimal number
Example: 1004
LASTDATE Meaning: the date that the last message was
locally received
Syntax: 822 date
Example: Thu, 19 Dec 85 10:26:48 -0800
Note that the last two values are locally determined for the maildrop
associated with the discussion group and with each message in that
maildrop. Note however that the last message in the maildrop have a
different MAXIMA and LASTDATE than the discussion group. This often
occurs when the maildrop has been archived.
Rose [Page 5]
RFC 1082 POP3 Extended Service November 1988
Finally, some local systems provide mechanisms for automatically
archiving discussion group mail. In some cases, a two-level archive
scheme is used: current mail is kept in the standard maildrop,
recent mail is kept in an archive maildrop, and older mail is kept
off-line. With this scheme, in addition to having a "standard"
maildrop for each discussion group, an "archive" maildrop may also be
available. This permits a user agent to examine the most recent
archive using the same mechanisms as those used on the current mail.
The XTND Command
The following commands are valid only in the TRANSACTION state of the
POP3. This implies that the POP3 server has already opened the
user's maildrop (which may be empty). This maildrop is called the
"default maildrop". The phrase "closes the current maildrop" has two
meanings, depending on whether the current maildrop is the default
maildrop or is a maildrop associated with a discussion group.
In the former context, when the current maildrop is closed any
messages marked as deleted are removed from the maildrop currently in
use. The exclusive-access lock on the maildrop is then released
along with any implementation-specific resources (e.g., file-
descriptors).
In the latter context, a maildrop associated with a discussion group
is considered to be read-only to the POP3 client. In this case, the
phrase "closes the current maildrop" merely means that any
implementation-specific resources are released. (Hence, the POP3
command DELE is a no-op.)
All the new facilities are introduced via a single POP3 command,
XTND. All positive reponses to the XTND command are multi-line.
The most common multi-line response to the commands contains a
"discussion group listing" which presents the name of the discussion
group along with it's maxima. In order to simplify parsing all POP3
servers are required to use a certain format for discussion group
listings:
NAME SP MAXIMA
This memo makes no requirement on what follows the maxima in the
listing. Minimal implementations should just end that line of the
response with a CRLF pair. More advanced implementations may include
other information, as parsed from the message.
NOTE: This memo STRONGLY discourages implementations from
supplying additional information in the listing.
Rose [Page 6]
RFC 1082 POP3 Extended Service November 1988
XTND BBOARDS [name]
Arguments: the name of a discussion group (optionally)
Restrictions: may only be given in the TRANSACTION state.
Discussion:
If an argument was given, the POP3 server closes the current
maildrop. The POP3 server then validates the argument as the name of
a discussion group. If this is successful, it opens the maildrop
associated with the group, and returns a multi-line response
containing the discussion group listing. If the discussion group
named is not valid, or the associated archive maildrop is not
readable by the user, then an error response is returned.
If no argument was given, the POP3 server issues a multi-line
response. After the initial +OK, for each discussion group known,
the POP3 server responds with a line containing the listing for that
discussion group. Note that only world-readable discussion groups
are included in the multi-line response.
In order to aid user agents, this memo requires an extension to the
scan listing when an "XTND BBOARDS" command has been given.
Normally, a scan listing, as generated by the LIST, takes the form:
MSGNO SIZE
where MSGNO is the number of the message being listed and SIZE is the
size of the message in octets. When reading a maildrop accessed via
"XTND BBOARDS", the scan listing takes the form
MSGNO SIZE MAXIMA
where MAXIMA is the maxima that was assigned to the message when it
was placed in the BBoard.
Possible Responses:
+OK XTND
-ERR no such bboard
Examples:
C: XTND BBOARDS
S: +OK XTND
S: system 10
S: mh-users 100
S: .
C: XTND BBOARDS system
S: + OK XTND
S: system 10
S: .
Rose [Page 7]
RFC 1082 POP3 Extended Service November 1988
XTND ARCHIVE name
Arguments: the name of a discussion group (required)
Restrictions: may only be given in the TRANSACTION state.
Discussion:
The POP3 server closes the current maildrop. The POP3 server then
validates the argument as the name of a discussion group. If this is
successful, it opens the archive maildrop associated with the group,
and returns a multi-line response containing the discussion group
listing. If the discussion group named is not valid, or the
associated archive maildrop is not readable by the user, then an
error response is returned.
In addition, the scan listing generated by the LIST command is
augmented (as described above).
Possible Responses:
+OK XTND
-ERR no such bboard Examples:
C: XTND ARCHIVE system
S: + OK XTND
S: system 3
S: .
XTND X-BBOARDS name
Arguments: the name of a discussion group (required)
Restrictions: may only be given in the TRANSACTION state.
Discussion:
The POP3 server validates the argument as the name of a
discussion group. If this is unsuccessful, then an error
response is returned. Otherwise a multi-line response is
returned. The first 14 lines of this response (after the
initial +OK) are defined in this memo. Minimal implementations
need not include other information (and may omit certain
information, outputing a bare CRLF pair). More advanced
implementations may include other information.
Line Information (refer to "Definition of Terms")
---- -----------
1 NAME
2 ALIASES, separated by SP
3 system-specific: maildrop
4 system-specific: archive maildrop
5 system-specific: information
6 system-specific: maildrop map
7 system-specific: encrypted password
8 system-specific: local leaders, separated by SP
Rose [Page 8]
RFC 1082 POP3 Extended Service November 1988
9 ADDRESS
10 REQUEST
11 system-specific: incoming feed
12 system-specific: outgoing feeds
13 FLAGS SP MAXIMA
14 LASTDATE
Most of this information is entirely too specific to the UCI Version
of the Rand MH Message Handling System [MRose85]. Nevertheless,
lines 1, 2, 9, 10, 13, and 14 are of general interest, regardless of
the implementation.
Possible Responses:
+OK XTND
-ERR no such bboard
Examples:
C: XTND X-BBOARDS system
S: + OK XTND
S: system
S: local general
S: /usr/bboards/system.mbox
S: /usr/bboards/archive/system.mbox
S: /usr/bboards/.system.cnt
S: /usr/bboards/.system.map
S: *
S: mother
S: system@nrtc.northrop.com
S: system-request@nrtc.northrop.com
S:
S: dist-system@nrtc-gremlin.northrop.com
S: 01 10
S: Thu, 19 Dec 85 00:08:49 -0800
S: .
Policy Notes
Depending on the particular entity administrating the POP3 service
host, two additional policies might be implemented:
1. Private Discussion Groups
In the general case, discussion groups are world-readable, any user,
once logged in (via a terminal, terminal server, or POP3, etc.), is
able to read the maildrop for each discussion group known to the POP3
service host. Nevertheless, it is desirable, usually for privacy
reasons, to implement private discussion groups as well.
Support of this is consistent with the extensions outlined in this
Rose [Page 9]
RFC 1082 POP3 Extended Service November 1988
memo. Once the AUTHORIZATION state has successfully concluded, the
POP3 server grants the user access to exactly those discussion groups
the POP3 service host permits the authenticated user to access. As a
"security" feature, discussion groups associated with unreadable
maildrops should not be listed in a positive response to the XTND
BBOARDS command.
2. Anonymous POP3 Users
In order to minimize the authentication problem, a policy permitting
"anonymous" access to the world-readable maildrops for discussion
groups on the POP3 server may be implemented.
Support of this is consistent with the extensions outlined in this
memo. The POP3 server can be modified to accept a USER command for a
well-known pseudonym (i.e., "anonymous") which is valid with any PASS
command. As a "security" feature, it is advisable to limit this kind
of access to only hosts at the local site, or to hosts named in an
access list.
Experiences and Conclusions
All of the facilities described in this memo and in [RFC1081] have
been implemented in MH #6.1. Initial experiences have been, on the
whole, very positive.
After the first implementation, some performance tuning was required.
This consisted primarily of caching the datastructures which describe
discussion groups in the POP3 server. A second optimization
pertained to the client: the program most commonly used to read
BBoards in MH was modified to retrieve messages only when needed.
Two schemes are used:
o If only the headers (and the first few lines of the body) of
the message are required (e.g., for a scan listing), then only
these are retrieved. The resulting output is then cached, on
a per-message basis.
o If the entire message is required, then it is retrieved intact,
and cached locally.
With these optimizations, response time is quite adequate when the
POP3 server and client are connected via a high-speed local area
network. In fact, the author uses this mechanism to access certain
private discussion groups over the Internet. In this case, response
is still good. When a 9.6Kbps modem is inserted in the path,
response went from good to almost tolerable (fortunately the author
only reads a few discussion groups in this fashion).
Rose [Page 10]
RFC 1082 POP3 Extended Service November 1988
To conclude: the POP3 is a good thing, not only for personal mail but
for discussion group mail as well.
References
[RFC1081] Rose, M., "Post Office Protocol - Verison 3 (POP3)", RFC
1081, TWG, November 1988.
[MRose85] Rose, M., and J. Romine, "The Rand MH Message Handling
System: User's Manual", University of California, Irvine,
November 1985.
[RFC822] Crocker, D., "Standard for the Format of ARPA-Internet
Text Messages", RFC 822, University of Delaware, August
1982.
[RFC918] Reynolds, J., "Post Office Protocol", RFC 918,
USC/Information Sciences Institute, October 1984.
[RFC937] Butler, M., J. Postel, D. Chase, J. Goldberger, and J.
Reynolds, "Post Office Protocol - Version 2", RFC 937,
USC/Information Sciences Institute, February 1985.
Author's Address:
Marshall Rose
The Wollongong Group
1129 San Antonio Rd.
Palo Alto, California 94303
Phone: (415) 962-7100
Email: MRose@TWG.COM
Rose [Page 11]

View File

@@ -1,183 +0,0 @@
/*
* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 <popper.h>
#ifdef SASL
#include <base64.h>
#include <pop_auth.h>
RCSID("$Id$");
/*
* auth: RFC1734
*/
static char *
getline(POP *p)
{
char *buf = NULL;
size_t size = 1024;
buf = malloc(size);
if(buf == NULL)
return NULL;
*buf = '\0';
while(fgets(buf + strlen(buf), size - strlen(buf), p->input) != NULL) {
char *p;
if((p = strchr(buf, '\n')) != NULL) {
while(p > buf && p[-1] == '\r')
p--;
*p = '\0';
return buf;
}
/* just assume we ran out of buffer space, we'll catch eof
next round */
size += 1024;
p = realloc(buf, size);
if(p == NULL)
break;
buf = p;
}
free(buf);
return NULL;
}
static char auth_msg[128];
void
pop_auth_set_error(const char *message)
{
strlcpy(auth_msg, message, sizeof(auth_msg));
}
static struct auth_mech *methods[] = {
#ifdef KRB5
&gssapi_mech,
#endif
NULL
};
static int
auth_execute(POP *p, struct auth_mech *m, void *state, const char *line)
{
void *input, *output;
size_t input_length, output_length;
int status;
if(line == NULL) {
input = NULL;
input_length = 0;
} else {
input = strdup(line);
if(input == NULL) {
pop_auth_set_error("out of memory");
return POP_AUTH_FAILURE;
}
input_length = base64_decode(line, input);
if(input_length == (size_t)-1) {
pop_auth_set_error("base64 decode error");
return POP_AUTH_FAILURE;
}
}
output = NULL; output_length = 0;
status = (*m->loop)(p, state, input, input_length, &output, &output_length);
if(output_length > 0) {
char *s;
base64_encode(output, output_length, &s);
fprintf(p->output, "+ %s\r\n", s);
fflush(p->output);
free(output);
free(s);
}
return status;
}
static int
auth_loop(POP *p, struct auth_mech *m)
{
int status;
void *state = NULL;
char *line;
status = (*m->init)(p, &state);
status = auth_execute(p, m, state, p->pop_parm[2]);
while(status == POP_AUTH_CONTINUE) {
line = getline(p);
if(line == NULL) {
(*m->cleanup)(p, state);
return pop_msg(p, POP_FAILURE, "error reading data");
}
if(strcmp(line, "*") == 0) {
(*m->cleanup)(p, state);
return pop_msg(p, POP_FAILURE, "terminated by client");
}
status = auth_execute(p, m, state, line);
free(line);
}
(*m->cleanup)(p, state);
if(status == POP_AUTH_FAILURE)
return pop_msg(p, POP_FAILURE, "%s", auth_msg);
status = login_user(p);
if(status != POP_SUCCESS)
return status;
return pop_msg(p, POP_SUCCESS, "authentication complete");
}
int
pop_auth (POP *p)
{
int i;
for (i = 0; methods[i] != NULL; ++i)
if (strcasecmp(p->pop_parm[1], methods[i]->name) == 0)
return auth_loop(p, methods[i]);
return pop_msg(p, POP_FAILURE,
"Authentication method %s unknown", p->pop_parm[1]);
}
void
pop_capa_sasl(POP *p)
{
int i;
if(methods[0] == NULL)
return;
fprintf(p->output, "SASL");
for (i = 0; methods[i] != NULL; ++i)
fprintf(p->output, " %s", methods[i]->name);
fprintf(p->output, "\r\n");
}
#endif

View File

@@ -1,57 +0,0 @@
/*
* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*/
/* $Id$ */
#ifndef __pop_auth_h__
#define __pop_auth_h__
struct auth_mech {
const char *name;
int (*init)(POP*, void**);
int (*loop)(POP*, void*, void*, size_t, void**, size_t*);
int (*cleanup)(POP*, void*);
};
#define POP_AUTH_CONTINUE 0
#define POP_AUTH_FAILURE 1
#define POP_AUTH_COMPLETE 2
void pop_auth_set_error(const char *message);
#ifdef KRB5
extern struct auth_mech gssapi_mech;
#endif
#endif /* __pop_auth_h__ */

View File

@@ -1,233 +0,0 @@
/*
* Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*/
/* Tiny program to help debug popper */
#include "popper.h"
RCSID("$Id$");
static void
loop(int s)
{
char cmd[1024];
char buf[1024];
fd_set fds;
while(1){
FD_ZERO(&fds);
FD_SET(0, &fds);
FD_SET(s, &fds);
if(select(s+1, &fds, 0, 0, 0) < 0)
err(1, "select");
if(FD_ISSET(0, &fds)){
fgets(cmd, sizeof(cmd), stdin);
cmd[strlen(cmd) - 1] = '\0';
strlcat (cmd, "\r\n", sizeof(cmd));
write(s, cmd, strlen(cmd));
}
if(FD_ISSET(s, &fds)){
int n = read(s, buf, sizeof(buf));
if(n == 0)
exit(0);
fwrite(buf, n, 1, stdout);
}
}
}
static int
get_socket (const char *hostname, int port)
{
int ret;
struct addrinfo *ai, *a;
struct addrinfo hints;
char portstr[NI_MAXSERV];
memset (&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
snprintf (portstr, sizeof(portstr), "%d", ntohs(port));
ret = getaddrinfo (hostname, portstr, &hints, &ai);
if (ret)
errx (1, "getaddrinfo %s: %s", hostname, gai_strerror (ret));
for (a = ai; a != NULL; a = a->ai_next) {
int s;
s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
if (s < 0)
continue;
if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
close (s);
continue;
}
freeaddrinfo (ai);
return s;
}
err (1, "failed to connect to %s", hostname);
}
#ifdef KRB5
static int
doit_v5 (char *host, int port)
{
krb5_error_code ret;
krb5_context context;
krb5_auth_context auth_context = NULL;
krb5_principal server;
int s = get_socket (host, port);
const char *estr;
ret = krb5_init_context (&context);
if (ret)
errx (1, "krb5_init_context failed: %d", ret);
ret = krb5_sname_to_principal (context,
host,
"pop",
KRB5_NT_SRV_HST,
&server);
if (ret) {
estr = krb5_get_error_message(context, ret);
warnx ("krb5_sname_to_principal: %s", estr);
krb5_free_error_message(context, estr);
return 1;
}
ret = krb5_sendauth (context,
&auth_context,
&s,
"KPOPV1.0",
NULL,
server,
0,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (ret) {
estr = krb5_get_error_message(context, ret);
warnx ("krb5_sendauth: %s", estr);
krb5_free_error_message(context, estr);
return 1;
}
loop (s);
return 0;
}
#endif
#ifdef KRB5
static int use_v5 = -1;
#endif
static char *port_str;
static int do_version;
static int do_help;
struct getargs args[] = {
#ifdef KRB5
{ "krb5", '5', arg_flag, &use_v5, "Use Kerberos V5",
NULL },
#endif
{ "port", 'p', arg_string, &port_str, "Use this port",
"number-or-service" },
{ "version", 0, arg_flag, &do_version, "Print version",
NULL },
{ "help", 0, arg_flag, &do_help, NULL,
NULL }
};
static void
usage (int ret)
{
arg_printusage (args,
sizeof(args) / sizeof(args[0]),
NULL,
"hostname");
exit (ret);
}
int
main(int argc, char **argv)
{
int port = 0;
int ret = 1;
int optind = 0;
setprogname(argv[0]);
if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
&optind))
usage (1);
argc -= optind;
argv += optind;
if (do_help)
usage (0);
if (do_version) {
print_version (NULL);
return 0;
}
if (argc < 1)
usage (1);
if (port_str) {
struct servent *s = roken_getservbyname (port_str, "tcp");
if (s)
port = s->s_port;
else {
char *ptr;
port = strtol (port_str, &ptr, 10);
if (port == 0 && ptr == port_str)
errx (1, "Bad port `%s'", port_str);
port = htons(port);
}
}
if (port == 0) {
#ifdef KRB5
port = krb5_getportbyname (NULL, "kpop", "tcp", 1109);
#else
#error must define KRB5
#endif
}
#ifdef KRB5
if (ret && use_v5) {
ret = doit_v5 (argv[0], port);
}
#endif
return ret;
}

View File

@@ -1,107 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* dele: Delete a message from the POP maildrop
*/
int
pop_dele (POP *p)
{
MsgInfoList * mp; /* Pointer to message info list */
int msg_num;
/* Convert the message number parameter to an integer */
msg_num = atoi(p->pop_parm[1]);
/* Is requested message out of range? */
if ((msg_num < 1) || (msg_num > p->msg_count))
return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_num));
/* Get a pointer to the message in the message list */
mp = &(p->mlp[msg_num-1]);
/* Is the message already flagged for deletion? */
if (mp->flags & DEL_FLAG)
return (pop_msg (p,POP_FAILURE,"Message %d has already been deleted.",
msg_num));
/* Flag the message for deletion */
mp->flags |= DEL_FLAG;
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG,
"Deleting message %u at offset %ld of length %ld\n",
mp->number, mp->offset, mp->length);
#endif /* DEBUG */
/* Update the messages_deleted and bytes_deleted counters */
p->msgs_deleted++;
p->bytes_deleted += mp->length;
/* Update the last-message-accessed number if it is lower than
the deleted message */
if (p->last_msg < msg_num) p->last_msg = msg_num;
return (pop_msg (p,POP_SUCCESS,"Message %d has been deleted.",msg_num));
}
#ifdef XDELE
/* delete a range of messages */
int
pop_xdele(POP *p)
{
MsgInfoList * mp; /* Pointer to message info list */
int msg_min, msg_max;
int i;
msg_min = atoi(p->pop_parm[1]);
if(p->parm_count == 1)
msg_max = msg_min;
else
msg_max = atoi(p->pop_parm[2]);
if (msg_min < 1)
return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_min));
if(msg_max > p->msg_count)
return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_max));
for(i = msg_min; i <= msg_max; i++) {
/* Get a pointer to the message in the message list */
mp = &(p->mlp[i - 1]);
/* Is the message already flagged for deletion? */
if (mp->flags & DEL_FLAG)
continue; /* no point in returning error */
/* Flag the message for deletion */
mp->flags |= DEL_FLAG;
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG,
"Deleting message %u at offset %ld of length %ld\n",
mp->number, mp->offset, mp->length);
#endif /* DEBUG */
/* Update the messages_deleted and bytes_deleted counters */
p->msgs_deleted++;
p->bytes_deleted += mp->length;
}
/* Update the last-message-accessed number if it is lower than
the deleted message */
if (p->last_msg < msg_max) p->last_msg = msg_max;
return (pop_msg (p,POP_SUCCESS,"Messages %d-%d has been deleted.",
msg_min, msg_max));
}
#endif /* XDELE */

View File

@@ -1,174 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* Run as the user in `pwd'
*/
int
changeuser(POP *p, struct passwd *pwd)
{
if(setgid(pwd->pw_gid) < 0) {
pop_log (p, POP_PRIORITY,
"Unable to change to gid %u: %s",
(unsigned)pwd->pw_gid,
strerror(errno));
return pop_msg (p, POP_FAILURE,
"Unable to change gid");
}
if(setuid(pwd->pw_uid) < 0) {
pop_log (p, POP_PRIORITY,
"Unable to change to uid %u: %s",
(unsigned)pwd->pw_uid,
strerror(errno));
return pop_msg (p, POP_FAILURE,
"Unable to change uid");
}
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG,"uid = %u, gid = %u",
(unsigned)getuid(),
(unsigned)getgid());
#endif /* DEBUG */
return POP_SUCCESS;
}
/*
* dropcopy: Make a temporary copy of the user's mail drop and
* save a stream pointer for it.
*/
int
pop_dropcopy(POP *p, struct passwd *pwp)
{
int mfd; /* File descriptor for
the user's maildrop */
int dfd; /* File descriptor for
the SERVER maildrop */
FILE *tf; /* The temp file */
char template[POP_TMPSIZE]; /* Temp name holder */
char buffer[BUFSIZ]; /* Read buffer */
long offset; /* Old/New boundary */
int nchar; /* Bytes written/read */
int tf_fd; /* fd for temp file */
int ret;
/* Create a temporary maildrop into which to copy the updated maildrop */
snprintf(p->temp_drop, sizeof(p->temp_drop), POP_DROP,p->user);
#ifdef DEBUG
if(p->debug)
pop_log(p,POP_DEBUG,"Creating temporary maildrop '%s'",
p->temp_drop);
#endif /* DEBUG */
/* Here we work to make sure the user doesn't cause us to remove or
* write over existing files by limiting how much work we do while
* running as root.
*/
strlcpy(template, POP_TMPDROP, sizeof(template));
if ((tf_fd = mkstemp(template)) < 0 ||
(tf = fdopen(tf_fd, "w+")) == NULL) {
pop_log(p,POP_PRIORITY,
"Unable to create temporary temporary maildrop '%s': %s",template,
strerror(errno));
return pop_msg(p,POP_FAILURE,
"System error, can't create temporary file.");
}
/* Now give this file to the user */
chown(template, pwp->pw_uid, pwp->pw_gid);
chmod(template, 0600);
/* Now link this file to the temporary maildrop. If this fails it
* is probably because the temporary maildrop already exists. If so,
* this is ok. We can just go on our way, because by the time we try
* to write into the file we will be running as the user.
*/
link(template,p->temp_drop);
fclose(tf);
unlink(template);
ret = changeuser(p, pwp);
if (ret != POP_SUCCESS)
return ret;
/* Open for append, this solves the crash recovery problem */
if ((dfd = open(p->temp_drop,O_RDWR|O_APPEND|O_CREAT,0600)) == -1){
pop_log(p,POP_PRIORITY,
"Unable to open temporary maildrop '%s': %s",p->temp_drop,
strerror(errno));
return pop_msg(p,POP_FAILURE,
"System error, can't open temporary file, do you own it?");
}
/* Lock the temporary maildrop */
if ( flock (dfd, (LOCK_EX | LOCK_NB)) == -1 )
switch(errno) {
case EWOULDBLOCK:
return pop_msg(p,POP_FAILURE,
"%sMaildrop lock busy! Is another session active?",
(p->flags & POP_FLAG_CAPA) ? "[IN-USE] " : "");
/* NOTREACHED */
default:
return pop_msg(p,POP_FAILURE,"flock: '%s': %s", p->temp_drop,
strerror(errno));
/* NOTREACHED */
}
/* May have grown or shrunk between open and lock! */
offset = lseek(dfd,0, SEEK_END);
/* Open the user's maildrop, If this fails, no harm in assuming empty */
if ((mfd = open(p->drop_name,O_RDWR)) > 0) {
/* Lock the maildrop */
if (flock (mfd, LOCK_EX) == -1) {
close(mfd) ;
return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
strerror(errno));
}
/* Copy the actual mail drop into the temporary mail drop */
while ( (nchar=read(mfd,buffer,BUFSIZ)) > 0 )
if ( nchar != write(dfd,buffer,nchar) ) {
nchar = -1 ;
break ;
}
if ( nchar != 0 ) {
/* Error adding new mail. Truncate to original size,
and leave the maildrop as is. The user will not
see the new mail until the error goes away.
Should let them process the current backlog, in case
the error is a quota problem requiring deletions! */
ftruncate(dfd,(int)offset) ;
} else {
/* Mail transferred! Zero the mail drop NOW, that we
do not have to do gymnastics to figure out what's new
and what is old later */
ftruncate(mfd,0) ;
}
/* Close the actual mail drop */
close (mfd);
}
/* Acquire a stream pointer for the temporary maildrop */
if ( (p->drop = fdopen(dfd,"a+")) == NULL ) {
close(dfd) ;
return pop_msg(p,POP_FAILURE,"Cannot assign stream for %s",
p->temp_drop);
}
rewind (p->drop);
return(POP_SUCCESS);
}

View File

@@ -1,231 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
#if defined(UIDL) || defined(XOVER)
/*
* Copy the string found after after : into a malloced buffer. Stop
* copying at end of string or end of line. End of line delimiter is
* not part of the resulting copy.
*/
static
char *
find_value_after_colon(char *p)
{
char *t, *tmp;
for (; *p != 0 && *p != ':'; p++) /* Find : */
;
if (*p == 0)
goto error;
p++; /* Skip over : */
for(; *p == ' ' || *p == '\t'; p++) /* Remove white space */
;
for (t = p; *t != 0 && *t != '\n' && *t != '\r'; t++) /* Find end of str */
;
tmp = t = malloc(t - p + 1);
if (tmp == 0)
goto error;
for (; *p != 0 && *p != '\n' && *p != '\r'; p++, t++) /* Copy characters */
*t = *p;
*t = 0; /* Terminate string */
return tmp;
error:
return "ErrorUIDL";
}
#endif
void
parse_header(MsgInfoList *mp, char *buffer)
{
#if defined(UIDL) || defined(XOVER)
if (strncasecmp("Message-Id:",buffer, 11) == 0) {
if (mp->msg_id == NULL)
mp->msg_id = find_value_after_colon(buffer);
}
#ifdef UIDL
else if (strncasecmp(buffer, "X-UIDL:", 7) == 0) {
/* Courtesy to Qualcomm, there really is no such
thing as X-UIDL */
mp->msg_id = find_value_after_colon(buffer);
}
#endif
#endif
#ifdef XOVER
else if (strncasecmp("Subject:", buffer, 8) == 0) {
if(mp->subject == NULL){
char *p;
mp->subject = find_value_after_colon(buffer);
for(p = mp->subject; *p; p++)
if(*p == '\t') *p = ' ';
}
}
else if (strncasecmp("From:", buffer, 5) == 0) {
if(mp->from == NULL){
char *p;
mp->from = find_value_after_colon(buffer);
for(p = mp->from; *p; p++)
if(*p == '\t') *p = ' ';
}
}
else if (strncasecmp("Date:", buffer, 5) == 0) {
if(mp->date == NULL){
char *p;
mp->date = find_value_after_colon(buffer);
for(p = mp->date; *p; p++)
if(*p == '\t') *p = ' ';
}
}
#endif
}
int
add_missing_headers(POP *p, MsgInfoList *mp)
{
#if defined(UIDL) || defined(XOVER)
if (mp->msg_id == NULL) {
if (asprintf(&mp->msg_id, "no-message-id-%d", mp->number) == -1) {
fclose (p->drop);
p->msg_count = 0;
return pop_msg (p,POP_FAILURE,
"Can't build message list for '%s': Out of memory",
p->user);
}
}
#endif
#ifdef XOVER
if (mp->subject == NULL)
mp->subject = "<none>";
if (mp->from == NULL)
mp->from = "<unknown>";
if (mp->date == NULL)
mp->date = "<unknown>";
#endif
return POP_SUCCESS;
}
/*
* dropinfo: Extract information about the POP maildrop and store
* it for use by the other POP routines.
*/
int
pop_dropinfo(POP *p)
{
char buffer[BUFSIZ]; /* Read buffer */
MsgInfoList * mp; /* Pointer to message
info list */
int msg_num; /* Current message
counter */
int nchar; /* Bytes written/read */
int blank_line = 1; /* previous line was blank */
int in_header = 0; /* if we are in a header block */
/* Initialize maildrop status variables in the POP parameter block */
p->msg_count = 0;
p->msgs_deleted = 0;
p->last_msg = 0;
p->bytes_deleted = 0;
p->drop_size = 0;
/* Allocate memory for message information structures */
p->msg_count = ALLOC_MSGS;
p->mlp = (MsgInfoList *)calloc((unsigned)p->msg_count,sizeof(MsgInfoList));
if (p->mlp == NULL){
fclose (p->drop);
p->msg_count = 0;
return pop_msg (p,POP_FAILURE,
"Can't build message list for '%s': Out of memory", p->user);
}
rewind (p->drop);
/* Scan the file, loading the message information list with
information about each message */
for (msg_num = p->drop_size = 0, mp = p->mlp - 1;
fgets(buffer,MAXMSGLINELEN,p->drop);) {
nchar = strlen(buffer);
if (blank_line && strncmp(buffer,"From ",5) == 0) {
in_header = 1;
if (++msg_num > p->msg_count) {
p->mlp=(MsgInfoList *) realloc(p->mlp,
(p->msg_count+=ALLOC_MSGS)*sizeof(MsgInfoList));
if (p->mlp == NULL){
fclose (p->drop);
p->msg_count = 0;
return pop_msg (p,POP_FAILURE,
"Can't build message list for '%s': Out of memory",
p->user);
}
mp = p->mlp + msg_num - 2;
}
++mp;
mp->number = msg_num;
mp->length = 0;
mp->lines = 0;
mp->offset = ftell(p->drop) - nchar;
mp->flags = 0;
#if defined(UIDL) || defined(XOVER)
mp->msg_id = 0;
#endif
#ifdef XOVER
mp->subject = 0;
mp->from = 0;
mp->date = 0;
#endif
#ifdef DEBUG
if(p->debug)
pop_log(p, POP_DEBUG,
"Msg %d at offset %ld being added to list",
mp->number, mp->offset);
#endif /* DEBUG */
} else if(in_header)
parse_header(mp, buffer);
blank_line = (strncmp(buffer, "\n", nchar) == 0);
if(blank_line) {
int e;
in_header = 0;
e = add_missing_headers(p, mp);
if(e != POP_SUCCESS)
return e;
}
mp->length += nchar;
p->drop_size += nchar;
mp->lines++;
}
p->msg_count = msg_num;
#ifdef DEBUG
if(p->debug && msg_num > 0) {
int i;
for (i = 0, mp = p->mlp; i < p->msg_count; i++, mp++)
#ifdef UIDL
pop_log(p,POP_DEBUG,
"Msg %d at offset %ld is %ld octets long and has %u lines and id %s.",
mp->number,mp->offset,mp->length,mp->lines, mp->msg_id);
#else
pop_log(p,POP_DEBUG,
"Msg %d at offset %d is %d octets long and has %u lines.",
mp->number,mp->offset,mp->length,mp->lines);
#endif
}
#endif /* DEBUG */
return(POP_SUCCESS);
}

View File

@@ -1,160 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* get_command: Extract the command from an input line form a POP client
*/
int pop_capa (POP *p);
static state_table states[] = {
{auth1, "user", 1, 1, pop_user, {auth1, auth2}},
{auth2, "pass", 1, 99, pop_pass, {auth1, trans}},
#ifdef RPOP
{auth2, "rpop", 1, 1, pop_rpop, {auth1, trans}},
#endif /* RPOP */
#ifdef SASL
{auth1, "auth", 1, 2, pop_auth, {auth1, trans}},
#endif
{auth1, "quit", 0, 0, pop_quit, {halt, halt}},
{auth2, "quit", 0, 0, pop_quit, {halt, halt}},
#ifdef CAPA
{auth1, "capa", 0, 0, pop_capa, {auth1, auth1}},
{auth2, "capa", 0, 0, pop_capa, {auth2, auth2}},
{trans, "capa", 0, 0, pop_capa, {trans, trans}},
#endif
{trans, "stat", 0, 0, pop_stat, {trans, trans}},
{trans, "list", 0, 1, pop_list, {trans, trans}},
{trans, "retr", 1, 1, pop_send, {trans, trans}},
{trans, "dele", 1, 1, pop_dele, {trans, trans}},
{trans, "noop", 0, 0, NULL, {trans, trans}},
{trans, "rset", 0, 0, pop_rset, {trans, trans}},
{trans, "top", 2, 2, pop_send, {trans, trans}},
{trans, "last", 0, 0, pop_last, {trans, trans}},
{trans, "quit", 0, 0, pop_updt, {halt, halt}},
{trans, "help", 0, 0, pop_help, {trans, trans}},
#ifdef UIDL
{trans, "uidl", 0, 1, pop_uidl, {trans, trans}},
#endif
#ifdef XOVER
{trans, "xover", 0, 0, pop_xover, {trans, trans}},
#endif
#ifdef XDELE
{trans, "xdele", 1, 2, pop_xdele, {trans, trans}},
#endif
{(state) 0, NULL, 0, 0, NULL, {halt, halt}},
};
int
pop_capa (POP *p)
{
/* Search for the POP command in the command/state table */
pop_msg (p,POP_SUCCESS, "Capability list follows");
if(p->auth_level == AUTH_NONE || p->auth_level == AUTH_OTP)
fprintf(p->output, "USER\r\n");
fprintf(p->output, "TOP\r\n");
fprintf(p->output, "PIPELINING\r\n");
fprintf(p->output, "EXPIRE NEVER\r\n");
fprintf(p->output, "RESP-CODES\r\n");
#ifdef SASL
pop_capa_sasl(p);
#endif
#ifdef UIDL
fprintf(p->output, "UIDL\r\n");
#endif
#ifdef XOVER
fprintf(p->output, "XOVER\r\n");
#endif
#ifdef XDELE
fprintf(p->output, "XDELE\r\n");
#endif
if(p->CurrentState == trans)
fprintf(p->output, "IMPLEMENTATION %s-%s\r\n", PACKAGE, VERSION);
fprintf(p->output,".\r\n");
fflush(p->output);
p->flags |= POP_FLAG_CAPA;
return(POP_SUCCESS);
}
state_table *
pop_get_command(POP *p, char *mp)
{
state_table * s;
char buf[MAXMSGLINELEN];
/* Save a copy of the original client line */
#ifdef DEBUG
if(p->debug) strlcpy (buf, mp, sizeof(buf));
#endif /* DEBUG */
/* Parse the message into the parameter array */
if ((p->parm_count = pop_parse(p,mp)) < 0) return(NULL);
/* Do not log cleartext passwords */
#ifdef DEBUG
if(p->debug){
if(strcmp(p->pop_command,"pass") == 0)
pop_log(p,POP_DEBUG,"Received: \"%s xxxxxxxxx\"",p->pop_command);
else {
/* Remove trailing <LF> */
buf[strlen(buf)-2] = '\0';
pop_log(p,POP_DEBUG,"Received: \"%s\"",buf);
}
}
#endif /* DEBUG */
/* Search for the POP command in the command/state table */
for (s = states; s->command; s++) {
/* Is this a valid command for the current operating state? */
if (strcmp(s->command,p->pop_command) == 0
&& s->ValidCurrentState == p->CurrentState) {
/* Were too few parameters passed to the command? */
if (p->parm_count < s->min_parms) {
pop_msg(p,POP_FAILURE,
"Too few arguments for the %s command.",
p->pop_command);
return NULL;
}
/* Were too many parameters passed to the command? */
if (p->parm_count > s->max_parms) {
pop_msg(p,POP_FAILURE,
"Too many arguments for the %s command.",
p->pop_command);
return NULL;
}
/* Return a pointer to the entry for this command in
the command/state table */
return (s);
}
}
/* The client command was not located in the command/state table */
pop_msg(p,POP_FAILURE,
"Unknown command: \"%s\".",p->pop_command);
return NULL;
}
int
pop_help (POP *p)
{
state_table *s;
pop_msg(p, POP_SUCCESS, "help");
for (s = states; s->command; s++) {
fprintf (p->output, "%s\r\n", s->command);
}
fprintf (p->output, ".\r\n");
fflush (p->output);
return POP_SUCCESS;
}

View File

@@ -1,367 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
#if defined(KRB5)
static int
pop_net_read(POP *p, int fd, void *buf, size_t len)
{
#ifdef KRB5
return krb5_net_read(p->context, &fd, buf, len);
#else
#error must define KRB5
#endif
}
#endif
static char *addr_log;
static void
pop_write_addr(POP *p, struct sockaddr *addr)
{
char ts[32];
char as[128];
time_t t;
FILE *f;
if(addr_log == NULL)
return;
t = time(NULL);
strftime(ts, sizeof(ts), "%Y%m%d%H%M%S", localtime(&t));
if(inet_ntop (addr->sa_family, socket_get_address(addr),
as, sizeof(as)) == NULL) {
pop_log(p, POP_PRIORITY, "failed to print address");
return;
}
f = fopen(addr_log, "a");
if(f == NULL) {
pop_log(p, POP_PRIORITY, "failed to open address log (%s)", addr_log);
return;
}
fprintf(f, "%s %s\n", as, ts);
fclose(f);
}
#ifdef KRB5
static int
krb5_authenticate (POP *p, int s, u_char *buf, struct sockaddr *addr)
{
krb5_error_code ret;
krb5_auth_context auth_context = NULL;
uint32_t len;
krb5_ticket *ticket;
const char *estr;
char *server;
if (memcmp (buf, "\x00\x00\x00\x13", 4) != 0)
return -1;
len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
if (krb5_net_read(p->context, &s, buf, len) != len)
return -1;
if (len != sizeof(KRB5_SENDAUTH_VERSION)
|| memcmp (buf, KRB5_SENDAUTH_VERSION, len) != 0)
return -1;
ret = krb5_recvauth (p->context,
&auth_context,
&s,
"KPOPV1.0",
NULL, /* let rd_req figure out what server to use */
KRB5_RECVAUTH_IGNORE_VERSION,
NULL,
&ticket);
if (ret) {
estr = krb5_get_error_message(p->context, ret);
pop_log(p, POP_PRIORITY, "krb5_recvauth: %s", estr);
krb5_free_error_message(p->context, estr);
return -1;
}
ret = krb5_unparse_name(p->context, ticket->server, &server);
if(ret) {
estr = krb5_get_error_message(p->context, ret);
pop_log(p, POP_PRIORITY, "krb5_unparse_name: %s", estr);
krb5_free_error_message(p->context, estr);
ret = -1;
goto out;
}
/* does this make sense? */
if(strncmp(server, "pop/", 4) != 0) {
pop_log(p, POP_PRIORITY,
"Got ticket for service `%s'", server);
ret = -1;
goto out;
} else if(p->debug)
pop_log(p, POP_DEBUG,
"Accepted ticket for service `%s'", server);
free(server);
out:
krb5_auth_con_free (p->context, auth_context);
krb5_copy_principal (p->context, ticket->client, &p->principal);
krb5_free_ticket (p->context, ticket);
return ret;
}
#endif
static int
krb_authenticate(POP *p, struct sockaddr *addr)
{
#if defined(KRB5)
u_char buf[BUFSIZ];
if (pop_net_read (p, 0, buf, 4) != 4) {
pop_msg(p, POP_FAILURE, "Reading four bytes: %s",
strerror(errno));
exit (1);
}
if (krb5_authenticate (p, 0, buf, addr) == 0){
pop_write_addr(p, addr);
p->version = 5;
return POP_SUCCESS;
}
#endif
exit (1);
return(POP_SUCCESS);
}
static int
plain_authenticate (POP *p, struct sockaddr *addr)
{
return(POP_SUCCESS);
}
static int kerberos_flag;
static char *auth_str;
static int debug_flag;
static int interactive_flag;
static char *port_str;
static char *trace_file;
static int timeout;
static int help_flag;
static int version_flag;
static struct getargs args[] = {
#if defined(KRB5)
{ "kerberos", 'k', arg_flag, &kerberos_flag, "use kerberos" },
#endif
{ "auth-mode", 'a', arg_string, &auth_str, "required authentication",
"plaintext"
#ifdef OTP
"|otp"
#endif
#ifdef SASL
"|sasl"
#endif
},
{ "debug", 'd', arg_flag, &debug_flag },
{ "interactive", 'i', arg_flag, &interactive_flag, "create new socket" },
{ "port", 'p', arg_string, &port_str, "port to listen to", "port" },
{ "trace-file", 't', arg_string, &trace_file, "trace all command to file", "file" },
{ "timeout", 'T', arg_integer, &timeout, "timeout", "seconds" },
{ "address-log", 0, arg_string, &addr_log, "enable address log", "file" },
{ "help", 'h', arg_flag, &help_flag },
{ "version", 'v', arg_flag, &version_flag }
};
static int num_args = sizeof(args) / sizeof(args[0]);
/*
* init: Start a Post Office Protocol session
*/
static int
pop_getportbyname(POP *p, const char *service,
const char *proto, short def)
{
#ifdef KRB5
return krb5_getportbyname(p->context, service, proto, def);
#else
return htons(default);
#endif
}
int
pop_init(POP *p,int argcount,char **argmessage)
{
struct sockaddr_storage cs_ss;
struct sockaddr *cs = (struct sockaddr *)&cs_ss;
socklen_t len;
char * trace_file_name = "/tmp/popper-trace";
int portnum = 0;
int optind = 0;
int error;
/* Initialize the POP parameter block */
memset (p, 0, sizeof(POP));
setprogname(argmessage[0]);
/* Save my name in a global variable */
p->myname = (char*)getprogname();
/* Get the name of our host */
gethostname(p->myhost,MaxHostNameLen);
#ifdef KRB5
{
krb5_error_code ret;
ret = krb5_init_context (&p->context);
if (ret)
errx (1, "krb5_init_context failed: %d", ret);
krb5_openlog(p->context, p->myname, &p->logf);
krb5_set_warn_dest(p->context, p->logf);
}
#else
/* Open the log file */
roken_openlog(p->myname,POP_LOGOPTS,POP_FACILITY);
#endif
p->auth_level = AUTH_NONE;
if(getarg(args, num_args, argcount, argmessage, &optind)){
arg_printusage(args, num_args, NULL, "");
exit(1);
}
if(help_flag){
arg_printusage(args, num_args, NULL, "");
exit(0);
}
if(version_flag){
print_version(NULL);
exit(0);
}
argcount -= optind;
argmessage += optind;
if (argcount != 0) {
arg_printusage(args, num_args, NULL, "");
exit(1);
}
if(auth_str){
if (strcasecmp (auth_str, "plaintext") == 0 ||
strcasecmp (auth_str, "none") == 0)
p->auth_level = AUTH_NONE;
else if(strcasecmp(auth_str, "otp") == 0) {
#ifdef OTP
p->auth_level = AUTH_OTP;
#else
pop_log (p, POP_PRIORITY, "support for OTP not enabled");
exit(1);
#endif
} else if(strcasecmp(auth_str, "sasl") == 0) {
#ifdef SASL
p->auth_level = AUTH_SASL;
#else
pop_log (p, POP_PRIORITY, "support for SASL not enabled");
exit(1);
#endif
} else {
pop_log (p, POP_PRIORITY, "bad value for -a: %s", auth_str);
exit(1);
}
}
/* Debugging requested */
p->debug = debug_flag;
if(port_str)
portnum = htons(atoi(port_str));
if(trace_file){
p->debug++;
if ((p->trace = fopen(trace_file, "a+")) == NULL) {
pop_log(p, POP_PRIORITY,
"Unable to open trace file \"%s\", err = %d",
optarg,errno);
exit (1);
}
trace_file_name = trace_file;
}
#if defined(KRB5)
p->kerberosp = kerberos_flag;
#endif
if(timeout)
pop_timeout = timeout;
/* Fake inetd */
if (interactive_flag) {
if (portnum == 0)
portnum = p->kerberosp ?
pop_getportbyname(p, "kpop", "tcp", 1109) :
pop_getportbyname(p, "pop", "tcp", 110);
mini_inetd (portnum, NULL);
}
/* Get the address and socket of the client to whom I am speaking */
len = sizeof(cs_ss);
if (getpeername(STDIN_FILENO, cs, &len) < 0) {
pop_log(p,POP_PRIORITY,
"Unable to obtain socket and address of client, err = %d",errno);
exit (1);
}
/* Save the dotted decimal form of the client's IP address
in the POP parameter block */
inet_ntop (cs->sa_family, socket_get_address (cs),
p->ipaddr, sizeof(p->ipaddr));
/* Save the client's port */
p->ipport = ntohs(socket_get_port (cs));
/* Get the canonical name of the host to whom I am speaking */
error = getnameinfo_verified (cs, len, p->client, sizeof(p->client),
NULL, 0, 0);
if (error) {
pop_log (p, POP_PRIORITY,
"getnameinfo: %s", gai_strerror (error));
strlcpy (p->client, p->ipaddr, sizeof(p->client));
}
/* Create input file stream for TCP/IP communication */
if ((p->input = fdopen(STDIN_FILENO,"r")) == NULL){
pop_log(p,POP_PRIORITY,
"Unable to open communication stream for input, err = %d",errno);
exit (1);
}
/* Create output file stream for TCP/IP communication */
if ((p->output = fdopen(STDOUT_FILENO,"w")) == NULL){
pop_log(p,POP_PRIORITY,
"Unable to open communication stream for output, err = %d",errno);
exit (1);
}
pop_log(p,POP_PRIORITY,
"(v%s) Servicing request from \"%s\" at %s\n",
VERSION,p->client,p->ipaddr);
#ifdef DEBUG
if (p->trace)
pop_log(p,POP_PRIORITY,
"Tracing session and debugging information in file \"%s\"",
trace_file_name);
else if (p->debug)
pop_log(p,POP_PRIORITY,"Debugging turned on");
#endif /* DEBUG */
if(p->kerberosp)
return krb_authenticate(p, cs);
else
return plain_authenticate(p, cs);
}

View File

@@ -1,18 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* last: Display the last message touched in a POP session
*/
int
pop_last (POP *p)
{
return (pop_msg(p,POP_SUCCESS,"%u is the last message seen.",p->last_msg));
}

View File

@@ -1,59 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* list: List the contents of a POP maildrop
*/
int
pop_list (POP *p)
{
MsgInfoList * mp; /* Pointer to message info list */
int i;
int msg_num;
/* Was a message number provided? */
if (p->parm_count > 0) {
msg_num = atoi(p->pop_parm[1]);
/* Is requested message out of range? */
if ((msg_num < 1) || (msg_num > p->msg_count))
return (pop_msg (p,POP_FAILURE,
"Message %d does not exist.",msg_num));
/* Get a pointer to the message in the message list */
mp = &p->mlp[msg_num-1];
/* Is the message already flagged for deletion? */
if (mp->flags & DEL_FLAG)
return (pop_msg (p,POP_FAILURE,
"Message %d has been deleted.",msg_num));
/* Display message information */
return (pop_msg(p,POP_SUCCESS,"%d %ld",msg_num,mp->length));
}
/* Display the entire list of messages */
pop_msg(p,POP_SUCCESS,
"%d messages (%ld octets)",
p->msg_count-p->msgs_deleted,
p->drop_size-p->bytes_deleted);
/* Loop through the message information list. Skip deleted messages */
for (i = p->msg_count, mp = p->mlp; i > 0; i--, mp++) {
if (!(mp->flags & DEL_FLAG))
fprintf(p->output,"%u %lu\r\n",mp->number,mp->length);
}
/* "." signals the end of a multi-line transmission */
fprintf(p->output,".\r\n");
fflush(p->output);
return(POP_SUCCESS);
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* log: Make a log entry
*/
int
pop_log(POP *p, int stat, char *format, ...)
{
char msgbuf[MAXLINELEN];
va_list ap;
va_start(ap, format);
vsnprintf(msgbuf, sizeof(msgbuf), format, ap);
if (p->debug && p->trace) {
fprintf(p->trace,"%s\n",msgbuf);
fflush(p->trace);
} else {
#ifdef KRB5
krb5_log(p->context, p->logf, stat, "%s", msgbuf);
#else
syslog (stat,"%s",msgbuf);
#endif
}
va_end(ap);
return(stat);
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* msg: Send a formatted line to the POP client
*/
int
pop_msg(POP *p, int stat, const char *format, ...)
{
char *mp;
char message[MAXLINELEN];
va_list ap;
va_start(ap, format);
/* Point to the message buffer */
mp = message;
/* Format the POP status code at the beginning of the message */
snprintf (mp, sizeof(message), "%s ",
(stat == POP_SUCCESS) ? POP_OK : POP_ERR);
/* Point past the POP status indicator in the message message */
mp += strlen(mp);
/* Append the message (formatted, if necessary) */
if (format)
vsnprintf (mp, sizeof(message) - strlen(message),
format, ap);
/* Log the message if debugging is turned on */
#ifdef DEBUG
if (p->debug && stat == POP_SUCCESS)
pop_log(p,POP_DEBUG,"%s",message);
#endif /* DEBUG */
/* Log the message if a failure occurred */
if (stat != POP_SUCCESS)
pop_log(p,POP_PRIORITY,"%s",message);
/* Append the <CR><LF> */
strlcat(message, "\r\n", sizeof(message));
/* Send the message to the client */
fputs(message, p->output);
fflush(p->output);
va_end(ap);
return(stat);
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* parse: Parse a raw input line from a POP client
* into null-delimited tokens
*/
int
pop_parse(POP *p, char *buf)
{
char * mp;
int i;
/* Loop through the POP command array */
for (mp = buf, i = 0; ; i++) {
/* Skip leading spaces and tabs in the message */
while (isspace((unsigned char)*mp))mp++;
/* Are we at the end of the message? */
if (*mp == 0) break;
/* Have we already obtained the maximum allowable parameters? */
if (i >= MAXPARMCOUNT) {
pop_msg(p,POP_FAILURE,"Too many arguments supplied.");
return(-1);
}
/* Point to the start of the token */
p->pop_parm[i] = mp;
/* Search for the first space character (end of the token) */
while (!isspace((unsigned char)*mp) && *mp) mp++;
/* Delimit the token with a null */
if (*mp) *mp++ = 0;
}
/* Were any parameters passed at all? */
if (i == 0) return (-1);
/* Convert the first token (POP command) to lower case */
strlwr(p->pop_command);
/* Return the number of tokens extracted minus the command itself */
return (i-1);
}

View File

@@ -1,207 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
RCSID("$Id$");
#ifdef KRB5
static int
krb5_verify_password (POP *p)
{
krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
krb5_get_init_creds_opt *get_options;
krb5_verify_init_creds_opt verify_options;
krb5_error_code ret;
krb5_principal client, server;
krb5_creds creds;
const char *estr;
ret = krb5_get_init_creds_opt_alloc (p->context, &get_options);
if (ret) {
estr = krb5_get_error_message(p->context, ret);
pop_log(p, POP_PRIORITY, "krb5_get_init_creds_opt_alloc: %s", estr);
krb5_free_error_message(p->context, estr);
return 1;
}
krb5_get_init_creds_opt_set_preauth_list (get_options,
pre_auth_types,
1);
krb5_verify_init_creds_opt_init (&verify_options);
ret = krb5_parse_name (p->context, p->user, &client);
if (ret) {
krb5_get_init_creds_opt_free(p->context, get_options);
estr = krb5_get_error_message(p->context, ret);
pop_log(p, POP_PRIORITY, "krb5_parse_name: %s", estr);
krb5_free_error_message(p->context, estr);
return 1;
}
ret = krb5_get_init_creds_password (p->context,
&creds,
client,
p->pop_parm[1],
NULL,
NULL,
0,
NULL,
get_options);
krb5_get_init_creds_opt_free(p->context, get_options);
if (ret) {
estr = krb5_get_error_message(p->context, ret);
pop_log(p, POP_PRIORITY, "krb5_get_init_creds_password: %s", estr);
krb5_free_error_message(p->context, estr);
return 1;
}
ret = krb5_sname_to_principal (p->context,
p->myhost,
"pop",
KRB5_NT_SRV_HST,
&server);
if (ret) {
estr = krb5_get_error_message(p->context, ret);
pop_log(p, POP_PRIORITY, "krb5_get_init_creds_password: %s", estr);
krb5_free_error_message(p->context, estr);
return 1;
}
ret = krb5_verify_init_creds (p->context,
&creds,
server,
NULL,
NULL,
&verify_options);
krb5_free_principal (p->context, client);
krb5_free_principal (p->context, server);
krb5_free_cred_contents (p->context, &creds);
return ret;
}
#endif
/*
* pass: Obtain the user password from a POP client
*/
int
login_user(POP *p)
{
struct stat st;
struct passwd *pw;
/* Look for the user in the password file */
if ((pw = k_getpwnam(p->user)) == NULL) {
pop_log(p, POP_PRIORITY, "user %s (from %s) not found",
p->user, p->ipaddr);
return pop_msg(p, POP_FAILURE, "Login incorrect.");
}
pop_log(p, POP_INFO, "login from %s as %s", p->ipaddr, p->user);
/* Build the name of the user's maildrop */
snprintf(p->drop_name, sizeof(p->drop_name), "%s/%s", POP_MAILDIR, p->user);
if(stat(p->drop_name, &st) < 0 || !S_ISDIR(st.st_mode)){
/* Make a temporary copy of the user's maildrop */
/* and set the group and user id */
if (pop_dropcopy(p, pw) != POP_SUCCESS) return (POP_FAILURE);
/* Get information about the maildrop */
if (pop_dropinfo(p) != POP_SUCCESS) return(POP_FAILURE);
} else {
if(changeuser(p, pw) != POP_SUCCESS) return POP_FAILURE;
if(pop_maildir_info(p) != POP_SUCCESS) return POP_FAILURE;
}
/* Initialize the last-message-accessed number */
p->last_msg = 0;
return POP_SUCCESS;
}
int
pop_pass (POP *p)
{
struct passwd *pw;
int i;
int status;
/* Make one string of all these parameters */
for (i = 1; i < p->parm_count; ++i)
p->pop_parm[i][strlen(p->pop_parm[i])] = ' ';
/* Look for the user in the password file */
if ((pw = k_getpwnam(p->user)) == NULL)
return (pop_msg(p,POP_FAILURE,
"Password supplied for \"%s\" is incorrect.",
p->user));
if (p->kerberosp) {
#ifdef KRB5
if (p->version == 5) {
char *name;
if (!krb5_kuserok (p->context, p->principal, p->user)) {
pop_log (p, POP_PRIORITY,
"krb5 permission denied");
return pop_msg(p, POP_FAILURE,
"Popping not authorized");
}
if(krb5_unparse_name (p->context, p->principal, &name) == 0) {
pop_log(p, POP_INFO, "%s: %s -> %s",
p->ipaddr, name, p->user);
free (name);
}
} else {
pop_log (p, POP_PRIORITY, "kerberos authentication failed");
return pop_msg (p, POP_FAILURE,
"kerberos authentication failed");
}
#endif
{ }
} else {
/* We don't accept connections from users with null passwords */
if (pw->pw_passwd == NULL)
return (pop_msg(p,
POP_FAILURE,
"Password supplied for \"%s\" is incorrect.",
p->user));
#ifdef OTP
if (otp_verify_user (&p->otp_ctx, p->pop_parm[1]) == 0)
/* pass OK */;
else
#endif
/* Compare the supplied password with the password file entry */
if (p->auth_level != AUTH_NONE)
return pop_msg(p, POP_FAILURE,
"Password supplied for \"%s\" is incorrect.",
p->user);
else if (!strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))
/* pass OK */;
else {
int ret = -1;
#ifdef KRB5
if(ret)
ret = krb5_verify_password (p);
#endif
if(ret)
return pop_msg(p, POP_FAILURE,
"Password incorrect");
}
}
status = login_user(p);
if(status != POP_SUCCESS)
return status;
/* Authorization completed successfully */
return (pop_msg (p, POP_SUCCESS,
"%s has %d message(s) (%ld octets).",
p->user, p->msg_count, p->drop_size));
}

View File

@@ -1,21 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* quit: Terminate a POP session
*/
int
pop_quit (POP *p)
{
/* Release the message information list */
if (p->mlp) free (p->mlp);
return(POP_SUCCESS);
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* rset: Unflag all messages flagged for deletion in a POP maildrop
*/
int
pop_rset (POP *p)
{
MsgInfoList * mp; /* Pointer to the message info list */
int i;
/* Unmark all the messages */
for (i = p->msg_count, mp = p->mlp; i > 0; i--, mp++)
mp->flags &= ~DEL_FLAG;
/* Reset the messages-deleted and bytes-deleted counters */
p->msgs_deleted = 0;
p->bytes_deleted = 0;
/* Reset the last-message-access flag */
p->last_msg = 0;
return (pop_msg(p,POP_SUCCESS,"Maildrop has %u messages (%ld octets)",
p->msg_count, p->drop_size));
}

View File

@@ -1,176 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* sendline: Send a line of a multi-line response to a client.
*/
static int
pop_sendline(POP *p, char *buffer)
{
char * bp;
/* Byte stuff lines that begin with the termination octet */
if (*buffer == POP_TERMINATE)
fputc(POP_TERMINATE,p->output);
/* Look for a <NL> in the buffer */
if ((bp = strchr(buffer, '\n')))
*bp = 0;
/* Send the line to the client */
fputs(buffer,p->output);
#ifdef DEBUG
if(p->debug)
pop_log(p,POP_DEBUG,"Sending line \"%s\"",buffer);
#endif /* DEBUG */
/* Put a <CR><NL> if a newline was removed from the buffer */
if (bp)
fputs ("\r\n",p->output);
return bp != NULL;
}
/*
* send: Send the header and a specified number of lines
* from a mail message to a POP client.
*/
int
pop_send(POP *p)
{
MsgInfoList * mp; /* Pointer to message info list */
int msg_num;
int msg_lines;
char buffer[MAXMSGLINELEN];
#ifdef RETURN_PATH_HANDLING
char * return_path_adr;
char * return_path_end;
int return_path_sent;
int return_path_linlen;
#endif
int sent_nl = 0;
/* Convert the first parameter into an integer */
msg_num = atoi(p->pop_parm[1]);
/* Is requested message out of range? */
if ((msg_num < 1) || (msg_num > p->msg_count))
return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_num));
/* Get a pointer to the message in the message list */
mp = &p->mlp[msg_num-1];
/* Is the message flagged for deletion? */
if (mp->flags & DEL_FLAG)
return (pop_msg (p,POP_FAILURE,
"Message %d has been deleted.",msg_num));
/* If this is a TOP command, get the number of lines to send */
if (strcmp(p->pop_command, "top") == 0) {
/* Convert the second parameter into an integer */
msg_lines = atoi(p->pop_parm[2]);
}
else {
/* Assume that a RETR (retrieve) command was issued */
msg_lines = -1;
/* Flag the message as retreived */
mp->flags |= RETR_FLAG;
}
/* Display the number of bytes in the message */
pop_msg(p, POP_SUCCESS, "%ld octets", mp->length);
if(IS_MAILDIR(p)) {
int e = pop_maildir_open(p, mp);
if(e != POP_SUCCESS)
return e;
}
/* Position to the start of the message */
fseek(p->drop, mp->offset, 0);
return_path_sent = 0;
if(!IS_MAILDIR(p)) {
/* Skip the first line (the sendmail "From" line) */
fgets (buffer,MAXMSGLINELEN,p->drop);
#ifdef RETURN_PATH_HANDLING
if (strncmp(buffer,"From ",5) == 0) {
return_path_linlen = strlen(buffer);
for (return_path_adr = buffer+5;
(*return_path_adr == ' ' || *return_path_adr == '\t') &&
return_path_adr < buffer + return_path_linlen;
return_path_adr++)
;
if (return_path_adr < buffer + return_path_linlen) {
if ((return_path_end = strchr(return_path_adr, ' ')) != NULL)
*return_path_end = '\0';
if (strlen(return_path_adr) != 0 && *return_path_adr != '\n') {
static char tmpbuf[MAXMSGLINELEN + 20];
if (snprintf (tmpbuf,
sizeof(tmpbuf),
"Return-Path: %s\n",
return_path_adr) < MAXMSGLINELEN) {
pop_sendline (p,tmpbuf);
if (hangup)
return pop_msg (p, POP_FAILURE,
"SIGHUP or SIGPIPE flagged");
return_path_sent++;
}
}
}
}
#endif
}
/* Send the header of the message followed by a blank line */
while (fgets(buffer,MAXMSGLINELEN,p->drop)) {
#ifdef RETURN_PATH_HANDLING
/* Don't send existing Return-Path-header if already sent own */
if (!return_path_sent || strncasecmp(buffer, "Return-Path:", 12) != 0)
#endif
sent_nl = pop_sendline (p,buffer);
/* A single newline (blank line) signals the
end of the header. sendline() converts this to a NULL,
so that's what we look for. */
if (*buffer == 0) break;
if (hangup)
return (pop_msg (p,POP_FAILURE,"SIGHUP or SIGPIPE flagged"));
}
/* Send the message body */
{
int blank_line = 1;
while (fgets(buffer, MAXMSGLINELEN-1, p->drop)) {
/* Look for the start of the next message */
if (!IS_MAILDIR(p) && blank_line && strncmp(buffer,"From ",5) == 0)
break;
blank_line = (strncmp(buffer, "\n", 1) == 0);
/* Decrement the lines sent (for a TOP command) */
if (msg_lines >= 0 && msg_lines-- == 0) break;
sent_nl = pop_sendline(p,buffer);
if (hangup)
return (pop_msg (p,POP_FAILURE,"SIGHUP or SIGPIPE flagged"));
}
/* add missing newline at end */
if(!sent_nl)
fputs("\r\n", p->output);
/* some pop-clients want a blank line at the end of the
message, we always add one here, but what the heck -- in
outer (white) space, no one can hear you scream */
if(IS_MAILDIR(p))
fputs("\r\n", p->output);
}
/* "." signals the end of a multi-line transmission */
fputs(".\r\n",p->output);
fflush(p->output);
return(POP_SUCCESS);
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* stat: Display the status of a POP maildrop to its client
*/
int
pop_stat (POP *p)
{
#ifdef DEBUG
if (p->debug) pop_log(p,POP_DEBUG,"%d message(s) (%ld octets).",
p->msg_count-p->msgs_deleted,
p->drop_size-p->bytes_deleted);
#endif /* DEBUG */
return (pop_msg (p,POP_SUCCESS,
"%d %ld",
p->msg_count-p->msgs_deleted,
p->drop_size-p->bytes_deleted));
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 <popper.h>
RCSID("$Id$");
#ifdef UIDL
/*
* uidl: Uidl the contents of a POP maildrop
*/
int
pop_uidl (POP *p)
{
MsgInfoList * mp; /* Pointer to message info list */
int i;
int msg_num;
/* Was a message number provided? */
if (p->parm_count > 0) {
msg_num = atoi(p->pop_parm[1]);
/* Is requested message out of range? */
if ((msg_num < 1) || (msg_num > p->msg_count))
return (pop_msg (p,POP_FAILURE,
"Message %d does not exist.",msg_num));
/* Get a pointer to the message in the message list */
mp = &p->mlp[msg_num-1];
/* Is the message already flagged for deletion? */
if (mp->flags & DEL_FLAG)
return (pop_msg (p,POP_FAILURE,
"Message %d has been deleted.",msg_num));
/* Display message information */
return (pop_msg(p,POP_SUCCESS,"%u %s",msg_num,mp->msg_id));
}
/* Display the entire list of messages */
pop_msg(p,POP_SUCCESS,
"%d messages (%ld octets)",
p->msg_count-p->msgs_deleted,
p->drop_size-p->bytes_deleted);
/* Loop through the message information list. Skip deleted messages */
for (i = p->msg_count, mp = p->mlp; i > 0; i--, mp++) {
if (!(mp->flags & DEL_FLAG))
fprintf(p->output,"%u %s\r\n",mp->number,mp->msg_id);
}
/* "." signals the end of a multi-line transmission */
fprintf(p->output,".\r\n");
fflush(p->output);
return(POP_SUCCESS);
}
#endif /* UIDL */

View File

@@ -1,199 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
static const char standard_error[] =
"Error error updating primary drop. Mailbox unchanged";
/*
* updt: Apply changes to a user's POP maildrop
*/
int
pop_updt (POP *p)
{
FILE * md; /* Stream pointer for
the user's maildrop */
int mfd; /* File descriptor for
above */
char buffer[BUFSIZ]; /* Read buffer */
MsgInfoList * mp; /* Pointer to message
info list */
int msg_num; /* Current message
counter */
int status_written; /* Status header field
written */
int nchar; /* Bytes read/written */
long offset; /* New mail offset */
int blank_line;
#ifdef DEBUG
if (p->debug) {
pop_log(p,POP_DEBUG,"Performing maildrop update...");
pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted");
}
#endif /* DEBUG */
if(IS_MAILDIR(p))
return pop_maildir_update(p);
if (p->msgs_deleted == p->msg_count) {
/* Truncate before close, to avoid race condition, DO NOT UNLINK!
Another process may have opened, and not yet tried to lock */
ftruncate ((int)fileno(p->drop),0);
fclose(p->drop) ;
return (POP_SUCCESS);
}
#ifdef DEBUG
if (p->debug)
pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"",p->drop_name);
#endif /* DEBUG */
/* Open the user's real maildrop */
if ((mfd = open(p->drop_name,O_RDWR|O_CREAT,0600)) == -1 ||
(md = fdopen(mfd,"r+")) == NULL) {
return pop_msg(p,POP_FAILURE,standard_error);
}
/* Lock the user's real mail drop */
if ( flock(mfd, LOCK_EX) == -1 ) {
fclose(md) ;
return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
strerror(errno));
}
/* Go to the right places */
offset = lseek((int)fileno(p->drop),0,SEEK_END) ;
/* Append any messages that may have arrived during the session
to the temporary maildrop */
while ((nchar=read(mfd,buffer,BUFSIZ)) > 0)
if ( nchar != write((int)fileno(p->drop),buffer,nchar) ) {
nchar = -1;
break ;
}
if ( nchar != 0 ) {
fclose(md) ;
ftruncate((int)fileno(p->drop),(int)offset) ;
fclose(p->drop) ;
return pop_msg(p,POP_FAILURE,standard_error);
}
rewind(md);
lseek(mfd,0,SEEK_SET);
ftruncate(mfd,0) ;
/* Synch stdio and the kernel for the POP drop */
rewind(p->drop);
lseek((int)fileno(p->drop),0,SEEK_SET);
/* Transfer messages not flagged for deletion from the temporary
maildrop to the new maildrop */
#ifdef DEBUG
if (p->debug)
pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"",
p->drop_name,p->temp_drop);
#endif /* DEBUG */
for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {
int doing_body;
/* Get a pointer to the message information list */
mp = &p->mlp[msg_num];
if (mp->flags & DEL_FLAG) {
#ifdef DEBUG
if(p->debug)
pop_log(p,POP_DEBUG,
"Message %d flagged for deletion.",mp->number);
#endif /* DEBUG */
continue;
}
fseek(p->drop,mp->offset,0);
#ifdef DEBUG
if(p->debug)
pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
#endif /* DEBUG */
blank_line = 1;
for(status_written = doing_body = 0 ;
fgets(buffer,MAXMSGLINELEN,p->drop);) {
if (doing_body == 0) { /* Header */
/* Update the message status */
if (strncasecmp(buffer,"Status:",7) == 0) {
if (mp->flags & RETR_FLAG)
fputs("Status: RO\n",md);
else
fputs(buffer, md);
status_written++;
continue;
}
/* A blank line signals the end of the header. */
if (*buffer == '\n') {
doing_body = 1;
if (status_written == 0) {
if (mp->flags & RETR_FLAG)
fputs("Status: RO\n\n",md);
else
fputs("Status: U\n\n",md);
}
else fputs ("\n", md);
continue;
}
/* Save another header line */
fputs (buffer, md);
}
else { /* Body */
if (blank_line && strncmp(buffer,"From ",5) == 0) break;
fputs (buffer, md);
blank_line = (*buffer == '\n');
}
}
}
/* flush and check for errors now! The new mail will writen
without stdio, since we need not separate messages */
fflush(md) ;
if (ferror(md)) {
ftruncate(mfd,0) ;
fclose(md) ;
fclose(p->drop) ;
return pop_msg(p,POP_FAILURE,standard_error);
}
/* Go to start of new mail if any */
lseek((int)fileno(p->drop),offset,SEEK_SET);
while((nchar=read((int)fileno(p->drop),buffer,BUFSIZ)) > 0)
if ( nchar != write(mfd,buffer,nchar) ) {
nchar = -1;
break ;
}
if ( nchar != 0 ) {
ftruncate(mfd,0) ;
fclose(md) ;
fclose(p->drop) ;
return pop_msg(p,POP_FAILURE,standard_error);
}
/* Close the maildrop and empty temporary maildrop */
fclose(md);
ftruncate((int)fileno(p->drop),0);
fclose(p->drop);
return(pop_quit(p));
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
/*
* user: Prompt for the user name at the start of a POP session
*/
int
pop_user (POP *p)
{
strlcpy(p->user, p->pop_parm[1], sizeof(p->user));
if (p->auth_level == AUTH_OTP) {
#ifdef OTP
char ss[256], *s;
if(otp_challenge (&p->otp_ctx, p->user, ss, sizeof(ss)) == 0)
return pop_msg(p, POP_SUCCESS, "Password %s required for %s.",
ss, p->user);
s = otp_error(&p->otp_ctx);
return pop_msg(p, POP_FAILURE, "Permission denied%s%s",
s ? ":" : "", s ? s : "");
#endif
}
if (p->auth_level == AUTH_SASL) {
return pop_msg(p, POP_FAILURE, "Permission denied");
}
return pop_msg(p, POP_SUCCESS, "Password required for %s.", p->user);
}

View File

@@ -1,37 +0,0 @@
#include <popper.h>
RCSID("$Id$");
int
pop_xover (POP *p)
{
#ifdef XOVER
MsgInfoList * mp; /* Pointer to message info list */
int i;
pop_msg(p,POP_SUCCESS,
"%d messages (%ld octets)",
p->msg_count-p->msgs_deleted,
p->drop_size-p->bytes_deleted);
/* Loop through the message information list. Skip deleted messages */
for (i = p->msg_count, mp = p->mlp; i > 0; i--, mp++) {
if (!(mp->flags & DEL_FLAG))
fprintf(p->output,"%u\t%s\t%s\t%s\t%s\t%lu\t%u\r\n",
mp->number,
mp->subject,
mp->from,
mp->date,
mp->msg_id,
mp->length,
mp->lines);
}
/* "." signals the end of a multi-line transmission */
fprintf(p->output,".\r\n");
fflush(p->output);
return(POP_SUCCESS);
#else
return pop_msg(p, POP_FAILURE, "Command not implemented.");
#endif
}

View File

@@ -1,103 +0,0 @@
.\" Copyright (c) 2001 - 2004 Kungliga Tekniska Högskolan
.\" (Royal Institute of Technology, Stockholm, Sweden).
.\" 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
.\"
.\" $Id$
.\"
.Dd July 14, 2004
.Dt POPPER 8
.Os HEIMDAL
.Sh NAME
.Nm popper
.Nd POP3 server
.Sh SYNOPSIS
.Nm
.Op Fl k
.Op Fl a Ar plaintext Ns \*(Ba Ns Ar otp Ns \*(Ba Ns Ar sasl
.Op Fl t Ar file
.Op Fl T Ar seconds
.Op Fl d
.Op Fl i
.Op Fl p Ar port
.Op Fl Fl address-log= Ns Pa file
.Sh DESCRIPTION
.Nm
serves mail via the Post Office Protocol. Supported options include:
.Bl -tag -width Ds
.It Fl a Ar plaintext Ns \*(Ba Ns Ar otp Ns \*(Ba Ns Ar sasl
Tells
.Nm
which authentication mode is acceptable,
.Ar sasl
enables SASL (RFC2222), and
.Ar otp
enables OTP (RFC1938) authentication. Both disable plaintext passwords.
.It Fl Fl address-log= Ns Pa file
Logs the addresses (along with a timestamp) of all clients to the
specified file. This can be used to implement POP-before-SMTP
authentication.
.It Fl d
Enables more verbose log messages.
.It Fl i
When not started by inetd, this flag tells
.Nm
that it has to create a socket by itself.
.It Fl k
Tells
.Nm
to use Kerberos for authentication. This is the traditional way of
doing Kerberos authentication, and is normally done on a separate port
(as it doesn't follow RFC1939), and should be used instead of using
SASL.
.It Fl p Ar port
Port to listen to, in combination with
.Fl i .
.It Fl t Ar file
Trace all commands to file.
.It Fl T Ar seconds
Set timeout to something other than the default of 120 seconds.
.El
.\".Sh ENVIRONMENT
.\".Sh FILES
.\".Sh EXAMPLES
.\".Sh DIAGNOSTICS
.Sh SEE ALSO
.Xr push 8 ,
.Xr movemail 8
.Sh STANDARDS
RFC1939 (Post Office Protocol - Version 3)
.\" RFC2449 (POP3 Extension Mechanism)
.\".Sh HISTORY
.Sh AUTHORS
The server was initially developed at the University of California,
Berkeley.
.Pp
Many changes have been made as part of the KTH Kerberos distributions.
.\".Sh BUGS

View File

@@ -1,45 +0,0 @@
Release Notes:
popper-1.831beta is no longer beta 30 July 91
Removed popper-1.7.tar.Z
popper-1.831beta.tar.Z 03 April 91
Changed mkstemp to mktemp for Ultrix. Sigh.
popper-1.83beta.tar.Z 02 April 91
This version makes certain that while running as root we do nothing
at all destructive.
popper-1.82beta.tar.Z 27 March 91
This version fixes problems on Encore MultiMax and some Sun releases
which wouldn't allow a user to ftruncate() a file from an open
file descripter unless the user owns the file. Now the user
owns the /usr/spool/mail/.userid.pop file. Thanks to Ben Levy
of FTP Software and Henry Holtzman of Apple.
popper-1.81beta.tar.Z 20 March 91
This version of popper is supposed to fix three problems reported
with various versions of popper (all called 1.7 or 1.7something).
1) Dropped network connections meant lost mail files. Some 1.7
versions also risked corrupting mail files.
2) Some versions of 1.7 created temporary drop files with world
read and write permissions.
3) Some versions of 1.7 were not careful about opening the temporary
drop file.
popper-1.7.tar.Z 09 September 90 (updated 20 March 91)
This version will exhibit the first problem listed above if it is
compiled with -DDEBUG and run without the "-d" (debug) flag.
If it is compiled without -DDEBUG it will exhibit only the second
and third bug listed above.
Cliff Frost poptest@nettlesome.berkeley.edu
UC Berkeley

View File

@@ -1,120 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <popper.h>
RCSID("$Id$");
int hangup = FALSE ;
static RETSIGTYPE
catchSIGHUP(int sig)
{
hangup = TRUE ;
/* This should not be a problem on BSD systems */
signal(SIGHUP, catchSIGHUP);
signal(SIGPIPE, catchSIGHUP);
SIGRETURN(0);
}
int pop_timeout = POP_TIMEOUT;
jmp_buf env;
static RETSIGTYPE
ring(int sig)
{
longjmp(env,1);
}
/*
* fgets, but with a timeout
*/
static char *
tgets(char *str, int size, FILE *fp, int timeout)
{
char *ret;
signal(SIGALRM, ring);
alarm(timeout);
if (setjmp(env)) {
alarm(0);
signal(SIGALRM, SIG_DFL);
return NULL;
}
ret = fgets(str, size, fp);
alarm(0);
signal(SIGALRM, SIG_DFL);
return ret;
}
/*
* popper: Handle a Post Office Protocol version 3 session
*/
int
main (int argc, char **argv)
{
POP p;
state_table * s;
char message[MAXLINELEN];
signal(SIGHUP, catchSIGHUP);
signal(SIGPIPE, catchSIGHUP);
/* Start things rolling */
pop_init(&p,argc,argv);
/* Tell the user that we are listenting */
pop_msg(&p,POP_SUCCESS, "POP3 server ready");
/* State loop. The POP server is always in a particular state in
which a specific suite of commands can be executed. The following
loop reads a line from the client, gets the command, and processes
it in the current context (if allowed) or rejects it. This continues
until the client quits or an error occurs. */
for (p.CurrentState=auth1;p.CurrentState!=halt&&p.CurrentState!=error;) {
if (hangup) {
pop_msg(&p, POP_FAILURE, "POP hangup: %s", p.myhost);
if (p.CurrentState > auth2 && !pop_updt(&p))
pop_msg(&p, POP_FAILURE,
"POP mailbox update failed: %s", p.myhost);
p.CurrentState = error;
} else if (tgets(message, MAXLINELEN, p.input, pop_timeout) == NULL) {
pop_msg(&p, POP_FAILURE, "POP timeout: %s", p.myhost);
if (p.CurrentState > auth2 && !pop_updt(&p))
pop_msg(&p,POP_FAILURE,
"POP mailbox update failed: %s", p.myhost);
p.CurrentState = error;
}
else {
/* Search for the command in the command/state table */
if ((s = pop_get_command(&p,message)) == NULL) continue;
/* Call the function associated with this command in
the current state */
if (s->function) p.CurrentState = s->result[(*s->function)(&p)];
/* Otherwise assume NOOP and send an OK message to the client */
else {
p.CurrentState = s->success_state;
pop_msg(&p,POP_SUCCESS,"time passes");
}
}
}
/* Say goodbye to the client */
pop_msg(&p,POP_SUCCESS,"Pop server at %s signing off.",p.myhost);
/* Log the end of activity */
pop_log(&p,POP_PRIORITY,
"(v%s) Ending request from \"%s\" at %s\n",VERSION,p.client,p.ipaddr);
/* Stop logging */
closelog();
return(0);
}

View File

@@ -1,349 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
* static char SccsId[] = "@(#)@(#)popper.h 2.2 2.2 4/2/91";
*
*/
/* $Id$ */
/*
* Header file for the POP programs
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#define UIDL
#define XOVER
#define XDELE
#define DEBUG
#define RETURN_PATH_HANDLING
#endif
/* Common include files */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <ctype.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#elif defined(HAVE_SYS_TIME_H)
#include <sys/time.h>
#else
#include <time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET6_IN6_H
#include <netinet6/in6.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#ifdef _AIX
struct sockaddr_dl; /* AIX fun */
struct ether_addr;
#endif
#include <arpa/inet.h>
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include "version.h"
#ifdef SOCKS
#include <socks.h>
#endif
#include <err.h>
#include <roken.h>
#include <getarg.h>
#ifdef KRB5
#include <krb5.h>
#endif
#define MAXUSERNAMELEN 65
#define MAXLINELEN 1024
#define MAXMSGLINELEN 1024
#define MAXCMDLEN 4
#define MAXPARMCOUNT 10
#define MAXPARMLEN 10
#define ALLOC_MSGS 20
#define MAIL_COMMAND "/usr/lib/sendmail"
#define POP_FACILITY LOG_LOCAL0
#define POP_PRIORITY LOG_NOTICE
#define POP_DEBUG LOG_DEBUG
#define POP_INFO LOG_INFO
#define POP_LOGOPTS 0
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifdef HAVE_MAILLOCK_H
#include <maillock.h>
#endif
#ifdef OTP
#include <otp.h>
#endif
#if defined(_PATH_MAILDIR)
#define POP_MAILDIR _PATH_MAILDIR
#elif defined(MAILDIR)
#define POP_MAILDIR MAILDIR
#else
#define POP_MAILDIR "/usr/spool/mail"
#endif
#define POP_DROP POP_MAILDIR "/.%s.pop"
/* POP_TMPSIZE needs to be big enough to hold the string
* defined by POP_TMPDROP. POP_DROP and POP_TMPDROP
* must be in the same filesystem.
*/
#define POP_TMPDROP POP_MAILDIR "/tmpXXXXXX"
#define POP_TMPSIZE 256
#define POP_TMPXMIT "/tmp/xmitXXXXXX"
#define POP_OK "+OK"
#define POP_ERR "-ERR"
#define POP_SUCCESS 1
#define POP_FAILURE 0
#define POP_TERMINATE '.'
#define POP_TIMEOUT 120 /* timeout connection after this many secs */
extern int pop_timeout;
extern int hangup;
#define AUTH_NONE 0
#define AUTH_OTP 1
#define AUTH_SASL 2
#define pop_command pop_parm[0] /* POP command is first token */
#define pop_subcommand pop_parm[1] /* POP XTND subcommand is the
second token */
typedef enum { /* POP processing states */
auth1, /* Authorization: waiting for
USER command */
auth2, /* Authorization: waiting for
PASS command */
trans, /* Transaction */
update, /* Update: session ended,
process maildrop changes */
halt, /* (Halt): stop processing
and exit */
error /* (Error): something really
bad happened */
} state;
#define DEL_FLAG 1
#define RETR_FLAG 2
#define NEW_FLAG 4
typedef struct { /* Message information */
int number; /* Message number relative to
the beginning of list */
long length; /* Length of message in
bytes */
int lines; /* Number of (null-terminated) lines in the message */
long offset; /* Offset from beginning of
file */
unsigned flags;
#if defined(UIDL) || defined(XOVER)
char *msg_id; /* The POP UIDL uniqueifier */
#endif
#ifdef XOVER
char *subject;
char *from;
char *date;
#endif
char *name;
} MsgInfoList;
#define IS_MAILDIR(P) ((P)->temp_drop[0] == '\0')
typedef struct { /* POP parameter block */
int debug; /* Debugging requested */
char * myname; /* The name of this POP
daemon program */
char myhost[MaxHostNameLen]; /* The name of our host
computer */
char client[MaxHostNameLen]; /* Canonical name of client
computer */
char ipaddr[MaxHostNameLen]; /* Dotted-notation format of
client IP address */
unsigned short ipport; /* Client port for privileged
operations */
char user[MAXUSERNAMELEN]; /* Name of the POP user */
state CurrentState; /* The current POP operational state */
MsgInfoList * mlp; /* Message information list */
int msg_count; /* Number of messages in
the maildrop */
int msgs_deleted; /* Number of messages flagged
for deletion */
int last_msg; /* Last message touched by
the user */
long bytes_deleted; /* Number of maildrop bytes
flagged for deletion */
char drop_name[MAXPATHLEN]; /* The name of the user's
maildrop */
char temp_drop[MAXPATHLEN]; /* The name of the user's
temporary maildrop */
long drop_size; /* Size of the maildrop in
bytes */
FILE * drop; /* (Temporary) mail drop */
FILE * input; /* Input TCP/IP communication
stream */
FILE * output; /* Output TCP/IP communication stream */
FILE * trace; /* Debugging trace file */
char * pop_parm[MAXPARMCOUNT]; /* Parse POP parameter list */
int parm_count; /* Number of parameters in
parsed list */
int kerberosp; /* Using KPOP? */
#ifdef KRB5
krb5_context context;
krb5_principal principal; /* principal auth as */
krb5_log_facility* logf;
#endif
int version; /* 4 or 5? */
int auth_level; /* Dont allow cleartext */
#ifdef OTP
OtpContext otp_ctx; /* OTP context */
#endif
unsigned int flags;
#define POP_FLAG_CAPA 1
} POP;
typedef struct { /* State information for
each POP command */
state ValidCurrentState; /* The operating state of
the command */
char * command; /* The POP command */
int min_parms; /* Minimum number of parms
for the command */
int max_parms; /* Maximum number of parms
for the command */
int (*function) (); /* The function that process
the command */
state result[2]; /* The resulting state after
command processing */
#define success_state result[0] /* State when a command
succeeds */
} state_table;
typedef struct { /* Table of extensions */
char * subcommand; /* The POP XTND subcommand */
int min_parms; /* Minimum number of parms for
the subcommand */
int max_parms; /* Maximum number of parms for
the subcommand */
int (*function) (); /* The function that processes
the subcommand */
} xtnd_table;
int pop_dele(POP *p);
int pop_dropcopy(POP *p, struct passwd *pwp);
int pop_dropinfo(POP *p);
int pop_init(POP *p,int argcount,char **argmessage);
int pop_last(POP *p);
int pop_list(POP *p);
int pop_parse(POP *p, char *buf);
int pop_pass(POP *p);
int pop_quit(POP *p);
int pop_rset(POP *p);
int pop_send(POP *p);
int pop_stat(POP *p);
int pop_updt(POP *p);
int pop_user(POP *p);
#ifdef UIDL
int pop_uidl(POP *p);
#endif
#ifdef XOVER
int pop_xover(POP *p);
#endif
#ifdef XDELE
int pop_xdele(POP *p);
#endif
int pop_help(POP *p);
state_table *pop_get_command(POP *p, char *mp);
void pop_lower(char *buf);
#ifdef SASL
int pop_auth (POP *p);
void pop_capa_sasl(POP *p);
#endif
int pop_log(POP *p, int stat, char *format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 3, 4)))
#endif
;
int pop_msg(POP *p, int stat, const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 3, 4)))
#endif
;
int pop_maildir_info (POP*);
int pop_maildir_open (POP*, MsgInfoList*);
int pop_maildir_update (POP*);
int changeuser(POP*, struct passwd*);
void parse_header(MsgInfoList*, char*);
int add_missing_headers(POP*, MsgInfoList*);
int login_user(POP *p);

View File

@@ -1,19 +0,0 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
* static char SccsId[] = "@(#)@(#)version.h 2.6 2.6 4/3/91";
*
*/
/* $Id$ */
/*
* Current version of this POP implementation
*/
#if 0
#define VERSION krb4_version
#endif

View File

@@ -1,130 +0,0 @@
2008-04-17 Love Hörnquist Åstrand <lha@it.su.se>
* Sync with NetBSD rcp, add v6 parsing support and no setuid code
at all.
2007-12-13 Love Hörnquist Åstrand <lha@it.su.se>
* Makefile.am: Add missing files, from Buchan Milne.
2006-10-20 Love Hörnquist Åstrand <lha@it.su.se>
* Makefile.am: more files
2006-08-08 Love Hörnquist Åstrand <lha@it.su.se>
* util.c: Check return values from setuid, prompted by MIT
advisory. Thanks to Tom Yu at MIT, and Michael Calmer and Marcus
Meissner at SUSE. Either of CVE-2006-3083 or CVE-2006-3084.
* rcp.c: Check return values from setuid, prompted by MIT
advisory. Thanks to Tom Yu at MIT, and Michael Calmer and Marcus
Meissner at SUSE. Either of CVE-2006-3083 or CVE-2006-3084.
* rcp.c: Check return values from seteuid, prompted by MIT
advisory. Thanks to Tom Yu at MIT, and Michael Calmer and Marcus
Meissner at SUSE. Either of CVE-2006-3083 or CVE-2006-3084.
2005-10-22 Love Hörnquist Åstrand <lha@it.su.se>
* rcp.c: Check return value from asprintf instead of string !=
NULL since it undefined behavior on Linux. From Björn Sandell
2005-08-30 Love Hörnquist Åstrand <lha@it.su.se>
* util.c: Explicit typecast to avoid signess warning.
2005-05-29 Love Hörnquist Åstrand <lha@it.su.se>
* rcp_locl.h: undef _PATH_RSH to make sure our version is used
2005-05-11 David Love <fx@gnu.org>
* rcp.c: MODEMASK is defined in sys/vnode.h on Solaris, so undef
it before we define our own.
2005-04-27 Love Hörnquist Åstrand <lha@it.su.se>
* rcp_locl.h: use BINDIR instead of "/usr/bin/ with _PATH_RSH
2005-04-18 Love Hörnquist Åstrand <lha@it.su.se>
* util.c: use unsigned char * to make sure its not negative when
passing it to is* functions
2004-05-14 Johan Danielsson <joda@pdc.kth.se>
* rcp.c: add -e (passed to rsh)
2003-04-16 Johan Danielsson <joda@pdc.kth.se>
* rcp.1: add a HISTORY section
* rcp.1: brief manpage
* rcp.c: add a -4 option
2001-09-24 Johan Danielsson <joda@pdc.kth.se>
* rcp.c: more va_* fixing; from Thomas Klausner
2001-09-08 Assar Westerlund <assar@sics.se>
* rcp.c (run_err): always match va_start and va_end
2001-09-04 Assar Westerlund <assar@sics.se>
* util.c (allocbuf): do not leak memory on failure and zero
re-used memory, from Markus Friedl <markus@openbsd.org>
2001-07-19 Assar Westerlund <assar@sics.se>
* rcp.c (main): add missing setprogname
2001-06-14 Assar Westerlund <assar@sics.se>
* rcp.c: add some const replace a few malloc/snprintf with
asprintf
* rcp.c (sizestr): remove and use snprintf to do this correctly
instead
2001-04-21 Johan Danielsson <joda@pdc.kth.se>
* rcp.c: convert to use getarg
* rcp.c: do a better job of supporting files larger than 2GB
2001-02-07 Assar Westerlund <assar@sics.se>
* rcp.c: add -F for forwarding ticket, from Ake Sandgren
<ake@cs.umu.se>
2001-01-29 Assar Westerlund <assar@sics.se>
* util.c (roundup): add fallback definition
* rcp.c: remove non-STDC code
* rcp_locl.h: add sys/types.h and sys/wait.h
* rcp.c: no calls to err with NULL
2001-01-28 Assar Westerlund <assar@sics.se>
* rcp_locl.h: add
* Makefile.am (LDADD): remove unused libraries
2001-01-27 Assar Westerlund <assar@sics.se>
* util.c: replace vfork by fork
* rcp.c: add RCSID S_ISTXT -> S_ISVTX printf sizes of files with
%lu instead of %q (which is not portable)
* util.c: add RCSID do not use sig_t
* rcp.c: remove __P, use st_mtime et al from struct stat
* extern.h: remove __P
* initial import of port of bsd rcp changed to use existing rsh,
contributed by Richard Nyberg <rnyberg@it.su.se>

View File

@@ -1,15 +0,0 @@
# $Id$
include $(top_srcdir)/Makefile.am.common
WFLAGS += $(WFLAGS_LITE)
bin_PROGRAMS = rcp
rcp_SOURCES = rcp.c util.c rcp_locl.h extern.h
man_MANS = rcp.1
EXTRA_DIST = NTMakefile $(man_MANS)
LDADD = $(LIB_roken)

View File

@@ -1,35 +0,0 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT HOLDER 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.
#
RELDIR=appl\rcp
!include ../../windows/NTMakefile.w32

View File

@@ -1,52 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
* $FreeBSD: src/bin/rcp/extern.h,v 1.5 1999/08/27 23:14:57 peter Exp $
*/
typedef struct {
int cnt;
char *buf;
} BUF;
extern int iamremote;
BUF *allocbuf (BUF *, int, int);
char *colon (char *);
char *unbracket(char *);
void lostconn (int);
void nospace (void);
int okname (char *);
void run_err (const char *, ...);
int susystem (char *);
void verifydir (char *);

View File

@@ -1,66 +0,0 @@
.\" $Id$
.\"
.Dd April 16, 2003
.Dt RCP 1
.Os HEIMDAL
.Sh NAME
.Nm rcp
.Nd copy file to and from remote machines
.Sh SYNOPSIS
.Nm rcp
.Op Fl 45FKpxz
.Op Fl P Ar port
.Ar file1 file2
.Nm rcp
.Op Fl 45FKprxz
.Op Fl P Ar port
.Ar file... directory
.Sh DESCRIPTION
.Nm rcp
copies files between machines. Each file argument is either a remote file name of the form
.Dq rname@rhost:path
or a local file (containing no colon or with a slash before the first
colon).
.Pp
Supported options:
.Bl -tag -width Ds
.It Xo
.Fl 4 ,
.Fl 5 ,
.Fl K ,
.Fl F ,
.Fl x ,
.Fl z
.Xc
These options are passed on to
.Xr rsh 1 .
.It Fl P Ar port
This will pass the option
.Fl p Ar port
to
.Xr rsh 1 .
.It Fl p
Preserve file permissions.
.It Fl r
Copy source directories recursively.
.El
.\".Sh ENVIRONMENT
.\".Sh FILES
.\".Sh EXAMPLES
.Sh DIAGNOSTICS
.Nm rcp
is implemented as a protocol on top of
.Xr rsh 1 ,
and thus requires a working rsh. If you intend to use Kerberos
authentication, rsh needs to be Kerberos aware, else you may see more
or less strange errors, such as "login incorrect", or "lost
connection".
.\".Sh SEE ALSO
.\".Sh STANDARDS
.Sh HISTORY
The
.Nm rcp
utility first appeared in 4.2BSD. This version is derived from
4.3BSD-Reno.
.\".Sh AUTHORS
.\".Sh BUGS

View File

@@ -1,791 +0,0 @@
/*
* Copyright (c) 1983, 1990, 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. 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 "rcp_locl.h"
#include <getarg.h>
#define RSH_PROGRAM "rsh"
struct passwd *pwd;
uid_t userid;
int errs, remin, remout;
int pflag, iamremote, iamrecursive, targetshouldbedirectory;
int doencrypt, noencrypt;
int usebroken, usekrb4, usekrb5, forwardtkt;
char *port;
int eflag = 0;
#define CMDNEEDS 64
char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
int response (void);
void rsource (char *, struct stat *);
void sink (int, char *[]);
void source (int, char *[]);
void tolocal (int, char *[]);
void toremote (char *, int, char *[]);
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
static int fflag, tflag;
static int version_flag, help_flag;
struct getargs args[] = {
{ NULL, '4', arg_flag, &usekrb4, "use Kerberos 4 authentication", NULL },
{ NULL, '5', arg_flag, &usekrb5, "use Kerberos 5 authentication", NULL },
{ NULL, 'F', arg_flag, &forwardtkt, "forward credentials", NULL },
{ NULL, 'K', arg_flag, &usebroken, "use BSD authentication",
NULL },
{ NULL, 'P', arg_string, &port, "non-default port", "port" },
{ NULL, 'p', arg_flag, &pflag, "preserve file permissions",
NULL },
{ NULL, 'r', arg_flag, &iamrecursive, "recursive mode", NULL },
{ NULL, 'x', arg_flag, &doencrypt, "use encryption", NULL },
{ NULL, 'z', arg_flag, &noencrypt, "don't encrypt", NULL },
{ NULL, 'd', arg_flag, &targetshouldbedirectory, NULL, NULL },
{ NULL, 'e', arg_flag, &eflag, "passed to rsh", NULL },
{ NULL, 'f', arg_flag, &fflag, NULL, NULL },
{ NULL, 't', arg_flag, &tflag, NULL, NULL },
{ "version", 0, arg_flag, &version_flag, NULL, NULL },
{ "help", 0, arg_flag, &help_flag, NULL, NULL }
};
static void
usage (int ret)
{
arg_printusage (args,
sizeof(args) / sizeof(args[0]),
NULL,
"file1 file2|file... directory");
exit (ret);
}
int
main(int argc, char **argv)
{
char *targ;
int optind = 0;
setprogname(argv[0]);
if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
&optind))
usage (1);
if(help_flag)
usage(0);
if (version_flag) {
print_version (NULL);
return 0;
}
iamremote = (fflag || tflag);
argc -= optind;
argv += optind;
if ((pwd = getpwuid(userid = getuid())) == NULL)
errx(1, "unknown user %d", (int)userid);
remin = STDIN_FILENO; /* XXX */
remout = STDOUT_FILENO;
if (fflag) { /* Follow "protocol", send data. */
(void)response();
source(argc, argv);
exit(errs);
}
if (tflag) { /* Receive data. */
sink(argc, argv);
exit(errs);
}
if (argc < 2)
usage(1);
if (argc > 2)
targetshouldbedirectory = 1;
remin = remout = -1;
/* Command to be executed on remote system using "rsh". */
snprintf(cmd, sizeof(cmd),
"rcp%s%s%s", iamrecursive ? " -r" : "",
pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
signal(SIGPIPE, lostconn);
if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
toremote(targ, argc, argv);
else {
tolocal(argc, argv); /* Dest is local host. */
if (targetshouldbedirectory)
verifydir(argv[argc - 1]);
}
exit(errs);
}
void
toremote(char *targ, int argc, char **argv)
{
int i;
char *bp, *host, *src, *suser, *thost, *tuser;
*targ++ = 0;
if (*targ == 0)
targ = ".";
if ((thost = strchr(argv[argc - 1], '@')) != NULL) {
/* user@host */
*thost++ = 0;
tuser = argv[argc - 1];
if (*tuser == '\0')
tuser = NULL;
else if (!okname(tuser))
exit(1);
} else {
thost = argv[argc - 1];
tuser = NULL;
}
thost = unbracket(thost);
for (i = 0; i < argc - 1; i++) {
src = colon(argv[i]);
if (src) { /* remote to remote */
int ret;
*src++ = 0;
if (*src == 0)
src = ".";
host = strchr(argv[i], '@');
if (host) {
*host++ = '\0';
host = unbracket(host);
suser = argv[i];
if (*suser == '\0')
suser = pwd->pw_name;
else if (!okname(suser))
continue;
ret = asprintf(&bp,
"%s%s %s -l %s -n %s %s '%s%s%s:%s'",
_PATH_RSH, eflag ? " -e" : "",
host, suser, cmd, src,
tuser ? tuser : "", tuser ? "@" : "",
thost, targ);
} else {
host = unbracket(argv[i]);
ret = asprintf(&bp,
"exec %s%s %s -n %s %s '%s%s%s:%s'",
_PATH_RSH, eflag ? " -e" : "",
host, cmd, src,
tuser ? tuser : "", tuser ? "@" : "",
thost, targ);
}
if (ret == -1)
err (1, "malloc");
susystem(bp);
free(bp);
} else { /* local to remote */
if (remin == -1) {
if (asprintf(&bp, "%s -t %s", cmd, targ) == -1)
err (1, "malloc");
host = thost;
if (do_cmd(host, tuser, bp, &remin, &remout) < 0)
exit(1);
if (response() < 0)
exit(1);
free(bp);
}
source(1, argv+i);
}
}
}
void
tolocal(int argc, char **argv)
{
int i;
char *bp, *host, *src, *suser;
for (i = 0; i < argc - 1; i++) {
int ret;
if (!(src = colon(argv[i]))) { /* Local to local. */
ret = asprintf(&bp, "exec %s%s%s %s %s", _PATH_CP,
iamrecursive ? " -PR" : "", pflag ? " -p" : "",
argv[i], argv[argc - 1]);
if (ret == -1)
err (1, "malloc");
if (susystem(bp))
++errs;
free(bp);
continue;
}
*src++ = 0;
if (*src == 0)
src = ".";
if ((host = strchr(argv[i], '@')) == NULL) {
host = argv[i];
suser = pwd->pw_name;
} else {
*host++ = 0;
suser = argv[i];
if (*suser == '\0')
suser = pwd->pw_name;
else if (!okname(suser))
continue;
}
ret = asprintf(&bp, "%s -f %s", cmd, src);
if (ret == -1)
err (1, "malloc");
if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
free(bp);
++errs;
continue;
}
free(bp);
sink(1, argv + argc - 1);
close(remin);
remin = remout = -1;
}
}
void
source(int argc, char **argv)
{
struct stat stb;
static BUF buffer;
BUF *bp;
off_t i;
off_t amt;
int fd, haderr, indx, result;
char *last, *name, buf[BUFSIZ];
for (indx = 0; indx < argc; ++indx) {
name = argv[indx];
if ((fd = open(name, O_RDONLY, 0)) < 0)
goto syserr;
if (fstat(fd, &stb)) {
syserr: run_err("%s: %s", name, strerror(errno));
goto next;
}
if (S_ISDIR(stb.st_mode) && iamrecursive) {
rsource(name, &stb);
goto next;
} else if (!S_ISREG(stb.st_mode)) {
run_err("%s: not a regular file", name);
goto next;
}
if ((last = strrchr(name, '/')) == NULL)
last = name;
else
++last;
if (pflag) {
/*
* Make it compatible with possible future
* versions expecting microseconds.
*/
snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
(long)stb.st_mtime,
(long)stb.st_atime);
write(remout, buf, strlen(buf));
if (response() < 0)
goto next;
}
#undef MODEMASK
#define MODEMASK (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
snprintf(buf, sizeof(buf), "C%04o %lu %s\n",
(unsigned int)(stb.st_mode & MODEMASK),
(unsigned long)stb.st_size,
last);
write(remout, buf, strlen(buf));
if (response() < 0)
goto next;
if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) {
next: close(fd);
continue;
}
/* Keep writing after an error so that we stay sync'd up. */
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
amt = bp->cnt;
if (i + amt > stb.st_size)
amt = stb.st_size - i;
if (!haderr) {
result = read(fd, bp->buf, (size_t)amt);
if (result != amt)
haderr = result >= 0 ? EIO : errno;
}
if (haderr)
write(remout, bp->buf, amt);
else {
result = write(remout, bp->buf, (size_t)amt);
if (result != amt)
haderr = result >= 0 ? EIO : errno;
}
}
if (close(fd) && !haderr)
haderr = errno;
if (!haderr)
write(remout, "", 1);
else
run_err("%s: %s", name, strerror(haderr));
response();
}
}
void
rsource(char *name, struct stat *statp)
{
DIR *dirp;
struct dirent *dp;
char *last, *vect[1], path[MAXPATHLEN];
if (!(dirp = opendir(name))) {
run_err("%s: %s", name, strerror(errno));
return;
}
last = strrchr(name, '/');
if (last == 0)
last = name;
else
last++;
if (pflag) {
snprintf(path, sizeof(path), "T%ld 0 %ld 0\n",
(long)statp->st_mtime,
(long)statp->st_atime);
write(remout, path, strlen(path));
if (response() < 0) {
closedir(dirp);
return;
}
}
snprintf(path, sizeof(path),
"D%04o %d %s\n",
(unsigned int)(statp->st_mode & MODEMASK), 0, last);
write(remout, path, strlen(path));
if (response() < 0) {
closedir(dirp);
return;
}
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_ino == 0)
continue;
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
run_err("%s/%s: name too long", name, dp->d_name);
continue;
}
snprintf(path, sizeof(path), "%s/%s", name, dp->d_name);
vect[0] = path;
source(1, vect);
}
closedir(dirp);
write(remout, "E\n", 2);
response();
}
void
sink(int argc, char **argv)
{
static BUF buffer;
struct stat stb;
struct timeval tv[2];
enum { YES, NO, DISPLAYED } wrerr;
BUF *bp;
off_t i, j, size;
int amt, count, exists, first, mask, mode, ofd, omode;
int setimes, targisdir, wrerrno = 0;
char ch, *cp, *np, *targ, *why, *vect[1], buf[BUFSIZ];
#define atime tv[0]
#define mtime tv[1]
#define SCREWUP(str) { why = str; goto screwup; }
setimes = targisdir = 0;
mask = umask(0);
if (!pflag)
umask(mask);
if (argc != 1) {
run_err("ambiguous target");
exit(1);
}
targ = *argv;
if (targetshouldbedirectory)
verifydir(targ);
write(remout, "", 1);
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
targisdir = 1;
for (first = 1;; first = 0) {
cp = buf;
if (read(remin, cp, 1) <= 0)
return;
if (*cp++ == '\n')
SCREWUP("unexpected <newline>");
do {
if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
SCREWUP("lost connection");
*cp++ = ch;
} while (cp < &buf[BUFSIZ - 1] && ch != '\n');
*cp = 0;
if (buf[0] == '\01' || buf[0] == '\02') {
if (iamremote == 0)
write(STDERR_FILENO,
buf + 1, strlen(buf + 1));
if (buf[0] == '\02')
exit(1);
++errs;
continue;
}
if (buf[0] == 'E') {
write(remout, "", 1);
return;
}
if (ch == '\n')
*--cp = 0;
cp = buf;
if (*cp == 'T') {
setimes++;
cp++;
mtime.tv_sec = strtol(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("mtime.sec not delimited");
mtime.tv_usec = strtol(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("mtime.usec not delimited");
atime.tv_sec = strtol(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("atime.sec not delimited");
atime.tv_usec = strtol(cp, &cp, 10);
if (!cp || *cp++ != '\0')
SCREWUP("atime.usec not delimited");
write(remout, "", 1);
continue;
}
if (*cp != 'C' && *cp != 'D') {
/*
* Check for the case "rcp remote:foo\* local:bar".
* In this case, the line "No match." can be returned
* by the shell before the rcp command on the remote is
* executed so the ^Aerror_message convention isn't
* followed.
*/
if (first) {
run_err("%s", cp);
exit(1);
}
SCREWUP("expected control record");
}
mode = 0;
for (++cp; cp < buf + 5; cp++) {
if (*cp < '0' || *cp > '7')
SCREWUP("bad mode");
mode = (mode << 3) | (*cp - '0');
}
if (*cp++ != ' ')
SCREWUP("mode not delimited");
for (size = 0; isdigit((unsigned char)*cp);)
size = size * 10 + (*cp++ - '0');
if (*cp++ != ' ')
SCREWUP("size not delimited");
if (targisdir) {
static char *namebuf;
static int cursize;
size_t need;
need = strlen(targ) + strlen(cp) + 250;
if (need > cursize) {
if (!(namebuf = malloc(need)))
run_err("%s", strerror(errno));
}
snprintf(namebuf, need, "%s%s%s", targ,
*targ ? "/" : "", cp);
np = namebuf;
} else
np = targ;
exists = stat(np, &stb) == 0;
if (buf[0] == 'D') {
int mod_flag = pflag;
if (exists) {
if (!S_ISDIR(stb.st_mode)) {
errno = ENOTDIR;
goto bad;
}
if (pflag)
chmod(np, mode);
} else {
/* Handle copying from a read-only directory */
mod_flag = 1;
if (mkdir(np, mode | S_IRWXU) < 0)
goto bad;
}
vect[0] = np;
sink(1, vect);
if (setimes) {
setimes = 0;
if (utimes(np, tv) < 0)
run_err("%s: set times: %s",
np, strerror(errno));
}
if (mod_flag)
chmod(np, mode);
continue;
}
omode = mode;
mode |= S_IWRITE;
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
bad: run_err("%s: %s", np, strerror(errno));
continue;
}
write(remout, "", 1);
if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) {
close(ofd);
continue;
}
cp = bp->buf;
wrerr = NO;
for (count = i = 0; i < size; i += BUFSIZ) {
amt = BUFSIZ;
if (i + amt > size)
amt = size - i;
count += amt;
if((j = net_read(remin, cp, amt)) != amt) {
run_err("%s", j ? strerror(errno) :
"dropped connection");
exit(1);
}
amt -= j;
cp += j;
if (count == bp->cnt) {
/* Keep reading so we stay sync'd up. */
if (wrerr == NO) {
j = write(ofd, bp->buf, (size_t)count);
if (j != count) {
wrerr = YES;
wrerrno = j >= 0 ? EIO : errno;
}
}
count = 0;
cp = bp->buf;
}
}
if (count != 0 && wrerr == NO &&
(j = write(ofd, bp->buf, (size_t)count)) != count) {
wrerr = YES;
wrerrno = j >= 0 ? EIO : errno;
}
if (ftruncate(ofd, size)) {
run_err("%s: truncate: %s", np, strerror(errno));
wrerr = DISPLAYED;
}
if (pflag) {
if (exists || omode != mode)
if (fchmod(ofd, omode))
run_err("%s: set mode: %s",
np, strerror(errno));
} else {
if (!exists && omode != mode)
if (fchmod(ofd, omode & ~mask))
run_err("%s: set mode: %s",
np, strerror(errno));
}
close(ofd);
response();
if (setimes && wrerr == NO) {
setimes = 0;
if (utimes(np, tv) < 0) {
run_err("%s: set times: %s",
np, strerror(errno));
wrerr = DISPLAYED;
}
}
switch(wrerr) {
case YES:
run_err("%s: %s", np, strerror(wrerrno));
break;
case NO:
write(remout, "", 1);
break;
case DISPLAYED:
break;
}
}
screwup:
run_err("protocol error: %s", why);
exit(1);
}
int
response(void)
{
char ch, *cp, resp, rbuf[BUFSIZ];
if (read(remin, &resp, sizeof(resp)) != sizeof(resp))
lostconn(0);
cp = rbuf;
switch(resp) {
case 0: /* ok */
return (0);
default:
*cp++ = resp;
/* FALLTHROUGH */
case 1: /* error, followed by error msg */
case 2: /* fatal error, "" */
do {
if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
lostconn(0);
*cp++ = ch;
} while (cp < &rbuf[BUFSIZ] && ch != '\n');
if (!iamremote)
write(STDERR_FILENO, rbuf, cp - rbuf);
++errs;
if (resp == 1)
return (-1);
exit(1);
}
/* NOTREACHED */
}
#include <stdarg.h>
void
run_err(const char *fmt, ...)
{
static FILE *fp;
va_list ap;
++errs;
if (fp == NULL && !(fp = fdopen(remout, "w")))
return;
va_start(ap, fmt);
fprintf(fp, "%c", 0x01);
fprintf(fp, "rcp: ");
vfprintf(fp, fmt, ap);
fprintf(fp, "\n");
fflush(fp);
va_end(ap);
if (!iamremote) {
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
}
/*
* This function executes the given command as the specified user on the
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
* assigns the input and output file descriptors on success.
*
* If it cannot create necessary pipes it exits with error message.
*/
int
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
{
int pin[2], pout[2], reserved[2];
/*
* Reserve two descriptors so that the real pipes won't get
* descriptors 0 and 1 because that will screw up dup2 below.
*/
pipe(reserved);
/* Create a socket pair for communicating with rsh. */
if (pipe(pin) < 0) {
perror("pipe");
exit(255);
}
if (pipe(pout) < 0) {
perror("pipe");
exit(255);
}
/* Free the reserved descriptors. */
close(reserved[0]);
close(reserved[1]);
/* For a child to execute the command on the remote host using rsh. */
if (fork() == 0) {
char *args[100];
unsigned int i;
/* Child. */
close(pin[1]);
close(pout[0]);
dup2(pin[0], 0);
dup2(pout[1], 1);
close(pin[0]);
close(pout[1]);
i = 0;
args[i++] = RSH_PROGRAM;
if (usekrb4)
args[i++] = "-4";
if (usekrb5)
args[i++] = "-5";
if (usebroken)
args[i++] = "-K";
if (doencrypt)
args[i++] = "-x";
if (forwardtkt)
args[i++] = "-F";
if (noencrypt)
args[i++] = "-z";
if (port != NULL) {
args[i++] = "-p";
args[i++] = port;
}
if (eflag)
args[i++] = "-e";
if (remuser != NULL) {
args[i++] = "-l";
args[i++] = remuser;
}
args[i++] = host;
args[i++] = cmd;
args[i++] = NULL;
execvp(RSH_PROGRAM, args);
perror(RSH_PROGRAM);
exit(1);
}
/* Parent. Close the other side, and return the local side. */
close(pin[0]);
*fdout = pin[1];
close(pout[1]);
*fdin = pout[0];
return 0;
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <unistd.h>
#include <roken.h>
#include "extern.h"
#ifndef _PATH_CP
#define _PATH_CP "/bin/cp"
#endif
#undef _PATH_RSH
#define _PATH_RSH BINDIR "/rsh"

View File

@@ -1,184 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
#if 0
static char sccsid[] = "@(#)util.c 8.2 (Berkeley) 4/2/94";
#endif
static const char rcsid[] =
"$FreeBSD: src/bin/rcp/util.c,v 1.9 1999/08/27 23:14:58 peter Exp $";
#endif /* not lint */
#endif
#include "rcp_locl.h"
RCSID("$Id$");
char *
colon(cp)
char *cp;
{
if (*cp == ':') /* Leading colon is part of file name. */
return (0);
for (; *cp; ++cp) {
if (*cp == ':')
return (cp);
if (*cp == '/')
return (0);
}
return (0);
}
char *
unbracket(char *cp)
{
char *ep;
if (*cp == '[') {
ep = cp + (strlen(cp) - 1);
if (*ep == ']') {
*ep = '\0';
++cp;
}
}
return (cp);
}
void
verifydir(cp)
char *cp;
{
struct stat stb;
if (!stat(cp, &stb)) {
if (S_ISDIR(stb.st_mode))
return;
errno = ENOTDIR;
}
run_err("%s: %s", cp, strerror(errno));
exit(1);
}
int
okname(cp0)
char *cp0;
{
int c;
unsigned char *cp;
cp = (unsigned char *)cp0;
do {
c = *cp;
if (c & 0200)
goto bad;
if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
goto bad;
} while (*++cp);
return (1);
bad: warnx("%s: invalid user name", cp0);
return (0);
}
int
susystem(s)
char *s;
{
void (*istat)(int), (*qstat)(int);
int status;
pid_t pid;
pid = fork();
switch (pid) {
case -1:
return (127);
case 0:
execl(_PATH_BSHELL, "sh", "-c", s, NULL);
_exit(127);
}
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
if (waitpid(pid, &status, 0) < 0)
status = -1;
(void)signal(SIGINT, istat);
(void)signal(SIGQUIT, qstat);
return (status);
}
#ifndef roundup
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#endif
BUF *
allocbuf(bp, fd, blksize)
BUF *bp;
int fd, blksize;
{
struct stat stb;
size_t size;
char *p;
if (fstat(fd, &stb) < 0) {
run_err("fstat: %s", strerror(errno));
return (0);
}
size = roundup(stb.st_blksize, blksize);
if (size == 0)
size = blksize;
if (bp->cnt >= size)
return (bp);
if ((p = realloc(bp->buf, size)) == NULL) {
if (bp->buf)
free(bp->buf);
bp->buf = NULL;
bp->cnt = 0;
run_err("%s", strerror(errno));
return (0);
}
memset(p, 0, size);
bp->buf = p;
bp->cnt = size;
return (bp);
}
void
lostconn(signo)
int signo;
{
if (!iamremote)
warnx("lost connection");
exit(1);
}

View File

@@ -1,549 +0,0 @@
2007-07-12 Love Hörnquist Åstrand <lha@it.su.se>
* rsh.c: Fix pointer vs strict alias rules.
* rshd.c: Fix pointer vs strict alias rules.
2007-01-04 Love Hörnquist Åstrand <lha@it.su.se>
* rshd.c: Declare iruserok if needed, based on bug report from
David Love.
2006-11-14 Love Hörnquist Åstrand <lha@it.su.se>
* rsh_locl.h: Forward decl.
2006-10-14 Love Hörnquist Åstrand <lha@it.su.se>
* rsh_locl.h: Include "crypto-headers.h".
2006-10-07 Love Hörnquist Åstrand <lha@it.su.se>
* Makefile.am: Add man_MANS to EXTRA_DIST
2006-04-27 Love Hörnquist Åstrand <lha@it.su.se>
* Makefile.am: rshd_SOURCES += add limits_conf.c
* rsh_locl.h: Include "loginpaths.h"
* rshd.c: Read limits from limits.confon non-root login, patch
from Daniel Ahlin
2006-02-27 Johan Danielsson <joda@pdc.kth.se>
* rshd.8: grammar (from Thomas Klausner)
2006-01-31 Johan Danielsson <joda@pdc.kth.se>
* rshd.c (krb5_start_session): syslog failures to store cred cache
2005-12-21 Love Hörnquist Åstrand <lha@it.su.se>
* rshd.c (doit): move creation of users ticket file to later to
avoid seteuid/setuid dance. this breaks DCE, so remove support for
it completely.
2005-10-22 Love Hörnquist Åstrand <lha@it.su.se>
* rshd.c: Check return value from asprintf instead of string !=
NULL since it undefined behavior on Linux. From Björn Sandell
* rsh.c: Check return value from asprintf instead of string !=
NULL since it undefined behavior on Linux. From Björn Sandell
2005-06-08 Love Hörnquist Åstrand <lha@it.su.se>
* rshd.c: init some important variables and check that they are
set checking authentication, all to please gcc
2005-05-27 Love Hörnquist Åstrand <lha@it.su.se>
* rshd.c: case uid_t to unsigned long in printf format
2005-04-27 Love Hörnquist Åstrand <lha@it.su.se>
* rsh_locl.h: Use larger buffer for recving data to be compatible
with older versions of heimdal (0.4 branch specificly)
* rshd.c: Use larger buffer for recving data to be compatible with
older versions of heimdal (0.4 branch specificly)
2005-04-25 Love Hörnquist Åstrand <lha@it.su.se>
* rshd.c: use snprintf to format tkfile
2005-04-24 Love Hörnquist Åstrand <lha@it.su.se>
* rsh.c: use strlcat
* rsh.c: use strlcpy
* rsh_locl.h: forward declaration for private structures
2005-04-20 Love Hörnquist Åstrand <lha@it.su.se>
* rsh.c: cast size_t to unsigned long
2004-09-21 Johan Danielsson <joda@pdc.kth.se>
* rshd.c: rename loop to rshd_loop
* rshd.c: pass errsock status to init_ivecs
* rsh.c: rename loop() to rsh_loop()
* rsh.c (loop): pass errsock status to init_ivecs
* common.c (init_ivecs): if we don't have an errsock the ivecs
should point to the same data
* rshd.c: if we don't have an errsock, dup stdout to stderr (this
would normally be done by inetd, but not by mini_inetd).
* rshd.c: move keepalive setting to after setting up sockets
2004-02-20 Johan Danielsson <joda@pdc.kth.se>
* rsh.1: reorder and document some options
* rsh_locl.h: include kafs.h if krb4 || krb5
* rsh.c: reorder some options
2003-09-04 Johan Danielsson <joda@pdc.kth.se>
* rsh.1: document -d
2003-08-19 Johan Danielsson <joda@pdc.kth.se>
* rshd.c: -P also with KRB5
2003-04-22 Love Hörnquist Åstrand <lha@it.su.se>
* rsh.1: replace > with \*[Gt]
2003-04-16 Johan Danielsson <joda@pdc.kth.se>
* rsh.c: use krb5_appdefault to get defaults for forward and
encrypt
* rshd.c: use ARG_MAX + 1
* rshd.c (read_str): return allocated string
* rsh_locl.h: set NCARGS to 8k if undefined
2003-03-23 Assar Westerlund <assar@kth.se>
* rsh.c (loop): only check errsock if it's valid
2003-03-18 Love Love Hörnquist Åstrand <lha@it.su.se>
* rshd.c: do krb5_afslog when compling with afs support
* rsh_locl.h: always include kafs.h
2002-11-22 Johan Danielsson <joda@pdc.kth.se>
* rshd.8: clarify -x and kerberos 5
2002-11-01 Johan Danielsson <joda@pdc.kth.se>
* rsh_locl.h: bump COMMAND_SZ to NCARGS+1
2002-09-04 Johan Danielsson <joda@pdc.kth.se>
* rsh.c: free some memory
2002-09-04 Assar Westerlund <assar@kth.se>
* common.c: krb5_crypto_block_size -> krb5_crypto_getblocksize
2002-09-04 Johan Danielsson <joda@pdc.kth.se>
* rsh.1: document -P
2002-09-03 Johan Danielsson <joda@pdc.kth.se>
* rsh.c: revert to protocol v1 if not asked for specific protocol
* rshd.c: handle protocol version 2
* rsh.c: handle protocol version 2
* common.c: handle protocol version 2
* rsh_locl.h: handle protocol version 2
2002-02-18 Johan Danielsson <joda@pdc.kth.se>
* rshd.c: don't show options that doesn't apply
* rsh.c: don't show options that doesn't apply
* rsh_locl.h: if we're not building with any kerberos support,
just call read/write directly
* common.c: if we're not building with any kerberos support, just
call read/write directly
* rshd.c: make this build without krb5; also use the addrinfo
interface to mini_inetd, and set the keepalive option if requested
* rsh.c: make this build without krb5
* rsh_locl.h: make this build without krb5
* common.c: make this build without krb5
2001-11-30 Johan Danielsson <joda@pdc.kth.se>
* rshd.c: make the syslog messages somewhat more informative
2001-08-15 Johan Danielsson <joda@pdc.kth.se>
* rsh.c: only complain about encryption flag when old
authentication is requested
2001-08-07 Johan Danielsson <joda@pdc.kth.se>
* rsh.c: don't try broken auth if rresvport failed; try to give
some more informative error messages
2001-07-31 Johan Danielsson <joda@pdc.kth.se>
* rshd.8: add an EXAMPLE
* rshd.8: manual page
* rshd.c: add some compat flags
* rsh.1: manual page
* rsh.c: iff -d, set the SO_DEBUG flags of the stdout and stderr
socket; implement parsing user@host
2001-07-19 Assar Westerlund <assar@sics.se>
* rshd.c (fatal): use vsnprintf correctly
2001-02-07 Assar Westerlund <assar@sics.se>
* Makefile.am: add login_access
* rshd.c (login_access): add prototype
(syslog_and_die, fatal): add printf attributes
(*): AIX -> _AIX
(doit): use login_access
based on patches from Ake Sandgren <ake@cs.umu.se>
2001-01-09 Assar Westerlund <assar@sics.se>
* rshd.c (save_krb5_creds): use krb5_rd_cred2 instead of
krb5_rd_cred
2000-12-31 Assar Westerlund <assar@sics.se>
* rshd.c (main): handle krb5_init_context failure consistently
* rsh.c (main): handle krb5_init_context failure consistently
2000-12-05 Johan Danielsson <joda@pdc.kth.se>
* rshd.c: require encryption if passed -x
2000-11-15 Assar Westerlund <assar@sics.se>
* rshd.c (loop): check that the fd's aren't too large to select on
* rsh.c (loop, proto): check that the fd's aren't too large to
select on
2000-08-10 Assar Westerlund <assar@sics.se>
* rsh.c: move code to do config/command parsing correctly.
2000-08-09 Assar Westerlund <assar@sics.se>
* rsh.c (main): only fetch stuff from krb5.conf when no option has
been given
2000-08-01 Assar Westerlund <assar@sics.se>
* rsh.c (doit): loop until we create an error socket of an
supported socket family
2000-07-02 Assar Westerlund <assar@sics.se>
* rshd.c: DCE stuff from Ake Sandgren <ake@cs.umu.se>
do not call syslog with a variable as format string
* rsh_locl.h (_PATH_ETC_ENVIRONMENT): add
2000-06-09 Assar Westerlund <assar@sics.se>
* rsh.c (main): work-around for setuid and capabilities bug fixed
in Linux 2.2.16
2000-06-06 Johan Danielsson <joda@pdc.kth.se>
* rsh.c: nuke long option from -z
* rsh.c: don't try to encrypt if auth is broken (Daniel Kouril)
2000-06-03 Assar Westerlund <assar@sics.se>
* rshd.c (doit): check return value of getspnam. From
<haba@pdc.kth.se>
2000-05-23 Assar Westerlund <assar@sics.se>
* rsh.c (proto): select on the normal socket when waiting for the
daemon to connect back to the stderr port, so that we discover
when data arrives there before. when that happens, we assume that
the daemon did not manage to connect (because of NAT/whatever) and
continue as if `-e' was given
* rshd.c (doit): if we fail to connect back to the stderr port,
act as if `-e' was given on the client side, i.e. without the
special TCP-connection. This tries to make things better when
running the head against a NAT wall, for example.
2000-02-07 Assar Westerlund <assar@sics.se>
* Makefile.am (LDADD): make sure we use the heimdal libdes
2000-02-06 Assar Westerlund <assar@sics.se>
* *: conditionalize des stuff on KRB4
1999-12-16 Assar Westerlund <assar@sics.se>
* rsh.c (doit): addrinfo returned from getaddrinfo() is not usable
directly as hints. copy it and set AI_PASSIVE.
1999-11-20 Assar Westerlund <assar@sics.se>
* rsh.c (main): remember to close the priviledged sockets before
calling rlogin
1999-11-02 Assar Westerlund <assar@sics.se>
* rsh.c (main): redo the v4/v5 selection for consistency. -4 ->
try only v4 -5 -> try only v5 none, -45 -> try v5, v4
1999-10-26 Assar Westerlund <assar@sics.se>
* rshd.c (main): ignore SIGPIPE
* common.c (do_read): the encoded length can be longer than the
buffer being used, allocate memory for it dynamically. From Brian
A May <bmay@dgs.monash.edu.au>
1999-10-14 Assar Westerlund <assar@sics.se>
* rsh.c (proto): be more careful and don't print errno when read()
returns 0
1999-09-20 Assar Westerlund <assar@sics.se>
* rshd.c (recv_krb4_auth): set `iv'
1999-08-16 Assar Westerlund <assar@sics.se>
* common.c (do_read): be careful with the return value from
krb5_net_read
1999-08-05 Assar Westerlund <assar@sics.se>
* rsh.c: call freehostent
* rsh.c: remove some dead code
1999-08-04 Assar Westerlund <assar@sics.se>
* rshd.c: re-write the handling of forwarded credentials and
stuff. From Miroslav Ruda <ruda@ics.muni.cz>
* rsh_locl.h: always include kafs.h
* rsh.c: add `-z' and `-G' options
* rsh.c (loop): shutdown one side of the TCP connection on EOF.
From Brian A May <bmay@dgs.monash.edu.au>
* common.c (do_read): handle EOF. From Brian A May
<bmay@dgs.monash.edu.au>
1999-08-01 Assar Westerlund <assar@sics.se>
* rsh.c: const fixes
1999-07-29 Assar Westerlund <assar@sics.se>
* rshd.c: v6-ify
* rsh.c: v6-ify
1999-07-28 Assar Westerlund <assar@sics.se>
* rsh_locl.h: move around kafs.h
1999-07-24 Assar Westerlund <assar@sics.se>
* rsh_locl.h: <shadow.h>
* rsh.c, rshd.c: improve forwarding and implement unique ccache on
server. From Miroslav Ruda <ruda@ics.muni.cz>
1999-07-03 Assar Westerlund <assar@sics.se>
* rsh.c (construct_command): handle argc == 0 for generality
1999-06-23 Assar Westerlund <assar@sics.se>
* rsh.c: new option `-e' for not trying to open an stderr socket
1999-06-17 Assar Westerlund <assar@sics.se>
* rsh_locl.h (RSH_BUFSIZ): bump to 16 * 1024 to be sure that we
don't leave any data inside des_enc_read. (that constant should
really be exported in some way...)
1999-06-15 Assar Westerlund <assar@sics.se>
* rsh.c: use get_default_username and resulting const pollution
1999-05-21 Assar Westerlund <assar@sics.se>
* rsh.c (main): try $USERNAME
1999-05-14 Assar Westerlund <assar@sics.se>
* rshd.c (doit): afslog correctly
1999-05-11 Assar Westerlund <assar@sics.se>
* rsh.c (main): add fallback to rlogin
1999-05-10 Assar Westerlund <assar@sics.se>
* rsh.c (send_krb5_auth): call krb5_sendauth with ccache == NULL.
check return value from krb5_crypto_init
* common.c (do_write, do_read): always return -1 for failure
(net_write, net_read): remove. they already exist in libroken
1999-05-09 Assar Westerlund <assar@sics.se>
* rsh.c: make sure it tries with all other authentication methods
after one has failed
* rsh.c (main): detect the case of no command given.
1999-04-11 Assar Westerlund <assar@sics.se>
* rsh.c: new option --forwardable. use print_version
Sat Apr 10 17:10:55 1999 Assar Westerlund <assar@sics.se>
* rshd.c (setup_copier): use `socketpair' instead of `pipe'. Some
shells don't think it's a rsh session if they find a pipe at the
other end.
(setup_environment): add SSH_CLIENT just to make bash happy
* common.c (do_read): use krb5_get_wrapped_length
Wed Mar 24 03:59:42 1999 Assar Westerlund <assar@sics.se>
* rsh.c (loop): more braces to make gcc happy
Tue Mar 23 17:08:32 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* rsh_locl.h: kafs.h
* rshd.c: add `-P', `-v', and `-L' flags
Thu Mar 18 11:37:24 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* Makefile.am: include Makefile.am.common
Tue Dec 1 14:44:44 1998 Johan Danielsson <joda@hella.pdc.kth.se>
* appl/rsh/rshd.c: update to new crypto framework
* appl/rsh/rsh_locl.h: update to new crypto framework
* appl/rsh/rsh.c: update to new crypto framework
* appl/rsh/common.c: update to new crypto framework
Mon Nov 2 01:15:06 1998 Assar Westerlund <assar@sics.se>
* appl/rsh/rsh.c (main): initialize host
* appl/rsh/rshd.c (recv_krb5_auth): disable `do_encrypt' if not
encrypting.
Thu Jul 30 23:12:17 1998 Assar Westerlund <assar@sics.se>
* appl/rsh/rsh.c: kludges for parsing `rsh hostname -l user'
Thu Jul 23 19:49:03 1998 Johan Danielsson <joda@emma.pdc.kth.se>
* appl/rsh/rshd.c: use krb5_verify_authenticator_checksum
Sat Apr 18 21:13:06 1998 Johan Danielsson <joda@emma.pdc.kth.se>
* appl/rsh/rsh.c: Don't try v5 if (only) `-4' is specified.
Sun Dec 21 09:44:05 1997 Assar Westerlund <assar@sics.se>
* appl/rsh/rshd.c (recv_krb5_auth): swap the order of the
`local_user' and the `remote_user'
* appl/rsh/rsh.c (send_krb5_auth): swap the order of the
`local_user' and the `remote_user'
Sat Nov 29 07:10:11 1997 Assar Westerlund <assar@sics.se>
* appl/rsh/rshd.c: updated to use getarg.
changed `struct fd_set' to `fd_set'.
implemented broken/BSD authentication (requires iruserok)
Wed Nov 12 02:35:57 1997 Assar Westerlund <assar@sics.se>
* appl/rsh/rsh_locl.h: add AUTH_BROKEN and PATH_RSH
* appl/rsh/Makefile.am: set BINDIR
* appl/rsh/rsh.c: implemented BSD-style reserved port
`authentication'
Sun Aug 24 08:06:54 1997 Assar Westerlund <assar@sics.se>
* appl/rsh/rshd.c: syslog remote shells
Tue Aug 12 01:29:46 1997 Assar Westerlund <assar@sics.se>
* appl/rshd/rshd.c: Use `krb5_sock_to_principal'. Send server
parameter to krb5_rd_req/krb5_recvauth. Set addresses in
auth_context.
Fri Jul 25 17:32:12 1997 Assar Westerlund <assar@sics.se>
* appl/rsh/rshd.c: implement forwarding
* appl/rsh/rsh.c: Use getarg. Implement forwarding.
Sun Jul 13 00:32:16 1997 Assar Westerlund <assar@sics.se>
* appl/rsh: Conditionalize the krb4-support.
Wed Jul 9 06:58:00 1997 Assar Westerlund <assar@sics.se>
* appl/rsh/rsh.c: use the correct user for the checksum
Mon Jul 7 11:15:51 1997 Assar Westerlund <assar@sics.se>
* appl/rsh/rshd.c: Now works. Also implementd encryption and
`-p'.
* appl/rsh/common.c: new file
Mon Jun 30 06:08:14 1997 Assar Westerlund <assar@sics.se>
* appl/rsh: New program.

View File

@@ -1,30 +0,0 @@
# $Id$
include $(top_srcdir)/Makefile.am.common
AM_CPPFLAGS += -I$(srcdir)/../login $(INCLUDE_hcrypto)
WFLAGS += $(WFLAGS_LITE)
bin_PROGRAMS = rsh
man_MANS = rsh.1 rshd.8
libexec_PROGRAMS = rshd
rsh_SOURCES = rsh.c common.c rsh_locl.h
rshd_SOURCES = rshd.c common.c login_access.c limits_conf.c rsh_locl.h
login_access.c:
$(LN_S) $(srcdir)/../login/login_access.c .
limits_conf.c:
$(LN_S) $(srcdir)/../login/limits_conf.c .
LDADD = $(LIB_kafs) \
$(LIB_krb5) \
$(LIB_hcrypto) \
$(LIB_roken)
EXTRA_DIST = NTMakefile $(man_MANS)

View File

@@ -1,35 +0,0 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT HOLDER 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.
#
RELDIR=appl\rsh
!include ../../windows/NTMakefile.w32

View File

@@ -1,172 +0,0 @@
/*
* Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 "rsh_locl.h"
RCSID("$Id$");
#if defined(KRB5)
#ifdef KRB5
int key_usage = 1026;
void *ivec_in[2];
void *ivec_out[2];
void
init_ivecs(int client, int have_errsock)
{
size_t blocksize;
krb5_crypto_getblocksize(context, crypto, &blocksize);
ivec_in[0] = malloc(blocksize);
memset(ivec_in[0], client, blocksize);
if(have_errsock) {
ivec_in[1] = malloc(blocksize);
memset(ivec_in[1], 2 | client, blocksize);
} else
ivec_in[1] = ivec_in[0];
ivec_out[0] = malloc(blocksize);
memset(ivec_out[0], !client, blocksize);
if(have_errsock) {
ivec_out[1] = malloc(blocksize);
memset(ivec_out[1], 2 | !client, blocksize);
} else
ivec_out[1] = ivec_out[0];
}
#endif
ssize_t
do_read (int fd, void *buf, size_t sz, void *ivec)
{
if (do_encrypt) {
#ifdef KRB5
if(auth_method == AUTH_KRB5) {
krb5_error_code ret;
uint32_t len, outer_len;
int status;
krb5_data data;
void *edata;
ret = krb5_net_read (context, &fd, &len, 4);
if (ret <= 0)
return ret;
len = ntohl(len);
if (len > sz)
abort ();
/* ivec will be non null for protocol version 2 */
if(ivec != NULL)
outer_len = krb5_get_wrapped_length (context, crypto, len + 4);
else
outer_len = krb5_get_wrapped_length (context, crypto, len);
edata = malloc (outer_len);
if (edata == NULL)
errx (1, "malloc: cannot allocate %u bytes", outer_len);
ret = krb5_net_read (context, &fd, edata, outer_len);
if (ret <= 0) {
free(edata);
return ret;
}
status = krb5_decrypt_ivec(context, crypto, key_usage,
edata, outer_len, &data, ivec);
free (edata);
if (status)
krb5_err (context, 1, status, "decrypting data");
if(ivec != NULL) {
unsigned long l;
if(data.length < len + 4)
errx (1, "data received is too short");
_krb5_get_int(data.data, &l, 4);
if(l != len)
errx (1, "inconsistency in received data");
memcpy (buf, (unsigned char *)data.data+4, len);
} else
memcpy (buf, data.data, len);
krb5_data_free (&data);
return len;
} else
#endif /* KRB5 */
abort ();
} else
return read (fd, buf, sz);
}
ssize_t
do_write (int fd, void *buf, size_t sz, void *ivec)
{
if (do_encrypt) {
#ifdef KRB5
if(auth_method == AUTH_KRB5) {
krb5_error_code status;
krb5_data data;
unsigned char len[4];
int ret;
_krb5_put_int(len, sz, 4);
if(ivec != NULL) {
unsigned char *tmp = malloc(sz + 4);
if(tmp == NULL)
err(1, "malloc");
_krb5_put_int(tmp, sz, 4);
memcpy(tmp + 4, buf, sz);
status = krb5_encrypt_ivec(context, crypto, key_usage,
tmp, sz + 4, &data, ivec);
free(tmp);
} else
status = krb5_encrypt_ivec(context, crypto, key_usage,
buf, sz, &data, ivec);
if (status)
krb5_err(context, 1, status, "encrypting data");
ret = krb5_net_write (context, &fd, len, 4);
if (ret != 4)
return ret;
ret = krb5_net_write (context, &fd, data.data, data.length);
if (ret != data.length)
return ret;
free (data.data);
return sz;
} else
#endif /* KRB5 */
abort();
} else
return write (fd, buf, sz);
}
#endif /* KRB5 */

View File

@@ -1,294 +0,0 @@
.\" Copyright (c) 2002 - 2003 Kungliga Tekniska Högskolan
.\" (Royal Institute of Technology, Stockholm, Sweden).
.\" 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
.\"
.\" $Id$
.\"
.Dd February 20, 2004
.Dt RSH 1
.Os HEIMDAL
.Sh NAME
.Nm rsh
.Nd remote shell
.Sh SYNOPSIS
.Nm
.Op Fl 45FGKdefnuxz
.Op Fl U Pa string
.Op Fl p Ar port
.Op Fl l Ar username
.Op Fl P Ar N|O
.Ar host [command]
.Sh DESCRIPTION
.Nm
authenticates to the
.Xr rshd 8
daemon on the remote
.Ar host ,
and then executes the specified
.Ar command .
.Pp
.Nm
copies its standard input to the remote command, and the standard
output and error of the remote command to its own.
.Pp
Valid options are:
.Bl -tag -width Ds
.It Xo
.Fl 4 ,
.Fl Fl krb4
.Xc
The
.Fl 4
option requests Kerberos 4 authentication. Normally all supported
authentication mechanisms will be tried, but in some cases more
explicit control is desired.
.It Xo
.Fl 5 ,
.Fl Fl krb5
.Xc
The
.Fl 5
option requests Kerberos 5 authentication. This is analogous to the
.Fl 4
option.
.It Xo
.Fl K ,
.Fl Fl broken
.Xc
The
.Fl K
option turns off all Kerberos authentication. The security in this
mode relies on reserved ports. The long name is an indication of how
good this is.
.It Xo
.Fl n ,
.Fl Fl no-input
.Xc
The
.Fl n
option directs the input from the
.Pa /dev/null
device (see the
.Sx BUGS
section of this manual page).
.It Fl d
Enable
.Xr setsockopt 2
socket debugging.
.It Xo
.Fl e ,
.Fl Fl no-stderr
.Xc
Don't use a separate socket for the stderr stream. This can be
necessary if rsh-ing through a NAT bridge.
.It Xo
.Fl x ,
.Fl Fl encrypt
.Xc
The
.Fl x
option enables encryption for all data exchange. This is only valid
for Kerberos authenticated connections (see the
.Sx BUGS
section for limitations).
.It Xo
.Fl z
.Xc
The opposite of
.Fl x .
This is the default, and is mainly useful if encryption has been
enabled by default, for instance in the
.Li appdefaults
section of
.Pa /etc/krb5.conf
when using Kerberos 5.
.It Xo
.Fl f ,
.Fl Fl forward
.Xc
Forward Kerberos 5 credentials to the remote host.
Also settable via
.Li appdefaults
(see
.Xr krb5.conf ) .
.It Xo
.Fl F ,
.Fl Fl forwardable
.Xc
Make the forwarded credentials re-forwardable.
Also settable via
.Li appdefaults
(see
.Xr krb5.conf ) .
.It Xo
.Fl l Ar string ,
.Fl Fl user= Ns Ar string
.Xc
By default the remote username is the same as the local. The
.Fl l
option or the
.Pa username@host
format allow the remote name to be specified.
.It Xo
.Fl n ,
.Fl Fl no-input
.Xc
Direct input from
.Pa /dev/null
(see the
.Sx BUGS
section).
.It Xo
.Fl p Ar number-or-service ,
.Fl Fl port= Ns Ar number-or-service
.Xc
Connect to this port instead of the default (which is 514 when using
old port based authentication, 544 for Kerberos 5 and non-encrypted
Kerberos 4, and 545 for encrytpted Kerberos 4; subject of course to
the contents of
.Pa /etc/services ) .
.It Xo
.Fl P Ar N|O|1|2 ,
.Fl Fl protocol= Ns Ar N|O|1|2
.Xc
Specifies the protocol version to use with Kerberos 5.
.Ar N
and
.Ar 2
select protocol version 2, while
.Ar O
and
.Ar 1
select version 1. Version 2 is believed to be more secure, and is the
default. Unless asked for a specific version,
.Nm
will try both. This behaviour may change in the future.
.It Xo
.Fl u ,
.Fl Fl unique
.Xc
Make sure the remote credentials cache is unique, that is, don't reuse
any existing cache. Mutually exclusive to
.Fl U .
.It Xo
.Fl U Pa string ,
.Fl Fl tkfile= Ns Pa string
.Xc
Name of the remote credentials cache. Mutually exclusive to
.Fl u .
.It Xo
.Fl x ,
.Fl Fl encrypt
.Xc
The
.Fl x
option enables encryption for all data exchange. This is only valid
for Kerberos authenticated connections (see the
.Sx BUGS
section for limitations).
.It Fl z
The opposite of
.Fl x .
This is the default, but encryption can be enabled when using
Kerberos 5, by setting the
.Li libdefaults/encrypt
option in
.Xr krb5.conf 5 .
.El
.\".Pp
.\"Without a
.\".Ar command
.\".Nm
.\"will just exec
.\".Xr rlogin 1
.\"with the same arguments.
.Sh EXAMPLES
Care should be taken when issuing commands containing shell meta
characters. Without quoting, these will be expanded on the local
machine.
.Pp
The following command:
.Pp
.Dl rsh otherhost cat remotefile \*[Gt] localfile
.Pp
will write the contents of the remote
.Pa remotefile
to the local
.Pa localfile ,
but:
.Pp
.Dl rsh otherhost 'cat remotefile \*[Gt] remotefile2'
.Pp
will write it to the remote
.Pa remotefile2 .
.\".Sh ENVIRONMENT
.Sh FILES
.Bl -tag -width /etc/hosts -compact
.It Pa /etc/hosts
.El
.\".Sh DIAGNOSTICS
.Sh SEE ALSO
.Xr rlogin 1 ,
.Xr krb_realmofhost 3 ,
.Xr krb_sendauth 3 ,
.Xr hosts.equiv 5 ,
.Xr krb5.conf 5 ,
.Xr rhosts 5 ,
.Xr kerberos 8
.Xr rshd 8
.\".Sh STANDARDS
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.2 .
.Sh AUTHORS
This implementation of
.Nm
was written as part of the Heimdal Kerberos 5 implementation.
.Sh BUGS
Some shells (notably
.Xr csh 1 )
will cause
.Nm
to block if run in the background, unless the standard input is directed away from the terminal. This is what the
.Fl n
option is for.
.Pp
The
.Fl x
options enables encryption for the session, but for both Kerberos 4
and 5 the actual command is sent unencrypted, so you should not send
any secret information in the command line (which is probably a bad
idea anyway, since the command line can usually be read with tools
like
.Xr ps 1 ) .
Forthermore in Kerberos 4 the command is not even integrity
protected, so anyone with the right tools can modify the command.

File diff suppressed because it is too large Load Diff

View File

@@ -1,166 +0,0 @@
/*
* Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET6_IN6_H
#include <netinet6/in6.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SHADOW_H
#include <shadow.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <errno.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <err.h>
#include <roken.h>
#include <getarg.h>
#ifdef KRB5
#include <krb5.h>
/* XXX */
struct hx509_certs_data;
struct krb5_pk_identity;
struct krb5_pk_cert;
struct ContentInfo;
struct AlgorithmIdentifier;
struct _krb5_krb_auth_data;
struct krb5_dh_moduli;
struct _krb5_key_data;
struct _krb5_encryption_type;
struct _krb5_key_type;
#include "crypto-headers.h"
#include <krb5-private.h> /* for _krb5_{get,put}_int */
#endif
#if defined(KRB5)
#include <kafs.h>
#endif
#ifndef _PATH_BSHELL
#define _PATH_BSHELL "/bin/sh"
#endif
#ifndef _PATH_DEFPATH
#define _PATH_DEFPATH "/usr/bin:/bin"
#endif
#include "loginpaths.h"
/*
*
*/
enum auth_method { AUTH_KRB5, AUTH_BROKEN };
extern enum auth_method auth_method;
extern int do_encrypt;
#ifdef KRB5
extern krb5_context context;
extern krb5_keyblock *keyblock;
extern krb5_crypto crypto;
extern int key_usage;
extern void *ivec_in[2];
extern void *ivec_out[2];
void init_ivecs(int, int);
#endif
#define KCMD_OLD_VERSION "KCMDV0.1"
#define KCMD_NEW_VERSION "KCMDV0.2"
#define USERNAME_SZ 16
#ifndef ARG_MAX
#define ARG_MAX 8192
#endif
#define RSH_BUFSIZ (5 * 1024) /* MIT kcmd can't handle larger buffers */
#define RSHD_BUFSIZ (16 * 1024) /* Old maxize for Heimdal 0.4 rsh */
#define PATH_RSH BINDIR "/rsh"
#if defined(KRB5)
ssize_t do_read (int, void*, size_t, void*);
ssize_t do_write (int, void*, size_t, void*);
#else
#define do_write(F, B, L, I) write((F), (B), (L))
#define do_read(F, B, L, I) read((F), (B), (L))
#endif

View File

@@ -1,161 +0,0 @@
.\" Copyright (c) 2001 - 2006 Kungliga Tekniska Högskolan
.\" (Royal Institute of Technology, Stockholm, Sweden).
.\" 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
.\"
.\" $Id$
.\"
.Dd November 22, 2002
.Dt RSHD 8
.Os HEIMDAL
.Sh NAME
.Nm rshd
.Nd remote shell server
.Sh SYNOPSIS
.Nm
.Op Fl aiklnvxPL
.Op Fl p Ar port
.Sh DESCRIPTION
.Nm
is the server for
the
.Xr rsh 1
program. It provides an authenticated remote command execution
service. Supported options are:
.Bl -tag -width Ds
.It Xo
.Fl n ,
.Fl Fl no-keepalive
.Xc
Disables keep-alive messages.
Keep-alives are packets sent at certain intervals to make sure that the
client is still there, even when it doesn't send any data.
.It Xo
.Fl k ,
.Fl Fl kerberos
.Xc
Assume that clients connecting to this server will use some form of
Kerberos authentication. See the
.Sx EXAMPLES
section for a sample
.Xr inetd.conf 5
configuration.
.It Xo
.Fl x ,
.Fl Fl encrypt
.Xc
For Kerberos 4 this means that the connections are encrypted. Kerberos
5 can negotiate encryption even without this option, but if it's
present
.Nm
will deny unencrypted connections. This option implies
.Fl k .
.\".It Xo
.\".Fl l ,
.\".Fl Fl no-rhosts
.\".Xc
.\"When using old port-based authentication, the user's
.\".Pa .rhosts
.\"files are normally checked. This option disables this.
.It Xo
.Fl v ,
.Fl Fl vacuous
.Xc
If the connecting client does not use any Kerberised authentication,
print a message that complains about this fact, and exit. This is
helpful if you want to move away from old port-based authentication.
.It Xo
.Fl P
.Xc
When using the AFS filesystem, users' authentication tokens are put in
something called a PAG (Process Authentication Group). Multiple
processes can share a PAG, but normally each login session has its own
PAG. This option disables the
.Fn setpag
call, so all tokens will be put in the default (uid-based) PAG, making
it possible to share tokens between sessions. This is only useful in
peculiar environments, such as some batch systems.
.It Xo
.Fl i ,
.Fl Fl no-inetd
.Xc
The
.Fl i
option will cause
.Nm
to create a socket, instead of assuming that its stdin came from
.Xr inetd 8 .
This is mostly useful for debugging.
.It Xo
.Fl p Ar port ,
.Fl Fl port= Ns Ar port
.Xc
Port to use with
.Fl i .
.It Xo
.Fl a
.Xc
This flag is for backwards compatibility only.
.It Xo
.Fl L
.Xc
This flag enables logging of connections to
.Xr syslogd 8 .
This option is always on in this implementation.
.El
.\".Sh ENVIRONMENT
.Sh FILES
.Bl -tag -width /etc/hosts.equiv -compact
.It Pa /etc/hosts.equiv
.It Pa ~/.rhosts
.El
.Sh EXAMPLES
The following can be used to enable Kerberised rsh in
.Xr inetd.cond 5 ,
while disabling non-Kerberised connections:
.Bd -literal
shell stream tcp nowait root /usr/libexec/rshd rshd -v
kshell stream tcp nowait root /usr/libexec/rshd rshd -k
ekshell stream tcp nowait root /usr/libexec/rshd rshd -kx
.Ed
.\".Sh DIAGNOSTICS
.Sh SEE ALSO
.Xr rsh 1 ,
.Xr iruserok 3
.\".Sh STANDARDS
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.2 .
.Sh AUTHORS
This implementation of
.Nm
was written as part of the Heimdal Kerberos 5 implementation.
.\".Sh BUGS

View File

@@ -1,992 +0,0 @@
/*
* Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 "rsh_locl.h"
#include "login_locl.h"
RCSID("$Id$");
int
login_access( struct passwd *user, char *from);
int
read_limits_conf(const char *file, const struct passwd *pwd);
#ifdef NEED_IRUSEROK_PROTO
int iruserok(uint32_t, int, const char *, const char *);
#endif
enum auth_method auth_method;
#ifdef KRB5
krb5_context context;
krb5_keyblock *keyblock;
krb5_crypto crypto;
#endif
#ifdef KRB5
krb5_ccache ccache, ccache2;
int kerberos_status = 0;
#endif
int do_encrypt = 0;
static int do_unique_tkfile = 0;
static char tkfile[MAXPATHLEN] = "";
static int do_inetd = 1;
static char *port_str;
static int do_rhosts = 1;
static int do_kerberos = 0;
#define DO_KRB5 4
static int do_vacuous = 0;
static int do_log = 1;
static int do_newpag = 1;
static int do_addr_verify = 0;
static int do_keepalive = 1;
static int do_version;
static int do_help = 0;
static void
syslog_and_die (const char *m, ...)
__attribute__ ((format (printf, 1, 2)));
static void
syslog_and_die (const char *m, ...)
{
va_list args;
va_start(args, m);
vsyslog (LOG_ERR, m, args);
va_end(args);
exit (1);
}
static void
fatal (int, const char*, const char *, ...)
__attribute__ ((noreturn, format (printf, 3, 4)));
static void
fatal (int sock, const char *what, const char *m, ...)
{
va_list args;
char buf[BUFSIZ];
size_t len;
*buf = 1;
va_start(args, m);
len = vsnprintf (buf + 1, sizeof(buf) - 1, m, args);
len = min(len, sizeof(buf) - 1);
va_end(args);
if(what != NULL)
syslog (LOG_ERR, "%s: %s: %s", what, strerror(errno), buf + 1);
else
syslog (LOG_ERR, "%s", buf + 1);
net_write (sock, buf, len + 1);
exit (1);
}
static char *
read_str (int s, size_t sz, char *expl)
{
char *str = malloc(sz);
char *p = str;
if(str == NULL)
fatal(s, NULL, "%s too long", expl);
while(p < str + sz) {
if(net_read(s, p, 1) != 1)
syslog_and_die("read: %s", strerror(errno));
if(*p == '\0')
return str;
p++;
}
fatal(s, NULL, "%s too long", expl);
}
static int
recv_bsd_auth (int s, u_char *buf,
struct sockaddr_in *thisaddr,
struct sockaddr_in *thataddr,
char **client_username,
char **server_username,
char **cmd)
{
struct passwd *pwd;
*client_username = read_str (s, USERNAME_SZ, "local username");
*server_username = read_str (s, USERNAME_SZ, "remote username");
*cmd = read_str (s, ARG_MAX + 1, "command");
pwd = getpwnam(*server_username);
if (pwd == NULL)
fatal(s, NULL, "Login incorrect.");
if (iruserok(thataddr->sin_addr.s_addr, pwd->pw_uid == 0,
*client_username, *server_username))
fatal(s, NULL, "Login incorrect.");
return 0;
}
#ifdef KRB5
static int
save_krb5_creds (int s,
krb5_auth_context auth_context,
krb5_principal client)
{
int ret;
krb5_data remote_cred;
const char *estr;
krb5_data_zero (&remote_cred);
ret= krb5_read_message (context, (void *)&s, &remote_cred);
if (ret) {
krb5_data_free(&remote_cred);
return 0;
}
if (remote_cred.length == 0)
return 0;
ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache);
if (ret) {
krb5_data_free(&remote_cred);
return 0;
}
krb5_cc_initialize(context,ccache,client);
ret = krb5_rd_cred2(context, auth_context, ccache, &remote_cred);
if(ret != 0) {
estr = krb5_get_error_message(context, ret);
syslog(LOG_INFO|LOG_AUTH, "reading creds: %s", estr);
krb5_free_error_message(context, estr);
}
krb5_data_free (&remote_cred);
if (ret)
return 0;
return 1;
}
static void
krb5_start_session (void)
{
krb5_error_code ret;
const char *estr;
ret = krb5_cc_resolve (context, tkfile, &ccache2);
if (ret) {
estr = krb5_get_error_message(context, ret);
syslog(LOG_WARNING, "resolve cred cache %s: %s",
tkfile,
estr ? estr : "could not get error string");
krb5_free_error_message(context, estr);
krb5_cc_destroy(context, ccache);
return;
}
ret = krb5_cc_copy_cache (context, ccache, ccache2);
if (ret) {
estr = krb5_get_error_message(context, ret);
syslog(LOG_WARNING, "storing credentials: %s", estr);
krb5_free_error_message(context, estr);
krb5_cc_destroy(context, ccache);
return ;
}
krb5_cc_close(context, ccache2);
krb5_cc_destroy(context, ccache);
return;
}
static int protocol_version;
static krb5_boolean
match_kcmd_version(const void *data, const char *version)
{
if(strcmp(version, KCMD_NEW_VERSION) == 0) {
protocol_version = 2;
return TRUE;
}
if(strcmp(version, KCMD_OLD_VERSION) == 0) {
protocol_version = 1;
key_usage = KRB5_KU_OTHER_ENCRYPTED;
return TRUE;
}
return FALSE;
}
static int
recv_krb5_auth (int s, u_char *buf,
struct sockaddr *thisaddr,
struct sockaddr *thataddr,
char **client_username,
char **server_username,
char **cmd)
{
uint32_t len;
krb5_auth_context auth_context = NULL;
krb5_ticket *ticket;
krb5_error_code status;
krb5_data cksum_data;
krb5_principal server;
const char *estr;
char *str;
if (memcmp (buf, "\x00\x00\x00\x13", 4) != 0)
return -1;
len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
if (net_read(s, buf, len) != len)
syslog_and_die ("reading auth info: %s", strerror(errno));
if (len != sizeof(KRB5_SENDAUTH_VERSION)
|| memcmp (buf, KRB5_SENDAUTH_VERSION, len) != 0)
syslog_and_die ("bad sendauth version: %.8s", buf);
status = krb5_sock_to_principal (context,
s,
"host",
KRB5_NT_SRV_HST,
&server);
if (status) {
estr = krb5_get_error_message(context, status);
syslog_and_die ("krb5_sock_to_principal: %s", estr);
krb5_free_error_message(context, estr);
}
status = krb5_recvauth_match_version(context,
&auth_context,
&s,
match_kcmd_version,
NULL,
server,
KRB5_RECVAUTH_IGNORE_VERSION,
NULL,
&ticket);
krb5_free_principal (context, server);
if (status) {
estr = krb5_get_error_message(context, status);
syslog_and_die ("krb5_recvauth: %s", estr);
krb5_free_error_message(context, estr);
}
*server_username = read_str (s, USERNAME_SZ, "remote username");
*cmd = read_str (s, ARG_MAX + 1, "command");
*client_username = read_str (s, ARG_MAX + 1, "local username");
if(protocol_version == 2) {
status = krb5_auth_con_getremotesubkey(context, auth_context,
&keyblock);
if(status != 0 || keyblock == NULL)
syslog_and_die("failed to get remote subkey");
} else if(protocol_version == 1) {
status = krb5_auth_con_getkey (context, auth_context, &keyblock);
if(status != 0 || keyblock == NULL)
syslog_and_die("failed to get key");
}
if (status != 0 || keyblock == NULL) {
estr = krb5_get_error_message(context, status);
syslog_and_die ("krb5_auth_con_getkey: %s", estr);
krb5_free_error_message(context, estr);
}
status = krb5_crypto_init(context, keyblock, 0, &crypto);
if (status) {
estr = krb5_get_error_message(context, status);
syslog_and_die("krb5_crypto_init: %s", estr);
krb5_free_error_message(context, estr);
}
cksum_data.length = asprintf (&str,
"%u:%s%s",
ntohs(socket_get_port (thisaddr)),
*cmd,
*server_username);
if (str == NULL)
syslog_and_die ("asprintf: out of memory");
cksum_data.data = str;
status = krb5_verify_authenticator_checksum(context,
auth_context,
cksum_data.data,
cksum_data.length);
if (status) {
estr = krb5_get_error_message(context, status);
syslog_and_die ("krb5_verify_authenticator_checksum: %s", estr);
krb5_free_error_message(context, estr);
}
free (cksum_data.data);
if (strncmp (*client_username, "-u ", 3) == 0) {
do_unique_tkfile = 1;
memmove (*client_username, *client_username + 3,
strlen(*client_username) - 2);
}
if (strncmp (*client_username, "-U ", 3) == 0) {
char *end, *temp_tkfile;
do_unique_tkfile = 1;
if (strncmp (*client_username + 3, "FILE:", 5) == 0) {
temp_tkfile = tkfile;
} else {
strlcpy (tkfile, "FILE:", sizeof(tkfile));
temp_tkfile = tkfile + 5;
}
end = strchr(*client_username + 3,' ');
if (end == NULL)
syslog_and_die("missing argument after -U");
snprintf(temp_tkfile, sizeof(tkfile) - (temp_tkfile - tkfile),
"%.*s",
(int)(end - *client_username - 3),
*client_username + 3);
memmove (*client_username, end + 1, strlen(end+1)+1);
}
kerberos_status = save_krb5_creds (s, auth_context, ticket->client);
if(!krb5_kuserok (context,
ticket->client,
*server_username))
fatal (s, NULL, "Permission denied.");
if (strncmp (*cmd, "-x ", 3) == 0) {
do_encrypt = 1;
memmove (*cmd, *cmd + 3, strlen(*cmd) - 2);
} else {
if(do_encrypt)
fatal (s, NULL, "Encryption is required.");
do_encrypt = 0;
}
{
char *name;
if (krb5_unparse_name (context, ticket->client, &name) == 0) {
char addr_str[256];
if (inet_ntop (thataddr->sa_family,
socket_get_address (thataddr),
addr_str, sizeof(addr_str)) == NULL)
strlcpy (addr_str, "unknown address",
sizeof(addr_str));
syslog(LOG_INFO|LOG_AUTH,
"kerberos v5 shell from %s on %s as %s, cmd '%.80s'",
name,
addr_str,
*server_username,
*cmd);
free (name);
}
}
krb5_auth_con_free(context, auth_context);
return 0;
}
#endif /* KRB5 */
static void
rshd_loop (int from0, int to0,
int to1, int from1,
int to2, int from2,
int have_errsock)
{
fd_set real_readset;
int max_fd;
int count = 2;
char *buf;
if(from0 >= FD_SETSIZE || from1 >= FD_SETSIZE || from2 >= FD_SETSIZE)
errx (1, "fd too large");
#ifdef KRB5
if(auth_method == AUTH_KRB5 && protocol_version == 2)
init_ivecs(0, have_errsock);
#endif
FD_ZERO(&real_readset);
FD_SET(from0, &real_readset);
FD_SET(from1, &real_readset);
FD_SET(from2, &real_readset);
max_fd = max(from0, max(from1, from2)) + 1;
buf = malloc(max(RSHD_BUFSIZ, RSH_BUFSIZ));
if (buf == NULL)
syslog_and_die("out of memory");
for (;;) {
int ret;
fd_set readset = real_readset;
ret = select (max_fd, &readset, NULL, NULL, NULL);
if (ret < 0) {
if (errno == EINTR)
continue;
else
syslog_and_die ("select: %s", strerror(errno));
}
if (FD_ISSET(from0, &readset)) {
ret = do_read (from0, buf, RSHD_BUFSIZ, ivec_in[0]);
if (ret < 0)
syslog_and_die ("read: %s", strerror(errno));
else if (ret == 0) {
close (from0);
close (to0);
FD_CLR(from0, &real_readset);
} else
net_write (to0, buf, ret);
}
if (FD_ISSET(from1, &readset)) {
ret = read (from1, buf, RSH_BUFSIZ);
if (ret < 0)
syslog_and_die ("read: %s", strerror(errno));
else if (ret == 0) {
close (from1);
close (to1);
FD_CLR(from1, &real_readset);
if (--count == 0)
exit (0);
} else
do_write (to1, buf, ret, ivec_out[0]);
}
if (FD_ISSET(from2, &readset)) {
ret = read (from2, buf, RSH_BUFSIZ);
if (ret < 0)
syslog_and_die ("read: %s", strerror(errno));
else if (ret == 0) {
close (from2);
close (to2);
FD_CLR(from2, &real_readset);
if (--count == 0)
exit (0);
} else
do_write (to2, buf, ret, ivec_out[1]);
}
}
}
/*
* Used by `setup_copier' to create some pipe-like means of
* communcation. Real pipes would probably be the best thing, but
* then the shell doesn't understand it's talking to rshd. If
* socketpair doesn't work everywhere, some autoconf magic would have
* to be added here.
*
* If it fails creating the `pipe', it aborts by calling fatal.
*/
static void
pipe_a_like (int fd[2])
{
if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd) < 0)
fatal (STDOUT_FILENO, "socketpair", "Pipe creation failed.");
}
/*
* Start a child process and leave the parent copying data to and from it. */
static void
setup_copier (int have_errsock)
{
int p0[2], p1[2], p2[2];
pid_t pid;
pipe_a_like(p0);
pipe_a_like(p1);
pipe_a_like(p2);
pid = fork ();
if (pid < 0)
fatal (STDOUT_FILENO, "fork", "Could not create child process.");
if (pid == 0) { /* child */
close (p0[1]);
close (p1[0]);
close (p2[0]);
dup2 (p0[0], STDIN_FILENO);
dup2 (p1[1], STDOUT_FILENO);
dup2 (p2[1], STDERR_FILENO);
close (p0[0]);
close (p1[1]);
close (p2[1]);
} else { /* parent */
close (p0[0]);
close (p1[1]);
close (p2[1]);
if (net_write (STDOUT_FILENO, "", 1) != 1)
fatal (STDOUT_FILENO, "net_write", "Write failure.");
rshd_loop (STDIN_FILENO, p0[1],
STDOUT_FILENO, p1[0],
STDERR_FILENO, p2[0],
have_errsock);
}
}
/*
* Is `port' a ``reserverd'' port?
*/
static int
is_reserved(u_short port)
{
return ntohs(port) < IPPORT_RESERVED;
}
/*
* Set the necessary part of the environment in `env'.
*/
static void
setup_environment (char ***env, const struct passwd *pwd)
{
int i, j, path;
char **e;
i = 0;
path = 0;
*env = NULL;
i = read_environment(_PATH_ETC_ENVIRONMENT, env);
e = *env;
for (j = 0; j < i; j++) {
if (!strncmp(e[j], "PATH=", 5)) {
path = 1;
}
}
e = *env;
e = realloc(e, (i + 7) * sizeof(char *));
if (asprintf (&e[i++], "USER=%s", pwd->pw_name) == -1)
syslog_and_die ("asprintf: out of memory");
if (asprintf (&e[i++], "HOME=%s", pwd->pw_dir) == -1)
syslog_and_die ("asprintf: out of memory");
if (asprintf (&e[i++], "SHELL=%s", pwd->pw_shell) == -1)
syslog_and_die ("asprintf: out of memory");
if (! path) {
if (asprintf (&e[i++], "PATH=%s", _PATH_DEFPATH) == -1)
syslog_and_die ("asprintf: out of memory");
}
asprintf (&e[i++], "SSH_CLIENT=only_to_make_bash_happy");
if (do_unique_tkfile)
if (asprintf (&e[i++], "KRB5CCNAME=%s", tkfile) == -1)
syslog_and_die ("asprintf: out of memory");
e[i++] = NULL;
*env = e;
}
static void
doit (void)
{
u_char buf[BUFSIZ];
u_char *p;
struct sockaddr_storage thisaddr_ss;
struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss;
struct sockaddr_storage thataddr_ss;
struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss;
struct sockaddr_storage erraddr_ss;
struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss;
socklen_t thisaddr_len, thataddr_len;
int port;
int errsock = -1;
char *client_user = NULL, *server_user = NULL, *cmd = NULL;
struct passwd *pwd;
int s = STDIN_FILENO;
char **env;
int ret;
char that_host[NI_MAXHOST];
thisaddr_len = sizeof(thisaddr_ss);
if (getsockname (s, thisaddr, &thisaddr_len) < 0)
syslog_and_die("getsockname: %s", strerror(errno));
thataddr_len = sizeof(thataddr_ss);
if (getpeername (s, thataddr, &thataddr_len) < 0)
syslog_and_die ("getpeername: %s", strerror(errno));
/* check for V4MAPPED addresses? */
if (do_kerberos == 0 && !is_reserved(socket_get_port(thataddr)))
fatal(s, NULL, "Permission denied.");
p = buf;
port = 0;
for(;;) {
if (net_read (s, p, 1) != 1)
syslog_and_die ("reading port number: %s", strerror(errno));
if (*p == '\0')
break;
else if (isdigit(*p))
port = port * 10 + *p - '0';
else
syslog_and_die ("non-digit in port number: %c", *p);
}
if (do_kerberos == 0 && !is_reserved(htons(port)))
fatal(s, NULL, "Permission denied.");
if (port) {
int priv_port = IPPORT_RESERVED - 1;
/*
* There's no reason to require a ``privileged'' port number
* here, but for some reason the brain dead rsh clients
* do... :-(
*/
erraddr->sa_family = thataddr->sa_family;
socket_set_address_and_port (erraddr,
socket_get_address (thataddr),
htons(port));
/*
* we only do reserved port for IPv4
*/
if (erraddr->sa_family == AF_INET)
errsock = rresvport (&priv_port);
else
errsock = socket (erraddr->sa_family, SOCK_STREAM, 0);
if (errsock < 0)
syslog_and_die ("socket: %s", strerror(errno));
if (connect (errsock,
erraddr,
socket_sockaddr_size (erraddr)) < 0) {
syslog (LOG_WARNING, "connect: %s", strerror(errno));
close (errsock);
}
}
if(do_kerberos) {
if (net_read (s, buf, 4) != 4)
syslog_and_die ("reading auth info: %s", strerror(errno));
#ifdef KRB5
if((do_kerberos & DO_KRB5) &&
recv_krb5_auth (s, buf, thisaddr, thataddr,
&client_user,
&server_user,
&cmd) == 0)
auth_method = AUTH_KRB5;
else
#endif /* KRB5 */
syslog_and_die ("unrecognized auth protocol: %x %x %x %x",
buf[0], buf[1], buf[2], buf[3]);
} else {
if(recv_bsd_auth (s, buf,
(struct sockaddr_in *)thisaddr,
(struct sockaddr_in *)thataddr,
&client_user,
&server_user,
&cmd) == 0) {
auth_method = AUTH_BROKEN;
if(do_vacuous) {
printf("Remote host requires Kerberos authentication\n");
exit(0);
}
} else
syslog_and_die("recv_bsd_auth failed");
}
if (client_user == NULL || server_user == NULL || cmd == NULL)
syslog_and_die("mising client/server/cmd");
pwd = getpwnam (server_user);
if (pwd == NULL)
fatal (s, NULL, "Login incorrect.");
if (*pwd->pw_shell == '\0')
pwd->pw_shell = _PATH_BSHELL;
if (pwd->pw_uid != 0 && access (_PATH_NOLOGIN, F_OK) == 0)
fatal (s, NULL, "Login disabled.");
ret = getnameinfo_verified (thataddr, thataddr_len,
that_host, sizeof(that_host),
NULL, 0, 0);
if (ret)
fatal (s, NULL, "getnameinfo: %s", gai_strerror(ret));
if (login_access(pwd, that_host) == 0) {
syslog(LOG_NOTICE, "Kerberos rsh denied to %s from %s",
server_user, that_host);
fatal(s, NULL, "Permission denied.");
}
#ifdef HAVE_GETSPNAM
{
struct spwd *sp;
long today;
sp = getspnam(server_user);
if (sp != NULL) {
today = time(0)/(24L * 60 * 60);
if (sp->sp_expire > 0)
if (today > sp->sp_expire)
fatal(s, NULL, "Account has expired.");
}
}
#endif
#ifdef HAVE_SETLOGIN
if (setlogin(pwd->pw_name) < 0)
syslog(LOG_ERR, "setlogin() failed: %s", strerror(errno));
#endif
#ifdef HAVE_SETPCRED
if (setpcred (pwd->pw_name, NULL) == -1)
syslog(LOG_ERR, "setpcred() failure: %s", strerror(errno));
#endif /* HAVE_SETPCRED */
/* Apply limits if not root */
if(pwd->pw_uid != 0) {
const char *file = _PATH_LIMITS_CONF;
read_limits_conf(file, pwd);
}
if (initgroups (pwd->pw_name, pwd->pw_gid) < 0)
fatal (s, "initgroups", "Login incorrect.");
if (setgid(pwd->pw_gid) < 0)
fatal (s, "setgid", "Login incorrect.");
if (setuid (pwd->pw_uid) < 0)
fatal (s, "setuid", "Login incorrect.");
if (chdir (pwd->pw_dir) < 0)
fatal (s, "chdir", "Remote directory.");
if (errsock >= 0) {
if (dup2 (errsock, STDERR_FILENO) < 0)
fatal (s, "dup2", "Cannot dup stderr.");
close (errsock);
} else {
if (dup2 (STDOUT_FILENO, STDERR_FILENO) < 0)
fatal (s, "dup2", "Cannot dup stderr.");
}
#ifdef KRB5
{
int fd;
if (!do_unique_tkfile)
snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_%lu",
(unsigned long)pwd->pw_uid);
else if (*tkfile=='\0') {
snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_XXXXXX");
fd = mkstemp(tkfile+5);
close(fd);
unlink(tkfile+5);
}
if (kerberos_status)
krb5_start_session();
}
#endif
setup_environment (&env, pwd);
if (do_encrypt) {
setup_copier (errsock >= 0);
} else {
if (net_write (s, "", 1) != 1)
fatal (s, "net_write", "write failed");
}
#if defined(KRB5)
if(k_hasafs()) {
char cell[64];
if(do_newpag)
k_setpag();
/* XXX */
if (kerberos_status) {
krb5_ccache ccache;
krb5_error_code status;
status = krb5_cc_resolve (context, tkfile, &ccache);
if (!status) {
if (k_afs_cell_of_file (pwd->pw_dir, cell, sizeof(cell)) == 0)
krb5_afslog_uid_home(context, ccache, cell, NULL,
pwd->pw_uid, pwd->pw_dir);
krb5_afslog_uid_home(context, ccache, NULL, NULL,
pwd->pw_uid, pwd->pw_dir);
krb5_cc_close (context, ccache);
}
}
}
#endif /* KRB5 */
execle (pwd->pw_shell, pwd->pw_shell, "-c", cmd, NULL, env);
err(1, "exec %s", pwd->pw_shell);
}
struct getargs args[] = {
{ NULL, 'a', arg_flag, &do_addr_verify },
{ "keepalive", 'n', arg_negative_flag, &do_keepalive },
{ "inetd", 'i', arg_negative_flag, &do_inetd,
"Not started from inetd" },
#if defined(KRB5)
{ "kerberos", 'k', arg_flag, &do_kerberos,
"Implement kerberised services" },
{ "encrypt", 'x', arg_flag, &do_encrypt,
"Implement encrypted service" },
#endif
{ "rhosts", 'l', arg_negative_flag, &do_rhosts,
"Don't check users .rhosts" },
{ "port", 'p', arg_string, &port_str, "Use this port",
"port" },
{ "vacuous", 'v', arg_flag, &do_vacuous,
"Don't accept non-kerberised connections" },
#if defined(KRB5)
{ NULL, 'P', arg_negative_flag, &do_newpag,
"Don't put process in new PAG" },
#endif
/* compatibility flag: */
{ NULL, 'L', arg_flag, &do_log },
{ "version", 0, arg_flag, &do_version },
{ "help", 0, arg_flag, &do_help }
};
static void
usage (int ret)
{
if(isatty(STDIN_FILENO))
arg_printusage (args,
sizeof(args) / sizeof(args[0]),
NULL,
"");
else
syslog (LOG_ERR, "Usage: %s [-ikxlvPL] [-p port]", getprogname());
exit (ret);
}
int
main(int argc, char **argv)
{
int optind = 0;
int on = 1;
setprogname (argv[0]);
roken_openlog ("rshd", LOG_ODELAY | LOG_PID, LOG_AUTH);
if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv,
&optind))
usage(1);
if(do_help)
usage (0);
if (do_version) {
print_version(NULL);
exit(0);
}
#if defined(KRB5)
if (do_encrypt)
do_kerberos = 1;
if(do_kerberos)
do_kerberos = DO_KRB5;
#endif
#ifdef KRB5
if((do_kerberos & DO_KRB5) && krb5_init_context (&context) != 0)
do_kerberos &= ~DO_KRB5;
#endif
if (!do_inetd) {
int error;
struct addrinfo *ai = NULL, hints;
char portstr[NI_MAXSERV];
memset (&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
if(port_str != NULL) {
error = getaddrinfo (NULL, port_str, &hints, &ai);
if (error)
errx (1, "getaddrinfo: %s", gai_strerror (error));
}
if (ai == NULL) {
#if defined(KRB5)
if (do_kerberos) {
if (do_encrypt) {
error = getaddrinfo(NULL, "ekshell", &hints, &ai);
if(error == EAI_NONAME) {
snprintf(portstr, sizeof(portstr), "%d", 545);
error = getaddrinfo(NULL, portstr, &hints, &ai);
}
if(error)
errx (1, "getaddrinfo: %s", gai_strerror (error));
} else {
error = getaddrinfo(NULL, "kshell", &hints, &ai);
if(error == EAI_NONAME) {
snprintf(portstr, sizeof(portstr), "%d", 544);
error = getaddrinfo(NULL, portstr, &hints, &ai);
}
if(error)
errx (1, "getaddrinfo: %s", gai_strerror (error));
}
} else
#endif
{
error = getaddrinfo(NULL, "shell", &hints, &ai);
if(error == EAI_NONAME) {
snprintf(portstr, sizeof(portstr), "%d", 514);
error = getaddrinfo(NULL, portstr, &hints, &ai);
}
if(error)
errx (1, "getaddrinfo: %s", gai_strerror (error));
}
}
mini_inetd_addrinfo (ai, NULL);
freeaddrinfo(ai);
}
if (do_keepalive &&
setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
sizeof(on)) < 0)
syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %s", strerror(errno));
/* set SO_LINGER? */
signal (SIGPIPE, SIG_IGN);
doit ();
return 0;
}

View File

@@ -1,831 +0,0 @@
2008-04-27 Love Hörnquist Åstrand <lha@it.su.se>
* libtelnet/enc_des.c: Use RAND_bytes() + DES_is_weak_key() to
generate random DES key. Introdunce random by feeding the des
session key into the random pool when the keys is recived instead
of encrypt the random key with the kerberos key.
This avoid depenency on DES_new_random_key() that doesn't exists
in OpenSSL.
2008-04-18 Love Hörnquist Åstrand <lha@it.su.se>
* libtelnet/enc_des.c: No need to call
DES_init_random_number_generator, hcrypto is sane now.
* libtelnet/enc_des.c: Use DES_new_random_key().
2008-04-10 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c: Really, mac os uses wtmpx (or asl).
2008-03-09 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c: Dont need to set this as the controlling PTY
on steams sockets, don't abort on failure. From Harald Barth and
Ian Delahorne.
2007-12-31 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c: Use strlcpy instead of strncpy, thanks to
Antoine Brodin.
2007-07-31 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.c (usage): use exit_code, add --version and
--help.
* telnetd/telnetd.c: Add --help, reported by David Love.
2007-07-30 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/main.c: Catch --help, reported by David Love.
2007-07-12 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c: GLIBC made the choice that ut_tv should be
shared between 32 and 64 bit platforms so now we can no longer use
struct timeval functions to compare or set/get data that uses
pointer (gettimeofday for example) since ut_tv is now not a struct
timeval but rather a struct { int32_t tv_sec; int32_t tv_usec; };
2006-10-21 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/telnet_locl.h: Include roken.h before the local
headerfiles.
* telnetd/telnetd.h: HP/UX defines SE in sys/uio.h, #undef it.
* telnetd/sys_term.c: Dont't include some streamspty headers here.
* telnetd/telnetd.c: Dont't include some streamspty headers here.
* telnetd/telnetd.h: includes some STREAMSPTY header here to avoid
ioctl vs socket_wrapper horror.
2006-10-20 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/Makefile.am: more files
* telnetd/Makefile.am: more files
2006-09-19 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.8: Add documentation for -e, require encryption.
* telnetd/telnetd.h: Add require_encryption.
* telnetd/telnetd.c: Allow encryption to be required, wait to the
client to turn it on, if failes, refuse the connection.
* telnetd/state.c: If encryption is required, don't allow it to be
turned off.
2006-09-04 Love Hörnquist Åstrand <lha@it.su.se>
* libtelnet/kerberos5.c (kerberos5_forward): use KDCOptions2int on
flags before passing them to krb5_get_forwarded_creds.
2006-05-05 Love Hörnquist Åstrand <lha@it.su.se>
* Rename u_intXX_t to uintXX_t
2006-03-23 Love Hörnquist Åstrand <lha@it.su.se>
* libtelnet/encrypt.c: Spelling.
2005-12-01 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.c: Initialize the slc mapping table before its
used. Based on bug report from Russell Sanford
<rrs@clyde.dcccd.edu>
2005-11-03 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/telnet.c: Spelling in comments, from Dave Love
<fx@gnu.org>
2005-10-31 Love Hörnquist Åstrand <lha@it.su.se>
* libtelnet/kerberos5.c (Data): Use right variable. From Tomas
Olsson
2005-10-22 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/commands.c: Check return value from asprintf instead of
string != NULL since it undefined behavior on Linux. From Björn
Sandell
* libtelnet/kerberos5.c: Check return value from asprintf instead
of string != NULL since it undefined behavior on Linux. From Björn
Sandell
* libtelnet/kerberos.c: Check return value from asprintf instead
of string != NULL since it undefined behavior on Linux. From Björn
Sandell
2005-08-08 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.c: Fix printing of /etc/issue{,.net}.
* telnetd/utility.c: make writenet take const void * and size_t,
abort if size it too large
* telnetd/state.c: Fix ansi c warning.
* telnetd/sys_term.c: no need to typecast argument to writenet
* telnetd/ext.h: make writenet take const void * and size_t
2005-07-07 Assar Westerlund <assar@kth.se>
* libtelnet/kerberos.c: Do not assume that des_key_schedule is an
array.
2005-05-27 Love Hörnquist Åstrand <lha@it.su.se>
* libtelnet/kerberos5.c: case uid_t to unsigned long in printf
format
* telnetd/sys_term.c (set_termbuf): use {} around if to make else
unambiguous
2005-05-20 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c (start_login): put utmpx code into a new
scope to avoid pre c99 problems.
2005-05-19 Dave Love <fx@gnu.org>
* telnet/telnet.c,telnet_locl.h: Make solaris find tgetent
2005-05-13 Johan Danielsson <joda@pdc.kth.se>
* telnetd/sys_term.c (start_login): set encryption pointers to
NULL, so we don't try to do either
2005-05-11 Dave Love <fx@gnu.org>
* telnet/telnet.c: undef ISASCII before we define our own (problem
on Irix)
2005-04-28 Johan Danielsson <joda@pdc.kth.se>
* telnetd/utility.c (putf): %t: the regular and streamspty case
are functionally equivalent, so merge them, this also makes it
work better on machines that puts their devices in a subdirectory
to /dev
2005-04-27 Dave Love <fx@gnu.org>
* telnetd/sys_term.c (getpty): Declare p.
2005-04-25 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.c: use strlcpy
2005-04-24 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/global.c, telnetd/state.c, telnetd/telnetd.c,
telentd/ext.h: remove another strcpy
2005-04-19 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c: rewrite getpty to make use openpty when its
found, save the slave fd so that cleanopen can use it if its
available
2005-04-07 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c: clean_ttyname might be unused, mark it so
with __attribute__
2005-04-06 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/sys_term.c: use NULL as last argument to execl, not 0
* telnet/commands.c: use NULL as last argument to execl, not 0
2005-03-29 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/telnet.c: From FreeBSD:
Correct a pair of buffer overflows in the telnet(1) command:
(CAN-2005-0468) A heap buffer overflow in env_opt_add() and related
functions.
(CAN-2005-0469) A global uninitialized data section buffer overflow in
slc_add_reply() and related functions.
As a result of these vulnerabilities, it may be possible for a
malicious telnet server or active network attacker to cause
telnet(1) to execute arbitrary code with the privileges of the
user running it.
Security: CAN-2005-0468, CAN-2005-0469 Security:
FreeBSD-SA-05:01.telnet Security:
http://www.idefense.com/application/poi/display?id=220&type=vulnerabilities
Security:
http://www.idefense.com/application/poi/display?id=221&type=vulnerabilities
These fixes are based in part on patches Submitted by: Solar
Designer <solar@openwall.com>
2005-03-23 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.c: remove setting of DES_check_key, all code
uses DES_set_key_checked
* libtelnet/enc_des.c: use DES_set_key_checked
2005-01-09 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/telnet.c: cast argument to toupper to unsigned char
* telnet/commands.c: cast argument to is* to unsigned char
2004-06-20 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/network.c: make network rings larger From: MAAAAA MOOOR
<huaraz@btinternet.com>
* telnetd/state.c: make subbuffer larger XXX resize dynamicly
From: MAAAAA MOOOR <huaraz@btinternet.com>
* libtelnet/kerberos5.c (Data): allocate the data needed to be
send From: MAAAAA MOOOR <huaraz@btinternet.com>
2004-04-02 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/main.c: make encrypt, forwardable, forward use appdefault
(that also searches libdefaults), prompted by Thomas Nystrom
<thn@saeab.se>
2004-03-22 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.c: call setprogname to make libvers happy
* telnet/main.c: call setprogname to make libvers happy
2003-09-25 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/externs.h: export Scheduler and scheduler_lockout_tty
* telnet/telnet.c (my_telnet): if telnet_spin returns failure,
complain that the server disconnected and exit
* telnet/authenc.c (telnet_spin): if Scheduler() returns failure
(-1) propagate to higher level
2003-09-03 Love Hörnquist Åstrand <lha@it.su.se>
* telnetd/telnetd.c: use new DES_ api
* libtelnet/enc_des.c: use new DES_ api
2003-04-22 Love Hörnquist Åstrand <lha@it.su.se>
* telnet/telnet.1: replace <,> with \*[Lt],\*[Gt]
2002-09-02 Johan Danielsson <joda@pdc.kth.se>
* libtelnet/kerberos5.c: set AP_OPTS_USE_SUBKEY
2002-08-28 Johan Danielsson <joda@pdc.kth.se>
* telnet/commands.c: remove extra "Toggle"'s
* telnet/commands.c: IRIX == 4 -> IRIX4
* telnet/main.c: rename functions to what they're really called
* telnet/commands.c: kill some might be uninitialized warnings
* telnet/commands.c: add forward and forwardable toggle options,
and call set_forward_options() after parsing .telnetrc
* telnet/externs.h: proto for set_forward_options
* telnet/main.c: only register what forwarding options are asked
for when parsing command line, we have to set the actual flags
later after we have read .telnetrc
* libtelnet/auth-proto.h: kerberos5_set_forward{,able} protos
* libtelnet/kerberos5.c: add kerberos5_set_forward{,able}
functions suitable for the command parser
2002-08-23 Assar Westerlund <assar@kth.se>
* telnetd/telnetd.c: add --version as a special case
* telnet/main.c: add --version as a special case
2002-05-03 Johan Danielsson <joda@pdc.kth.se>
* telnet/telnet.c: only try to negotiate encryption if we're
talking to a real telnet
2002-03-31 Johan Danielsson <joda@pdc.kth.se>
* telnet/commands.c: fix an old cut-n-paste typo (via debian)
2002-02-07 Johan Danielsson <joda@pdc.kth.se>
* telnet/telnet.c: print a more informative message than "done"
after negotiating encryption
2001-09-17 Assar Westerlund <assar@sics.se>
* telnetd/telnetd.c: add a kludge to make it build on aix (that
defines NOERROR in both sys/stream.h and arpa/nameser.h and
considers that a fatal error)
* telnet/telnet.c: undef PUTSHORT to avoid conflict
2001-08-26 Assar Westerlund <assar@sics.se>
* telnetd/Makefile.am: also link with the library for logout
2001-08-22 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c: include libutil.h if it exists
2001-08-10 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (getpty): call openpty if it exists
2001-07-19 Assar Westerlund <assar@sics.se>
* telnetd/global.c (output_data): make sure of not forwarding
`nfrontp' too far, thereby allowing writes after the end of
`netobuf'
2001-06-18 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos5.c: update to new krb5_auth_con* names
2001-04-25 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (start_login): give the correct error if exec
fails
* telnetd/utility.c (fatalperror_errno): add a new function with
explicit errno parameter
2001-03-07 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c: some minimal more amount of
const-correctness
2001-02-24 Assar Westerlund <assar@sics.se>
* libtelnet/enc_des.c: learn to live with libcrypto (from openssl)
2001-02-20 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): copy the hostname so it doesn't get
overwritten while reading ~/.telnetrc
(*): removed some unneeded externs
2001-02-08 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (startslave, start_login): re-write code to
keep track both of remote hostname and utmp string to be used
* telnetd/telnetd.c (doit, my_telnet): re-write code to keep track
both of remote hostname and utmp string to be used
2001-02-07 Assar Westerlund <assar@sics.se>
* telnet/Makefile.am, telnetd/Makefile.am: add LIB_kdfs
2001-01-09 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos5.c (kerberos5_is): use krb5_rd_cred2 instead
of krb5_rd_cred
2000-12-31 Assar Westerlund <assar@sics.se>
* telnet/main.c (krb5_init): check krb5_init_context for success
* libtelnet/kerberos5.c (kerberos5_init): check krb5_init_context
for success
2000-12-11 Assar Westerlund <assar@sics.se>
* telnet/commands.c (sourceroute): make it not break if the
rfc2292 api does not exist
2000-12-09 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (scrub_env): add supporting non-file TERMCAP
variables
2000-12-07 Assar Westerlund <assar@sics.se>
* telnetd/telnetd.h: move include files around to avoid getting SE
from sys/*.h on HP to override SE from telnet.h
* telnetd/sys_term.c (scrub_env): remove some const-ness
* telnetd/sys_term.c (scrub_env): add LOGNAME and POSIXLY_CORRECT
to the list of authorized environment variables to be compatible
with linux-telnetd
* telnetd/sys_term.c (scrub_env): change filtering algoritm from
allowing everything except a few bad cases to not allowing
anything except a few non-dangerous cases
2000-12-06 Johan Danielsson <joda@pdc.kth.se>
* libtelnet/kerberos5.c: de-pointerise auth_context parameter to
krb5_mk_rep
2000-11-23 Johan Danielsson <joda@pdc.kth.se>
* libtelnet/kerberos5.c: print the principal we're trying to use
* libtelnet/kerberos.c: print the principal we're trying to use
2000-11-16 Assar Westerlund <assar@sics.se>
* libtelnet/misc-proto.h (telnet_getenv): const-ize some
2000-11-08 Johan Danielsson <joda@pdc.kth.se>
* telnet/telnet.c: fake entry if no tgetent
2000-10-08 Assar Westerlund <assar@sics.se>
* telnetd/utility.c (stilloob): check that fds are not too large
to select on
(ttloop): remove confusing output of errno
* telnetd/telnetd.c (my_telnet): check that fds are not too large
to select on
* telnet/utilities.c (EmptyTerminal): check that fds are not too
large to select on
* telnet/sys_bsd.c (process_rings): check that fds are not too
large to select on
* telnet/network.c (stilloob): check that fds are not too large to
select on
2000-06-09 Assar Westerlund <assar@sics.se>
* telnet/commands.c: remove all setuid(getuid()). we do not
support telnet being setuid root
2000-05-05 Assar Westerlund <assar@sics.se>
* telnet/externs.h (sourceroute): update prototype
* telnet/commands.c (tn): re-enable source routing
(sourceroute): make it work again based on the code from
itojun@kame.net
2000-03-28 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): clean-up a tiny little bit. give-up if
we do not manage to connect to any address
2000-03-26 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (*): make sure to always call time, ctime,
and gmtime with `time_t's. there were some types (like in
lastlog) that we believed to always be time_t. this has proven
wrong on Solaris 8 in 64-bit mode, where they are stored as 32-bit
quantities but time_t has gone up to 64 bits
2000-03-03 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos5.c (kerberos5_init): check that we do have a
keytab before saying that we will support KERBEROS5
2000-02-12 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): only set tos for AF_INET. From
itojun@iijlab.net
2000-02-07 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos.c (kerberos4_is): send a reject back to the
client when we're not authorized
2000-02-06 Assar Westerlund <assar@sics.se>
* telnet/ring.h (ring_encrypt): better proto
* telnet/ring.c (ring_encrypt): better proto
2000-02-04 Assar Westerlund <assar@sics.se>
* telnet/telnet_locl.h: klduge-around KLUDGELINEMODE
2000-01-18 Assar Westerlund <assar@sics.se>
* libtelnet/misc.c (auth_encrypt_user): const-ify
* libtelnet/misc.h (RemoteHostName, LocalHostName): const-ify
* libtelnet/misc.c (auth_encrypt_init, RemoteHostName,
LocalHostName): const-ify
* libtelnet/misc-proto.h (auth_encrypt_init, auth_encrypt_user):
const-ify
* libtelnet/encrypt.c (encrypt_init, Name): const-ify
* libtelnet/enc-proto.h (encrypt_init): const-ify
* libtelnet/auth.c (auth_init, Name): const-ify
* libtelnet/auth-proto.h (auth_init): const-ify
2000-01-08 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): handle ai_canonname being set in any of
the addresses returnedby getaddrinfo. glibc apparently returns
the reverse lookup of every address in ai_canonname. remove some
unused variables.
2000-01-01 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (addarg): make void (return value isn't check
anyway). fatal error when malloc fails
1999-12-16 Assar Westerlund <assar@sics.se>
* telnet/commands.c (*): handle ai_canonname not being set
1999-12-04 Assar Westerlund <assar@sics.se>
* telnetd/telnetd.c (doit): use getnameinfo_verified
* telnetd/telnetd.c: use getnameinfo
* telnet/commands.c: re-write to using getaddrinfo. disable
source-routing for the moment, it doesn't seem to be used anyways.
1999-09-16 Assar Westerlund <assar@sics.se>
* telnet/commands.c: revert 1.54, get_default_username should DTRT
now
1999-09-05 Assar Westerlund <assar@sics.se>
* telnetd/utility.c (ttloop): make it return 1 if interrupted by a
signal, which must have been what was meant from the beginning
* telnetd/ext.h (ttloop): update prototype
* telnetd/authenc.c (telnet_spin): actually return the value from
ttloop (otherwise it's kind of bogus)
1999-08-05 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (rmut): free utxp
1999-08-04 Assar Westerlund <assar@sics.se>
* telnet/main.c: add -G and config file support. From Miroslav
Ruda <ruda@ics.muni.cz>
* telnetd/sys_term.c (rmut): work around utmpx strangness. From
Miroslav Ruda <ruda@ics.muni.cz>
1999-08-02 Assar Westerlund <assar@sics.se>
* telnetd/telnetd.c (doit): only free hp if != NULL. From: Jonas
Oberg <jonas@coyote.org>
1999-07-29 Assar Westerlund <assar@sics.se>
* telnetd/telnetd.c (doit): remove unused variable mapped_sin
1999-07-26 Assar Westerlund <assar@sics.se>
* telnetd/ext.h: update prototypes
* telnetd/telnetd.c: make it handle v4 and v6 sockets. (it
doesn't handle being given a v6 socket that's really talking to an
v4 adress (mapped) because the rest of the code in telnetd is not
able to handle it anyway). please run two telnetd from your
inetd, one for v4 and one for v6.
1999-07-07 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): extra bogus const-cast
1999-07-06 Assar Westerlund <assar@sics.se>
* telnetd/sys_term.c (start_login): print a different warning with
`-a otp'
1999-06-24 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos5.c (kerberos5_send): set the addresses in the
auth_context
1999-06-23 Assar Westerlund <assar@sics.se>
* telnet/Makefile.am (INCLUDES): add $(INCLUDE_krb4)
* telnet/commands.c (togkrbdebug): conditionalize on
krb_disable_debug
1999-06-16 Johan Danielsson <joda@pdc.kth.se>
* telnet/commands.c: add kerberos debugging option
1999-06-15 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): use get_default_username
1999-05-14 Assar Westerlund <assar@sics.se>
* telnetd/state.c (telrcv): magic patch to make it work against
DOS Clarkson Telnet. From Miroslav Ruda <ruda@ics.muni.cz>
1999-04-25 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos5.c (kerberos5_send): use
`krb5_auth_setkeytype' instead of `krb5_auth_setenctype' to make
sure we get a DES session key.
Thu Apr 1 16:59:27 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* telnetd/Makefile.am: don't run check-local
* telnet/Makefile.am: don't run check-local
Mon Mar 29 16:11:33 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* telnetd/sys_term.c: _CRAY -> HAVE_STRUCT_UTMP_UT_ID
Sat Mar 20 00:12:54 1999 Assar Westerlund <assar@sics.se>
* telnet/authenc.c (telnet_gets): remove old extern declarations
Thu Mar 18 11:20:16 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* telnetd/Makefile.am: include Makefile.am.common
* telnet/Makefile.am: include Makefile.am.common
* libtelnet/Makefile.am: include Makefile.am.common
* Makefile.am: include Makefile.am.common
Mon Mar 15 17:40:53 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* telnetd/telnetd.c: replace perror/exit with fatalperror
Sat Mar 13 22:18:57 1999 Assar Westerlund <assar@sics.se>
* telnetd/telnetd.c (main): 0 -> STDIN_FILENO. remove abs
* libtelnet/kerberos.c (kerberos4_is): syslog root logins
Thu Mar 11 14:48:54 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* telnetd/Makefile.in: add WFLAGS
* telnet/Makefile.in: add WFLAGS
* libtelnet/Makefile.in: add WFLAGS
* telnetd/sys_term.c: remove unused variables
* telnet/telnet.c: fix some warnings
* telnet/main.c: fix some warnings
* telnet/commands.c: fix types in format string
* libtelnet/auth.c: fix types in format string
Mon Mar 1 10:50:30 1999 Johan Danielsson <joda@hella.pdc.kth.se>
* telnetd/sys_term.c: HAVE_UT_* -> HAVE_STRUCT_UTMP*_UT_*
Mon Feb 1 04:08:36 1999 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): only call gethostbyname2 with AF_INET6
if we actually have IPv6. From "Brandon S. Allbery KF8NH"
<allbery@kf8nh.apk.net>
Sat Nov 21 16:51:00 1998 Johan Danielsson <joda@hella.pdc.kth.se>
* telnetd/sys_term.c (cleanup): don't call vhangup() on sgi:s
Fri Aug 14 16:29:18 1998 Johan Danielsson <joda@emma.pdc.kth.se>
* libtelnet/kerberos.c: krb_put_int -> KRB_PUT_INT
Thu Jul 23 20:29:05 1998 Johan Danielsson <joda@emma.pdc.kth.se>
* libtelnet/kerberos5.c: use krb5_verify_authenticator_checksum
Mon Jul 13 22:00:09 1998 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): don't advance hostent->h_addr_list, use
a copy instead
Wed May 27 04:19:17 1998 Assar Westerlund <assar@sics.se>
* telnet/sys_bsd.c (process_rings): correct call to `stilloob'
Fri May 15 19:38:19 1998 Johan Danielsson <joda@blubb.pdc.kth.se>
* libtelnet/kerberos5.c: Always print errors from mk_req.
Fri May 1 07:16:59 1998 Assar Westerlund <assar@sics.se>
* telnet/commands.c: unifdef -DHAVE_H_ERRNO
Sat Apr 4 15:00:29 1998 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): moved the printing of `trying...' to the
loop
Thu Mar 12 02:33:48 1998 Assar Westerlund <assar@sics.se>
* telnet/telnet_locl.h: include <term.h>. From Gregory S. Stark
<gsstark@mit.edu>
Sat Feb 21 15:12:38 1998 Assar Westerlund <assar@sics.se>
* telnetd/ext.h: add prototype for login_tty
* telnet/utilities.c (printsub): `direction' is now an int.
* libtelnet/misc-proto.h: add prototype for `printsub'
Tue Feb 17 02:45:01 1998 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos.c (kerberos4_is): cred.pname should be
cred.pinst. From <art@stacken.kth.se>
Sun Feb 15 02:46:39 1998 Assar Westerlund <assar@sics.se>
* telnet/*/*.c: renamed `telnet' to `my_telnet' to avoid
conflicts with system header files on mklinux.
Tue Feb 10 02:09:03 1998 Assar Westerlund <assar@sics.se>
* telnetd/telnetd.c: new signature for `getterminaltype' and
`auth_wait'
* libtelnet: changed the signature of the authentication method
`status'
Sat Feb 7 07:21:29 1998 Assar Westerlund <assar@sics.se>
* */*.c: replace HAS_GETTOS by HAVE_PARSETOS and HAVE_GETTOSBYNAME
Fri Dec 26 16:17:10 1997 Assar Westerlund <assar@sics.se>
* telnet/commands.c (tn): repair support for numeric addresses
Sun Dec 21 09:40:31 1997 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos.c: fix up lots of stuff related to the
forwarding of v4 tickets.
* libtelnet/kerberos5.c (kerberos5_forward): zero out `creds'.
Mon Dec 15 20:53:13 1997 Johan Danielsson <joda@emma.pdc.kth.se>
* telnet/sys_bsd.c: Don't turn off OPOST in 8bit-mode.
Tue Dec 9 19:26:50 1997 Assar Westerlund <assar@sics.se>
* telnet/main.c (main): add 'b' to getopt
Sat Nov 29 03:28:54 1997 Johan Danielsson <joda@emma.pdc.kth.se>
* telnet/telnet.c: Change binary mode to do just that, and add a
eight-bit mode for just passing all characters.
Sun Nov 16 04:37:02 1997 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos5.c (kerberos5_send): always ask for a session
key of type DES
* libtelnet/kerberos5.c: remove old garbage and fix call to
krb5_auth_con_setaddrs_from_fd
Fri Nov 14 20:35:18 1997 Johan Danielsson <joda@emma.pdc.kth.se>
* telnetd/telnetd.c: Output contents of /etc/issue.
Mon Nov 3 07:09:16 1997 Assar Westerlund <assar@sics.se>
* telnet/telnet_locl.h: only include <sys/termio.h> iff
!defined(HAVE_TERMIOS_H)
* libtelnet/kerberos.c (kerberos4_is): send the peer address to
krb_rd_req
* telnetd/telnetd.c (terminaltypeok): always return OK. It used
to call `tgetent' to figure if it was a defined terminal type.
It's possible to overflow tgetent so that's a bad idea. The worst
that could happen by saying yes to all terminals is that the user
ends up with a terminal that has no definition on the local
system. And besides, most telnet client has no support for
falling back to a different terminal type.
Mon Oct 20 05:47:19 1997 Assar Westerlund <assar@sics.se>
* libtelnet/kerberos5.c: remove lots of old junk. clean-up.
better error checking and reporting. tell the user permission
denied much earlier.
* libtelnet/kerberos.c (kerberos4_is): only print
UserNameRequested if != NULL

View File

@@ -1,11 +0,0 @@
# $Id$
include $(top_srcdir)/Makefile.am.common
SUBDIRS = libtelnet telnet telnetd
dist-hook:
$(mkinstalldirs) $(distdir)/arpa
$(INSTALL_DATA) $(srcdir)/arpa/telnet.h $(distdir)/arpa
EXTRA_DIST = NTMakefile README.ORIG telnet.state

View File

@@ -1,35 +0,0 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT HOLDER 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.
#
RELDIR=appl\telnet
!include ../../windows/NTMakefile.w32

View File

@@ -1,743 +0,0 @@
This is a distribution of both client and server telnet. These programs
have been compiled on:
telnet telnetd
4.4 BSD-Lite x x
4.3 BSD Reno X X
UNICOS 9.1 X X
UNICOS 9.0 X X
UNICOS 8.0 X X
BSDI 2.0 X X
Solaris 2.4 x x (no linemode in server)
SunOs 4.1.4 X X (no linemode in server)
Ultrix 4.3 X X (no linemode in server)
Ultrix 4.1 X X (no linemode in server)
In addition, previous versions have been compiled on the following
machines, but were not available for testing this version.
telnet telnetd
Next1.0 X X
UNICOS 8.3 X X
UNICOS 7.C X X
UNICOS 7.0 X X
SunOs 4.0.3c X X (no linemode in server)
4.3 BSD X X (no linemode in server)
DYNIX V3.0.12 X X (no linemode in server)
Ultrix 3.1 X X (no linemode in server)
Ultrix 4.0 X X (no linemode in server)
SunOs 3.5 X X (no linemode in server)
SunOs 4.1.3 X X (no linemode in server)
Solaris 2.2 x x (no linemode in server)
Solaris 2.3 x x (no linemode in server)
BSDI 1.0 X X
BSDI 1.1 X X
DYNIX V3.0.17.9 X X (no linemode in server)
HP-UX 8.0 x x (no linemode in server)
This code should work, but there are no guarantees.
May 30, 1995
This release represents what is on the 4.4BSD-Lite2 release, which
should be the final BSD release. I will continue to support of
telnet, The code (without encryption) is available via anonymous ftp
from ftp.cray.com, in src/telnet/telnet.YY.MM.DD.NE.tar.Z, where
YY.MM.DD is replaced with the year, month and day of the release.
If you can't find it at one of these places, at some point in the
near future information about the latest releases should be available
from ftp.borman.com.
In addition, the version with the encryption code is available via
ftp from net-dist.mit.edu, in the directory /pub/telnet. There
is a README file there that gives further information on how
to get the distribution.
Questions, comments, bug reports and bug fixes can be sent to
one of these addresses:
dab@borman.com
dab@cray.com
dab@bsdi.com
This release is mainly bug fixes and code cleanup.
Replace all calls to bcopy()/bzero() with calls to
memmove()/memset() and all calls to index()/rindex()
with calls to strchr()/strrchr().
Add some missing diagnostics for option tracing
to telnetd.
Add support for BSDI 2.0 and Solaris 2.4.
Add support for UNICOS 8.0
Get rid of expanded tabs and trailing white spaces.
From Paul Vixie:
Fix for telnet going into an endless spin
when the session dies abnormally.
From Jef Poskanzer:
Changes to allow telnet to compile
under SunOS 3.5.
From Philip Guenther:
makeutx() doesn't expand utmpx,
use pututxline() instead.
From Chris Torek:
Add a sleep(1) before execing login
to avoid race condition that can eat
up the login prompt.
Use terminal speed directly if it is
not an encoded value.
From Steve Parker:
Fix to realloc() call. Fix for execing
login on solaris with no user name.
January 19, 1994
This is a list of some of the changes since the last tar release
of telnet/telnetd. There are probably other changes that aren't
listed here, but this should hit a lot of the main ones.
General:
Changed #define for AUTHENTICATE to AUTHENTICATION
Changed #define for ENCRYPT to ENCRYPTION
Changed #define for DES_ENCRYPT to DES_ENCRYPTION
Added support for SPX authentication: -DSPX
Added support for Kerberos Version 5 authentication: -DKRB5
Added support for ANSI C function prototypes
Added support for the NEW-ENVIRON option (RFC-1572)
including support for USERVAR.
Made support for the old Environment Option (RFC-1408)
conditional on -DOLD_ENVIRON
Added #define ENV_HACK - support for RFC 1571
The encryption code is removed from the public distributions.
Domestic 4.4 BSD distributions contain the encryption code.
ENV_HACK: Code to deal with systems that only implement
the old ENVIRON option, and have reversed definitions
of ENV_VAR and ENV_VAL. Also fixes ENV processing in
client to handle things besides just the default set...
NO_BSD_SETJMP: UNICOS configuration for
UNICOS 6.1/6.0/5.1/5.0 systems.
STREAMSPTY: Use /dev/ptmx to get a clean pty. This
is for SVr4 derivatives (Like Solaris)
UTMPX: For systems that have /etc/utmpx. This is for
SVr4 derivatives (Like Solaris)
Definitions for BSDI 1.0
Definitions for 4.3 Reno and 4.4 BSD.
Definitions for UNICOS 8.0 and UNICOS 7.C
Definitions for Solaris 2.0
Definitions for HP-UX 8.0
Latest Copyright notices from Berkeley.
FLOW-CONTROL: support for RFC-XXXx
Client Specific:
Fix the "send" command to not send garbage...
Fix status message for "skiprc"
Make sure to send NAWS after telnet has been suspended
or an external command has been run, if the window size
has changed.
sysV88 support.
Server Specific:
Support flowcontrol option in non-linemode servers.
-k Server supports Kludge Linemode, but will default to
either single character mode or real Linemode support.
The user will have to explicitly ask to switch into
kludge linemode. ("stty extproc", or escape back to
to telnet and say "mode line".)
-u Specify the length of the hostname field in the utmp
file. Hostname longer than this length will be put
into the utmp file in dotted decimal notation, rather
than putting in a truncated hostname.
-U Registered hosts only. If a reverse hostname lookup
fails, the connection will be refused.
-f/-F
Allows forwarding of credentials for KRB5.
Februrary 22, 1991:
Features:
This version of telnet/telnetd has support for both
the AUTHENTICATION and ENCRYPTION options. The
AUTHENTICATION option is fairly well defined, and
an option number has been assigned to it. The
ENCRYPTION option is still in a state of flux; an
option number has been assigned to, but it is still
subject to change. The code is provided in this release
for experimental and testing purposes.
The telnet "send" command can now be used to send
do/dont/will/wont commands, with any telnet option
name. The rules for when do/dont/will/wont are sent
are still followed, so just because the user requests
that one of these be sent doesn't mean that it will
be sent...
The telnet "getstatus" command no longer requires
that option printing be enabled to see the response
to the "DO STATUS" command.
A -n flag has been added to telnetd to disable
keepalives.
A new telnet command, "auth" has been added (if
AUTHENTICATE is defined). It has four sub-commands,
"status", "disable", "enable" and "help".
A new telnet command, "encrypt" has been added (if
ENCRYPT is defined). It has many sub-commands:
"enable", "type", "start", "stop", "input",
"-input", "output", "-output", "status", and "help".
The LOGOUT option is now supported by both telnet
and telnetd, a new command, "logout", was added
to support this.
Several new toggle options were added:
"autoencrypt", "autodecrypt", "autologin", "authdebug",
"encdebug", "skiprc", "verbose_encrypt"
An "rlogin" interface has been added. If the program
is named "rlogin", or the "-r" flag is given, then
an rlogin type of interface will be used.
~. Terminates the session
~<susp> Suspend the session
~^] Escape to telnet command mode
~~ Pass through the ~.
BUG: If you type the rlogin escape character
in the middle of a line while in rlogin
mode, you cannot erase it or any characters
before it. Hopefully this can be fixed
in a future release...
General changes:
A "libtelnet.a" has now been created. This libraray
contains code that is common to both telnet and
telnetd. This is also where library routines that
are needed, but are not in the standard C library,
are placed.
The makefiles have been re-done. All of the site
specific configuration information has now been put
into a single "Config.generic" file, in the top level
directory. Changing this one file will take care of
all three subdirectories. Also, to add a new/local
definition, a "Config.local" file may be created
at the top level; if that file exists, the subdirectories
will use that file instead of "Config.generic".
Many 1-2 line functions in commands.c have been
removed, and just inserted in-line, or replaced
with a macro.
Bug Fixes:
The non-termio code in both telnet and telnetd was
setting/clearing CTLECH in the sg_flags word. This
was incorrect, and has been changed to set/clear the
LCTLECH bit in the local mode word.
The SRCRT #define has been removed. If IP_OPTIONS
and IPPROTO_IP are defined on the system, then the
source route code is automatically enabled.
The NO_GETTYTAB #define has been removed; there
is a compatability routine that can be built into
libtelnet to achive the same results.
The server, telnetd, has been switched to use getopt()
for parsing the argument list.
The code for getting the input/output speeds via
cfgetispeed()/cfgetospeed() was still not quite
right in telnet. Posix says if the ispeed is 0,
then it is really equal to the ospeed.
The suboption processing code in telnet now has
explicit checks to make sure that we received
the entire suboption (telnetd was already doing this).
The telnet code for processing the terminal type
could cause a core dump if an existing connection
was closed, and a new connection opened without
exiting telnet.
Telnetd was doing a TCSADRAIN when setting the new
terminal settings; This is not good, because it means
that the tcsetattr() will hang waiting for output to
drain, and telnetd is the only one that will drain
the output... The fix is to use TCSANOW which does
not wait.
Telnetd was improperly setting/clearing the ISTRIP
flag in the c_lflag field, it should be using the
c_iflag field.
When the child process of telnetd was opening the
slave side of the pty, it was re-setting the EXTPROC
bit too early, and some of the other initialization
code was wiping it out. This would cause telnetd
to go out of linemode and into single character mode.
One instance of leaving linemode in telnetd forgot
to send a WILL ECHO to the client, the net result
would be that the user would see double character
echo.
If the MODE was being changed several times very
quickly, telnetd could get out of sync with the
state changes and the returning acks; and wind up
being left in the wrong state.
September 14, 1990:
Switch the client to use getopt() for parsing the
argument list. The 4.3Reno getopt.c is included for
systems that don't have getopt().
Use the posix _POSIX_VDISABLE value for what value
to use when disabling special characters. If this
is undefined, it defaults to 0x3ff.
For non-termio systems, TIOCSETP was being used to
change the state of the terminal. This causes the
input queue to be flushed, which we don't want. This
is now changed to TIOCSETN.
Take out the "#ifdef notdef" around the code in the
server that generates a "sync" when the pty oputput
is flushed. The potential problem is that some older
telnet clients may go into an infinate loop when they
receive a "sync", if so, the server can be compiled
with "NO_URGENT" defined.
Fix the client where it was setting/clearing the OPOST
bit in the c_lflag field, not the c_oflag field.
Fix the client where it was setting/clearing the ISTRIP
bit in the c_lflag field, not the c_iflag field. (On
4.3Reno, this is the ECHOPRT bit in the c_lflag field.)
The client also had its interpretation of WILL BINARY
and DO BINARY reversed.
Fix a bug in client that would cause a core dump when
attempting to remove the last environment variable.
In the client, there were a few places were switch()
was being passed a character, and if it was a negative
value, it could get sign extended, and not match
the 8 bit case statements. The fix is to and the
switch value with 0xff.
Add a couple more printoption() calls in the client, I
don't think there are any more places were a telnet
command can be received and not printed out when
"options" is on.
A new flag has been added to the client, "-a". Currently,
this just causes the USER name to be sent across, in
the future this may be used to signify that automatic
authentication is requested.
The USER variable is now only sent by the client if
the "-a" or "-l user" options are explicity used, or
if the user explicitly asks for the "USER" environment
variable to be exported. In the server, if it receives
the "USER" environment variable, it won't print out the
banner message, so that only "Password:" will be printed.
This makes the symantics more like rlogin, and should be
more familiar to the user. (People are not used to
getting a banner message, and then getting just a
"Password:" prompt.)
Re-vamp the code for starting up the child login
process. The code was getting ugly, and it was
hard to tell what was really going on. What we
do now is after the fork(), in the child:
1) make sure we have no controlling tty
2) open and initialize the tty
3) do a setsid()/setpgrp()
4) makes the tty our controlling tty.
On some systems, #2 makes the tty our controlling
tty, and #4 is a no-op. The parent process does
a gets rid of any controlling tty after the child
is fork()ed.
Use the strdup() library routine in telnet, instead
of the local savestr() routine. If you don't have
strdup(), you need to define NO_STRDUP.
Add support for ^T (SIGINFO/VSTATUS), found in the
4.3Reno distribution. This maps to the AYT character.
You need a 4-line bugfix in the kernel to get this
to work properly:
> *** tty_pty.c.ORG Tue Sep 11 09:41:53 1990
> --- tty_pty.c Tue Sep 11 17:48:03 1990
> ***************
> *** 609,613 ****
> if ((tp->t_lflag&NOFLSH) == 0)
> ttyflush(tp, FREAD|FWRITE);
> ! pgsignal(tp->t_pgrp, *(unsigned int *)data);
> return(0);
> }
> --- 609,616 ----
> if ((tp->t_lflag&NOFLSH) == 0)
> ttyflush(tp, FREAD|FWRITE);
> ! pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
> ! if ((*(unsigned int *)data == SIGINFO) &&
> ! ((tp->t_lflag&NOKERNINFO) == 0))
> ! ttyinfo(tp);
> return(0);
> }
The client is now smarter when setting the telnet escape
character; it only sets it to one of VEOL and VEOL2 if
one of them is undefined, and the other one is not already
defined to the telnet escape character.
Handle TERMIOS systems that have seperate input and output
line speed settings imbedded in the flags.
Many other minor bug fixes.
June 20, 1990:
Re-organize makefiles and source tree. The telnet/Source
directory is now gone, and all the source that was in
telnet/Source is now just in the telnet directory.
Seperate makefile for each system are now gone. There
are two makefiles, Makefile and Makefile.generic.
The "Makefile" has the definitions for the various
system, and "Makefile.generic" does all the work.
There is a variable called "WHAT" that is used to
specify what to make. For example, in the telnet
directory, you might say:
make 4.4bsd WHAT=clean
to clean out the directory.
Add support for the ENVIRON and XDISPLOC options.
In order for the server to work, login has to have
the "-p" option to preserve environment variables.
Add the SOFT_TAB and LIT_ECHO modes in the LINEMODE support.
Add the "-l user" option to command line and open command
(This is passed through the ENVIRON option).
Add the "-e" command line option, for setting the escape
character.
Add the "-D", diagnostic, option to the server. This allows
the server to print out debug information, which is very
useful when trying to debug a telnet that doesn't have any
debugging ability.
Turn off the literal next character when not in LINEMODE.
Don't recognize ^Y locally, just pass it through.
Make minor modifications for Sun4.0 and Sun4.1
Add support for both FORW1 and FORW2 characters. The
telnet escpape character is set to whichever of the
two is not being used. If both are in use, the escape
character is not set, so when in linemode the user will
have to follow the escape character with a <CR> or <EOF)
to get it passed through.
Commands can now be put in single and double quotes, and
a backslash is now an escape character. This is needed
for allowing arbitrary strings to be assigned to environment
variables.
Switch telnetd to use macros like telnet for keeping
track of the state of all the options.
Fix telnetd's processing of options so that we always do
the right processing of the LINEMODE option, regardless
of who initiates the request to turn it on. Also, make
sure that if the other side went "WILL ECHO" in response
to our "DO ECHO", that we send a "DONT ECHO" to get the
option turned back off!
Fix the TERMIOS setting of the terminal speed to handle both
BSD's seperate fields, and the SYSV method of CBAUD bits.
Change how we deal with the other side refusing to enable
an option. The sequence used to be: send DO option; receive
WONT option; send DONT option. Now, the sequence is: send
DO option; receive WONT option. Both should be valid
according to the spec, but there has been at least one
client implementation of telnet identified that can get
really confused by this. (The exact sequence, from a trace
on the server side, is (numbers are number of responses that
we expect to get after that line...):
send WILL ECHO 1 (initial request)
send WONT ECHO 2 (server is changing state)
recv DO ECHO 1 (first reply, ok. expect DONT ECHO next)
send WILL ECHO 2 (server changes state again)
recv DONT ECHO 1 (second reply, ok. expect DO ECHO next)
recv DONT ECHO 0 (third reply, wrong answer. got DONT!!!)
*** send WONT ECHO (send WONT to acknowledge the DONT)
send WILL ECHO 1 (ask again to enable option)
recv DO ECHO 0
recv DONT ECHO 0
send WONT ECHO 1
recv DONT ECHO 0
recv DO ECHO 1
send WILL ECHO 0
(and the last 5 lines loop forever)
The line with the "***" is last of the WILL/DONT/WONT sequence.
The change to the server to not generate that makes this same
example become:
send will ECHO 1
send wont ECHO 2
recv do ECHO 1
send will ECHO 2
recv dont ECHO 1
recv dont ECHO 0
recv do ECHO 1
send will ECHO 0
There is other option negotiation going on, and not sending
the third part changes some of the timings, but this specific
example no longer gets stuck in a loop. The "telnet.state"
file has been modified to reflect this change to the algorithm.
A bunch of miscellaneous bug fixes and changes to make
lint happier.
This version of telnet also has some KERBEROS stuff in
it. This has not been tested, it uses an un-authorized
telnet option number, and uses an out-of-date version
of the (still being defined) AUTHENTICATION option.
There is no support for this code, do not enable it.
March 1, 1990:
CHANGES/BUGFIXES SINCE LAST RELEASE:
Some support for IP TOS has been added. Requires that the
kernel support the IP_TOS socket option (currently this
is only in UNICOS 6.0).
Both telnet and telnetd now use the cc_t typedef. typedefs are
included for systems that don't have it (in termios.h).
SLC_SUSP was not supported properly before. It is now.
IAC EOF was not translated properly in telnetd for SYSV_TERMIO
when not in linemode. It now saves a copy of the VEOF character,
so that when ICANON is turned off and we can't trust it anymore
(because it is now the VMIN character) we use the saved value.
There were two missing "break" commands in the linemode
processing code in telnetd.
Telnetd wasn't setting the kernel window size information
properly. It was using the rows for both rows and columns...
Questions/comments go to
David Borman
Cray Research, Inc.
655F Lone Oak Drive
Eagan, MN 55123
dab@cray.com.
README: You are reading it.
Config.generic:
This file contains all the OS specific definitions. It
has pre-definitions for many common system types, and is
in standard makefile fromat. See the comments at the top
of the file for more information.
Config.local:
This is not part of the distribution, but if this file exists,
it is used instead of "Config.generic". This allows site
specific configuration without having to modify the distributed
"Config.generic" file.
kern.diff:
This file contains the diffs for the changes needed for the
kernel to support LINEMODE is the server. These changes are
for a 4.3BSD system. You may need to make some changes for
your particular system.
There is a new bit in the terminal state word, TS_EXTPROC.
When this bit is set, several aspects of the terminal driver
are disabled. Input line editing, character echo, and
mapping of signals are all disabled. This allows the telnetd
to turn of these functions when in linemode, but still keep
track of what state the user wants the terminal to be in.
New ioctl()s:
TIOCEXT Turn on/off the TS_EXTPROC bit
TIOCGSTATE Get t_state of tty to look at TS_EXTPROC bit
TIOCSIG Generate a signal to processes in the
current process group of the pty.
There is a new mode for packet driver, the TIOCPKT_IOCTL bit.
When packet mode is turned on in the pty, and the TS_EXTPROC
bit is set, then whenever the state of the pty is changed, the
next read on the master side of the pty will have the TIOCPKT_IOCTL
bit set, and the data will contain the following:
struct xx {
struct sgttyb a;
struct tchars b;
struct ltchars c;
int t_state;
int t_flags;
}
This allows the process on the server side of the pty to know
when the state of the terminal has changed, and what the new
state is.
However, if you define USE_TERMIO or SYSV_TERMIO, the code will
expect that the structure returned in the TIOCPKT_IOCTL is
the termio/termios structure.
stty.diff:
This file contains the changes needed for the stty(1) program
to report on the current status of the TS_EXTPROC bit. It also
allows the user to turn on/off the TS_EXTPROC bit. This is useful
because it allows the user to say "stty -extproc", and the
LINEMODE option will be automatically disabled, and saying "stty
extproc" will re-enable the LINEMODE option.
telnet.state:
Both the client and server have code in them to deal
with option negotiation loops. The algorithm that is
used is described in this file.
telnet:
This directory contains the client code. No kernel changes are
needed to use this code.
telnetd:
This directory contains the server code. If LINEMODE or KLUDGELINEMODE
are defined, then the kernel modifications listed above are needed.
libtelnet:
This directory contains code that is common to both the client
and the server.
arpa:
This directory has a new <arpa/telnet.h>
libtelnet/Makefile.4.4:
telnet/Makefile.4.4:
telnetd/Makefile.4.4:
These are the makefiles that can be used on a 4.3Reno
system when this software is installed in /usr/src/lib/libtelnet,
/usr/src/libexec/telnetd, and /usr/src/usr.bin/telnet.
The following TELNET options are supported:
LINEMODE:
The LINEMODE option is supported as per RFC1116. The
FORWARDMASK option is not currently supported.
BINARY: The client has the ability to turn on/off the BINARY
option in each direction. Turning on BINARY from
server to client causes the LITOUT bit to get set in
the terminal driver on both ends, turning on BINARY
from the client to the server causes the PASS8 bit
to get set in the terminal driver on both ends.
TERMINAL-TYPE:
This is supported as per RFC1091. On the server side,
when a terminal type is received, termcap/terminfo
is consulted to determine if it is a known terminal
type. It keeps requesting terminal types until it
gets one that it recongnizes, or hits the end of the
list. The server side looks up the entry in the
termcap/terminfo data base, and generates a list of
names which it then passes one at a time to each
request for a terminal type, duplicating the last
entry in the list before cycling back to the beginning.
NAWS: The Negotiate about Window Size, as per RFC 1073.
TERMINAL-SPEED:
Implemented as per RFC 1079
TOGGLE-FLOW-CONTROL:
Implemented as per RFC 1080
TIMING-MARK:
As per RFC 860
SGA: As per RFC 858
ECHO: As per RFC 857
LOGOUT: As per RFC 727
STATUS:
The server will send its current status upon
request. It does not ask for the clients status.
The client will request the servers current status
from the "send getstatus" command.
ENVIRON:
This option is currently being defined by the IETF
Telnet Working Group, and an RFC has not yet been
issued, but should be in the near future...
X-DISPLAY-LOCATION:
This functionality can be done through the ENVIRON
option, it is added here for completeness.
AUTHENTICATION:
This option is currently being defined by the IETF
Telnet Working Group, and an RFC has not yet been
issued. The basic framework is pretty much decided,
but the definitions for the specific authentication
schemes is still in a state of flux.
ENCRYPTION:
This option is currently being defined by the IETF
Telnet Working Group, and an RFC has not yet been
issued. The draft RFC is still in a state of flux,
so this code may change in the future.

View File

@@ -1,323 +0,0 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)telnet.h 8.2 (Berkeley) 12/15/93
*/
#ifndef _TELNET_H_
#define _TELNET_H_
/*
* Definitions for the TELNET protocol.
*/
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */
#define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */
#define SE 240 /* end sub negotiation */
#define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */
#define SYNCH 242 /* for telfunc calls */
#ifdef TELCMDS
char *telcmds[] = {
"EOF", "SUSP", "ABORT", "EOR",
"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
};
#else
extern char *telcmds[];
#endif
#define TELCMD_FIRST xEOF
#define TELCMD_LAST IAC
#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \
(unsigned int)(x) >= TELCMD_FIRST)
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
/* telnet options */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35 /* X Display Location */
#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
#define TELOPT_AUTHENTICATION 37/* Authenticate */
#define TELOPT_ENCRYPT 38 /* Encryption option */
#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
#define TELOPT_EXOPL 255 /* extended-options-list */
#define NTELOPTS (1+TELOPT_NEW_ENVIRON)
#ifdef TELOPTS
char *telopts[NTELOPTS+1] = {
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
"TACACS UID", "OUTPUT MARKING", "TTYLOC",
"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
"ENCRYPT", "NEW-ENVIRON",
0,
};
#define TELOPT_FIRST TELOPT_BINARY
#define TELOPT_LAST TELOPT_NEW_ENVIRON
#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST)
#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
#endif
/* sub-option qualifiers */
#define TELQUAL_IS 0 /* option is... */
#define TELQUAL_SEND 1 /* send option */
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */
#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */
#define LFLOW_OFF 0 /* Disable remote flow control */
#define LFLOW_ON 1 /* Enable remote flow control */
#define LFLOW_RESTART_ANY 2 /* Restart output on any char */
#define LFLOW_RESTART_XON 3 /* Restart output only on XON */
/*
* LINEMODE suboptions
*/
#define LM_MODE 1
#define LM_FORWARDMASK 2
#define LM_SLC 3
#define MODE_EDIT 0x01
#define MODE_TRAPSIG 0x02
#define MODE_ACK 0x04
#define MODE_SOFT_TAB 0x08
#define MODE_LIT_ECHO 0x10
#define MODE_MASK 0x1f
/* Not part of protocol, but needed to simplify things... */
#define MODE_FLOW 0x0100
#define MODE_ECHO 0x0200
#define MODE_INBIN 0x0400
#define MODE_OUTBIN 0x0800
#define MODE_FORCE 0x1000
#define SLC_SYNCH 1
#define SLC_BRK 2
#define SLC_IP 3
#define SLC_AO 4
#define SLC_AYT 5
#define SLC_EOR 6
#define SLC_ABORT 7
#define SLC_EOF 8
#define SLC_SUSP 9
#define SLC_EC 10
#define SLC_EL 11
#define SLC_EW 12
#define SLC_RP 13
#define SLC_LNEXT 14
#define SLC_XON 15
#define SLC_XOFF 16
#define SLC_FORW1 17
#define SLC_FORW2 18
#define NSLC 18
/*
* For backwards compatability, we define SLC_NAMES to be the
* list of names if SLC_NAMES is not defined.
*/
#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
#ifdef SLC_NAMES
char *slc_names[] = {
SLC_NAMELIST
};
#else
extern char *slc_names[];
#define SLC_NAMES SLC_NAMELIST
#endif
#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC)
#define SLC_NAME(x) slc_names[x]
#define SLC_NOSUPPORT 0
#define SLC_CANTCHANGE 1
#define SLC_VARIABLE 2
#define SLC_DEFAULT 3
#define SLC_LEVELBITS 0x03
#define SLC_FUNC 0
#define SLC_FLAGS 1
#define SLC_VALUE 2
#define SLC_ACK 0x80
#define SLC_FLUSHIN 0x40
#define SLC_FLUSHOUT 0x20
#define OLD_ENV_VAR 1
#define OLD_ENV_VALUE 0
#define NEW_ENV_VAR 0
#define NEW_ENV_VALUE 1
#define ENV_ESC 2
#define ENV_USERVAR 3
/*
* AUTHENTICATION suboptions
*/
/*
* Who is authenticating who ...
*/
#define AUTH_WHO_CLIENT 0 /* Client authenticating server */
#define AUTH_WHO_SERVER 1 /* Server authenticating client */
#define AUTH_WHO_MASK 1
/*
* amount of authentication done
*/
#define AUTH_HOW_ONE_WAY 0
#define AUTH_HOW_MUTUAL 2
#define AUTH_HOW_MASK 2
#define AUTHTYPE_NULL 0
#define AUTHTYPE_KERBEROS_V4 1
#define AUTHTYPE_KERBEROS_V5 2
#define AUTHTYPE_SPX 3
#define AUTHTYPE_MINK 4
#define AUTHTYPE_SRA 5
#define AUTHTYPE_CNT 6
/* #define AUTHTYPE_UNSECURE 6 */
#define AUTHTYPE_TEST 99
#ifdef AUTH_NAMES
char *authtype_names[] = {
"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
"SRA", 0,
};
#else
extern char *authtype_names[];
#endif
#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT)
#define AUTHTYPE_NAME(x) authtype_names[x]
/*
* ENCRYPTion suboptions
*/
#define ENCRYPT_IS 0 /* I pick encryption type ... */
#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */
#define ENCRYPT_REPLY 2 /* Initial setup response */
#define ENCRYPT_START 3 /* Am starting to send encrypted */
#define ENCRYPT_END 4 /* Am ending encrypted */
#define ENCRYPT_REQSTART 5 /* Request you start encrypting */
#define ENCRYPT_REQEND 6 /* Request you send encrypting */
#define ENCRYPT_ENC_KEYID 7
#define ENCRYPT_DEC_KEYID 8
#define ENCRYPT_CNT 9
#define ENCTYPE_ANY 0
#define ENCTYPE_DES_CFB64 1
#define ENCTYPE_DES_OFB64 2
#define ENCTYPE_CNT 3
#ifdef ENCRYPT_NAMES
char *encrypt_names[] = {
"IS", "SUPPORT", "REPLY", "START", "END",
"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
0,
};
char *enctype_names[] = {
"ANY", "DES_CFB64", "DES_OFB64", 0,
};
#else
extern char *encrypt_names[];
extern char *enctype_names[];
#endif
#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT)
#define ENCRYPT_NAME(x) encrypt_names[x]
#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT)
#define ENCTYPE_NAME(x) enctype_names[x]
#endif /* !_TELNET_H_ */

View File

@@ -1,25 +0,0 @@
# $Id$
include $(top_srcdir)/Makefile.am.common
AM_CPPFLAGS += -I$(srcdir)/.. $(INCLUDE_hcrypto)
WFLAGS += $(WFLAGS_LITE)
noinst_LIBRARIES = libtelnet.a
libtelnet_a_SOURCES = \
auth-proto.h \
auth.c \
auth.h \
enc-proto.h \
enc_des.c \
encrypt.c \
encrypt.h \
genget.c \
kerberos5.c \
misc-proto.h \
misc.c \
misc.h
EXTRA_DIST = NTMakefile rsaencpwd.c spx.c

View File

@@ -1,35 +0,0 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT HOLDER 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.
#
RELDIR=appl\telnet\libtelnet
!include ../../../windows/NTMakefile.w32

View File

@@ -1,111 +0,0 @@
/*-
* 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
*/
/*
* 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.
*/
/* $Id$ */
#ifdef AUTHENTICATION
Authenticator *findauthenticator (int, int);
int auth_wait (char *, size_t);
void auth_disable_name (char *);
void auth_finished (Authenticator *, int);
void auth_gen_printsub (unsigned char *, size_t, unsigned char *, size_t);
void auth_init (const char *, int);
void auth_is (unsigned char *, int);
void auth_name(unsigned char*, int);
void auth_reply (unsigned char *, int);
void auth_request (void);
void auth_send (unsigned char *, int);
void auth_send_retry (void);
void auth_printsub(unsigned char*, size_t, unsigned char*, size_t);
int getauthmask(char *type, int *maskp);
int auth_enable(char *type);
int auth_disable(char *type);
int auth_onoff(char *type, int on);
int auth_togdebug(int on);
int auth_status(void);
int auth_sendname(unsigned char *cp, int len);
void auth_debug(int mode);
#ifdef UNSAFE
int unsafe_init (Authenticator *, int);
int unsafe_send (Authenticator *);
void unsafe_is (Authenticator *, unsigned char *, int);
void unsafe_reply (Authenticator *, unsigned char *, int);
int unsafe_status (Authenticator *, char *, int);
void unsafe_printsub (unsigned char *, size_t, unsigned char *, size_t);
#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 *, size_t, unsigned char *, size_t);
#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 *, size_t, int);
void kerberos5_printsub (unsigned char *, size_t, unsigned char *, size_t);
int kerberos5_set_forward(int);
int kerberos5_set_forwardable(int);
#endif
#endif

View File

@@ -1,628 +0,0 @@
/*-
* 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 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.
*/
#include <config.h>
RCSID("$Id$");
#if defined(AUTHENTICATION)
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <signal.h>
#define AUTH_NAMES
#ifdef HAVE_ARPA_TELNET_H
#include <arpa/telnet.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <roken.h>
#ifdef SOCKS
#include <socks.h>
#endif
#include "encrypt.h"
#include "auth.h"
#include "misc-proto.h"
#include "auth-proto.h"
#define typemask(x) (1<<((x)-1))
#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;
int auth_has_failed = 0;
int auth_enable_encrypt = 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;
/*
* Authentication types supported. Plese note that these are stored
* in priority order, i.e. try the first one first.
*/
Authenticator authenticators[] = {
#ifdef UNSAFE
{ AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
unsafe_init,
unsafe_send,
unsafe_is,
unsafe_reply,
unsafe_status,
unsafe_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
#ifdef SPX
{ AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
spx_init,
spx_send,
spx_is,
spx_reply,
spx_status,
spx_printsub },
{ AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
spx_init,
spx_send,
spx_is,
spx_reply,
spx_status,
spx_printsub },
#endif
#ifdef KRB5
{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
kerberos5_init,
kerberos5_send_mutual,
kerberos5_is,
kerberos5_reply,
kerberos5_status,
kerberos5_printsub },
{ 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 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
{ 0, 0, NULL, NULL, NULL, NULL, NULL, NULL },
};
static Authenticator NoAuth = { 0, 0, NULL, NULL, NULL, NULL, NULL, NULL };
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 (!strcasecmp(name, AUTHTYPE_NAME(x))) {
i_wont_support |= typemask(x);
break;
}
}
}
int
getauthmask(char *type, int *maskp)
{
int x;
if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
*maskp = -1;
return(1);
}
for (x = 1; x < AUTHTYPE_CNT; ++x) {
if (!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;
telnet_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 = cnt > sizeof(_auth_send_data)
? sizeof(_auth_send_data)
: cnt;
memmove(_auth_send_data, 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;
}
telnet_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);
auth_has_failed = 1;
#ifdef KANNAN
/*
* We requested strong authentication, however no mechanisms worked.
* Therefore, exit on client end.
*/
printf("Unable to securely authenticate user ... exit\n");
exit(0);
#endif /* KANNAN */
}
void
auth_send_retry(void)
{
/*
* 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)
{
char savename[256];
if (cnt < 1) {
if (auth_debug_mode)
printf(">>>%s: Empty name in NAME\r\n", Name);
return;
}
if (cnt > sizeof(savename) - 1) {
if (auth_debug_mode)
printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n",
Name, cnt, (unsigned long)(sizeof(savename)-1));
return;
}
memmove(savename, 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;
telnet_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)
{
auth_finished(0, AUTH_REJECT);
}
int
auth_wait(char *name, size_t name_sz)
{
if (auth_debug_mode)
printf(">>>%s: in auth_wait.\r\n", Name);
if (Server && !authenticating)
return(0);
signal(SIGALRM, auth_intr);
alarm(30);
while (!authenticated)
if (telnet_spin())
break;
alarm(0);
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, name_sz,
validuser);
return(validuser);
}
void
auth_debug(int mode)
{
auth_debug_mode = mode;
}
void
auth_printsub(unsigned char *data, size_t cnt,
unsigned char *buf, size_t 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, size_t cnt,
unsigned char *buf, size_t 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++) {
snprintf((char*)tbuf, sizeof(tbuf), " %d", *data);
for (cp = tbuf; *cp && buflen > 0; --buflen)
*buf++ = *cp++;
if (buflen <= 0)
return;
}
*buf = '\0';
}
#endif

View File

@@ -1,81 +0,0 @@
/*-
* 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
*/
/*
* 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.
*/
/* $Id$ */
#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 *, size_t, int);
void (*printsub) (unsigned char *, size_t, unsigned char *, size_t);
} Authenticator;
#include "auth-proto.h"
extern int auth_debug_mode;
#endif

View File

@@ -1,133 +0,0 @@
/*-
* 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
*
* @(#)enc-proto.h 5.2 (Berkeley) 3/22/91
*/
/*
* 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.
*/
/* $Id$ */
#if defined(ENCRYPTION)
Encryptions *findencryption (int);
Encryptions *finddecryption(int);
int EncryptAutoDec(int);
int EncryptAutoEnc(int);
int EncryptDebug(int);
int EncryptDisable(char*, char*);
int EncryptEnable(char*, char*);
int EncryptStart(char*);
int EncryptStartInput(void);
int EncryptStartOutput(void);
int EncryptStatus(void);
int EncryptStop(char*);
int EncryptStopInput(void);
int EncryptStopOutput(void);
int EncryptType(char*, char*);
int EncryptVerbose(int);
void decrypt_auto(int);
void encrypt_auto(int);
void encrypt_debug(int);
void encrypt_dec_keyid(unsigned char*, int);
void encrypt_display(void);
void encrypt_enc_keyid(unsigned char*, int);
void encrypt_end(void);
void encrypt_gen_printsub(unsigned char*, size_t, unsigned char*, size_t);
void encrypt_init(const char*, int);
void encrypt_is(unsigned char*, int);
void encrypt_list_types(void);
void encrypt_not(void);
void encrypt_printsub(unsigned char*, size_t, unsigned char*, size_t);
void encrypt_reply(unsigned char*, int);
void encrypt_request_end(void);
void encrypt_request_start(unsigned char*, int);
void encrypt_send_end(void);
void encrypt_send_keyid(int, unsigned char*, int, int);
void encrypt_send_request_end(void);
int encrypt_is_encrypting(void);
void encrypt_send_request_start(void);
void encrypt_send_support(void);
void encrypt_session_key(Session_Key*, int);
void encrypt_start(unsigned char*, int);
void encrypt_start_output(int);
void encrypt_support(unsigned char*, int);
void encrypt_verbose_quiet(int);
void encrypt_wait(void);
int encrypt_delay(void);
#ifdef TELENTD
void encrypt_wait (void);
#else
void encrypt_display (void);
#endif
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 *, size_t, unsigned char *, size_t);
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 *, size_t, unsigned char *, size_t);
#endif

View File

@@ -1,659 +0,0 @@
/*-
* 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 <config.h>
RCSID("$Id$");
#if defined(AUTHENTICATION) && defined(ENCRYPTION) && defined(DES_ENCRYPTION)
#include <arpa/telnet.h>
#include <stdio.h>
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#endif
#include <roken.h>
#ifdef SOCKS
#include <socks.h>
#endif
#include "encrypt.h"
#include "misc-proto.h"
#include "crypto-headers.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 stinfo {
DES_cblock str_output;
DES_cblock str_feed;
DES_cblock str_iv;
DES_cblock str_ikey;
DES_key_schedule str_sched;
int str_index;
int str_flagshift;
};
struct fb {
DES_cblock krbdes_key;
DES_key_schedule krbdes_sched;
DES_cblock temp_feed;
unsigned char fb_feed[64];
int need_start;
int state[2];
int keyid[2];
struct stinfo streams[2];
};
static struct fb fb[2];
struct keyidlist {
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 (DES_cblock, 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 (DES_cblock, struct stinfo *);
int fb64_keyid (int, unsigned char *, int *, struct fb *);
void fb64_printsub(unsigned char *, size_t ,
unsigned char *, size_t , char *);
void cfb64_init(int server)
{
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)
{
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(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)
{
int 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.
*/
do {
if (RAND_bytes(fbp->temp_feed,
sizeof(*fbp->temp_feed)) != 1)
abort();
DES_set_odd_parity(&fbp->temp_feed);
} while(DES_is_weak_key(&fbp->temp_feed));
p = fbp->fb_feed + 3;
*p++ = ENCRYPT_IS;
p++;
*p++ = FB64_IV;
for (x = 0; x < sizeof(DES_cblock); ++x) {
if ((*p++ = fbp->temp_feed[x]) == IAC)
*p++ = IAC;
}
*p++ = IAC;
*p++ = SE;
printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
telnet_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(DES_cblock)) {
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(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]);
telnet_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]);
telnet_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, (unsigned char *)"\0", 1, 1);
break;
case FB64_IV_BAD:
memset(fbp->temp_feed, 0, sizeof(DES_cblock));
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;
}
memcpy(fbp->krbdes_key, key->data, sizeof(DES_cblock));
fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
RAND_seed(key->data, key->length);
DES_set_key_checked((DES_cblock *)&fbp->krbdes_key,
&fbp->krbdes_sched);
/*
* Now look to see if krbdes_start() 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, size_t cnt,
unsigned char *buf, size_t buflen, 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:
snprintf(lbuf, sizeof(lbuf), "%s_IV", type);
cp = lbuf;
goto common;
case FB64_IV_OK:
snprintf(lbuf, sizeof(lbuf), "%s_IV_OK", type);
cp = lbuf;
goto common;
case FB64_IV_BAD:
snprintf(lbuf, sizeof(lbuf), "%s_IV_BAD", type);
cp = lbuf;
goto common;
default:
snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[2]);
cp = lbuf;
common:
for (; (buflen > 0) && (*buf = *cp++); buf++)
buflen--;
for (i = 3; i < cnt; i++) {
snprintf(lbuf, sizeof(lbuf), " %d", data[i]);
for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
buflen--;
}
break;
}
}
void cfb64_printsub(unsigned char *data, size_t cnt,
unsigned char *buf, size_t buflen)
{
fb64_printsub(data, cnt, buf, buflen, "CFB64");
}
void ofb64_printsub(unsigned char *data, size_t cnt,
unsigned char *buf, size_t buflen)
{
fb64_printsub(data, cnt, buf, buflen, "OFB64");
}
void fb64_stream_iv(DES_cblock seed, struct stinfo *stp)
{
memcpy(stp->str_iv, seed,sizeof(DES_cblock));
memcpy(stp->str_output, seed, sizeof(DES_cblock));
DES_set_key_checked(&stp->str_ikey, &stp->str_sched);
stp->str_index = sizeof(DES_cblock);
}
void fb64_stream_key(DES_cblock key, struct stinfo *stp)
{
memcpy(stp->str_ikey, key, sizeof(DES_cblock));
DES_set_key_checked((DES_cblock*)key, &stp->str_sched);
memcpy(stp->str_output, stp->str_iv, sizeof(DES_cblock));
stp->str_index = sizeof(DES_cblock);
}
/*
* 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 index;
index = stp->str_index;
while (c-- > 0) {
if (index == sizeof(DES_cblock)) {
DES_cblock b;
DES_ecb_encrypt(&stp->str_output, &b,&stp->str_sched, 1);
memcpy(stp->str_feed, b, sizeof(DES_cblock));
index = 0;
}
/* On encryption, we store (feed ^ data) which is cypher */
*s = stp->str_output[index] = (stp->str_feed[index] ^ *s);
s++;
index++;
}
stp->str_index = index;
}
int cfb64_decrypt(int data)
{
struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
int index;
if (data == -1) {
/*
* Back up one byte. It is assumed that we will
* never back up more than one byte. If we do, this
* may or may not work.
*/
if (stp->str_index)
--stp->str_index;
return(0);
}
index = stp->str_index++;
if (index == sizeof(DES_cblock)) {
DES_cblock b;
DES_ecb_encrypt(&stp->str_output,&b, &stp->str_sched, 1);
memcpy(stp->str_feed, b, sizeof(DES_cblock));
stp->str_index = 1; /* Next time will be 1 */
index = 0; /* But now use 0 */
}
/* On decryption we store (data) which is cypher. */
stp->str_output[index] = data;
return(data ^ stp->str_feed[index]);
}
/*
* 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 index;
index = stp->str_index;
while (c-- > 0) {
if (index == sizeof(DES_cblock)) {
DES_cblock b;
DES_ecb_encrypt(&stp->str_feed,&b, &stp->str_sched, 1);
memcpy(stp->str_feed, b, sizeof(DES_cblock));
index = 0;
}
*s++ ^= stp->str_feed[index];
index++;
}
stp->str_index = index;
}
int ofb64_decrypt(int data)
{
struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
int index;
if (data == -1) {
/*
* Back up one byte. It is assumed that we will
* never back up more than one byte. If we do, this
* may or may not work.
*/
if (stp->str_index)
--stp->str_index;
return(0);
}
index = stp->str_index++;
if (index == sizeof(DES_cblock)) {
DES_cblock b;
DES_ecb_encrypt(&stp->str_feed,&b,&stp->str_sched, 1);
memcpy(stp->str_feed, b, sizeof(DES_cblock));
stp->str_index = 1; /* Next time will be 1 */
index = 0; /* But now use 0 */
}
return(data ^ stp->str_feed[index]);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,103 +0,0 @@
/*-
* 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
*
* @(#)encrypt.h 5.2 (Berkeley) 3/22/91
*/
/*
* 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.
*/
/* $Id$ */
#ifndef __ENCRYPT__
#define __ENCRYPT__
#define DIR_DECRYPT 1
#define DIR_ENCRYPT 2
#define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \
key[4] | key[5] | key[6] | key[7])
#define SAMEKEY(k1, k2) (!memcmp(k1, k2, sizeof(des_cblock)))
typedef struct {
short type;
int length;
unsigned char *data;
} Session_Key;
typedef struct {
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 *, size_t, unsigned char *, size_t);
} Encryptions;
#define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */
#include "crypto-headers.h"
#ifdef HAVE_OPENSSL
#define des_new_random_key des_random_key
#endif
#include "enc-proto.h"
extern int encrypt_debug_mode;
extern int (*decrypt_input) (int);
extern void (*encrypt_output) (unsigned char *, int);
#endif

View File

@@ -1,106 +0,0 @@
/*-
* 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 <config.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <ctype.h>
#include "misc-proto.h"
RCSID("$Id$");
#define LOWER(x) (isupper(x) ? tolower(x) : (x))
/*
* The prefix function returns 0 if *s1 is not a prefix
* of *s2. If *s1 exactly matches *s2, the negative of
* the length is returned. If *s1 is a prefix of *s2,
* the length of *s1 is returned.
*/
int
isprefix(char *s1, char *s2)
{
char *os1;
char c1, c2;
if (*s1 == '\0')
return(-1);
os1 = s1;
c1 = *s1;
c2 = *s2;
while (tolower((unsigned char)c1) == tolower((unsigned char)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)
/* name to match */
/* name entry in table */
{
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(void *s)
{
return((char **)s == &ambiguous);
}

View File

@@ -1,926 +0,0 @@
/*-
* 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 <config.h>
RCSID("$Id$");
#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 <roken.h>
#ifdef SOCKS
#include <socks.h>
#endif
#include "encrypt.h"
#include "auth.h"
#include "misc.h"
#if defined(DCE)
int dfsk5ok = 0;
int dfspag = 0;
int dfsfwd = 0;
#endif
int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
int forward(int);
int forwardable(int);
/* 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[4] = { IAC, SB, TELOPT_AUTHENTICATION, 0 };
#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 void *d, int c)
{
const unsigned char *cp, *cd = d;
unsigned char *p0, *p;
size_t len = sizeof(str_data) + 3 + 2;
int ret;
if (c == -1)
c = strlen((const char*)cd);
for (cp = cd; cp - cd < c; cp++, len++)
if (*cp == IAC)
len++;
p0 = malloc(len);
if (p0 == NULL)
return 0;
memcpy(p0, str_data, sizeof(str_data));
p = p0 + sizeof(str_data);
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('>', &p0[2], len - 2);
ret = telnet_net_write(p0, len);
free(p0);
return ret;
}
int
kerberos5_init(Authenticator *ap, 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(char *name, Authenticator *ap)
{
krb5_error_code ret;
krb5_ccache ccache;
int ap_opts;
krb5_data cksum_data;
const char *estr;
char ap_msg[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) {
estr = krb5_get_error_message (context, ret);
printf("Kerberos V5: could not get default ccache: %s\r\n", estr);
krb5_free_error_message(context, estr);
}
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) {
estr = krb5_get_error_message (context, ret);
printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", estr);
krb5_free_error_message(context, estr);
}
return(0);
}
ret = krb5_auth_con_setaddrs_from_fd (context,
auth_context,
&net);
if (ret) {
if (auth_debug_mode) {
estr = krb5_get_error_message (context, ret);
printf ("Kerberos V5:"
" krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", estr);
krb5_free_error_message(context, estr);
}
return(0);
}
krb5_auth_con_setkeytype (context, auth_context, KRB5_ENCTYPE_DES_CBC_CRC);
ap_msg[0] = ap->type;
ap_msg[1] = ap->way;
cksum_data.length = sizeof(ap_msg);
cksum_data.data = ap_msg;
{
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) {
estr = krb5_get_error_message (context, ret);
printf ("Kerberos V5:"
" krb5_sname_to_principal(%s) failed (%s)\r\n",
RemoteHostName, estr);
krb5_free_error_message(context, estr);
}
return 0;
}
ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname));
if(ret) {
if (auth_debug_mode) {
estr = krb5_get_error_message (context, ret);
printf ("Kerberos V5:"
" krb5_unparse_name_fixed failed (%s)\r\n", estr);
krb5_free_error_message(context, estr);
}
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) {
estr = krb5_get_error_message (context, ret);
printf("Kerberos V5: mk_req failed (%s)\r\n", estr);
krb5_free_error_message(context, estr);
}
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);
}
static void log_message(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (auth_debug_mode) {
va_start(ap, fmt);
vfprintf(stdout, fmt, ap);
va_end(ap);
fprintf(stdout, "\r\n");
}
va_start(ap, fmt);
vsyslog(LOG_NOTICE, fmt, ap);
va_end(ap);
}
void
kerberos5_is(Authenticator *ap, unsigned char *data, int cnt)
{
krb5_error_code ret;
krb5_data outbuf;
krb5_keyblock *key_block;
const char *estr;
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);
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: krb5_auth_con_init failed (%s)", estr);
krb5_free_error_message(context, estr);
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);
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: "
"krb5_auth_con_setaddrs_from_fd failed (%s)", estr);
krb5_free_error_message(context, estr);
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);
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: "
"krb5_sock_to_principal failed (%s)", estr);
krb5_free_error_message(context, estr);
return;
}
ret = krb5_rd_req(context,
&auth_context,
&auth,
server,
NULL,
NULL,
&ticket);
krb5_free_principal (context, server);
if (ret) {
const char *errbuf2 = "Read req failed";
char *errbuf;
int ret2;
estr = krb5_get_error_message (context, ret);
ret2 = asprintf(&errbuf, "Read req failed: %s", estr);
krb5_free_error_message(context, estr);
if (ret2 != -1)
errbuf2 = errbuf;
Data(ap, KRB_REJECT, errbuf2, -1);
log_message("%s", errbuf2);
if (ret2 != -1)
free (errbuf);
return;
}
{
char ap_msg[2];
ap_msg[0] = ap->type;
ap_msg[1] = ap->way;
ret = krb5_verify_authenticator_checksum(context,
auth_context,
ap_msg,
sizeof(ap_msg));
if (ret) {
const char *errbuf2 = "Bad checksum";
char *errbuf;
int ret2;
estr = krb5_get_error_message (context, ret);
ret2 = asprintf(&errbuf, "Bad checksum: %s", estr);
krb5_free_error_message(context, estr);
if (ret2 != -1)
errbuf2 = errbuf;
Data(ap, KRB_REJECT, errbuf2, -1);
log_message("%s", errbuf2);
if (ret2 != -1)
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);
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: "
"krb5_auth_con_getremotesubkey failed (%s)", estr);
krb5_free_error_message(context, estr);
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);
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: "
"krb5_auth_con_getkey failed (%s)", estr);
krb5_free_error_message(context, estr);
return;
}
if (key_block == NULL) {
Data(ap, KRB_REJECT, "no subkey received", -1);
auth_finished(ap, AUTH_REJECT);
log_message("Kerberos V5: "
"krb5_auth_con_getremotesubkey returned NULL key");
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);
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: "
"krb5_mk_rep failed (%s)", estr);
krb5_free_error_message(context, estr);
krb5_free_keyblock(context, key_block);
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);
log_message("%s accepted as user %s from %s",
name ? name : "<unknown>",
UserNameRequested ? UserNameRequested : "<unknown>",
RemoteHostName ? RemoteHostName : "<unknown>");
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 {
const char *msg2 = "user is not authorized to login";
char *msg;
ret = asprintf (&msg, "user `%s' is not authorized to "
"login as `%s'",
name ? name : "<unknown>",
UserNameRequested ? UserNameRequested : "<nobody>");
if (ret != -1)
msg2 = msg;
Data(ap, KRB_REJECT, (void *)msg2, -1);
if (ret != -1)
free(msg);
auth_finished (ap, AUTH_REJECT);
krb5_free_keyblock(context, key_block);
break;
}
auth_finished(ap, AUTH_USER);
krb5_free_keyblock(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_%lu", (unsigned long)pwd->pw_uid);
ret = krb5_cc_resolve (context, ccname, &ccache);
if (ret) {
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: could not get ccache: %s", estr);
krb5_free_error_message(context, estr);
break;
}
ret = krb5_cc_initialize (context,
ccache,
ticket->client);
if (ret) {
estr = krb5_get_error_message (context, ret);
log_message("Kerberos V5: could not init ccache: %s", estr);
krb5_free_error_message(context, estr);
break;
}
#if defined(DCE)
esetenv("KRB5CCNAME", ccname, 1);
#endif
ret = krb5_rd_cred2 (context,
auth_context,
ccache,
&inbuf);
if(ret) {
const char *errbuf2 = "Read forwarded creds failed";
char *errbuf;
int ret2;
estr = krb5_get_error_message (context, ret);
ret2 = asprintf (&errbuf, "Read forwarded creds failed: %s", estr);
krb5_free_error_message(context, estr);
if (ret2 != -1)
errbuf2 = errbuf;
Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
log_message("Could not read forwarded credentials: %s", errbuf2);
if (ret2 != -1)
free (errbuf);
} else {
Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
#if defined(DCE)
dfsfwd = 1;
#endif
}
chown (ccname + 5, pwd->pw_uid, -1);
log_message("Forwarded credentials obtained");
break;
}
default:
log_message("Unknown Kerberos option %d", data[-1]);
Data(ap, KRB_REJECT, 0, 0);
break;
}
}
void
kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt)
{
static int mutual_complete = 0;
const char *estr;
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) {
estr = krb5_get_error_message (context, ret);
printf("[ krb5_auth_con_getkey: %s ]\r\n", estr);
krb5_free_error_message(context, estr);
auth_send_retry();
return;
}
skey.type = SK_DES;
skey.length = 8;
skey.data = keyblock->keyvalue.data;
encrypt_session_key(&skey, 0);
krb5_free_keyblock (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) {
estr = krb5_get_error_message (context, ret);
printf("[ Mutual authentication failed: %s ]\r\n", estr);
krb5_free_error_message(context, estr);
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, char *name, size_t name_sz, int level)
{
if (level < AUTH_USER)
return(level);
if (UserNameRequested &&
krb5_kuserok(context,
ticket->client,
UserNameRequested))
{
strlcpy(name, UserNameRequested, name_sz);
#if defined(DCE)
dfsk5ok = 1;
#endif
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, size_t cnt,
unsigned char *buf, size_t buflen)
{
int i;
buf[buflen-1] = '\0'; /* make sure it's 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((char*)buf, buflen, " %d (unknown)", data[3]);
common2:
BUMP(buf, buflen);
for (i = 4; i < cnt; i++) {
snprintf((char*)buf, buflen, " %d", data[i]);
BUMP(buf, buflen);
}
break;
}
}
void
kerberos5_forward(Authenticator *ap)
{
krb5_error_code ret;
krb5_ccache ccache;
krb5_creds creds;
KDCOptions flags;
krb5_data out_data;
krb5_principal principal;
const char *estr;
ret = krb5_cc_default (context, &ccache);
if (ret) {
if (auth_debug_mode) {
estr = krb5_get_error_message (context, ret);
printf ("KerberosV5: could not get default ccache: %s\r\n", estr);
krb5_free_error_message(context, estr);
}
return;
}
ret = krb5_cc_get_principal (context, ccache, &principal);
if (ret) {
if (auth_debug_mode) {
estr = krb5_get_error_message (context, ret);
printf ("KerberosV5: could not get principal: %s\r\n", estr);
krb5_free_error_message(context, estr);
}
return;
}
memset (&creds, 0, sizeof(creds));
creds.client = principal;
ret = krb5_make_principal(context,
&creds.server,
principal->realm,
"krbtgt",
principal->realm,
NULL);
if (ret) {
if (auth_debug_mode) {
estr = krb5_get_error_message (context, ret);
printf ("KerberosV5: could not get principal: %s\r\n", estr);
krb5_free_error_message(context, estr);
}
return;
}
creds.times.endtime = 0;
memset(&flags, 0, sizeof(flags));
flags.forwarded = 1;
if (forward_flags & OPTS_FORWARDABLE_CREDS)
flags.forwardable = 1;
ret = krb5_get_forwarded_creds (context,
auth_context,
ccache,
KDCOptions2int(flags),
RemoteHostName,
&creds,
&out_data);
if (ret) {
if (auth_debug_mode) {
estr = krb5_get_error_message (context, ret);
printf ("Kerberos V5: error getting forwarded creds: %s\r\n", estr);
krb5_free_error_message(context, estr);
}
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
int
kerberos5_set_forward(int on)
{
if(on == 0)
forward_flags &= ~OPTS_FORWARD_CREDS;
if(on == 1)
forward_flags |= OPTS_FORWARD_CREDS;
if(on == -1)
forward_flags ^= OPTS_FORWARD_CREDS;
return 0;
}
int
kerberos5_set_forwardable(int on)
{
if(on == 0)
forward_flags &= ~OPTS_FORWARDABLE_CREDS;
if(on == 1)
forward_flags |= OPTS_FORWARDABLE_CREDS;
if(on == -1)
forward_flags ^= OPTS_FORWARDABLE_CREDS;
return 0;
}
#endif /* KRB5 */

View File

@@ -1,79 +0,0 @@
/*-
* 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
*/
/*
* 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.
*/
/* $Id$ */
#ifndef __MISC_PROTO__
#define __MISC_PROTO__
void auth_encrypt_init (const char *, const char *, const char *, int);
void auth_encrypt_user(const char *name);
void auth_encrypt_connect (int);
void printd (const unsigned char *, int);
char** genget (char *name, char **table, int stlen);
int isprefix(char *s1, char *s2);
int Ambiguous(void *s);
/*
* These functions are imported from the application
*/
int telnet_net_write (unsigned char *, int);
void net_encrypt (void);
int telnet_spin (void);
char *telnet_getenv (const char *);
char *telnet_gets (char *, char *, int, int);
void printsub(int direction, unsigned char *pointer, size_t);
#endif

View File

@@ -1,95 +0,0 @@
/*-
* 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 <config.h>
RCSID("$Id$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <roken.h>
#ifdef SOCKS
#include <socks.h>
#endif
#include "misc.h"
#include "auth.h"
#include "encrypt.h"
const char *RemoteHostName;
const char *LocalHostName;
char *UserNameRequested = 0;
int ConnectedCount = 0;
void
auth_encrypt_init(const char *local, const char *remote, const char *name,
int server)
{
RemoteHostName = remote;
LocalHostName = local;
#ifdef AUTHENTICATION
auth_init(name, server);
#endif
#ifdef ENCRYPTION
encrypt_init(name, server);
#endif
if (UserNameRequested) {
free(UserNameRequested);
UserNameRequested = 0;
}
}
void
auth_encrypt_user(const char *name)
{
if (UserNameRequested)
free(UserNameRequested);
UserNameRequested = name ? strdup(name) : 0;
}
void
auth_encrypt_connect(int cnt)
{
}
void
printd(const unsigned char *data, int cnt)
{
if (cnt > 16)
cnt = 16;
while (cnt-- > 0) {
printf(" %02x", *data);
++data;
}
}

View File

@@ -1,42 +0,0 @@
/*-
* 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 const char *LocalHostName;
extern const char *RemoteHostName;
extern int ConnectedCount;
extern int ReservedPort;
#include "misc-proto.h"

View File

@@ -1,486 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <config.h>
RCSID("$Id$");
#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>
#ifdef HAVE_ARPA_TELNET_H
#include <arpa/telnet.h>
#endif
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef SOCKS
#include <socks.h>
#endif
#include "encrypt.h"
#include "auth.h"
#include "misc.h"
#include "cdc.h"
extern auth_debug_mode;
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
AUTHTYPE_RSA_ENCPWD, };
static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
TELQUAL_NAME, };
#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */
#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
#define RSA_ENCPWD_ACCEPT 2 /* Accepted */
#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */
#define NAME_SZ 40
#define CHAL_SZ 20
#define PWD_SZ 40
static KTEXT_ST auth;
static char name[NAME_SZ];
static char user_passwd[PWD_SZ];
static char key_file[2*NAME_SZ];
static char lhostname[NAME_SZ];
static char challenge[CHAL_SZ];
static int challenge_len;
static int
Data(ap, type, d, c)
Authenticator *ap;
int type;
void *d;
int c;
{
unsigned char *p = str_data + 4;
unsigned char *cd = (unsigned char *)d;
if (c == -1)
c = strlen((char *)cd);
if (0) {
printf("%s:%d: [%d] (%d)",
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
str_data[3],
type, c);
printd(d, c);
printf("\r\n");
}
*p++ = ap->type;
*p++ = ap->way;
if (type != NULL) *p++ = type;
while (c-- > 0) {
if ((*p++ = *cd++) == IAC)
*p++ = IAC;
}
*p++ = IAC;
*p++ = SE;
if (str_data[3] == TELQUAL_IS)
printsub('>', &str_data[2], p - (&str_data[2]));
return(telnet_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';
snprintf(key_file, sizeof(key_file),
SYSCONFDIR "/.%s_privkey", lhostname);
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 ... ]\r\n");
if (!UserNameRequested) {
return(0);
}
if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
return(0);
}
if (!Data(ap, NULL, NULL, 0)) {
return(0);
}
return(1);
}
void
rsaencpwd_is(ap, data, cnt)
Authenticator *ap;
unsigned char *data;
int cnt;
{
Session_Key skey;
des_cblock 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(auth.dat, data, auth.length = cnt);
if ((fp=fopen(key_file, "r"))==NULL) {
Data(ap, RSA_ENCPWD_REJECT, "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, "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, "Illegal password", -1);
auth_finished(ap, AUTH_REJECT);
return;
}
Data(ap, RSA_ENCPWD_ACCEPT, 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) {
int i;
time(&now);
if ((now % 2) == 0) {
snprintf(challenge, sizeof(challenge), "%x", now);
challenge_len = strlen(challenge);
} else {
strlcpy(challenge, "randchal", sizeof(challenge));
challenge_len = 8;
}
if ((fp=fopen(key_file, "r"))==NULL) {
Data(ap, RSA_ENCPWD_REJECT, "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, 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;
des_cblock 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 ]\r\n");
auth_finished(ap, AUTH_USER);
return;
case RSA_ENCPWD_CHALLENGEKEY:
/*
* Verify that the response to the challenge is correct.
*/
memmove(chalkey, 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));
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, token.dat, token.length)) {
return;
}
break;
default:
return;
}
}
int
rsaencpwd_status(ap, name, name_sz, level)
Authenticator *ap;
char *name;
size_t name_sz;
int level;
{
if (level < AUTH_USER)
return(level);
if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) {
strlcpy(name, UserNameRequested, name_sz);
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(unsigned char *data, size_t cnt,
unsigned char * buf, size_t buflen)
{
size_t i;
buf[buflen-1] = '\0'; /* make sure it's NULL terminated */
buflen -= 1;
switch(data[3]) {
case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */
strlcpy((char *)buf, " REJECT ", buflen);
goto common;
case RSA_ENCPWD_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 RSA_ENCPWD_AUTH: /* Authentication data follows */
strlcpy((char *)buf, " AUTH", buflen);
goto common2;
case RSA_ENCPWD_CHALLENGEKEY:
strlcpy((char *)buf, " CHALLENGEKEY", 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;
}
}
int rsaencpwd_passwdok(name, passwd)
char *name, *passwd;
{
char *crypt();
char *salt, *p;
struct passwd *pwd;
int passwdok_status = 0;
if (pwd = k_getpwnam(name))
salt = pwd->pw_passwd;
else salt = "xx";
p = crypt(passwd, salt);
if (pwd && !strcmp(p, pwd->pw_passwd)) {
passwdok_status = 1;
} else passwdok_status = 0;
return(passwdok_status);
}
#endif
#ifdef notdef
prkey(msg, key)
char *msg;
unsigned char *key;
{
int i;
printf("%s:", msg);
for (i = 0; i < 8; i++)
printf(" %3d", key[i]);
printf("\r\n");
}
#endif

View File

@@ -1,589 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <config.h>
RCSID("$Id$");
#ifdef SPX
/*
* COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
* ALL RIGHTS RESERVED
*
* "Digital Equipment Corporation authorizes the reproduction,
* distribution and modification of this software subject to the following
* restrictions:
*
* 1. Any partial or whole copy of this software, or any modification
* thereof, must include this copyright notice in its entirety.
*
* 2. This software is supplied "as is" with no warranty of any kind,
* expressed or implied, for any purpose, including any warranty of fitness
* or merchantibility. DIGITAL assumes no responsibility for the use or
* reliability of this software, nor promises to provide any form of
* support for it on any basis.
*
* 3. Distribution of this software is authorized only if no profit or
* remuneration of any kind is received in exchange for such distribution.
*
* 4. This software produces public key authentication certificates
* bearing an expiration date established by DIGITAL and RSA Data
* Security, Inc. It may cease to generate certificates after the expiration
* date. Any modification of this software that changes or defeats
* the expiration date or its effect is unauthorized.
*
* 5. Software that will renew or extend the expiration date of
* authentication certificates produced by this software may be obtained
* from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
* 94065, (415)595-8782, or from DIGITAL"
*
*/
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_ARPA_TELNET_H
#include <arpa/telnet.h>
#endif
#include <stdio.h>
#include "gssapi_defs.h"
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#ifdef SOCKS
#include <socks.h>
#endif
#include "encrypt.h"
#include "auth.h"
#include "misc.h"
extern auth_debug_mode;
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
AUTHTYPE_SPX, };
static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
TELQUAL_NAME, };
#define SPX_AUTH 0 /* Authentication data follows */
#define SPX_REJECT 1 /* Rejected (reason might follow) */
#define SPX_ACCEPT 2 /* Accepted */
static des_key_schedule sched;
static des_cblock challenge = { 0 };
/*******************************************************************/
gss_OID_set actual_mechs;
gss_OID actual_mech_type, output_name_type;
int major_status, status, msg_ctx = 0, new_status;
int req_flags = 0, ret_flags, lifetime_rec;
gss_cred_id_t gss_cred_handle;
gss_ctx_id_t actual_ctxhandle, context_handle;
gss_buffer_desc output_token, input_token, input_name_buffer;
gss_buffer_desc status_string;
gss_name_t desired_targname, src_name;
gss_channel_bindings input_chan_bindings;
char lhostname[GSS_C_MAX_PRINTABLE_NAME];
char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
int to_addr=0, from_addr=0;
char *address;
gss_buffer_desc fullname_buffer;
gss_OID fullname_type;
gss_cred_id_t gss_delegated_cred_handle;
/*******************************************************************/
static int
Data(ap, type, d, c)
Authenticator *ap;
int type;
void *d;
int c;
{
unsigned char *p = str_data + 4;
unsigned char *cd = (unsigned char *)d;
if (c == -1)
c = strlen((char *)cd);
if (0) {
printf("%s:%d: [%d] (%d)",
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
str_data[3],
type, c);
printd(d, c);
printf("\r\n");
}
*p++ = ap->type;
*p++ = ap->way;
*p++ = type;
while (c-- > 0) {
if ((*p++ = *cd++) == IAC)
*p++ = IAC;
}
*p++ = IAC;
*p++ = SE;
if (str_data[3] == TELQUAL_IS)
printsub('>', &str_data[2], p - (&str_data[2]));
return(telnet_net_write(str_data, p - str_data));
}
int
spx_init(ap, server)
Authenticator *ap;
int server;
{
gss_cred_id_t tmp_cred_handle;
if (server) {
str_data[3] = TELQUAL_REPLY;
gethostname(lhostname, sizeof(lhostname));
snprintf (targ_printable, sizeof(targ_printable),
"SERVICE:rcmd@%s", lhostname);
input_name_buffer.length = strlen(targ_printable);
input_name_buffer.value = targ_printable;
major_status = gss_import_name(&status,
&input_name_buffer,
GSS_C_NULL_OID,
&desired_targname);
major_status = gss_acquire_cred(&status,
desired_targname,
0,
GSS_C_NULL_OID_SET,
GSS_C_ACCEPT,
&tmp_cred_handle,
&actual_mechs,
&lifetime_rec);
if (major_status != GSS_S_COMPLETE) return(0);
} else {
str_data[3] = TELQUAL_IS;
}
return(1);
}
int
spx_send(ap)
Authenticator *ap;
{
des_cblock enckey;
int r;
gss_OID actual_mech_type, output_name_type;
int msg_ctx = 0, new_status, status;
int req_flags = 0, ret_flags, lifetime_rec, major_status;
gss_buffer_desc output_token, input_token, input_name_buffer;
gss_buffer_desc output_name_buffer, status_string;
gss_name_t desired_targname;
gss_channel_bindings input_chan_bindings;
char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
int from_addr=0, to_addr=0, myhostlen, j;
int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0;
char *address;
printf("[ Trying SPX ... ]\r\n");
snprintf (targ_printable, sizeof(targ_printable),
"SERVICE:rcmd@%s", RemoteHostName);
input_name_buffer.length = strlen(targ_printable);
input_name_buffer.value = targ_printable;
if (!UserNameRequested) {
return(0);
}
major_status = gss_import_name(&status,
&input_name_buffer,
GSS_C_NULL_OID,
&desired_targname);
major_status = gss_display_name(&status,
desired_targname,
&output_name_buffer,
&output_name_type);
printf("target is '%.*s'\n", (int)output_name_buffer.length,
(char*)output_name_buffer.value);
fflush(stdout);
major_status = gss_release_buffer(&status, &output_name_buffer);
input_chan_bindings = (gss_channel_bindings)
malloc(sizeof(gss_channel_bindings_desc));
input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
input_chan_bindings->initiator_address.length = 4;
address = (char *) malloc(4);
input_chan_bindings->initiator_address.value = (char *) address;
address[0] = ((from_addr & 0xff000000) >> 24);
address[1] = ((from_addr & 0xff0000) >> 16);
address[2] = ((from_addr & 0xff00) >> 8);
address[3] = (from_addr & 0xff);
input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
input_chan_bindings->acceptor_address.length = 4;
address = (char *) malloc(4);
input_chan_bindings->acceptor_address.value = (char *) address;
address[0] = ((to_addr & 0xff000000) >> 24);
address[1] = ((to_addr & 0xff0000) >> 16);
address[2] = ((to_addr & 0xff00) >> 8);
address[3] = (to_addr & 0xff);
input_chan_bindings->application_data.length = 0;
req_flags = 0;
if (deleg_flag) req_flags = req_flags | 1;
if (mutual_flag) req_flags = req_flags | 2;
if (replay_flag) req_flags = req_flags | 4;
if (seq_flag) req_flags = req_flags | 8;
major_status = gss_init_sec_context(&status, /* minor status */
GSS_C_NO_CREDENTIAL, /* cred handle */
&actual_ctxhandle, /* ctx handle */
desired_targname, /* target name */
GSS_C_NULL_OID, /* mech type */
req_flags, /* req flags */
0, /* time req */
input_chan_bindings, /* chan binding */
GSS_C_NO_BUFFER, /* input token */
&actual_mech_type, /* actual mech */
&output_token, /* output token */
&ret_flags, /* ret flags */
&lifetime_rec); /* time rec */
if ((major_status != GSS_S_COMPLETE) &&
(major_status != GSS_S_CONTINUE_NEEDED)) {
gss_display_status(&new_status,
status,
GSS_C_MECH_CODE,
GSS_C_NULL_OID,
&msg_ctx,
&status_string);
printf("%.*s\n", (int)status_string.length,
(char*)status_string.value);
return(0);
}
if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
return(0);
}
if (!Data(ap, SPX_AUTH, output_token.value, output_token.length)) {
return(0);
}
return(1);
}
void
spx_is(ap, data, cnt)
Authenticator *ap;
unsigned char *data;
int cnt;
{
Session_Key skey;
des_cblock datablock;
int r;
if (cnt-- < 1)
return;
switch (*data++) {
case SPX_AUTH:
input_token.length = cnt;
input_token.value = (char *) data;
gethostname(lhostname, sizeof(lhostname));
snprintf(targ_printable, sizeof(targ_printable),
"SERVICE:rcmd@%s", lhostname);
input_name_buffer.length = strlen(targ_printable);
input_name_buffer.value = targ_printable;
major_status = gss_import_name(&status,
&input_name_buffer,
GSS_C_NULL_OID,
&desired_targname);
major_status = gss_acquire_cred(&status,
desired_targname,
0,
GSS_C_NULL_OID_SET,
GSS_C_ACCEPT,
&gss_cred_handle,
&actual_mechs,
&lifetime_rec);
major_status = gss_release_name(&status, desired_targname);
input_chan_bindings = (gss_channel_bindings)
malloc(sizeof(gss_channel_bindings_desc));
input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
input_chan_bindings->initiator_address.length = 4;
address = (char *) malloc(4);
input_chan_bindings->initiator_address.value = (char *) address;
address[0] = ((from_addr & 0xff000000) >> 24);
address[1] = ((from_addr & 0xff0000) >> 16);
address[2] = ((from_addr & 0xff00) >> 8);
address[3] = (from_addr & 0xff);
input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
input_chan_bindings->acceptor_address.length = 4;
address = (char *) malloc(4);
input_chan_bindings->acceptor_address.value = (char *) address;
address[0] = ((to_addr & 0xff000000) >> 24);
address[1] = ((to_addr & 0xff0000) >> 16);
address[2] = ((to_addr & 0xff00) >> 8);
address[3] = (to_addr & 0xff);
input_chan_bindings->application_data.length = 0;
major_status = gss_accept_sec_context(&status,
&context_handle,
gss_cred_handle,
&input_token,
input_chan_bindings,
&src_name,
&actual_mech_type,
&output_token,
&ret_flags,
&lifetime_rec,
&gss_delegated_cred_handle);
if (major_status != GSS_S_COMPLETE) {
major_status = gss_display_name(&status,
src_name,
&fullname_buffer,
&fullname_type);
Data(ap, SPX_REJECT, "auth failed", -1);
auth_finished(ap, AUTH_REJECT);
return;
}
major_status = gss_display_name(&status,
src_name,
&fullname_buffer,
&fullname_type);
Data(ap, SPX_ACCEPT, output_token.value, output_token.length);
auth_finished(ap, AUTH_USER);
break;
default:
Data(ap, SPX_REJECT, 0, 0);
break;
}
}
void
spx_reply(ap, data, cnt)
Authenticator *ap;
unsigned char *data;
int cnt;
{
Session_Key skey;
if (cnt-- < 1)
return;
switch (*data++) {
case SPX_REJECT:
if (cnt > 0) {
printf("[ SPX refuses authentication because %.*s ]\r\n",
cnt, data);
} else
printf("[ SPX refuses authentication ]\r\n");
auth_send_retry();
return;
case SPX_ACCEPT:
printf("[ SPX accepts you ]\r\n");
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
/*
* Send over the encrypted challenge.
*/
input_token.value = (char *) data;
input_token.length = cnt;
major_status = gss_init_sec_context(&status, /* minor stat */
GSS_C_NO_CREDENTIAL, /* cred handle */
&actual_ctxhandle, /* ctx handle */
desired_targname, /* target name */
GSS_C_NULL_OID, /* mech type */
req_flags, /* req flags */
0, /* time req */
input_chan_bindings, /* chan binding */
&input_token, /* input token */
&actual_mech_type, /* actual mech */
&output_token, /* output token */
&ret_flags, /* ret flags */
&lifetime_rec); /* time rec */
if (major_status != GSS_S_COMPLETE) {
gss_display_status(&new_status,
status,
GSS_C_MECH_CODE,
GSS_C_NULL_OID,
&msg_ctx,
&status_string);
printf("[ SPX mutual response fails ... '%.*s' ]\r\n",
(int)status_string.length,
(char*)status_string.value);
auth_send_retry();
return;
}
}
auth_finished(ap, AUTH_USER);
return;
default:
return;
}
}
int
spx_status(ap, name, name_sz, level)
Authenticator *ap;
char *name;
size_t name_sz;
int level;
{
gss_buffer_desc fullname_buffer, acl_file_buffer;
gss_OID fullname_type;
char acl_file[160], fullname[160];
int major_status, status = 0;
struct passwd *pwd;
/*
* hard code fullname to
* "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan"
* and acl_file to "~kannan/.sphinx"
*/
pwd = k_getpwnam(UserNameRequested);
if (pwd == NULL) {
return(AUTH_USER); /* not authenticated */
}
snprintf (acl_file, sizeof(acl_file),
"%s/.sphinx", pwd->pw_dir);
acl_file_buffer.value = acl_file;
acl_file_buffer.length = strlen(acl_file);
major_status = gss_display_name(&status,
src_name,
&fullname_buffer,
&fullname_type);
if (level < AUTH_USER)
return(level);
major_status = gss__check_acl(&status, &fullname_buffer,
&acl_file_buffer);
if (major_status == GSS_S_COMPLETE) {
strlcpy(name, UserNameRequested, name_sz);
return(AUTH_VALID);
} else {
return(AUTH_USER);
}
}
#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
void
spx_printsub(unsigned char *data, size_t cnt,
unsigned char *buf, size_t buflen)
{
size_t i;
buf[buflen-1] = '\0'; /* make sure it's NULL terminated */
buflen -= 1;
switch(data[3]) {
case SPX_REJECT: /* Rejected (reason might follow) */
strlcpy((char *)buf, " REJECT ", buflen);
goto common;
case SPX_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 SPX_AUTH: /* Authentication data follows */
strlcpy((char *)buf, " AUTH", 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;
}
}
#endif
#ifdef notdef
prkey(msg, key)
char *msg;
unsigned char *key;
{
int i;
printf("%s:", msg);
for (i = 0; i < 8; i++)
printf(" %3d", key[i]);
printf("\r\n");
}
#endif

View File

@@ -1,80 +0,0 @@
Three pieces of state need to be kept for each side of each option.
(You need the localside, sending WILL/WONT & receiving DO/DONT, and
the remoteside, sending DO/DONT and receiving WILL/WONT)
MY_STATE: What state am I in?
WANT_STATE: What state do I want?
WANT_RESP: How many requests have I initiated?
Default values:
MY_STATE = WANT_STATE = DONT
WANT_RESP = 0
The local setup will change based on the state of the Telnet
variables. When we are the originator, we can either make the
local setup changes at option request time (in which case if
the option is denied we need to change things back) or when
the option is acknowledged.
To initiate a switch to NEW_STATE:
if ((WANT_RESP == 0 && NEW_STATE == MY_STATE) ||
WANT_STATE == NEW_STATE) {
do nothing;
} else {
/*
* This is where the logic goes to change the local setup
* if we are doing so at request initiation
*/
WANT_STATE = NEW_STATE;
send NEW_STATE;
WANT_RESP += 1;
}
When receiving NEW_STATE:
if (WANT_RESP) {
--WANT_RESP;
if (WANT_RESP && (NEW_STATE == MY_STATE))
--WANT_RESP;
}
if (WANT_RESP == 0) {
if (NEW_STATE != WANT_STATE) {
/*
* This is where the logic goes to decide if it is ok
* to switch to NEW_STATE, and if so, do any necessary
* local setup changes.
*/
if (ok_to_switch_to NEW_STATE)
WANT_STATE = NEW_STATE;
else
WANT_RESP++;
* if (MY_STATE != WANT_STATE)
reply with WANT_STATE;
} else {
/*
* This is where the logic goes to change the local setup
* if we are doing so at request acknowledgment
*/
}
}
MY_STATE = NEW_STATE;
* This if() line is not needed, it should be ok to always do the
"reply with WANT_STATE". With the if() line, asking to turn on
an option that the other side doesn't understand is:
Send DO option
Recv WONT option
Without the if() line, it is:
Send DO option
Recv WONT option
Send DONT option
If the other side does not expect to receive the latter case,
but generates the latter case, then there is a potential for
option negotiation loops. An implementation that does not expect
to get the second case should not generate it, an implementation
that does expect to get it may or may not generate it, and things
will still work. Being conservative in what we send, we have the
if() statement in, but we expect the other side to generate the
last response.

View File

@@ -1,26 +0,0 @@
# $Id$
include $(top_srcdir)/Makefile.am.common
WFLAGS += $(WFLAGS_LITE)
AM_CPPFLAGS += -I$(srcdir)/.. $(INCLUDE_hcrypto)
bin_PROGRAMS = telnet
CHECK_LOCAL =
telnet_SOURCES = authenc.c commands.c main.c network.c ring.c \
sys_bsd.c telnet.c terminal.c \
utilities.c defines.h externs.h ring.h telnet_locl.h types.h
man_MANS = telnet.1
LDADD = ../libtelnet/libtelnet.a \
$(LIB_krb5) \
$(LIB_hcrypto) \
$(LIB_tgetent) \
$(LIB_kdfs) \
$(LIB_roken)
EXTRA_DIST = NTMakefile $(man_MANS)

View File

@@ -1,35 +0,0 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT HOLDER 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.
#
RELDIR=appl\telnet\telnet
!include ../../../windows/NTMakefile.w32

View File

@@ -1,99 +0,0 @@
/*-
* 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 "telnet_locl.h"
RCSID("$Id$");
#if defined(AUTHENTICATION) || defined(ENCRYPTION)
int
telnet_net_write(unsigned char *str, int len)
{
if (NETROOM() > len) {
ring_supply_data(&netoring, str, len);
if (str[0] == IAC && str[1] == SE)
printsub('>', &str[2], len-2);
return(len);
}
return(0);
}
void
net_encrypt(void)
{
#if defined(ENCRYPTION)
if (encrypt_output)
ring_encrypt(&netoring, encrypt_output);
else
ring_clearto(&netoring);
#endif
}
int
telnet_spin(void)
{
int ret = 0;
scheduler_lockout_tty = 1;
if (Scheduler(0) == -1)
ret = 1;
scheduler_lockout_tty = 0;
return ret;
}
char *
telnet_getenv(const char *val)
{
return((char *)env_getvalue((unsigned char *)val));
}
char *
telnet_gets(char *prompt, char *result, int length, int echo)
{
int om = globalmode;
char *res;
TerminalNewMode(-1);
if (echo) {
printf("%s", prompt);
res = fgets(result, length, stdin);
} else if ((res = getpass(prompt))) {
strlcpy(result, res, length);
res = result;
}
TerminalNewMode(om);
return(res);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,60 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)defines.h 8.1 (Berkeley) 6/6/93
*/
#define settimer(x) clocks.x = clocks.system++
#define NETADD(c) { *netoring.supply = c; ring_supplied(&netoring, 1); }
#define NET2ADD(c1,c2) { NETADD(c1); NETADD(c2); }
#define NETBYTES() (ring_full_count(&netoring))
#define NETROOM() (ring_empty_count(&netoring))
#define TTYADD(c) if (!(SYNCHing||flushout)) { \
*ttyoring.supply = c; \
ring_supplied(&ttyoring, 1); \
}
#define TTYBYTES() (ring_full_count(&ttyoring))
#define TTYROOM() (ring_empty_count(&ttyoring))
/* Various modes */
#define MODE_LOCAL_CHARS(m) ((m)&(MODE_EDIT|MODE_TRAPSIG))
#define MODE_LOCAL_ECHO(m) ((m)&MODE_ECHO)
#define MODE_COMMAND_LINE(m) ((m)==-1)
#define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */
/* XXX extra mode bits, these should be synced with <arpa/telnet.h> */
#define MODE_OUT8 0x8000 /* binary mode sans -opost */

View File

@@ -1,443 +0,0 @@
/*
* Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)externs.h 8.3 (Berkeley) 5/30/95
*/
/* $Id$ */
#ifndef BSD
# define BSD 43
#endif
#ifndef _POSIX_VDISABLE
# ifdef sun
# include <sys/param.h> /* pick up VDISABLE definition, mayby */
# endif
# ifdef VDISABLE
# define _POSIX_VDISABLE VDISABLE
# else
# define _POSIX_VDISABLE ((cc_t)'\377')
# endif
#endif
#define SUBBUFSIZE 256
extern int
autologin, /* Autologin enabled */
skiprc, /* Don't process the ~/.telnetrc file */
eight, /* use eight bit mode (binary in and/or out */
binary,
flushout, /* flush output */
connected, /* Are we connected to the other side? */
globalmode, /* Mode tty should be in */
telnetport, /* Are we connected to the telnet port? */
localflow, /* Flow control handled locally */
restartany, /* If flow control, restart output on any character */
localchars, /* we recognize interrupt/quit */
donelclchars, /* the user has set "localchars" */
showoptions,
wantencryption, /* User has requested encryption */
net, /* Network file descriptor */
tin, /* Terminal input file descriptor */
tout, /* Terminal output file descriptor */
crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
autoflush, /* flush output when interrupting? */
autosynch, /* send interrupt characters with SYNCH? */
SYNCHing, /* Is the stream in telnet SYNCH mode? */
donebinarytoggle, /* the user has put us in binary */
dontlecho, /* do we suppress local echoing right now? */
crmod,
netdata, /* Print out network data flow */
prettydump, /* Print "netdata" output in user readable format */
termdata, /* Print out terminal data flow */
debug; /* Debug level */
extern int intr_happened, intr_waiting; /* for interrupt handling */
extern cc_t escape; /* Escape to command mode */
extern cc_t rlogin; /* Rlogin mode escape character */
#ifdef KLUDGELINEMODE
extern cc_t echoc; /* Toggle local echoing */
#endif
extern char
*prompt; /* Prompt for command. */
extern char
doopt[],
dont[],
will[],
wont[],
do_dont_resp[],
will_wont_resp[],
options[], /* All the little options */
*hostname; /* Who are we connected to? */
#if defined(ENCRYPTION)
extern void (*encrypt_output) (unsigned char *, int);
extern int (*decrypt_input) (int);
#endif
/*
* We keep track of each side of the option negotiation.
*/
#define MY_STATE_WILL 0x01
#define MY_WANT_STATE_WILL 0x02
#define MY_STATE_DO 0x04
#define MY_WANT_STATE_DO 0x08
/*
* Macros to check the current state of things
*/
#define my_state_is_do(opt) (options[opt]&MY_STATE_DO)
#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL)
#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO)
#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL)
#define my_state_is_dont(opt) (!my_state_is_do(opt))
#define my_state_is_wont(opt) (!my_state_is_will(opt))
#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt))
#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt))
#define set_my_state_do(opt) {options[opt] |= MY_STATE_DO;}
#define set_my_state_will(opt) {options[opt] |= MY_STATE_WILL;}
#define set_my_want_state_do(opt) {options[opt] |= MY_WANT_STATE_DO;}
#define set_my_want_state_will(opt) {options[opt] |= MY_WANT_STATE_WILL;}
#define set_my_state_dont(opt) {options[opt] &= ~MY_STATE_DO;}
#define set_my_state_wont(opt) {options[opt] &= ~MY_STATE_WILL;}
#define set_my_want_state_dont(opt) {options[opt] &= ~MY_WANT_STATE_DO;}
#define set_my_want_state_wont(opt) {options[opt] &= ~MY_WANT_STATE_WILL;}
/*
* Make everything symmetrical
*/
#define HIS_STATE_WILL MY_STATE_DO
#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO
#define HIS_STATE_DO MY_STATE_WILL
#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL
#define his_state_is_do my_state_is_will
#define his_state_is_will my_state_is_do
#define his_want_state_is_do my_want_state_is_will
#define his_want_state_is_will my_want_state_is_do
#define his_state_is_dont my_state_is_wont
#define his_state_is_wont my_state_is_dont
#define his_want_state_is_dont my_want_state_is_wont
#define his_want_state_is_wont my_want_state_is_dont
#define set_his_state_do set_my_state_will
#define set_his_state_will set_my_state_do
#define set_his_want_state_do set_my_want_state_will
#define set_his_want_state_will set_my_want_state_do
#define set_his_state_dont set_my_state_wont
#define set_his_state_wont set_my_state_dont
#define set_his_want_state_dont set_my_want_state_wont
#define set_his_want_state_wont set_my_want_state_dont
extern FILE
*NetTrace; /* Where debugging output goes */
extern char
NetTraceFile[]; /* Name of file where debugging output goes */
extern void
SetNetTrace (char *); /* Function to change where debugging goes */
extern jmp_buf
peerdied,
toplevel; /* For error conditions. */
int Scheduler(int);
extern int scheduler_lockout_tty;
/* authenc.c */
#if defined(AUTHENTICATION) || defined(ENCRYPTION)
int telnet_net_write(unsigned char *str, int len);
void net_encrypt(void);
int telnet_spin(void);
char *telnet_getenv(const char *val);
char *telnet_gets(char *prompt, char *result, int length, int echo);
#endif
/* commands.c */
struct env_lst *env_define (unsigned char *, unsigned char *);
struct env_lst *env_find(unsigned char *var);
void env_init (void);
void env_undefine (unsigned char *);
void env_export (unsigned char *);
void env_unexport (unsigned char *);
void env_send (unsigned char *);
void env_list (void);
unsigned char * env_default(int init, int welldefined);
unsigned char * env_getvalue(unsigned char *var);
void set_escape_char(char *s);
int sourceroute(struct addrinfo *ai, char *arg, char **cpp,
int *prototp, int *optp);
#if defined(AUTHENTICATION)
int auth_enable (char *);
int auth_disable (char *);
int auth_status (void);
#endif
#if defined(ENCRYPTION)
int EncryptEnable (char *, char *);
int EncryptDisable (char *, char *);
int EncryptType (char *, char *);
int EncryptStart (char *);
int EncryptStartInput (void);
int EncryptStartOutput (void);
int EncryptStop (char *);
int EncryptStopInput (void);
int EncryptStopOutput (void);
int EncryptStatus (void);
#endif
#ifdef SIGINFO
RETSIGTYPE ayt_status(int);
#endif
int tn(int argc, char **argv);
void command(int top, char *tbuf, int cnt);
/* main.c */
void tninit(void);
void set_forward_options(void);
/* network.c */
void init_network(void);
int stilloob(void);
void setneturg(void);
int netflush(void);
/* sys_bsd.c */
void init_sys(void);
int TerminalWrite(char *buf, int n);
int TerminalRead(unsigned char *buf, int n);
int TerminalAutoFlush(void);
int TerminalSpecialChars(int c);
void TerminalFlushOutput(void);
void TerminalSaveState(void);
void TerminalDefaultChars(void);
void TerminalNewMode(int f);
cc_t *tcval(int func);
void TerminalSpeeds(long *input_speed, long *output_speed);
int TerminalWindowSize(long *rows, long *cols);
int NetClose(int fd);
void NetNonblockingIO(int fd, int onoff);
int process_rings(int netin, int netout, int netex, int ttyin, int ttyout,
int poll);
/* telnet.c */
void init_telnet(void);
void tel_leave_binary(int rw);
void tel_enter_binary(int rw);
int opt_welldefined(char *ep);
int telrcv(void);
int rlogin_susp(void);
void intp(void);
void sendbrk(void);
void sendabort(void);
void sendsusp(void);
void sendeof(void);
void sendayt(void);
void xmitAO(void);
void xmitEL(void);
void xmitEC(void);
void Dump (char, unsigned char *, int);
void printoption (char *, int, int);
void sendnaws (void);
void setconnmode (int);
void setcommandmode (void);
void setneturg (void);
void sys_telnet_init (void);
void my_telnet (char *);
void tel_enter_binary (int);
void TerminalFlushOutput (void);
void TerminalNewMode (int);
void TerminalRestoreState (void);
void TerminalSaveState (void);
void willoption (int);
void wontoption (int);
void send_do (int, int);
void send_dont (int, int);
void send_will (int, int);
void send_wont (int, int);
void lm_will (unsigned char *, int);
void lm_wont (unsigned char *, int);
void lm_do (unsigned char *, int);
void lm_dont (unsigned char *, int);
void lm_mode (unsigned char *, int, int);
void slc_init (void);
void slcstate (void);
void slc_mode_export (void);
void slc_mode_import (int);
void slc_import (int);
void slc_export (void);
void slc (unsigned char *, int);
void slc_check (void);
void slc_start_reply (void);
void slc_add_reply (unsigned char, unsigned char, cc_t);
void slc_end_reply (void);
int slc_update (void);
void env_opt (unsigned char *, int);
void env_opt_start (void);
void env_opt_start_info (void);
void env_opt_add (unsigned char *);
void env_opt_end (int);
unsigned char *env_default (int, int);
unsigned char *env_getvalue (unsigned char *);
int get_status (void);
int dosynch (void);
cc_t *tcval (int);
int quit (void);
/* terminal.c */
void init_terminal(void);
int ttyflush(int drop);
int getconnmode(void);
/* utilities.c */
int SetSockOpt(int fd, int level, int option, int yesno);
void SetNetTrace(char *file);
void Dump(char direction, unsigned char *buffer, int length);
void printoption(char *direction, int cmd, int option);
void optionstatus(void);
void printsub(int direction, unsigned char *pointer, size_t length);
void EmptyTerminal(void);
void SetForExit(void);
void Exit(int returnCode);
void ExitString(char *string, int returnCode);
extern struct termios new_tc;
# define termEofChar new_tc.c_cc[VEOF]
# define termEraseChar new_tc.c_cc[VERASE]
# define termIntChar new_tc.c_cc[VINTR]
# define termKillChar new_tc.c_cc[VKILL]
# define termQuitChar new_tc.c_cc[VQUIT]
# ifndef VSUSP
extern cc_t termSuspChar;
# else
# define termSuspChar new_tc.c_cc[VSUSP]
# endif
# if defined(VFLUSHO) && !defined(VDISCARD)
# define VDISCARD VFLUSHO
# endif
# ifndef VDISCARD
extern cc_t termFlushChar;
# else
# define termFlushChar new_tc.c_cc[VDISCARD]
# endif
# ifndef VWERASE
extern cc_t termWerasChar;
# else
# define termWerasChar new_tc.c_cc[VWERASE]
# endif
# ifndef VREPRINT
extern cc_t termRprntChar;
# else
# define termRprntChar new_tc.c_cc[VREPRINT]
# endif
# ifndef VLNEXT
extern cc_t termLiteralNextChar;
# else
# define termLiteralNextChar new_tc.c_cc[VLNEXT]
# endif
# ifndef VSTART
extern cc_t termStartChar;
# else
# define termStartChar new_tc.c_cc[VSTART]
# endif
# ifndef VSTOP
extern cc_t termStopChar;
# else
# define termStopChar new_tc.c_cc[VSTOP]
# endif
# ifndef VEOL
extern cc_t termForw1Char;
# else
# define termForw1Char new_tc.c_cc[VEOL]
# endif
# ifndef VEOL2
extern cc_t termForw2Char;
# else
# define termForw2Char new_tc.c_cc[VEOL]
# endif
# ifndef VSTATUS
extern cc_t termAytChar;
#else
# define termAytChar new_tc.c_cc[VSTATUS]
#endif
/* Ring buffer structures which are shared */
extern Ring
netoring,
netiring,
ttyoring,
ttyiring;
extern int resettermname;
extern int linemode;
#ifdef KLUDGELINEMODE
extern int kludgelinemode;
#endif
extern int want_status_response;

View File

@@ -1,358 +0,0 @@
/*
* Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static char *copyright[] = {
"@(#) Copyright (c) 1988, 1990, 1993\n"
"\tThe Regents of the University of California. All rights reserved.\n",
(char*)copyright
};
#include "telnet_locl.h"
RCSID("$Id$");
#if KRB5
#define FORWARD
#endif
/*
* Initialize variables.
*/
void
tninit(void)
{
init_terminal();
init_network();
init_telnet();
init_sys();
}
static void
usage(int exit_code)
{
fprintf(stderr, "Usage: %s %s%s%s%s\n", prompt,
#ifdef AUTHENTICATION
"[-8] [-E] [-K] [-L] [-G] [-S tos] [-X atype] [-a] [-c] [-d] [-e char]",
"\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] ",
#else
"[-8] [-E] [-L] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
"\n\t[-n tracefile]",
#endif
"[-r] ",
#ifdef ENCRYPTION
"[-x] [host-name [port]]"
#else
"[host-name [port]]"
#endif
);
exit(exit_code);
}
/*
* main. Parse arguments, invoke the protocol or command parser.
*/
#ifdef FORWARD
int forward_option = 0; /* forward flags set from command line */
#endif /* FORWARD */
void
set_forward_options(void)
{
#ifdef FORWARD
switch(forward_option) {
case 'f':
kerberos5_set_forward(1);
kerberos5_set_forwardable(0);
break;
case 'F':
kerberos5_set_forward(1);
kerberos5_set_forwardable(1);
break;
case 'G':
kerberos5_set_forward(0);
kerberos5_set_forwardable(0);
break;
default:
break;
}
#endif
}
#ifdef KRB5
#define Authenticator asn1_Authenticator
#include <krb5.h>
static void
krb5_init(void)
{
krb5_context context;
krb5_error_code ret;
krb5_boolean ret_val;
ret = krb5_init_context(&context);
if (ret)
return;
#if defined(AUTHENTICATION) && defined(FORWARD)
krb5_appdefault_boolean(context, NULL,
NULL, "forward",
0, &ret_val);
if (ret_val)
kerberos5_set_forward(1);
krb5_appdefault_boolean(context, NULL,
NULL, "forwardable",
0, &ret_val);
if (ret_val)
kerberos5_set_forwardable(1);
#endif
#ifdef ENCRYPTION
krb5_appdefault_boolean(context, NULL,
NULL, "encrypt",
0, &ret_val);
if (ret_val) {
encrypt_auto(1);
decrypt_auto(1);
wantencryption = 1;
EncryptVerbose(1);
}
#endif
krb5_free_context(context);
}
#endif
int
main(int argc, char **argv)
{
int ch;
char *user;
setprogname(argv[0]);
#ifdef KRB5
krb5_init();
#endif
tninit(); /* Clear out things */
TerminalSaveState();
if ((prompt = strrchr(argv[0], '/')))
++prompt;
else
prompt = argv[0];
user = NULL;
rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
/*
* if AUTHENTICATION and ENCRYPTION is set autologin will be
* se to true after the getopt switch; unless the -K option is
* passed
*/
autologin = -1;
if (argc == 2 && strcmp(argv[1], "--version") == 0) {
print_version(NULL);
exit(0);
}
if (argc == 2 && strcmp(argv[1], "--help") == 0)
usage(0);
while((ch = getopt(argc, argv,
"78DEKLS:X:abcde:fFk:l:n:rxG")) != -1) {
switch(ch) {
case '8':
eight = 3; /* binary output and input */
break;
case '7':
eight = 0;
break;
case 'b':
binary = 3;
break;
case 'D': {
/* sometimes we don't want a mangled display */
char *p;
if((p = getenv("DISPLAY")))
env_define((unsigned char*)"DISPLAY", (unsigned char*)p);
break;
}
case 'E':
rlogin = escape = _POSIX_VDISABLE;
break;
case 'K':
#ifdef AUTHENTICATION
autologin = 0;
#endif
break;
case 'L':
eight |= 2; /* binary output only */
break;
case 'S':
{
#ifdef HAVE_PARSETOS
extern int tos;
if ((tos = parsetos(optarg, "tcp")) < 0)
fprintf(stderr, "%s%s%s%s\n",
prompt, ": Bad TOS argument '",
optarg,
"; will try to use default TOS");
#else
fprintf(stderr,
"%s: Warning: -S ignored, no parsetos() support.\n",
prompt);
#endif
}
break;
case 'X':
#ifdef AUTHENTICATION
auth_disable_name(optarg);
#endif
break;
case 'a':
autologin = 1;
break;
case 'c':
skiprc = 1;
break;
case 'd':
debug = 1;
break;
case 'e':
set_escape_char(optarg);
break;
case 'f':
case 'F':
case 'G':
#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
if (forward_option) {
fprintf(stderr,
"%s: Only one of -f, -F and -G allowed.\n",
prompt);
usage(1);
}
forward_option = ch;
#else
fprintf(stderr,
"%s: Warning: -%c ignored, no Kerberos V5 support.\n",
prompt, ch);
#endif
break;
case 'k':
fprintf(stderr,
"%s: Warning: -k ignored, no Kerberos V4 support.\n",
prompt);
break;
case 'l':
if(autologin == 0){
fprintf(stderr, "%s: Warning: -K ignored\n", prompt);
autologin = -1;
}
user = optarg;
break;
case 'n':
SetNetTrace(optarg);
break;
case 'r':
rlogin = '~';
break;
case 'x':
#ifdef ENCRYPTION
encrypt_auto(1);
decrypt_auto(1);
wantencryption = 1;
EncryptVerbose(1);
#else
fprintf(stderr,
"%s: Warning: -x ignored, no ENCRYPT support.\n",
prompt);
#endif
break;
case '?':
default:
usage(1);
/* NOTREACHED */
}
}
if (autologin == -1) { /* esc@magic.fi; force */
#if defined(AUTHENTICATION)
autologin = 1;
#endif
#if defined(ENCRYPTION)
encrypt_auto(1);
decrypt_auto(1);
wantencryption = -1;
#endif
}
if (autologin == -1)
autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
argc -= optind;
argv += optind;
if (argc) {
char *args[7], **argp = args;
if (argc > 2)
usage(1);
*argp++ = prompt;
if (user) {
*argp++ = "-l";
*argp++ = user;
}
*argp++ = argv[0]; /* host */
if (argc > 1)
*argp++ = argv[1]; /* port */
*argp = 0;
if (setjmp(toplevel) != 0)
Exit(0);
if (tn(argp - args, args) == 1)
return (0);
else
return (1);
}
setjmp(toplevel);
for (;;) {
command(1, 0, 0);
}
}

View File

@@ -1,173 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "telnet_locl.h"
RCSID("$Id$");
Ring netoring, netiring;
size_t netobufsize = 64*1024;
size_t netibufsize = 64*1024;
/*
* Initialize internal network data structures.
*/
void
init_network(void)
{
void *obuf, *ibuf;
if ((obuf = malloc(netobufsize)) == NULL)
exit(1);
if ((ibuf = malloc(netibufsize)) == NULL)
exit(1);
if (ring_init(&netoring, obuf, netobufsize) != 1) {
exit(1);
}
if (ring_init(&netiring, ibuf, netibufsize) != 1) {
exit(1);
}
NetTrace = stdout;
}
/*
* Check to see if any out-of-band data exists on a socket (for
* Telnet "synch" processing).
*/
int
stilloob(void)
{
static struct timeval timeout = { 0 };
fd_set excepts;
int value;
do {
FD_ZERO(&excepts);
if (net >= FD_SETSIZE)
errx (1, "fd too large");
FD_SET(net, &excepts);
value = select(net+1, 0, 0, &excepts, &timeout);
} while ((value == -1) && (errno == EINTR));
if (value < 0) {
perror("select");
quit();
/* NOTREACHED */
}
if (FD_ISSET(net, &excepts)) {
return 1;
} else {
return 0;
}
}
/*
* setneturg()
*
* Sets "neturg" to the current location.
*/
void
setneturg(void)
{
ring_mark(&netoring);
}
/*
* netflush
* Send as much data as possible to the network,
* handling requests for urgent data.
*
* The return value indicates whether we did any
* useful work.
*/
int
netflush(void)
{
int n, n1;
#if defined(ENCRYPTION)
if (encrypt_output)
ring_encrypt(&netoring, encrypt_output);
#endif
if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
if (!ring_at_mark(&netoring)) {
n = send(net, (char *)netoring.consume, n, 0); /* normal write */
} else {
/*
* In 4.2 (and 4.3) systems, there is some question about
* what byte in a sendOOB operation is the "OOB" data.
* To make ourselves compatible, we only send ONE byte
* out of band, the one WE THINK should be OOB (though
* we really have more the TCP philosophy of urgent data
* rather than the Unix philosophy of OOB data).
*/
n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
}
}
if (n < 0) {
if (errno != ENOBUFS && errno != EWOULDBLOCK) {
setcommandmode();
perror(hostname);
NetClose(net);
ring_clear_mark(&netoring);
longjmp(peerdied, -1);
/*NOTREACHED*/
}
n = 0;
}
if (netdata && n) {
Dump('>', netoring.consume, n);
}
if (n) {
ring_consumed(&netoring, n);
/*
* If we sent all, and more to send, then recurse to pick
* up the other half.
*/
if ((n1 == n) && ring_full_consecutive(&netoring)) {
netflush();
}
return 1;
} else {
return 0;
}
}

View File

@@ -1,321 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "telnet_locl.h"
RCSID("$Id$");
/*
* This defines a structure for a ring buffer.
*
* The circular buffer has two parts:
*(((
* full: [consume, supply)
* empty: [supply, consume)
*]]]
*
*/
/* Internal macros */
#define ring_subtract(d,a,b) (((a)-(b) >= 0)? \
(a)-(b): (((a)-(b))+(d)->size))
#define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \
(a)+(c) : (((a)+(c))-(d)->size))
#define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \
(a)-(c) : (((a)-(c))-(d)->size))
/*
* The following is a clock, used to determine full, empty, etc.
*
* There is some trickiness here. Since the ring buffers are initialized
* to ZERO on allocation, we need to make sure, when interpreting the
* clock, that when the times are EQUAL, then the buffer is FULL.
*/
static u_long ring_clock = 0;
#define ring_empty(d) (((d)->consume == (d)->supply) && \
((d)->consumetime >= (d)->supplytime))
#define ring_full(d) (((d)->supply == (d)->consume) && \
((d)->supplytime > (d)->consumetime))
/* Buffer state transition routines */
int
ring_init(Ring *ring, unsigned char *buffer, int count)
{
memset(ring, 0, sizeof *ring);
ring->size = count;
ring->supply = ring->consume = ring->bottom = buffer;
ring->top = ring->bottom+ring->size;
#if defined(ENCRYPTION)
ring->clearto = 0;
#endif
return 1;
}
/* Mark routines */
/*
* Mark the most recently supplied byte.
*/
void
ring_mark(Ring *ring)
{
ring->mark = ring_decrement(ring, ring->supply, 1);
}
/*
* Is the ring pointing to the mark?
*/
int
ring_at_mark(Ring *ring)
{
if (ring->mark == ring->consume) {
return 1;
} else {
return 0;
}
}
/*
* Clear any mark set on the ring.
*/
void
ring_clear_mark(Ring *ring)
{
ring->mark = 0;
}
/*
* Add characters from current segment to ring buffer.
*/
void
ring_supplied(Ring *ring, int count)
{
ring->supply = ring_increment(ring, ring->supply, count);
ring->supplytime = ++ring_clock;
}
/*
* We have just consumed "c" bytes.
*/
void
ring_consumed(Ring *ring, int count)
{
if (count == 0) /* don't update anything */
return;
if (ring->mark &&
(ring_subtract(ring, ring->mark, ring->consume) < count)) {
ring->mark = 0;
}
#if defined(ENCRYPTION)
if (ring->consume < ring->clearto &&
ring->clearto <= ring->consume + count)
ring->clearto = 0;
else if (ring->consume + count > ring->top &&
ring->bottom <= ring->clearto &&
ring->bottom + ((ring->consume + count) - ring->top))
ring->clearto = 0;
#endif
ring->consume = ring_increment(ring, ring->consume, count);
ring->consumetime = ++ring_clock;
/*
* Try to encourage "ring_empty_consecutive()" to be large.
*/
if (ring_empty(ring)) {
ring->consume = ring->supply = ring->bottom;
}
}
/* Buffer state query routines */
/* Number of bytes that may be supplied */
int
ring_empty_count(Ring *ring)
{
if (ring_empty(ring)) { /* if empty */
return ring->size;
} else {
return ring_subtract(ring, ring->consume, ring->supply);
}
}
/* number of CONSECUTIVE bytes that may be supplied */
int
ring_empty_consecutive(Ring *ring)
{
if ((ring->consume < ring->supply) || ring_empty(ring)) {
/*
* if consume is "below" supply, or empty, then
* return distance to the top
*/
return ring_subtract(ring, ring->top, ring->supply);
} else {
/*
* else, return what we may.
*/
return ring_subtract(ring, ring->consume, ring->supply);
}
}
/* Return the number of bytes that are available for consuming
* (but don't give more than enough to get to cross over set mark)
*/
int
ring_full_count(Ring *ring)
{
if ((ring->mark == 0) || (ring->mark == ring->consume)) {
if (ring_full(ring)) {
return ring->size; /* nothing consumed, but full */
} else {
return ring_subtract(ring, ring->supply, ring->consume);
}
} else {
return ring_subtract(ring, ring->mark, ring->consume);
}
}
/*
* Return the number of CONSECUTIVE bytes available for consuming.
* However, don't return more than enough to cross over set mark.
*/
int
ring_full_consecutive(Ring *ring)
{
if ((ring->mark == 0) || (ring->mark == ring->consume)) {
if ((ring->supply < ring->consume) || ring_full(ring)) {
return ring_subtract(ring, ring->top, ring->consume);
} else {
return ring_subtract(ring, ring->supply, ring->consume);
}
} else {
if (ring->mark < ring->consume) {
return ring_subtract(ring, ring->top, ring->consume);
} else { /* Else, distance to mark */
return ring_subtract(ring, ring->mark, ring->consume);
}
}
}
/*
* Move data into the "supply" portion of of the ring buffer.
*/
void
ring_supply_data(Ring *ring, unsigned char *buffer, int count)
{
int i;
while (count) {
i = min(count, ring_empty_consecutive(ring));
memmove(ring->supply, buffer, i);
ring_supplied(ring, i);
count -= i;
buffer += i;
}
}
#ifdef notdef
/*
* Move data from the "consume" portion of the ring buffer
*/
void
ring_consume_data(Ring *ring, unsigned char *buffer, int count)
{
int i;
while (count) {
i = min(count, ring_full_consecutive(ring));
memmove(buffer, ring->consume, i);
ring_consumed(ring, i);
count -= i;
buffer += i;
}
}
#endif
#if defined(ENCRYPTION)
void
ring_encrypt(Ring *ring, void (*encryptor)(unsigned char *, int))
{
unsigned char *s, *c;
if (ring_empty(ring) || ring->clearto == ring->supply)
return;
if (!(c = ring->clearto))
c = ring->consume;
s = ring->supply;
if (s <= c) {
(*encryptor)(c, ring->top - c);
(*encryptor)(ring->bottom, s - ring->bottom);
} else
(*encryptor)(c, s - c);
ring->clearto = ring->supply;
}
void
ring_clearto(Ring *ring)
{
if (!ring_empty(ring))
ring->clearto = ring->supply;
else
ring->clearto = 0;
}
#endif

View File

@@ -1,99 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ring.h 8.1 (Berkeley) 6/6/93
*/
/* $Id$ */
/*
* This defines a structure for a ring buffer.
*
* The circular buffer has two parts:
*(((
* full: [consume, supply)
* empty: [supply, consume)
*]]]
*
*/
typedef struct {
unsigned char *consume, /* where data comes out of */
*supply, /* where data comes in to */
*bottom, /* lowest address in buffer */
*top, /* highest address+1 in buffer */
*mark; /* marker (user defined) */
#if defined(ENCRYPTION)
unsigned char *clearto; /* Data to this point is clear text */
unsigned char *encryyptedto; /* Data is encrypted to here */
#endif
int size; /* size in bytes of buffer */
u_long consumetime, /* help us keep straight full, empty, etc. */
supplytime;
} Ring;
/* Here are some functions and macros to deal with the ring buffer */
/* Initialization routine */
extern int
ring_init (Ring *ring, unsigned char *buffer, int count);
/* Data movement routines */
extern void
ring_supply_data (Ring *ring, unsigned char *buffer, int count);
#ifdef notdef
extern void
ring_consume_data (Ring *ring, unsigned char *buffer, int count);
#endif
/* Buffer state transition routines */
extern void
ring_supplied (Ring *ring, int count),
ring_consumed (Ring *ring, int count);
/* Buffer state query routines */
extern int
ring_empty_count (Ring *ring),
ring_empty_consecutive (Ring *ring),
ring_full_count (Ring *ring),
ring_full_consecutive (Ring *ring);
#if defined(ENCRYPTION)
extern void
ring_encrypt (Ring *ring, void (*func)(unsigned char *, int)),
ring_clearto (Ring *ring);
#endif
extern int ring_at_mark(Ring *ring);
extern void
ring_clear_mark(Ring *ring),
ring_mark(Ring *ring);

View File

@@ -1,979 +0,0 @@
/*
* Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "telnet_locl.h"
RCSID("$Id$");
/*
* The following routines try to encapsulate what is system dependent
* (at least between 4.x and dos) which is used in telnet.c.
*/
int
tout, /* Output file descriptor */
tin, /* Input file descriptor */
net;
struct termios old_tc = { 0 };
extern struct termios new_tc;
# ifndef TCSANOW
# ifdef TCSETS
# define TCSANOW TCSETS
# define TCSADRAIN TCSETSW
# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
# else
# ifdef TCSETA
# define TCSANOW TCSETA
# define TCSADRAIN TCSETAW
# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
# else
# define TCSANOW TIOCSETA
# define TCSADRAIN TIOCSETAW
# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
# endif
# endif
# define tcsetattr(f, a, t) ioctl(f, a, (char *)t)
# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD)
# ifdef CIBAUD
# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
# else
# define cfgetispeed(ptr) cfgetospeed(ptr)
# endif
# endif /* TCSANOW */
static fd_set ibits, obits, xbits;
void
init_sys(void)
{
tout = fileno(stdout);
tin = fileno(stdin);
FD_ZERO(&ibits);
FD_ZERO(&obits);
FD_ZERO(&xbits);
errno = 0;
}
int
TerminalWrite(char *buf, int n)
{
return write(tout, buf, n);
}
int
TerminalRead(unsigned char *buf, int n)
{
return read(tin, buf, n);
}
/*
*
*/
int
TerminalAutoFlush(void)
{
#if defined(LNOFLSH)
int flush;
ioctl(0, TIOCLGET, (char *)&flush);
return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */
#else /* LNOFLSH */
return 1;
#endif /* LNOFLSH */
}
/*
* TerminalSpecialChars()
*
* Look at an input character to see if it is a special character
* and decide what to do.
*
* Output:
*
* 0 Don't add this character.
* 1 Do add this character
*/
int
TerminalSpecialChars(int c)
{
if (c == termIntChar) {
intp();
return 0;
} else if (c == termQuitChar) {
#ifdef KLUDGELINEMODE
if (kludgelinemode)
sendbrk();
else
#endif
sendabort();
return 0;
} else if (c == termEofChar) {
if (my_want_state_is_will(TELOPT_LINEMODE)) {
sendeof();
return 0;
}
return 1;
} else if (c == termSuspChar) {
sendsusp();
return(0);
} else if (c == termFlushChar) {
xmitAO(); /* Transmit Abort Output */
return 0;
} else if (!MODE_LOCAL_CHARS(globalmode)) {
if (c == termKillChar) {
xmitEL();
return 0;
} else if (c == termEraseChar) {
xmitEC(); /* Transmit Erase Character */
return 0;
}
}
return 1;
}
/*
* Flush output to the terminal
*/
void
TerminalFlushOutput(void)
{
#ifdef TIOCFLUSH
ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
#else
ioctl(fileno(stdout), TCFLSH, (char *) 0);
#endif
}
void
TerminalSaveState(void)
{
tcgetattr(0, &old_tc);
new_tc = old_tc;
#ifndef VDISCARD
termFlushChar = CONTROL('O');
#endif
#ifndef VWERASE
termWerasChar = CONTROL('W');
#endif
#ifndef VREPRINT
termRprntChar = CONTROL('R');
#endif
#ifndef VLNEXT
termLiteralNextChar = CONTROL('V');
#endif
#ifndef VSTART
termStartChar = CONTROL('Q');
#endif
#ifndef VSTOP
termStopChar = CONTROL('S');
#endif
#ifndef VSTATUS
termAytChar = CONTROL('T');
#endif
}
cc_t*
tcval(int func)
{
switch(func) {
case SLC_IP: return(&termIntChar);
case SLC_ABORT: return(&termQuitChar);
case SLC_EOF: return(&termEofChar);
case SLC_EC: return(&termEraseChar);
case SLC_EL: return(&termKillChar);
case SLC_XON: return(&termStartChar);
case SLC_XOFF: return(&termStopChar);
case SLC_FORW1: return(&termForw1Char);
case SLC_FORW2: return(&termForw2Char);
# ifdef VDISCARD
case SLC_AO: return(&termFlushChar);
# endif
# ifdef VSUSP
case SLC_SUSP: return(&termSuspChar);
# endif
# ifdef VWERASE
case SLC_EW: return(&termWerasChar);
# endif
# ifdef VREPRINT
case SLC_RP: return(&termRprntChar);
# endif
# ifdef VLNEXT
case SLC_LNEXT: return(&termLiteralNextChar);
# endif
# ifdef VSTATUS
case SLC_AYT: return(&termAytChar);
# endif
case SLC_SYNCH:
case SLC_BRK:
case SLC_EOR:
default:
return((cc_t *)0);
}
}
void
TerminalDefaultChars(void)
{
memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
# ifndef VDISCARD
termFlushChar = CONTROL('O');
# endif
# ifndef VWERASE
termWerasChar = CONTROL('W');
# endif
# ifndef VREPRINT
termRprntChar = CONTROL('R');
# endif
# ifndef VLNEXT
termLiteralNextChar = CONTROL('V');
# endif
# ifndef VSTART
termStartChar = CONTROL('Q');
# endif
# ifndef VSTOP
termStopChar = CONTROL('S');
# endif
# ifndef VSTATUS
termAytChar = CONTROL('T');
# endif
}
#ifdef notdef
void
TerminalRestoreState()
{
}
#endif
/*
* TerminalNewMode - set up terminal to a specific mode.
* MODE_ECHO: do local terminal echo
* MODE_FLOW: do local flow control
* MODE_TRAPSIG: do local mapping to TELNET IAC sequences
* MODE_EDIT: do local line editing
*
* Command mode:
* MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
* local echo
* local editing
* local xon/xoff
* local signal mapping
*
* Linemode:
* local/no editing
* Both Linemode and Single Character mode:
* local/remote echo
* local/no xon/xoff
* local/no signal mapping
*/
#ifdef SIGTSTP
static RETSIGTYPE susp(int);
#endif /* SIGTSTP */
#ifdef SIGINFO
static RETSIGTYPE ayt(int);
#endif
void
TerminalNewMode(int f)
{
static int prevmode = 0;
struct termios tmp_tc;
int onoff;
int old;
cc_t esc;
globalmode = f&~MODE_FORCE;
if (prevmode == f)
return;
/*
* Write any outstanding data before switching modes
* ttyflush() returns 0 only when there is no more data
* left to write out, it returns -1 if it couldn't do
* anything at all, otherwise it returns 1 + the number
* of characters left to write.
*/
old = ttyflush(SYNCHing|flushout);
if (old < 0 || old > 1) {
tcgetattr(tin, &tmp_tc);
do {
/*
* Wait for data to drain, then flush again.
*/
tcsetattr(tin, TCSADRAIN, &tmp_tc);
old = ttyflush(SYNCHing|flushout);
} while (old < 0 || old > 1);
}
old = prevmode;
prevmode = f&~MODE_FORCE;
tmp_tc = new_tc;
if (f&MODE_ECHO) {
tmp_tc.c_lflag |= ECHO;
tmp_tc.c_oflag |= ONLCR;
if (crlf)
tmp_tc.c_iflag |= ICRNL;
} else {
tmp_tc.c_lflag &= ~ECHO;
tmp_tc.c_oflag &= ~ONLCR;
# ifdef notdef
if (crlf)
tmp_tc.c_iflag &= ~ICRNL;
# endif
}
if ((f&MODE_FLOW) == 0) {
tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */
} else {
if (restartany < 0) {
tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */
} else if (restartany > 0) {
tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
} else {
tmp_tc.c_iflag |= IXOFF|IXON;
tmp_tc.c_iflag &= ~IXANY;
}
}
if ((f&MODE_TRAPSIG) == 0) {
tmp_tc.c_lflag &= ~ISIG;
localchars = 0;
} else {
tmp_tc.c_lflag |= ISIG;
localchars = 1;
}
if (f&MODE_EDIT) {
tmp_tc.c_lflag |= ICANON;
} else {
tmp_tc.c_lflag &= ~ICANON;
tmp_tc.c_iflag &= ~ICRNL;
tmp_tc.c_cc[VMIN] = 1;
tmp_tc.c_cc[VTIME] = 0;
}
if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
# ifdef VLNEXT
tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
# endif
}
if (f&MODE_SOFT_TAB) {
# ifdef OXTABS
tmp_tc.c_oflag |= OXTABS;
# endif
# ifdef TABDLY
tmp_tc.c_oflag &= ~TABDLY;
tmp_tc.c_oflag |= TAB3;
# endif
} else {
# ifdef OXTABS
tmp_tc.c_oflag &= ~OXTABS;
# endif
# ifdef TABDLY
tmp_tc.c_oflag &= ~TABDLY;
# endif
}
if (f&MODE_LIT_ECHO) {
# ifdef ECHOCTL
tmp_tc.c_lflag &= ~ECHOCTL;
# endif
} else {
# ifdef ECHOCTL
tmp_tc.c_lflag |= ECHOCTL;
# endif
}
if (f == -1) {
onoff = 0;
} else {
if (f & MODE_INBIN)
tmp_tc.c_iflag &= ~ISTRIP;
else
tmp_tc.c_iflag |= ISTRIP;
if ((f & MODE_OUTBIN) || (f & MODE_OUT8)) {
tmp_tc.c_cflag &= ~(CSIZE|PARENB);
tmp_tc.c_cflag |= CS8;
if(f & MODE_OUTBIN)
tmp_tc.c_oflag &= ~OPOST;
else
tmp_tc.c_oflag |= OPOST;
} else {
tmp_tc.c_cflag &= ~(CSIZE|PARENB);
tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
tmp_tc.c_oflag |= OPOST;
}
onoff = 1;
}
if (f != -1) {
#ifdef SIGTSTP
signal(SIGTSTP, susp);
#endif /* SIGTSTP */
#ifdef SIGINFO
signal(SIGINFO, ayt);
#endif
#ifdef NOKERNINFO
tmp_tc.c_lflag |= NOKERNINFO;
#endif
/*
* We don't want to process ^Y here. It's just another
* character that we'll pass on to the back end. It has
* to process it because it will be processed when the
* user attempts to read it, not when we send it.
*/
# ifdef VDSUSP
tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
# endif
/*
* If the VEOL character is already set, then use VEOL2,
* otherwise use VEOL.
*/
esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
if ((tmp_tc.c_cc[VEOL] != esc)
# ifdef VEOL2
&& (tmp_tc.c_cc[VEOL2] != esc)
# endif
) {
if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
tmp_tc.c_cc[VEOL] = esc;
# ifdef VEOL2
else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
tmp_tc.c_cc[VEOL2] = esc;
# endif
}
} else {
sigset_t sm;
#ifdef SIGINFO
signal(SIGINFO, ayt_status);
#endif
#ifdef SIGTSTP
signal(SIGTSTP, SIG_DFL);
sigemptyset(&sm);
sigaddset(&sm, SIGTSTP);
sigprocmask(SIG_UNBLOCK, &sm, NULL);
#endif /* SIGTSTP */
tmp_tc = old_tc;
}
if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
tcsetattr(tin, TCSANOW, &tmp_tc);
ioctl(tin, FIONBIO, (char *)&onoff);
ioctl(tout, FIONBIO, (char *)&onoff);
}
/*
* Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
*/
#if B4800 != 4800
#define DECODE_BAUD
#endif
#ifdef DECODE_BAUD
#ifndef B7200
#define B7200 B4800
#endif
#ifndef B14400
#define B14400 B9600
#endif
#ifndef B19200
# define B19200 B14400
#endif
#ifndef B28800
#define B28800 B19200
#endif
#ifndef B38400
# define B38400 B28800
#endif
#ifndef B57600
#define B57600 B38400
#endif
#ifndef B76800
#define B76800 B57600
#endif
#ifndef B115200
#define B115200 B76800
#endif
#ifndef B230400
#define B230400 B115200
#endif
/*
* This code assumes that the values B0, B50, B75...
* are in ascending order. They do not have to be
* contiguous.
*/
struct termspeeds {
long speed;
long value;
} termspeeds[] = {
{ 0, B0 }, { 50, B50 }, { 75, B75 },
{ 110, B110 }, { 134, B134 }, { 150, B150 },
{ 200, B200 }, { 300, B300 }, { 600, B600 },
{ 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
{ 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 },
{ 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 },
{ 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 },
{ 230400, B230400 }, { -1, B230400 }
};
#endif /* DECODE_BAUD */
void
TerminalSpeeds(long *input_speed, long *output_speed)
{
#ifdef DECODE_BAUD
struct termspeeds *tp;
#endif /* DECODE_BAUD */
long in, out;
out = cfgetospeed(&old_tc);
in = cfgetispeed(&old_tc);
if (in == 0)
in = out;
#ifdef DECODE_BAUD
tp = termspeeds;
while ((tp->speed != -1) && (tp->value < in))
tp++;
*input_speed = tp->speed;
tp = termspeeds;
while ((tp->speed != -1) && (tp->value < out))
tp++;
*output_speed = tp->speed;
#else /* DECODE_BAUD */
*input_speed = in;
*output_speed = out;
#endif /* DECODE_BAUD */
}
int
TerminalWindowSize(long *rows, long *cols)
{
int irows, icols;
if (get_window_size(STDIN_FILENO, &irows, &icols) == 0) {
*rows = irows;
*cols = icols;
return 1;
} else
return 0;
}
int
NetClose(int fd)
{
return close(fd);
}
void
NetNonblockingIO(int fd, int onoff)
{
ioctl(fd, FIONBIO, (char *)&onoff);
}
/*
* Various signal handling routines.
*/
static RETSIGTYPE deadpeer(int),
intr(int), intr2(int), susp(int), sendwin(int);
#ifdef SIGINFO
static RETSIGTYPE ayt(int);
#endif
/* ARGSUSED */
static RETSIGTYPE
deadpeer(int sig)
{
setcommandmode();
longjmp(peerdied, -1);
}
int intr_happened = 0;
int intr_waiting = 0;
/* ARGSUSED */
static RETSIGTYPE
intr(int sig)
{
if (intr_waiting) {
intr_happened = 1;
return;
}
if (localchars) {
intp();
return;
}
setcommandmode();
longjmp(toplevel, -1);
}
/* ARGSUSED */
static RETSIGTYPE
intr2(int sig)
{
if (localchars) {
#ifdef KLUDGELINEMODE
if (kludgelinemode)
sendbrk();
else
#endif
sendabort();
return;
}
}
#ifdef SIGTSTP
/* ARGSUSED */
static RETSIGTYPE
susp(int sig)
{
if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
return;
if (localchars)
sendsusp();
}
#endif
#ifdef SIGWINCH
/* ARGSUSED */
static RETSIGTYPE
sendwin(int sig)
{
if (connected) {
sendnaws();
}
}
#endif
#ifdef SIGINFO
/* ARGSUSED */
static RETSIGTYPE
ayt(int sig)
{
if (connected)
sendayt();
else
ayt_status(sig);
}
#endif
void
sys_telnet_init(void)
{
signal(SIGINT, intr);
signal(SIGQUIT, intr2);
signal(SIGPIPE, deadpeer);
#ifdef SIGWINCH
signal(SIGWINCH, sendwin);
#endif
#ifdef SIGTSTP
signal(SIGTSTP, susp);
#endif
#ifdef SIGINFO
signal(SIGINFO, ayt);
#endif
setconnmode(0);
NetNonblockingIO(net, 1);
#if defined(SO_OOBINLINE)
if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1)
perror("setsockopt (SO_OOBINLINE) (ignored)");
#endif /* defined(SO_OOBINLINE) */
}
/*
* Process rings -
*
* This routine tries to fill up/empty our various rings.
*
* The parameter specifies whether this is a poll operation,
* or a block-until-something-happens operation.
*
* The return value is 1 if something happened, 0 if not.
*/
int
process_rings(int netin,
int netout,
int netex,
int ttyin,
int ttyout,
int poll) /* If 0, then block until something to do */
{
int c;
/* One wants to be a bit careful about setting returnValue
* to one, since a one implies we did some useful work,
* and therefore probably won't be called to block next
* time (TN3270 mode only).
*/
int returnValue = 0;
static struct timeval TimeValue = { 0 };
if (net >= FD_SETSIZE
|| tout >= FD_SETSIZE
|| tin >= FD_SETSIZE)
errx (1, "fd too large");
if (netout) {
FD_SET(net, &obits);
}
if (ttyout) {
FD_SET(tout, &obits);
}
if (ttyin) {
FD_SET(tin, &ibits);
}
if (netin) {
FD_SET(net, &ibits);
}
#if !defined(SO_OOBINLINE)
if (netex) {
FD_SET(net, &xbits);
}
#endif
if ((c = select(FD_SETSIZE, &ibits, &obits, &xbits,
(poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
if (c == -1) {
/*
* we can get EINTR if we are in line mode,
* and the user does an escape (TSTP), or
* some other signal generator.
*/
if (errno == EINTR) {
return 0;
}
/* I don't like this, does it ever happen? */
printf("sleep(5) from telnet, after select\r\n");
sleep(5);
}
return 0;
}
/*
* Any urgent data?
*/
if (FD_ISSET(net, &xbits)) {
FD_CLR(net, &xbits);
SYNCHing = 1;
ttyflush(1); /* flush already enqueued data */
}
/*
* Something to read from the network...
*/
if (FD_ISSET(net, &ibits)) {
int canread;
FD_CLR(net, &ibits);
canread = ring_empty_consecutive(&netiring);
#if !defined(SO_OOBINLINE)
/*
* In 4.2 (and some early 4.3) systems, the
* OOB indication and data handling in the kernel
* is such that if two separate TCP Urgent requests
* come in, one byte of TCP data will be overlaid.
* This is fatal for Telnet, but we try to live
* with it.
*
* In addition, in 4.2 (and...), a special protocol
* is needed to pick up the TCP Urgent data in
* the correct sequence.
*
* What we do is: if we think we are in urgent
* mode, we look to see if we are "at the mark".
* If we are, we do an OOB receive. If we run
* this twice, we will do the OOB receive twice,
* but the second will fail, since the second
* time we were "at the mark", but there wasn't
* any data there (the kernel doesn't reset
* "at the mark" until we do a normal read).
* Once we've read the OOB data, we go ahead
* and do normal reads.
*
* There is also another problem, which is that
* since the OOB byte we read doesn't put us
* out of OOB state, and since that byte is most
* likely the TELNET DM (data mark), we would
* stay in the TELNET SYNCH (SYNCHing) state.
* So, clocks to the rescue. If we've "just"
* received a DM, then we test for the
* presence of OOB data when the receive OOB
* fails (and AFTER we did the normal mode read
* to clear "at the mark").
*/
if (SYNCHing) {
int atmark;
static int bogus_oob = 0, first = 1;
ioctl(net, SIOCATMARK, (char *)&atmark);
if (atmark) {
c = recv(net, netiring.supply, canread, MSG_OOB);
if ((c == -1) && (errno == EINVAL)) {
c = recv(net, netiring.supply, canread, 0);
if (clocks.didnetreceive < clocks.gotDM) {
SYNCHing = stilloob();
}
} else if (first && c > 0) {
/*
* Bogosity check. Systems based on 4.2BSD
* do not return an error if you do a second
* recv(MSG_OOB). So, we do one. If it
* succeeds and returns exactly the same
* data, then assume that we are running
* on a broken system and set the bogus_oob
* flag. (If the data was different, then
* we probably got some valid new data, so
* increment the count...)
*/
int i;
i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
if (i == c &&
memcmp(netiring.supply, netiring.supply + c, i) == 0) {
bogus_oob = 1;
first = 0;
} else if (i < 0) {
bogus_oob = 0;
first = 0;
} else
c += i;
}
if (bogus_oob && c > 0) {
int i;
/*
* Bogosity. We have to do the read
* to clear the atmark to get out of
* an infinate loop.
*/
i = read(net, netiring.supply + c, canread - c);
if (i > 0)
c += i;
}
} else {
c = recv(net, netiring.supply, canread, 0);
}
} else {
c = recv(net, netiring.supply, canread, 0);
}
settimer(didnetreceive);
#else /* !defined(SO_OOBINLINE) */
c = recv(net, (char *)netiring.supply, canread, 0);
#endif /* !defined(SO_OOBINLINE) */
if (c < 0 && errno == EWOULDBLOCK) {
c = 0;
} else if (c <= 0) {
return -1;
}
if (netdata) {
Dump('<', netiring.supply, c);
}
if (c)
ring_supplied(&netiring, c);
returnValue = 1;
}
/*
* Something to read from the tty...
*/
if (FD_ISSET(tin, &ibits)) {
FD_CLR(tin, &ibits);
c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
if (c < 0 && errno == EIO)
c = 0;
if (c < 0 && errno == EWOULDBLOCK) {
c = 0;
} else {
/* EOF detection for line mode!!!! */
if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
/* must be an EOF... */
*ttyiring.supply = termEofChar;
c = 1;
}
if (c <= 0) {
return -1;
}
if (termdata) {
Dump('<', ttyiring.supply, c);
}
ring_supplied(&ttyiring, c);
}
returnValue = 1; /* did something useful */
}
if (FD_ISSET(net, &obits)) {
FD_CLR(net, &obits);
returnValue |= netflush();
}
if (FD_ISSET(tout, &obits)) {
FD_CLR(tout, &obits);
returnValue |= (ttyflush(SYNCHing|flushout) > 0);
}
return returnValue;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,181 +0,0 @@
/*
* Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <errno.h>
#include <setjmp.h>
#ifdef HAVE_BSDSETJMP_H
#include <bsdsetjmp.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
/* termios.h *must* be included before curses.h, but not on Solaris 9,
at least, where we end up with
"/usr/include/term.h", line 1060: incomplete struct/union/enum termio: Ottyb
*/
#if defined HAVE_TERMIOS_H && !defined __sun
#include <termios.h>
#endif
#if defined(HAVE_CURSES_H)
#include <curses.h>
#ifdef HAVE_TERM_H
#include <term.h>
#endif
#elif defined(HAVE_TERMCAP_H)
#include <termcap.h>
#endif
#if defined(HAVE_SYS_TERMIO_H) && !defined(HAVE_TERMIOS_H)
#include <sys/termio.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#elif defined(HAVE_SYS_TIME_H)
#include <sys/time.h>
#else
#include <time.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
/* not with SunOS 4 */
#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif /* HAVE_SYS_RESOURCE_H */
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET6_IN6_H
#include <netinet6/in6.h>
#endif
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
#ifdef HAVE_ARPA_INET_H
#ifdef _AIX
struct sockaddr_dl; /* AIX fun */
struct ether_addr;
#endif
#include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_TELNET_H
#include <arpa/telnet.h>
#endif
#ifdef SOCKS
#include <socks.h>
#endif
#if defined(AUTHENTICATION) || defined(ENCRYPTION)
#include <libtelnet/auth.h>
#include <libtelnet/encrypt.h>
#endif
#include <libtelnet/misc.h>
#include <libtelnet/misc-proto.h>
#define LINEMODE
#ifndef KLUDGELINEMODE
#define KLUDGELINEMODE
#endif
#include <err.h>
#include <roken.h>
#include "ring.h"
#include "externs.h"
#include "defines.h"
#include "types.h"
/* prototypes */

View File

@@ -1,221 +0,0 @@
/*
* Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "telnet_locl.h"
RCSID("$Id$");
Ring ttyoring, ttyiring;
unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ];
int termdata; /* Debugging flag */
# ifndef VDISCARD
cc_t termFlushChar;
# endif
# ifndef VLNEXT
cc_t termLiteralNextChar;
# endif
# ifndef VSUSP
cc_t termSuspChar;
# endif
# ifndef VWERASE
cc_t termWerasChar;
# endif
# ifndef VREPRINT
cc_t termRprntChar;
# endif
# ifndef VSTART
cc_t termStartChar;
# endif
# ifndef VSTOP
cc_t termStopChar;
# endif
# ifndef VEOL
cc_t termForw1Char;
# endif
# ifndef VEOL2
cc_t termForw2Char;
# endif
# ifndef VSTATUS
cc_t termAytChar;
# endif
/*
* initialize the terminal data structures.
*/
void
init_terminal(void)
{
if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) {
exit(1);
}
if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) {
exit(1);
}
autoflush = TerminalAutoFlush();
}
/*
* Send as much data as possible to the terminal.
*
* Return value:
* -1: No useful work done, data waiting to go out.
* 0: No data was waiting, so nothing was done.
* 1: All waiting data was written out.
* n: All data - n was written out.
*/
int
ttyflush(int drop)
{
int n, n0, n1;
n0 = ring_full_count(&ttyoring);
if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
if (drop) {
TerminalFlushOutput();
/* we leave 'n' alone! */
} else {
n = TerminalWrite((char *)ttyoring.consume, n);
}
}
if (n > 0) {
if (termdata && n) {
Dump('>', ttyoring.consume, n);
}
/*
* If we wrote everything, and the full count is
* larger than what we wrote, then write the
* rest of the buffer.
*/
if (n1 == n && n0 > n) {
n1 = n0 - n;
if (!drop)
n1 = TerminalWrite((char *)ttyoring.bottom, n1);
if (n1 > 0)
n += n1;
}
ring_consumed(&ttyoring, n);
}
if (n < 0)
return -1;
if (n == n0) {
if (n0)
return -1;
return 0;
}
return n0 - n + 1;
}
/*
* These routines decides on what the mode should be (based on the values
* of various global variables).
*/
int
getconnmode(void)
{
int mode = 0;
if (my_want_state_is_dont(TELOPT_ECHO))
mode |= MODE_ECHO;
if (localflow)
mode |= MODE_FLOW;
if ((eight & 1) || my_want_state_is_will(TELOPT_BINARY))
mode |= MODE_INBIN;
if (eight & 2)
mode |= MODE_OUT8;
if (his_want_state_is_will(TELOPT_BINARY))
mode |= MODE_OUTBIN;
#ifdef KLUDGELINEMODE
if (kludgelinemode) {
if (my_want_state_is_dont(TELOPT_SGA)) {
mode |= (MODE_TRAPSIG|MODE_EDIT);
if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
mode &= ~MODE_ECHO;
}
}
return(mode);
}
#endif
if (my_want_state_is_will(TELOPT_LINEMODE))
mode |= linemode;
return(mode);
}
void
setconnmode(force)
int force;
{
#ifdef ENCRYPTION
static int enc_passwd = 0;
#endif
int newmode;
newmode = getconnmode()|(force?MODE_FORCE:0);
TerminalNewMode(newmode);
#ifdef ENCRYPTION
if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
if (my_want_state_is_will(TELOPT_ENCRYPT)
&& (enc_passwd == 0) && !encrypt_output) {
encrypt_request_start(0, 0);
enc_passwd = 1;
}
} else {
if (enc_passwd) {
encrypt_request_end();
enc_passwd = 0;
}
}
#endif
}
void
setcommandmode()
{
TerminalNewMode(-1);
}

View File

@@ -1,52 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)types.h 8.1 (Berkeley) 6/6/93
*/
typedef struct {
char *modedescriptions;
char modetype;
} Modelist;
extern Modelist modelist[];
typedef 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 */
gotDM; /* when did we last see a data mark */
} Clocks;
extern Clocks clocks;

View File

@@ -1,865 +0,0 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define TELOPTS
#define TELCMDS
#define SLC_NAMES
#include "telnet_locl.h"
RCSID("$Id$");
FILE *NetTrace = 0; /* Not in bss, since needs to stay */
int prettydump;
/*
* SetSockOpt()
*
* Compensate for differences in 4.2 and 4.3 systems.
*/
int
SetSockOpt(int fd, int level, int option, int yesno)
{
#ifdef HAVE_SETSOCKOPT
#ifndef NOT43
return setsockopt(fd, level, option,
(void *)&yesno, sizeof yesno);
#else /* NOT43 */
if (yesno == 0) { /* Can't do that in 4.2! */
fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
option);
return -1;
}
return setsockopt(fd, level, option, 0, 0);
#endif /* NOT43 */
#else
return -1;
#endif
}
/*
* The following are routines used to print out debugging information.
*/
char NetTraceFile[256] = "(standard output)";
void
SetNetTrace(char *file)
{
if (NetTrace && NetTrace != stdout)
fclose(NetTrace);
if (file && (strcmp(file, "-") != 0)) {
NetTrace = fopen(file, "w");
if (NetTrace) {
strlcpy(NetTraceFile, file, sizeof(NetTraceFile));
return;
}
fprintf(stderr, "Cannot open %s.\n", file);
}
NetTrace = stdout;
strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile));
}
void
Dump(char direction, unsigned char *buffer, int length)
{
# define BYTES_PER_LINE 32
unsigned char *pThis;
int offset;
offset = 0;
while (length) {
/* print one line */
fprintf(NetTrace, "%c 0x%x\t", direction, offset);
pThis = buffer;
if (prettydump) {
buffer = buffer + min(length, BYTES_PER_LINE/2);
while (pThis < buffer) {
fprintf(NetTrace, "%c%.2x",
(((*pThis)&0xff) == 0xff) ? '*' : ' ',
(*pThis)&0xff);
pThis++;
}
length -= BYTES_PER_LINE/2;
offset += BYTES_PER_LINE/2;
} else {
buffer = buffer + min(length, BYTES_PER_LINE);
while (pThis < buffer) {
fprintf(NetTrace, "%.2x", (*pThis)&0xff);
pThis++;
}
length -= BYTES_PER_LINE;
offset += BYTES_PER_LINE;
}
if (NetTrace == stdout) {
fprintf(NetTrace, "\r\n");
} else {
fprintf(NetTrace, "\n");
}
if (length < 0) {
fflush(NetTrace);
return;
}
/* find next unique line */
}
fflush(NetTrace);
}
void
printoption(char *direction, int cmd, int option)
{
if (!showoptions)
return;
if (cmd == IAC) {
if (TELCMD_OK(option))
fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
else
fprintf(NetTrace, "%s IAC %d", direction, option);
} else {
char *fmt;
fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
(cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
if (fmt) {
fprintf(NetTrace, "%s %s ", direction, fmt);
if (TELOPT_OK(option))
fprintf(NetTrace, "%s", TELOPT(option));
else if (option == TELOPT_EXOPL)
fprintf(NetTrace, "EXOPL");
else
fprintf(NetTrace, "%d", option);
} else
fprintf(NetTrace, "%s %d %d", direction, cmd, option);
}
if (NetTrace == stdout) {
fprintf(NetTrace, "\r\n");
fflush(NetTrace);
} else {
fprintf(NetTrace, "\n");
}
return;
}
void
optionstatus(void)
{
int i;
for (i = 0; i < 256; i++) {
if (do_dont_resp[i]) {
if (TELOPT_OK(i))
printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
else if (TELCMD_OK(i))
printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
else
printf("resp DO_DONT %d: %d\n", i,
do_dont_resp[i]);
if (my_want_state_is_do(i)) {
if (TELOPT_OK(i))
printf("want DO %s\n", TELOPT(i));
else if (TELCMD_OK(i))
printf("want DO %s\n", TELCMD(i));
else
printf("want DO %d\n", i);
} else {
if (TELOPT_OK(i))
printf("want DONT %s\n", TELOPT(i));
else if (TELCMD_OK(i))
printf("want DONT %s\n", TELCMD(i));
else
printf("want DONT %d\n", i);
}
} else {
if (my_state_is_do(i)) {
if (TELOPT_OK(i))
printf(" DO %s\n", TELOPT(i));
else if (TELCMD_OK(i))
printf(" DO %s\n", TELCMD(i));
else
printf(" DO %d\n", i);
}
}
if (will_wont_resp[i]) {
if (TELOPT_OK(i))
printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
else if (TELCMD_OK(i))
printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
else
printf("resp WILL_WONT %d: %d\n",
i, will_wont_resp[i]);
if (my_want_state_is_will(i)) {
if (TELOPT_OK(i))
printf("want WILL %s\n", TELOPT(i));
else if (TELCMD_OK(i))
printf("want WILL %s\n", TELCMD(i));
else
printf("want WILL %d\n", i);
} else {
if (TELOPT_OK(i))
printf("want WONT %s\n", TELOPT(i));
else if (TELCMD_OK(i))
printf("want WONT %s\n", TELCMD(i));
else
printf("want WONT %d\n", i);
}
} else {
if (my_state_is_will(i)) {
if (TELOPT_OK(i))
printf(" WILL %s\n", TELOPT(i));
else if (TELCMD_OK(i))
printf(" WILL %s\n", TELCMD(i));
else
printf(" WILL %d\n", i);
}
}
}
}
static void __attribute__((format (printf, 3, 4)))
qprintf(int quote, FILE *f, const char *fmt, ...)
{
va_list va;
if (quote)
fprintf(f, "\" ");
va_start(va, fmt);
vfprintf(f, fmt, va);
va_end(va);
}
void
printsub(int direction, unsigned char *pointer, size_t length)
{
int i;
unsigned char buf[512];
if (showoptions || direction == 0 ||
(want_status_response && (pointer[0] == TELOPT_STATUS))) {
if (direction) {
fprintf(NetTrace, "%s IAC SB ",
(direction == '<')? "RCVD":"SENT");
if (length >= 3) {
int j;
i = pointer[length-2];
j = pointer[length-1];
if (i != IAC || j != SE) {
fprintf(NetTrace, "(terminated by ");
if (TELOPT_OK(i))
fprintf(NetTrace, "%s ", TELOPT(i));
else if (TELCMD_OK(i))
fprintf(NetTrace, "%s ", TELCMD(i));
else
fprintf(NetTrace, "%d ", i);
if (TELOPT_OK(j))
fprintf(NetTrace, "%s", TELOPT(j));
else if (TELCMD_OK(j))
fprintf(NetTrace, "%s", TELCMD(j));
else
fprintf(NetTrace, "%d", j);
fprintf(NetTrace, ", not IAC SE!) ");
}
}
length -= 2;
}
if (length < 1) {
fprintf(NetTrace, "(Empty suboption??\?)");
if (NetTrace == stdout)
fflush(NetTrace);
return;
}
switch (pointer[0]) {
case TELOPT_TTYPE:
fprintf(NetTrace, "TERMINAL-TYPE ");
switch (pointer[1]) {
case TELQUAL_IS:
fprintf(NetTrace, "IS \"%.*s\"",
(int)(length-2),
(char *)pointer+2);
break;
case TELQUAL_SEND:
fprintf(NetTrace, "SEND");
break;
default:
fprintf(NetTrace,
"- unknown qualifier %d (0x%x).",
pointer[1], pointer[1]);
}
break;
case TELOPT_TSPEED:
fprintf(NetTrace, "TERMINAL-SPEED");
if (length < 2) {
fprintf(NetTrace, " (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case TELQUAL_IS:
fprintf(NetTrace, " IS ");
fprintf(NetTrace, "%.*s", (int)(length-2), (char *)pointer+2);
break;
default:
if (pointer[1] == 1)
fprintf(NetTrace, " SEND");
else
fprintf(NetTrace, " %d (unknown)", pointer[1]);
for (i = 2; i < length; i++)
fprintf(NetTrace, " ?%d?", pointer[i]);
break;
}
break;
case TELOPT_LFLOW:
fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
if (length < 2) {
fprintf(NetTrace, " (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case LFLOW_OFF:
fprintf(NetTrace, " OFF"); break;
case LFLOW_ON:
fprintf(NetTrace, " ON"); break;
case LFLOW_RESTART_ANY:
fprintf(NetTrace, " RESTART-ANY"); break;
case LFLOW_RESTART_XON:
fprintf(NetTrace, " RESTART-XON"); break;
default:
fprintf(NetTrace, " %d (unknown)", pointer[1]);
}
for (i = 2; i < length; i++)
fprintf(NetTrace, " ?%d?", pointer[i]);
break;
case TELOPT_NAWS:
fprintf(NetTrace, "NAWS");
if (length < 2) {
fprintf(NetTrace, " (empty suboption??\?)");
break;
}
if (length == 2) {
fprintf(NetTrace, " ?%d?", pointer[1]);
break;
}
fprintf(NetTrace, " %d %d (%d)",
pointer[1], pointer[2],
(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
if (length == 4) {
fprintf(NetTrace, " ?%d?", pointer[3]);
break;
}
fprintf(NetTrace, " %d %d (%d)",
pointer[3], pointer[4],
(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
for (i = 5; i < length; i++)
fprintf(NetTrace, " ?%d?", pointer[i]);
break;
#if defined(AUTHENTICATION)
case TELOPT_AUTHENTICATION:
fprintf(NetTrace, "AUTHENTICATION");
if (length < 2) {
fprintf(NetTrace, " (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case TELQUAL_REPLY:
case TELQUAL_IS:
fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
"IS" : "REPLY");
if (AUTHTYPE_NAME_OK(pointer[2]))
fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
else
fprintf(NetTrace, "%d ", pointer[2]);
if (length < 3) {
fprintf(NetTrace, "(partial suboption??\?)");
break;
}
fprintf(NetTrace, "%s|%s",
((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
"CLIENT" : "SERVER",
((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
"MUTUAL" : "ONE-WAY");
auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
fprintf(NetTrace, "%s", buf);
break;
case TELQUAL_SEND:
i = 2;
fprintf(NetTrace, " SEND ");
while (i < length) {
if (AUTHTYPE_NAME_OK(pointer[i]))
fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
else
fprintf(NetTrace, "%d ", pointer[i]);
if (++i >= length) {
fprintf(NetTrace, "(partial suboption??\?)");
break;
}
fprintf(NetTrace, "%s|%s ",
((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
"CLIENT" : "SERVER",
((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
"MUTUAL" : "ONE-WAY");
++i;
}
break;
case TELQUAL_NAME:
i = 2;
fprintf(NetTrace, " NAME \"");
while (i < length)
putc(pointer[i++], NetTrace);
putc('"', NetTrace);
break;
default:
for (i = 2; i < length; i++)
fprintf(NetTrace, " ?%d?", pointer[i]);
break;
}
break;
#endif
#if defined(ENCRYPTION)
case TELOPT_ENCRYPT:
fprintf(NetTrace, "ENCRYPT");
if (length < 2) {
fprintf(NetTrace, " (empty suboption?)");
break;
}
switch (pointer[1]) {
case ENCRYPT_START:
fprintf(NetTrace, " START");
break;
case ENCRYPT_END:
fprintf(NetTrace, " END");
break;
case ENCRYPT_REQSTART:
fprintf(NetTrace, " REQUEST-START");
break;
case ENCRYPT_REQEND:
fprintf(NetTrace, " REQUEST-END");
break;
case ENCRYPT_IS:
case ENCRYPT_REPLY:
fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
"IS" : "REPLY");
if (length < 3) {
fprintf(NetTrace, " (partial suboption?)");
break;
}
if (ENCTYPE_NAME_OK(pointer[2]))
fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
else
fprintf(NetTrace, " %d (unknown)", pointer[2]);
encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
fprintf(NetTrace, "%s", buf);
break;
case ENCRYPT_SUPPORT:
i = 2;
fprintf(NetTrace, " SUPPORT ");
while (i < length) {
if (ENCTYPE_NAME_OK(pointer[i]))
fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
else
fprintf(NetTrace, "%d ", pointer[i]);
i++;
}
break;
case ENCRYPT_ENC_KEYID:
fprintf(NetTrace, " ENC_KEYID ");
goto encommon;
case ENCRYPT_DEC_KEYID:
fprintf(NetTrace, " DEC_KEYID ");
goto encommon;
default:
fprintf(NetTrace, " %d (unknown)", pointer[1]);
encommon:
for (i = 2; i < length; i++)
fprintf(NetTrace, " %d", pointer[i]);
break;
}
break;
#endif
case TELOPT_LINEMODE:
fprintf(NetTrace, "LINEMODE ");
if (length < 2) {
fprintf(NetTrace, " (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case WILL:
fprintf(NetTrace, "WILL ");
goto common;
case WONT:
fprintf(NetTrace, "WONT ");
goto common;
case DO:
fprintf(NetTrace, "DO ");
goto common;
case DONT:
fprintf(NetTrace, "DONT ");
common:
if (length < 3) {
fprintf(NetTrace, "(no option??\?)");
break;
}
switch (pointer[2]) {
case LM_FORWARDMASK:
fprintf(NetTrace, "Forward Mask");
for (i = 3; i < length; i++)
fprintf(NetTrace, " %x", pointer[i]);
break;
default:
fprintf(NetTrace, "%d (unknown)", pointer[2]);
for (i = 3; i < length; i++)
fprintf(NetTrace, " %d", pointer[i]);
break;
}
break;
case LM_SLC:
fprintf(NetTrace, "SLC");
for (i = 2; i < length - 2; i += 3) {
if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
else
fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
case SLC_NOSUPPORT:
fprintf(NetTrace, " NOSUPPORT"); break;
case SLC_CANTCHANGE:
fprintf(NetTrace, " CANTCHANGE"); break;
case SLC_VARIABLE:
fprintf(NetTrace, " VARIABLE"); break;
case SLC_DEFAULT:
fprintf(NetTrace, " DEFAULT"); break;
}
fprintf(NetTrace, "%s%s%s",
pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
SLC_FLUSHOUT| SLC_LEVELBITS))
fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
if ((pointer[i+SLC_VALUE] == IAC) &&
(pointer[i+SLC_VALUE+1] == IAC))
i++;
}
for (; i < length; i++)
fprintf(NetTrace, " ?%d?", pointer[i]);
break;
case LM_MODE:
fprintf(NetTrace, "MODE ");
if (length < 3) {
fprintf(NetTrace, "(no mode??\?)");
break;
}
{
char tbuf[64];
snprintf(tbuf, sizeof(tbuf),
"%s%s%s%s%s",
pointer[2]&MODE_EDIT ? "|EDIT" : "",
pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
pointer[2]&MODE_ACK ? "|ACK" : "");
fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
}
if (pointer[2]&~(MODE_MASK))
fprintf(NetTrace, " (0x%x)", pointer[2]);
for (i = 3; i < length; i++)
fprintf(NetTrace, " ?0x%x?", pointer[i]);
break;
default:
fprintf(NetTrace, "%d (unknown)", pointer[1]);
for (i = 2; i < length; i++)
fprintf(NetTrace, " %d", pointer[i]);
}
break;
case TELOPT_STATUS: {
char *cp;
int j, k;
fprintf(NetTrace, "STATUS");
switch (pointer[1]) {
default:
if (pointer[1] == TELQUAL_SEND)
fprintf(NetTrace, " SEND");
else
fprintf(NetTrace, " %d (unknown)", pointer[1]);
for (i = 2; i < length; i++)
fprintf(NetTrace, " ?%d?", pointer[i]);
break;
case TELQUAL_IS:
if (--want_status_response < 0)
want_status_response = 0;
if (NetTrace == stdout)
fprintf(NetTrace, " IS\r\n");
else
fprintf(NetTrace, " IS\n");
for (i = 2; i < length; i++) {
switch(pointer[i]) {
case DO: cp = "DO"; goto common2;
case DONT: cp = "DONT"; goto common2;
case WILL: cp = "WILL"; goto common2;
case WONT: cp = "WONT"; goto common2;
common2:
i++;
if (TELOPT_OK((int)pointer[i]))
fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
else
fprintf(NetTrace, " %s %d", cp, pointer[i]);
if (NetTrace == stdout)
fprintf(NetTrace, "\r\n");
else
fprintf(NetTrace, "\n");
break;
case SB:
fprintf(NetTrace, " SB ");
i++;
j = k = i;
while (j < length) {
if (pointer[j] == SE) {
if (j+1 == length)
break;
if (pointer[j+1] == SE)
j++;
else
break;
}
pointer[k++] = pointer[j++];
}
printsub(0, &pointer[i], k - i);
if (i < length) {
fprintf(NetTrace, " SE");
i = j;
} else
i = j - 1;
if (NetTrace == stdout)
fprintf(NetTrace, "\r\n");
else
fprintf(NetTrace, "\n");
break;
default:
fprintf(NetTrace, " %d", pointer[i]);
break;
}
}
break;
}
break;
}
case TELOPT_XDISPLOC:
fprintf(NetTrace, "X-DISPLAY-LOCATION ");
switch (pointer[1]) {
case TELQUAL_IS:
fprintf(NetTrace, "IS \"%.*s\"", (int)(length-2), (char *)pointer+2);
break;
case TELQUAL_SEND:
fprintf(NetTrace, "SEND");
break;
default:
fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
pointer[1], pointer[1]);
}
break;
case TELOPT_NEW_ENVIRON:
fprintf(NetTrace, "NEW-ENVIRON ");
#ifdef OLD_ENVIRON
goto env_common1;
case TELOPT_OLD_ENVIRON:
fprintf(NetTrace, "OLD-ENVIRON");
env_common1:
#endif
switch (pointer[1]) {
case TELQUAL_IS:
fprintf(NetTrace, "IS ");
goto env_common;
case TELQUAL_SEND:
fprintf(NetTrace, "SEND ");
goto env_common;
case TELQUAL_INFO:
fprintf(NetTrace, "INFO ");
env_common:
{
int quote = 0;
for (i = 2; i < length; i++ ) {
switch (pointer[i]) {
case NEW_ENV_VAR:
qprintf(quote, NetTrace, "VAR ");
quote = 0;
break;
case NEW_ENV_VALUE:
qprintf(quote, NetTrace, "VALUE");
quote = 0;
break;
case ENV_ESC:
qprintf(quote, NetTrace, "ESC ");
quote = 0;
break;
case ENV_USERVAR:
qprintf(quote, NetTrace, "USERVAR ");
quote = 0;
break;
default:
if (isprint(pointer[i]) && pointer[i] != '"') {
if (!quote) {
putc('"', NetTrace);
quote = 1;
}
putc(pointer[i], NetTrace);
} else {
qprintf(quote, NetTrace, "%03o ", pointer[i]);
quote = 0;
}
break;
}
}
if (quote)
putc('"', NetTrace);
break;
}
}
break;
default:
if (TELOPT_OK(pointer[0]))
fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
else
fprintf(NetTrace, "%d (unknown)", pointer[0]);
for (i = 1; i < length; i++)
fprintf(NetTrace, " %d", pointer[i]);
break;
}
if (direction) {
if (NetTrace == stdout)
fprintf(NetTrace, "\r\n");
else
fprintf(NetTrace, "\n");
}
if (NetTrace == stdout)
fflush(NetTrace);
}
}
/* EmptyTerminal - called to make sure that the terminal buffer is empty.
* Note that we consider the buffer to run all the
* way to the kernel (thus the select).
*/
void
EmptyTerminal(void)
{
fd_set outs;
FD_ZERO(&outs);
if (tout >= FD_SETSIZE)
ExitString("fd too large", 1);
if (TTYBYTES() == 0) {
FD_SET(tout, &outs);
select(tout+1, 0, &outs, 0,
(struct timeval *) 0); /* wait for TTLOWAT */
} else {
while (TTYBYTES()) {
ttyflush(0);
FD_SET(tout, &outs);
select(tout+1, 0, &outs, 0,
(struct timeval *) 0); /* wait for TTLOWAT */
}
}
}
void
SetForExit(void)
{
setconnmode(0);
do {
telrcv(); /* Process any incoming data */
EmptyTerminal();
} while (ring_full_count(&netiring)); /* While there is any */
setcommandmode();
fflush(stdout);
fflush(stderr);
setconnmode(0);
EmptyTerminal(); /* Flush the path to the tty */
setcommandmode();
}
void
Exit(int returnCode)
{
SetForExit();
exit(returnCode);
}
void
ExitString(char *string, int returnCode)
{
SetForExit();
fwrite(string, 1, strlen(string), stderr);
exit(returnCode);
}

View File

@@ -1,29 +0,0 @@
# $Id$
include $(top_srcdir)/Makefile.am.common
WFLAGS += $(WFLAGS_LITE)
AM_CPPFLAGS += -I$(srcdir)/.. $(INCLUDE_hcrypto)
libexec_PROGRAMS = telnetd
CHECK_LOCAL =
telnetd_SOURCES = telnetd.c state.c termstat.c slc.c sys_term.c \
utility.c global.c authenc.c defs.h ext.h telnetd.h
man_MANS = telnetd.8
LDADD = \
../libtelnet/libtelnet.a \
$(LIB_krb5) \
$(LIB_hcrypto) \
$(LIB_tgetent) \
$(LIB_logwtmp) \
$(LIB_logout) \
$(LIB_openpty) \
$(LIB_kdfs) \
$(LIB_roken)
EXTRA_DIST = NTMakefile $(man_MANS)

View File

@@ -1,35 +0,0 @@
########################################################################
#
# Copyright (c) 2009, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT HOLDER 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.
#
RELDIR=appl\telnet\telnetd
!include ../../../windows/NTMakefile.w32

View File

@@ -1,80 +0,0 @@
/*-
* 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 "telnetd.h"
RCSID("$Id$");
#ifdef AUTHENTICATION
int
telnet_net_write(unsigned char *str, int len)
{
if (nfrontp + len < netobuf + BUFSIZ) {
memmove(nfrontp, str, len);
nfrontp += 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
}
int
telnet_spin(void)
{
return ttloop();
}
char *
telnet_getenv(const char *val)
{
return(getenv(val));
}
char *
telnet_gets(char *prompt, char *result, int length, int echo)
{
return NULL;
}
#endif

View File

@@ -1,190 +0,0 @@
/*
* 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
*/
/*
* Telnet server defines
*/
#ifndef __DEFS_H__
#define __DEFS_H__
#ifndef BSD
# define BSD 43
#endif
#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS)
#define TELOPTS
#define TELCMDS
#define SLC_NAMES
#endif
#if !defined(TIOCSCTTY) && defined(TCSETCTTY)
# define TIOCSCTTY TCSETCTTY
#endif
#ifndef TIOCPKT_FLUSHWRITE
#define TIOCPKT_FLUSHWRITE 0x02
#endif
#ifndef TIOCPKT_NOSTOP
#define TIOCPKT_NOSTOP 0x10
#endif
#ifndef TIOCPKT_DOSTOP
#define TIOCPKT_DOSTOP 0x20
#endif
/*
* I/O data buffers defines
*/
#define NETSLOP 64
#ifdef _CRAY
#undef BUFSIZ
#define BUFSIZ 2048
#endif
#define NIACCUM(c) { *netip++ = c; \
ncc++; \
}
/* clock manipulations */
#define settimer(x) (clocks.x = ++clocks.system)
#define sequenceIs(x,y) (clocks.x < clocks.y)
/*
* 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 symmetrical
*/
#define HIS_STATE_WILL MY_STATE_DO
#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO
#define HIS_STATE_DO MY_STATE_WILL
#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL
#define his_state_is_do my_state_is_will
#define his_state_is_will my_state_is_do
#define his_want_state_is_do my_want_state_is_will
#define his_want_state_is_will my_want_state_is_do
#define his_state_is_dont my_state_is_wont
#define his_state_is_wont my_state_is_dont
#define his_want_state_is_dont my_want_state_is_wont
#define his_want_state_is_wont my_want_state_is_dont
#define set_his_state_do set_my_state_will
#define set_his_state_will set_my_state_do
#define set_his_want_state_do set_my_want_state_will
#define set_his_want_state_will set_my_want_state_do
#define set_his_state_dont set_my_state_wont
#define set_his_state_wont set_my_state_dont
#define set_his_want_state_dont set_my_want_state_wont
#define set_his_want_state_wont set_my_want_state_dont
#define his_will_wont_is_changing my_do_dont_is_changing
#define his_do_dont_is_changing my_will_wont_is_changing
#endif /* __DEFS_H__ */

View File

@@ -1,208 +0,0 @@
/*
* 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
*/
/* $Id$ */
#ifndef __EXT_H__
#define __EXT_H__
/*
* Telnet server variable declarations
*/
extern char options[256];
extern char do_dont_resp[256];
extern char will_wont_resp[256];
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 */
extern int require_otp;
#ifdef AUTHENTICATION
extern int auth_level;
#endif
extern const char *new_login;
extern slcfun slctab[NSLC + 1]; /* slc mapping table */
extern char terminaltype[41];
/*
* I/O data buffers, pointers, and counters.
*/
extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
extern char netibuf[BUFSIZ], *netip;
extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
extern char *neturg; /* one past last bye of urgent data */
extern int pcc, ncc;
extern int ourpty, net;
extern char *line;
extern int SYNCHing; /* we are in TELNET SYNCH mode */
int telnet_net_write (unsigned char *str, int len);
void net_encrypt (void);
int telnet_spin (void);
char *telnet_getenv (const char *val);
char *telnet_gets (char *prompt, char *result, int length, int echo);
void get_slc_defaults (void);
void telrcv (void);
void send_do (int option, int init);
void willoption (int option);
void send_dont (int option, int init);
void wontoption (int option);
void send_will (int option, int init);
void dooption (int option);
void send_wont (int option, int init);
void dontoption (int option);
void suboption (void);
void doclientstat (void);
void send_status (void);
void init_termbuf (void);
void set_termbuf (void);
int spcset (int func, cc_t *valp, cc_t **valpp);
void set_utid (void);
int getpty (int *ptynum);
int tty_isecho (void);
int tty_flowmode (void);
int tty_restartany (void);
void tty_setecho (int on);
int tty_israw (void);
void tty_binaryin (int on);
void tty_binaryout (int on);
int tty_isbinaryin (void);
int tty_isbinaryout (void);
int tty_issofttab (void);
void tty_setsofttab (int on);
int tty_islitecho (void);
void tty_setlitecho (int on);
int tty_iscrnl (void);
void tty_tspeed (int val);
void tty_rspeed (int val);
void getptyslave (void);
int cleanopen (char *);
void startslave (const char *host, const char *, int autologin, char *autoname);
void init_env (void);
void start_login (const char *host, int autologin, char *name);
void cleanup (int sig);
int main (int argc, char **argv);
int getterminaltype (char *name, size_t);
void _gettermname (void);
int terminaltypeok (char *s);
void my_telnet (int f, int p, const char*, const char *, int, char*);
void interrupt (void);
void sendbrk (void);
void sendsusp (void);
void recv_ayt (void);
void doeof (void);
void flowstat (void);
void clientstat (int code, int parm1, int parm2);
int ttloop (void);
int stilloob (int s);
void ptyflush (void);
char *nextitem (char *current);
void netclear (void);
void netflush (void);
void writenet (const void *, size_t);
void fatal (int f, char *msg);
void fatalperror (int f, const char *msg);
void fatalperror_errno (int f, const char *msg, int error);
void edithost (char *pat, char *host);
void putstr (char *s);
void putchr (int cc);
void putf (char *cp, char *where);
void printoption (char *fmt, int option);
void printsub (int direction, unsigned char *pointer, size_t length);
void printdata (char *tag, char *ptr, size_t cnt);
int login_tty(int t);
#ifdef ENCRYPTION
extern void (*encrypt_output) (unsigned char *, int);
extern int (*decrypt_input) (int);
extern char *nclearto;
#endif
/*
* The following are some clocks used to decide how to interpret
* the relationship between various variables.
*/
struct clocks_t{
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 */
};
extern struct clocks_t clocks;
extern int log_unauth;
extern int no_warn;
extern int def_tspeed, def_rspeed;
#ifdef TIOCSWINSZ
extern int def_row, def_col;
#endif
#ifdef STREAMSPTY
extern int really_stream;
#endif
#ifndef USE_IM
# ifdef CRAY
# define USE_IM "Cray UNICOS (%h) (%t)"
# endif
# ifdef _AIX
# define USE_IM "%s %v.%r (%h) (%t)"
# endif
# ifndef USE_IM
# define USE_IM "%s %r (%h) (%t)"
# endif
#endif
#define DEFAULT_IM "\r\n\r\n" USE_IM "\r\n\r\n\r\n"
#endif /* __EXT_H__ */

View File

@@ -1,107 +0,0 @@
/*
* 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.
*/
/* a *lot* of ugly global definitions that really should be removed...
*/
#include "telnetd.h"
RCSID("$Id$");
/*
* Telnet server variable declarations
*/
char options[256];
char do_dont_resp[256];
char will_wont_resp[256];
int linemode; /* linemode on/off */
int flowmode; /* current flow control state */
int restartany; /* restart output on any character state */
#ifdef DIAGNOSTICS
int diagnostic; /* telnet diagnostic capabilities */
#endif /* DIAGNOSTICS */
int require_otp;
slcfun slctab[NSLC + 1]; /* slc mapping table */
char terminaltype[41];
/*
* I/O data buffers, pointers, and counters.
*/
char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
char netibuf[BUFSIZ], *netip;
char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
char *neturg; /* one past last bye of urgent data */
int pcc, ncc;
int ourpty, net;
int SYNCHing; /* we are in TELNET SYNCH mode */
/*
* The following are some clocks used to decide how to interpret
* the relationship between various variables.
*/
struct clocks_t clocks;
/* whether to log unauthenticated login attempts */
int log_unauth;
/* do not print warning if connection is not encrypted */
int no_warn;
/*
* This function appends data to nfrontp and advances nfrontp.
*/
int
output_data (const char *format, ...)
{
va_list args;
int remaining, ret;
va_start(args, format);
remaining = BUFSIZ - (nfrontp - netobuf);
ret = vsnprintf (nfrontp,
remaining,
format,
args);
nfrontp += min(ret, remaining-1);
va_end(args);
return ret;
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "telnetd.h"
RCSID("$Id$");
/*
* 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;
}
}

Some files were not shown because too many files have changed in this diff Show More