delete POP3, telnet and rsh/rcp support
This commit is contained in:
@@ -15,13 +15,9 @@ SUBDIRS = \
|
||||
login \
|
||||
$(dir_otp) \
|
||||
gssmask \
|
||||
popper \
|
||||
push \
|
||||
rsh \
|
||||
rcp \
|
||||
su \
|
||||
xnlock \
|
||||
telnet \
|
||||
test \
|
||||
kx \
|
||||
kf \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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 *);
|
||||
@@ -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
|
||||
791
appl/rcp/rcp.c
791
appl/rcp/rcp.c
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
184
appl/rcp/util.c
184
appl/rcp/util.c
@@ -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);
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
294
appl/rsh/rsh.1
294
appl/rsh/rsh.1
@@ -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.
|
||||
1047
appl/rsh/rsh.c
1047
appl/rsh/rsh.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
161
appl/rsh/rshd.8
161
appl/rsh/rshd.8
@@ -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
|
||||
992
appl/rsh/rshd.c
992
appl/rsh/rshd.c
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user