summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/appl
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/appl')
-rw-r--r--crypto/kerberosIV/appl/Makefile.in8
-rw-r--r--crypto/kerberosIV/appl/afsutil/Makefile.in89
-rw-r--r--crypto/kerberosIV/appl/afsutil/aklog.c239
-rw-r--r--crypto/kerberosIV/appl/afsutil/kstring2key.c142
-rw-r--r--crypto/kerberosIV/appl/afsutil/pagsh.c141
-rw-r--r--crypto/kerberosIV/appl/bsd/Makefile.in65
-rw-r--r--crypto/kerberosIV/appl/bsd/bsd_locl.h46
-rw-r--r--crypto/kerberosIV/appl/bsd/encrypt.c24
-rw-r--r--crypto/kerberosIV/appl/bsd/forkpty.c53
-rw-r--r--crypto/kerberosIV/appl/bsd/kcmd.c12
-rw-r--r--crypto/kerberosIV/appl/bsd/klogin.c86
-rw-r--r--crypto/kerberosIV/appl/bsd/login.c268
-rw-r--r--crypto/kerberosIV/appl/bsd/login_access.c71
-rw-r--r--crypto/kerberosIV/appl/bsd/login_fbtab.c18
-rw-r--r--crypto/kerberosIV/appl/bsd/osfc2.c84
-rw-r--r--crypto/kerberosIV/appl/bsd/pathnames.h11
-rw-r--r--crypto/kerberosIV/appl/bsd/rcmd_util.c4
-rw-r--r--crypto/kerberosIV/appl/bsd/rcp.c165
-rw-r--r--crypto/kerberosIV/appl/bsd/rcp_util.c42
-rw-r--r--crypto/kerberosIV/appl/bsd/rlogin.c66
-rw-r--r--crypto/kerberosIV/appl/bsd/rlogind.c51
-rw-r--r--crypto/kerberosIV/appl/bsd/rsh.c65
-rw-r--r--crypto/kerberosIV/appl/bsd/rshd.c33
-rw-r--r--crypto/kerberosIV/appl/bsd/su.c42
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_default.c6
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_environ.c7
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_shadow.c4
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_shadow.h4
-rw-r--r--crypto/kerberosIV/appl/bsd/utmp_login.c18
-rw-r--r--crypto/kerberosIV/appl/bsd/utmpx_login.c6
-rw-r--r--crypto/kerberosIV/appl/ftp/ChangeLog196
-rw-r--r--crypto/kerberosIV/appl/ftp/Makefile.am5
-rw-r--r--crypto/kerberosIV/appl/ftp/Makefile.in7
-rw-r--r--crypto/kerberosIV/appl/ftp/common/Makefile.am12
-rw-r--r--crypto/kerberosIV/appl/ftp/common/Makefile.in13
-rw-r--r--crypto/kerberosIV/appl/ftp/common/buffer.c3
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/Makefile.am44
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/Makefile.in66
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/cmds.c581
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/cmdtab.c11
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/domacro.c4
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/extern.h12
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/ftp.c1121
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h21
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/gssapi.c334
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/kauth.c57
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/krb4.c612
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/main.c21
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/ruserpass.c350
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/security.c730
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/security.h130
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/Makefile.am53
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/Makefile.in40
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/extern.h21
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y543
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpd.c381
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h168
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c74
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/kauth.c161
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c28
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/popen.c8
-rw-r--r--crypto/kerberosIV/appl/kauth/ChangeLog24
-rw-r--r--crypto/kerberosIV/appl/kauth/Makefile.am42
-rw-r--r--crypto/kerberosIV/appl/kauth/Makefile.in36
-rw-r--r--crypto/kerberosIV/appl/kauth/kauth.c141
-rw-r--r--crypto/kerberosIV/appl/kauth/kauth.h9
-rw-r--r--crypto/kerberosIV/appl/kauth/kauthd.c18
-rw-r--r--crypto/kerberosIV/appl/kauth/ksrvtgt.in4
-rw-r--r--crypto/kerberosIV/appl/kauth/marshall.c86
-rw-r--r--crypto/kerberosIV/appl/kauth/rkinit.c16
-rw-r--r--crypto/kerberosIV/appl/kip/Makefile.in30
-rw-r--r--crypto/kerberosIV/appl/kip/kip.c22
-rw-r--r--crypto/kerberosIV/appl/kip/kip.h5
-rw-r--r--crypto/kerberosIV/appl/kip/kipd.c8
-rw-r--r--crypto/kerberosIV/appl/sample/Makefile.in83
-rw-r--r--crypto/kerberosIV/appl/sample/sample.h81
-rw-r--r--crypto/kerberosIV/appl/sample/sample_client.c168
-rw-r--r--crypto/kerberosIV/appl/sample/sample_server.c153
-rw-r--r--crypto/kerberosIV/appl/sample/simple.h14
-rw-r--r--crypto/kerberosIV/appl/sample/simple_client.c202
-rw-r--r--crypto/kerberosIV/appl/sample/simple_server.c140
-rw-r--r--crypto/kerberosIV/appl/telnet/ChangeLog232
-rw-r--r--crypto/kerberosIV/appl/telnet/Makefile.am11
-rw-r--r--crypto/kerberosIV/appl/telnet/Makefile.in42
-rw-r--r--crypto/kerberosIV/appl/telnet/README.ORIG743
-rw-r--r--crypto/kerberosIV/appl/telnet/arpa/telnet.h323
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/Makefile.am24
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/Makefile.in54
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/auth-proto.h122
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/auth.c657
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/auth.h81
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/enc-proto.h132
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c671
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/encrypt.c995
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/encrypt.h98
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/genget.c103
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c717
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c734
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c437
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/misc-proto.h79
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/misc.c94
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/misc.h42
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/rsaencpwd.c487
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/spx.c586
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet.state80
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/Makefile.am20
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/Makefile.in75
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/authenc.c91
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/commands.c2693
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/defines.h60
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/externs.h429
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/main.c321
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/network.c163
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/ring.c321
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/ring.h99
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c972
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/telnet.c2313
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h176
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/terminal.c225
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/types.h52
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/utilities.c863
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/Makefile.am21
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/Makefile.in79
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/authenc.c82
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/defs.h190
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/ext.h204
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/global.c107
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/slc.c57
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/state.c1356
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/sys_term.c1863
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/telnetd.c1357
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/telnetd.h224
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/termstat.c140
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/utility.c1157
134 files changed, 29588 insertions, 2625 deletions
diff --git a/crypto/kerberosIV/appl/Makefile.in b/crypto/kerberosIV/appl/Makefile.in
index c951258..2cc8391 100644
--- a/crypto/kerberosIV/appl/Makefile.in
+++ b/crypto/kerberosIV/appl/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.27 1997/05/20 18:58:37 bg Exp $
+# $Id: Makefile.in,v 1.31 1998/04/26 09:59:31 assar Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -7,8 +7,8 @@ SHELL = /bin/sh
@SET_MAKE@
-SUBDIRS = sample kauth bsd movemail afsutil \
- kpopper xnlock kx otp @APPL_KIP_DIR@ ftp telnet
+SUBDIRS = sample kauth bsd movemail push afsutil \
+ popper xnlock kx @OTP_dir@ @APPL_KIP_DIR@ ftp telnet
all:
for i in $(SUBDIRS); \
@@ -40,4 +40,4 @@ realclean:
for i in $(SUBDIRS); \
do (cd $$i && $(MAKE) $(MFLAGS) realclean); done
-.PHONY: all install uninstall clean distclean realclean mostlyclean
+.PHONY: all Wall install uninstall clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/afsutil/Makefile.in b/crypto/kerberosIV/appl/afsutil/Makefile.in
new file mode 100644
index 0000000..86adb88
--- /dev/null
+++ b/crypto/kerberosIV/appl/afsutil/Makefile.in
@@ -0,0 +1,89 @@
+# $Id: Makefile.in,v 1.27 1999/03/10 19:01:10 joda Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+top_builddir = ../..
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS= @LD_FLAGS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LIBROKEN = -L../../lib/roken -lroken
+LIBS = @KRB_KAFS_LIB@ -L../../lib/krb -lkrb -L../../lib/des -ldes $(LIBROKEN) @LIBS@ $(LIBROKEN)
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+libexecdir = @libexecdir@
+bindir = @bindir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+PROG_BIN = pagsh$(EXECSUFFIX) \
+ afslog$(EXECSUFFIX) \
+ kstring2key$(EXECSUFFIX)
+PROG_LIBEXEC =
+PROGS = $(PROG_BIN) $(PROG_LIBEXEC)
+
+SOURCES = pagsh.c aklog.c kstring2key.c
+
+OBJECTS = pagsh.o aklog.o kstring2key.o
+
+all: $(PROGS)
+
+Wall:
+ make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__"
+
+.c.o:
+ $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $<
+
+install: all
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
+ for x in $(PROG_BIN); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(PROG_BIN); do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+check:
+
+clean:
+ rm -f *.a *.o $(PROGS)
+
+mostlyclean: clean
+
+distclean: clean
+ rm -f Makefile *.tab.c *~
+
+realclean: distclean
+ rm -f TAGS
+
+pagsh$(EXECSUFFIX): pagsh.o
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ pagsh.o $(LIBS)
+
+afslog$(EXECSUFFIX): aklog.o
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ aklog.o $(LIBS)
+
+kstring2key$(EXECSUFFIX): kstring2key.o
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ kstring2key.o $(LIBS)
+
+
+$(OBJECTS): ../../include/config.h
+
+.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/afsutil/aklog.c b/crypto/kerberosIV/appl/afsutil/aklog.c
new file mode 100644
index 0000000..f3bcb8b
--- /dev/null
+++ b/crypto/kerberosIV/appl/afsutil/aklog.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 1995 - 1999 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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.
+ */
+
+#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_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <err.h>
+#include <krb.h>
+#include <kafs.h>
+
+#include <roken.h>
+
+RCSID("$Id: aklog.c,v 1.22.2.1 1999/07/22 03:13:22 assar Exp $");
+
+static int debug = 0;
+
+static void
+DEBUG(const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+static void
+DEBUG(const char *fmt, ...)
+{
+ va_list ap;
+ if (debug) {
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ }
+}
+
+static char *
+expand_cell_name(char *cell)
+{
+ FILE *f;
+ static char buf[128];
+ char *p;
+
+ f = fopen(_PATH_CELLSERVDB, "r");
+ if(f == NULL)
+ return cell;
+ while(fgets(buf, sizeof(buf), f) != NULL) {
+ if(buf[0] == '>') {
+ for(p=buf; *p && !isspace(*p) && *p != '#'; p++)
+ ;
+ *p = '\0';
+ if(strstr(buf, cell)){
+ fclose(f);
+ return buf + 1;
+ }
+ }
+ buf[0] = 0;
+ }
+ fclose(f);
+ return cell;
+}
+
+static int
+createuser (char *cell)
+{
+ char cellbuf[64];
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ char realm[REALM_SZ];
+ char cmd[1024];
+
+ if (cell == NULL) {
+ FILE *f;
+ int len;
+
+ f = fopen (_PATH_THISCELL, "r");
+ if (f == NULL)
+ err (1, "open(%s)", _PATH_THISCELL);
+ if (fgets (cellbuf, sizeof(cellbuf), f) == NULL)
+ err (1, "read cellname from %s", _PATH_THISCELL);
+ fclose (f);
+ len = strlen(cellbuf);
+ if (cellbuf[len-1] == '\n')
+ cellbuf[len-1] = '\0';
+ cell = cellbuf;
+ }
+
+ if(krb_get_default_principal(name, instance, realm))
+ errx (1, "Could not even figure out who you are");
+
+ snprintf (cmd, sizeof(cmd),
+ "pts createuser %s%s%s@%s -cell %s",
+ name, *instance ? "." : "", instance, strlwr(realm),
+ cell);
+ DEBUG("Executing %s", cmd);
+ return system(cmd);
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ int do_aklog = -1;
+ int do_createuser = -1;
+ char *cell = NULL;
+ char *realm = NULL;
+ char cellbuf[64];
+
+ set_progname (argv[0]);
+
+ if(!k_hasafs())
+ exit(1);
+
+ for(i = 1; i < argc; i++){
+ if(!strncmp(argv[i], "-createuser", 11)){
+ do_createuser = do_aklog = 1;
+
+ }else if(!strncmp(argv[i], "-c", 2) && i + 1 < argc){
+ cell = expand_cell_name(argv[++i]);
+ do_aklog = 1;
+
+ }else if(!strncmp(argv[i], "-k", 2) && i + 1 < argc){
+ realm = argv[++i];
+
+ }else if(!strncmp(argv[i], "-p", 2) && i + 1 < argc){
+ if(k_afs_cell_of_file(argv[++i], cellbuf, sizeof(cellbuf)))
+ errx (1, "No cell found for file \"%s\".", argv[i]);
+ else
+ cell = cellbuf;
+ do_aklog = 1;
+
+ }else if(!strncmp(argv[i], "-unlog", 6)){
+ exit(k_unlog());
+
+ }else if(!strncmp(argv[i], "-hosts", 6)){
+ warnx ("Argument -hosts is not implemented.");
+
+ }else if(!strncmp(argv[i], "-zsubs", 6)){
+ warnx("Argument -zsubs is not implemented.");
+
+ }else if(!strncmp(argv[i], "-noprdb", 6)){
+ warnx("Argument -noprdb is not implemented.");
+
+ }else if(!strncmp(argv[i], "-d", 6)){
+ debug = 1;
+
+ }else{
+ if(!strcmp(argv[i], ".") ||
+ !strcmp(argv[i], "..") ||
+ strchr(argv[i], '/')){
+ DEBUG("I guess that \"%s\" is a filename.", argv[i]);
+ if(k_afs_cell_of_file(argv[i], cellbuf, sizeof(cellbuf)))
+ errx (1, "No cell found for file \"%s\".", argv[i]);
+ else {
+ cell = cellbuf;
+ DEBUG("The file \"%s\" lives in cell \"%s\".", argv[i], cell);
+ }
+ }else{
+ cell = expand_cell_name(argv[i]);
+ DEBUG("I guess that %s is cell %s.", argv[i], cell);
+ }
+ do_aklog = 1;
+ }
+ if(do_aklog == 1){
+ do_aklog = 0;
+ if(krb_afslog(cell, realm))
+ errx (1, "Failed getting tokens for cell %s in realm %s.",
+ cell?cell:"(local cell)", realm?realm:"(local realm)");
+ }
+ if(do_createuser == 1) {
+ do_createuser = 0;
+ if(createuser(cell))
+ errx (1, "Failed creating user in cell %s", cell?cell:"(local cell)");
+ }
+ }
+ if(do_aklog == -1 && do_createuser == -1 && krb_afslog(0, realm))
+ errx (1, "Failed getting tokens for cell %s in realm %s.",
+ cell?cell:"(local cell)", realm?realm:"(local realm)");
+ return 0;
+}
diff --git a/crypto/kerberosIV/appl/afsutil/kstring2key.c b/crypto/kerberosIV/appl/afsutil/kstring2key.c
new file mode 100644
index 0000000..30482f0
--- /dev/null
+++ b/crypto/kerberosIV/appl/afsutil/kstring2key.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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 "config.h"
+
+RCSID("$Id: kstring2key.c,v 1.14 1998/06/09 19:24:14 joda Exp $");
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <err.h>
+
+#include <roken.h>
+
+#include <des.h>
+#include <krb.h>
+
+#define VERIFY 0
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s [-c AFS cellname] [ -5 krb5salt ] [ password ]\n",
+ __progname);
+ fprintf(stderr,
+ " krb5salt is realmname APPEND principal APPEND instance\n");
+ exit(1);
+}
+
+static
+void
+krb5_string_to_key(char *str,
+ char *salt,
+ des_cblock *key)
+{
+ char *foo;
+
+ asprintf(&foo, "%s%s", str, salt);
+ if (foo == NULL)
+ errx (1, "malloc: out of memory");
+ des_string_to_key(foo, key);
+ free (foo);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ des_cblock key;
+ char buf[1024];
+ char *cellname = 0, *salt = 0;
+
+ set_progname (argv[0]);
+
+ if (argc >= 3 && argv[1][0] == '-' && argv[1][1] == 'c')
+ {
+ cellname = argv[2];
+ argv += 2;
+ argc -= 2;
+ }
+ else if (argc >= 3 && argv[1][0] == '-' && argv[1][1] == '5')
+ {
+ salt = argv[2];
+ argv += 2;
+ argc -= 2;
+ }
+ if (argc >= 2 && argv[1][0] == '-')
+ usage();
+
+ switch (argc) {
+ case 1:
+ if (des_read_pw_string(buf, sizeof(buf)-1, "password: ", VERIFY))
+ errx (1, "Error reading password.");
+ break;
+ case 2:
+ strcpy_truncate(buf, argv[1], sizeof(buf));
+ break;
+ default:
+ usage();
+ break;
+ }
+
+ if (cellname != 0)
+ afs_string_to_key(buf, cellname, &key);
+ else if (salt != 0)
+ krb5_string_to_key(buf, salt, &key);
+ else
+ des_string_to_key(buf, &key);
+
+ {
+ int j;
+ unsigned char *tkey = (unsigned char *) &key;
+ printf("ascii = ");
+ for(j = 0; j < 8; j++)
+ if(tkey[j] != '\\' && isalpha(tkey[j]) != 0)
+ printf("%c", tkey[j]);
+ else
+ printf("\\%03o",(unsigned char)tkey[j]);
+ printf("\n");
+ printf("hex = ");
+ for(j = 0; j < 8; j++)
+ printf("%02x",(unsigned char)tkey[j]);
+ printf("\n");
+ }
+ exit(0);
+}
diff --git a/crypto/kerberosIV/appl/afsutil/pagsh.c b/crypto/kerberosIV/appl/afsutil/pagsh.c
new file mode 100644
index 0000000..1f02ee8
--- /dev/null
+++ b/crypto/kerberosIV/appl/afsutil/pagsh.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$Id: pagsh.c,v 1.21 1999/03/11 13:56:55 joda Exp $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <time.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include <err.h>
+#include <roken.h>
+
+#include <krb.h>
+#include <kafs.h>
+
+int
+main(int argc, char **argv)
+{
+ int f;
+ char tf[1024];
+ char *p;
+
+ char *path;
+ char **args;
+ int i;
+
+ do {
+ snprintf(tf, sizeof(tf), "%s%u_%u", TKT_ROOT, (unsigned int)getuid(),
+ (unsigned int)(getpid()*time(0)));
+ f = open(tf, O_CREAT|O_EXCL|O_RDWR);
+ } while(f < 0);
+ close(f);
+ unlink(tf);
+ setenv("KRBTKFILE", tf, 1);
+
+ i = 0;
+
+ args = (char **) malloc((argc + 10)*sizeof(char *));
+ if (args == NULL)
+ errx (1, "Out of memory allocating %lu bytes",
+ (unsigned long)((argc + 10)*sizeof(char *)));
+
+ argv++;
+
+ if(*argv == NULL) {
+ path = getenv("SHELL");
+ if(path == NULL){
+ struct passwd *pw = k_getpwuid(geteuid());
+ path = strdup(pw->pw_shell);
+ }
+ } else {
+ if(strcmp(*argv, "-c") == 0) argv++;
+ path = strdup(*argv++);
+ }
+ if (path == NULL)
+ errx (1, "Out of memory copying path");
+
+ p=strrchr(path, '/');
+ if(p)
+ args[i] = strdup(p+1);
+ else
+ args[i] = strdup(path);
+
+ if (args[i++] == NULL)
+ errx (1, "Out of memory copying arguments");
+
+ while(*argv)
+ args[i++] = *argv++;
+
+ args[i++] = NULL;
+
+ if(k_hasafs())
+ k_setpag();
+
+ execvp(path, args);
+ if (errno == ENOENT) {
+ char **sh_args = malloc ((i + 2) * sizeof(char *));
+ int j;
+
+ if (sh_args == NULL)
+ errx (1, "Out of memory copying sh arguments");
+ for (j = 1; j < i; ++j)
+ sh_args[j + 2] = args[j];
+ sh_args[0] = "sh";
+ sh_args[1] = "-c";
+ sh_args[2] = path;
+ execv ("/bin/sh", sh_args);
+ }
+ perror("execvp");
+ exit(1);
+}
diff --git a/crypto/kerberosIV/appl/bsd/Makefile.in b/crypto/kerberosIV/appl/bsd/Makefile.in
index 57a8108..fdda8c1 100644
--- a/crypto/kerberosIV/appl/bsd/Makefile.in
+++ b/crypto/kerberosIV/appl/bsd/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.56 1997/05/20 20:35:04 assar Exp $
+# $Id: Makefile.in,v 1.68 1999/03/27 17:05:34 joda Exp $
SHELL = /bin/sh
@@ -6,13 +6,15 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
-topdir = ../..
+top_builddir = ../..
CC = @CC@
+LINK = @LINK@
AR = ar
RANLIB = @RANLIB@
DEFS = @DEFS@ -DBINDIR='"$(bindir)"'
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
LD_FLAGS = @LD_FLAGS@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -39,19 +41,20 @@ PROG_LIBEXEC = rshd$(EXECSUFFIX) \
PROGS = $(PROG_SUIDBIN) $(PROG_BIN) $(PROG_LIBEXEC)
SOURCES = rsh.c kcmd.c krcmd.c rlogin.c rcp.c rcp_util.c rshd.c \
- login.c klogin.c login_access.c su.c rlogind.c iruserok.c \
+ login.c klogin.c login_access.c su.c rlogind.c \
login_fbtab.c forkpty.c sysv_default.c sysv_environ.c sysv_shadow.c \
- utmp_login.c utmpx_login.c stty_default.c encrypt.c rcmd_util.c tty.c
+ utmp_login.c utmpx_login.c stty_default.c encrypt.c rcmd_util.c tty.c \
+ osfc2.c
rsh_OBJS = rsh.o kcmd.o krcmd.o encrypt.o rcmd_util.o
-rcp_OBJS = rcp.o rcp_util.o kcmd.o krcmd.o encrypt.o rcmd_util.o
+rcp_OBJS = rcp.o rcp_util.o kcmd.o krcmd.o encrypt.o rcmd_util.o osfc2.o
rlogin_OBJS = rlogin.o kcmd.o krcmd.o encrypt.o rcmd_util.o
login_OBJS = login.o klogin.o login_fbtab.o login_access.o \
sysv_default.o sysv_environ.o sysv_shadow.o \
- utmp_login.o utmpx_login.o stty_default.o tty.o
+ utmp_login.o utmpx_login.o stty_default.o tty.o osfc2.o
su_OBJS = su.o
-rshd_OBJS = rshd.o iruserok.o encrypt.o rcmd_util.o
-rlogind_OBJS = rlogind.o iruserok.o forkpty.o encrypt.o rcmd_util.o tty.o
+rshd_OBJS = rshd.o encrypt.o rcmd_util.o osfc2.o
+rlogind_OBJS = rlogind.o forkpty.o encrypt.o rcmd_util.o tty.o
all: $(PROGS)
@@ -60,30 +63,30 @@ Wall:
make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__"
.c.o:
- $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $<
+ $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $<
install: all
- $(MKINSTALLDIRS) $(libexecdir)
+ $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir)
for x in $(PROG_LIBEXEC); do \
- $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \
done
- $(MKINSTALLDIRS) $(bindir)
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
for x in $(PROG_BIN); do \
- $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x| sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
done
-for x in $(PROG_SUIDBIN); do \
- $(INSTALL_PROGRAM) -o root -m 04555 $$x $(bindir)/`echo $$x| sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) -o root -m 04555 $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
done
uninstall:
for x in $(PROG_LIBEXEC); do \
- rm -f $(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \
done
for x in $(PROG_BIN); do \
- rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
done
for x in $(PROG_SUIDBIN); do \
- rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
done
TAGS: $(SOURCES)
@@ -102,34 +105,32 @@ distclean: clean
realclean: distclean
rm -f TAGS
-dist: $(DISTFILES)
- for file in $(DISTFILES); do \
- ln $$file ../`cat ../.fname`/lib \
- || cp -p $$file ../`cat ../.fname`/lib; \
- done
-
KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
KLIB_AFS=@KRB_KAFS_LIB@ $(KLIB)
-OTPLIB=-L../../lib/otp -lotp
+OTPLIB=@LIB_otp@
LIBROKEN=-L../../lib/roken -lroken
+LIB_security=@LIB_security@
+
rcp$(EXECSUFFIX): $(rcp_OBJS)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rcp_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rcp_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) $(LIB_security)
rsh$(EXECSUFFIX): $(rsh_OBJS)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rsh_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rsh_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
rshd$(EXECSUFFIX): $(rshd_OBJS)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rshd_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rshd_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) $(LIB_security)
rlogin$(EXECSUFFIX): $(rlogin_OBJS)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogin_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogin_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
rlogind$(EXECSUFFIX): $(rlogind_OBJS)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogind_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogind_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
login$(EXECSUFFIX): $(login_OBJS)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(login_OBJS) $(OTPLIB) $(KLIB_AFS) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(login_OBJS) $(OTPLIB) $(KLIB_AFS) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN) $(LIB_security)
su$(EXECSUFFIX): $(su_OBJS)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(su_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(su_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/bsd/bsd_locl.h b/crypto/kerberosIV/appl/bsd/bsd_locl.h
index d0b37aa..2731f03 100644
--- a/crypto/kerberosIV/appl/bsd/bsd_locl.h
+++ b/crypto/kerberosIV/appl/bsd/bsd_locl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*/
-/* $Id: bsd_locl.h,v 1.98 1997/05/25 01:14:17 assar Exp $ */
+/* $Id: bsd_locl.h,v 1.109.2.1 1999/07/22 03:13:49 assar Exp $ */
#define LOGALL
#define KERBEROS
@@ -49,7 +49,7 @@
#endif
/* Any better way to test NO_MOTD? */
-#if (SunOS == 5) || defined(__hpux)
+#if (SunOS >= 50) || defined(__hpux)
#define NO_MOTD
#endif
@@ -62,13 +62,20 @@
#include <stdlib.h>
#include <ctype.h>
#include <setjmp.h>
+#include <limits.h>
#include <stdarg.h>
#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -145,7 +152,7 @@
#include <netdb.h>
#endif
-#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_IOCCOM_H
@@ -228,10 +235,10 @@
#ifdef HAVE_UTMP_H
#include <utmp.h>
-#endif
#ifndef UT_NAMESIZE
#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name)
#endif
+#endif
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
@@ -242,9 +249,14 @@
#endif /* HAVE_USERPW_H */
#ifdef HAVE_USERSEC_H
+struct aud_rec;
#include <usersec.h>
#endif /* HAVE_USERSEC_H */
+#ifdef HAVE_OSFC2
+#include "/usr/include/prot.h"
+#endif
+
#ifndef PRIO_PROCESS
#define PRIO_PROCESS 0
#endif
@@ -255,6 +267,9 @@
#ifdef SOCKS
#include <socks.h>
+/* This doesn't belong here. */
+struct tm *localtime(const time_t *);
+struct hostent *gethostbyname(const char *);
#endif
#include <des.h>
@@ -289,6 +304,9 @@ int susystem(char *s, int userid);
int forkpty(int *amaster, char *name,
struct termios *termp, struct winsize *winp);
+int forkpty_truncate(int *amaster, char *name, size_t name_sz,
+ struct termios *termp, struct winsize *winp);
+
#ifndef MODEMASK
#define MODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
#endif
@@ -310,11 +328,7 @@ extern char **environ;
void sysv_newenv(int argc, char **argv, struct passwd *pwd,
char *term, int pflag);
-int login_access(char *user, char *from);
-#ifndef HAVE_IRUSEROK
-int iruserok(u_int32_t raddr, int superuser, const char *ruser,
- const char *luser);
-#endif
+int login_access(struct passwd *user, char *from);
void fatal(int f, const char *msg, int syserr);
extern int LEFT_JUSTIFIED;
@@ -323,6 +337,10 @@ int des_enc_read(int fd,char *buf,int len,des_key_schedule sched,
int des_enc_write(int fd,char *buf,int len,des_key_schedule sched,
des_cblock *iv);
+/* used in des_read and des_write */
+#define DES_RW_MAXWRITE (1024*16)
+#define DES_RW_BSIZE (DES_RW_MAXWRITE+4)
+
void sysv_defaults(void);
void utmp_login(char *tty, char *username, char *hostname);
void sleepexit (int);
@@ -342,11 +360,11 @@ void sleepexit (int);
#ifndef _POSIX_VDISABLE
#define _POSIX_VDISABLE 0
#endif /* _POSIX_VDISABLE */
-#if SunOS == 4
+#if SunOS == 40
#include <sys/ttold.h>
#endif
-#if defined(_AIX)
+#if defined(HAVE_SYS_TERMIO_H) && !defined(HAVE_TERMIOS_H)
#include <sys/termio.h>
#endif
@@ -376,5 +394,9 @@ __attribute__ ((format (printf, 1, 2)))
char *clean_ttyname (char *tty);
char *make_id (char *tty);
+#ifdef HAVE_UTMP_H
void prepare_utmp (struct utmp *utmp, char *tty, char *username,
char *hostname);
+#endif
+
+int do_osfc2_magic(uid_t);
diff --git a/crypto/kerberosIV/appl/bsd/encrypt.c b/crypto/kerberosIV/appl/bsd/encrypt.c
index b74f329..9f835c6 100644
--- a/crypto/kerberosIV/appl/bsd/encrypt.c
+++ b/crypto/kerberosIV/appl/bsd/encrypt.c
@@ -46,13 +46,7 @@
#include "bsd_locl.h"
-RCSID("$Id: encrypt.c,v 1.3 1996/04/30 13:50:54 bg Exp $");
-
-#undef BSIZE
-
-/* used in des_read and des_write */
-#define MAXWRITE (1024*16)
-#define BSIZE (MAXWRITE+4)
+RCSID("$Id: encrypt.c,v 1.4 1999/06/17 18:47:26 assar Exp $");
/* replacements for htonl and ntohl since I have no idea what to do
* when faced with machines with 8 byte longs. */
@@ -78,11 +72,11 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock
{
/* data to be unencrypted */
int net_num=0;
- unsigned char net[BSIZE];
+ unsigned char net[DES_RW_BSIZE];
/* extra unencrypted data
* for when a block of 100 comes in but is des_read one byte at
* a time. */
- static char unnet[BSIZE];
+ static char unnet[DES_RW_BSIZE];
static int unnet_start=0;
static int unnet_left=0;
int i;
@@ -114,7 +108,7 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock
}
/* We need to get more data. */
- if (len > MAXWRITE) len=MAXWRITE;
+ if (len > DES_RW_MAXWRITE) len=DES_RW_MAXWRITE;
/* first - get the length */
net_num=0;
@@ -133,7 +127,7 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock
/* num should be rounded up to the next group of eight
* we make sure that we have read a multiple of 8 bytes from the net.
*/
- if ((num > MAXWRITE) || (num < 0)) /* error */
+ if ((num > DES_RW_MAXWRITE) || (num < 0)) /* error */
return(-1);
rnum=(num < 8)?8:((num+7)/8*8);
@@ -172,7 +166,7 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock
* FIXED - Should be ok now 18-9-90 - eay */
if (len < rnum)
{
- char tmpbuf[BSIZE];
+ char tmpbuf[DES_RW_BSIZE];
if (des_rw_mode & DES_PCBC_MODE)
des_pcbc_encrypt((des_cblock *)net,
@@ -223,7 +217,7 @@ des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cbloc
{
long rnum;
int i,j,k,outnum;
- char outbuf[BSIZE+HDRSIZE];
+ char outbuf[DES_RW_BSIZE+HDRSIZE];
char shortbuf[8];
char *p;
static int start=1;
@@ -237,13 +231,13 @@ des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cbloc
}
/* lets recurse if we want to send the data in small chunks */
- if (len > MAXWRITE)
+ if (len > DES_RW_MAXWRITE)
{
j=0;
for (i=0; i<len; i+=k)
{
k=des_enc_write(fd,&(buf[i]),
- ((len-i) > MAXWRITE)?MAXWRITE:(len-i),sched,iv);
+ ((len-i) > DES_RW_MAXWRITE)?DES_RW_MAXWRITE:(len-i),sched,iv);
if (k < 0)
return(k);
else
diff --git a/crypto/kerberosIV/appl/bsd/forkpty.c b/crypto/kerberosIV/appl/bsd/forkpty.c
index 5c0aaaf..0ab7ef2 100644
--- a/crypto/kerberosIV/appl/bsd/forkpty.c
+++ b/crypto/kerberosIV/appl/bsd/forkpty.c
@@ -40,7 +40,7 @@
#ifndef HAVE_FORKPTY
-RCSID("$Id: forkpty.c,v 1.52 1997/05/25 07:37:01 assar Exp $");
+RCSID("$Id: forkpty.c,v 1.53.2.2 1999/08/19 13:37:16 assar Exp $");
/* Only CRAY is known to have problems with forkpty(). */
#if defined(CRAY)
@@ -150,7 +150,9 @@ pty_scan_tty(char *buf, size_t sz)
}
static int
-ptym_open_streams_flavor(char *pts_name, int *streams_pty)
+ptym_open_streams_flavor(char *pts_name,
+ size_t pts_name_sz,
+ int *streams_pty)
{
/* Try clone device master ptys */
const char *const clone[] = { "/dev/ptc", "/dev/ptmx",
@@ -166,7 +168,8 @@ ptym_open_streams_flavor(char *pts_name, int *streams_pty)
if (fdm >= 0) {
char *ptr1;
if ((ptr1 = ptsname(fdm)) != NULL) /* Get slave's name */
- strcpy(pts_name, ptr1); /* Return name of slave */
+ /* Return name of slave */
+ strcpy_truncate(pts_name, ptr1, pts_name_sz);
else {
close(fdm);
return(-4);
@@ -185,7 +188,7 @@ ptym_open_streams_flavor(char *pts_name, int *streams_pty)
}
static int
-ptym_open_bsd_flavor(char *pts_name, int *streams_pty)
+ptym_open_bsd_flavor(char *pts_name, size_t pts_name_sz, int *streams_pty)
{
int fdm;
char ptm[MaxPathLen];
@@ -196,7 +199,7 @@ ptym_open_bsd_flavor(char *pts_name, int *streams_pty)
fdm = open(ptm, O_RDWR);
if (fdm < 0)
continue;
-#if SunOS == 4
+#if SunOS == 40
/* Avoid a bug in SunOS4 ttydriver */
if (fdm > 0) {
int pgrp;
@@ -265,14 +268,14 @@ ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty)
char *p = _getpty(&fdm, O_RDWR, 0600, 1);
if (p) {
*streams_pty = 1;
- strcpy (pts_name, p);
+ strcpy_truncate (pts_name, p, pts_name_sz);
return fdm;
}
}
#endif
#ifdef STREAMSPTY
- fdm = ptym_open_streams_flavor(pts_name, streams_pty);
+ fdm = ptym_open_streams_flavor(pts_name, pts_name_sz, streams_pty);
if (fdm >= 0)
{
*streams_pty = 1;
@@ -280,7 +283,7 @@ ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty)
}
#endif
- fdm = ptym_open_bsd_flavor(pts_name, streams_pty);
+ fdm = ptym_open_bsd_flavor(pts_name, pts_name_sz, streams_pty);
if (fdm >= 0)
{
*streams_pty = 0;
@@ -288,7 +291,7 @@ ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty)
}
#ifndef STREAMSPTY
- fdm = ptym_open_streams_flavor(pts_name, streams_pty);
+ fdm = ptym_open_streams_flavor(pts_name, pts_name_sz, streams_pty);
if (fdm >= 0)
{
*streams_pty = 1;
@@ -363,8 +366,10 @@ ptys_open(int fdm, char *pts_name, int streams_pty)
gid = -1; /* group tty is not in the group file */
/* Grant access to slave */
- chown(pts_name, getuid(), gid);
- chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);
+ if (chown(pts_name, getuid(), gid) < 0)
+ fatal(0, "chown slave tty failed", 1);
+ if (chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP) < 0)
+ fatal(0, "chmod slave tty failed", 1);
if ( (fds = open(pts_name, O_RDWR)) < 0) {
close(fdm);
@@ -375,10 +380,11 @@ ptys_open(int fdm, char *pts_name, int streams_pty)
}
int
-forkpty(int *ptrfdm,
- char *slave_name,
- struct termios *slave_termios,
- struct winsize *slave_winsize)
+forkpty_truncate(int *ptrfdm,
+ char *slave_name,
+ size_t slave_name_sz,
+ struct termios *slave_termios,
+ struct winsize *slave_winsize)
{
int fdm, fds, streams_pty;
pid_t pid;
@@ -391,7 +397,8 @@ forkpty(int *ptrfdm,
return -1;
if (slave_name != NULL)
- strcpy(slave_name, pts_name); /* Return name of slave */
+ /* Return name of slave */
+ strcpy_truncate(slave_name, pts_name, slave_name_sz);
pid = fork();
if (pid < 0)
@@ -458,4 +465,18 @@ forkpty(int *ptrfdm,
return(pid); /* Parent returns pid of child */
}
}
+
+int
+forkpty(int *ptrfdm,
+ char *slave_name,
+ struct termios *slave_termios,
+ struct winsize *slave_winsize)
+{
+ return forkpty_truncate (ptrfdm,
+ slave_name,
+ MaxPathLen,
+ slave_termios,
+ slave_winsize);
+}
+
#endif /* HAVE_FORKPTY */
diff --git a/crypto/kerberosIV/appl/bsd/kcmd.c b/crypto/kerberosIV/appl/bsd/kcmd.c
index 9fa7ab2..af20357 100644
--- a/crypto/kerberosIV/appl/bsd/kcmd.c
+++ b/crypto/kerberosIV/appl/bsd/kcmd.c
@@ -33,7 +33,7 @@
#include "bsd_locl.h"
-RCSID("$Id: kcmd.c,v 1.19 1997/05/02 14:27:42 assar Exp $");
+RCSID("$Id: kcmd.c,v 1.20 1998/07/13 13:54:07 assar Exp $");
#define START_PORT 5120 /* arbitrary */
@@ -100,6 +100,7 @@ kcmd(int *sock,
int rc;
char *host_save;
int status;
+ char **h_addr_list;
pid = getpid();
hp = gethostbyname(*ahost);
@@ -112,6 +113,7 @@ kcmd(int *sock,
if (host_save == NULL)
return -1;
*ahost = host_save;
+ h_addr_list = hp->h_addr_list;
/* If realm is null, look up from table */
if (realm == NULL || realm[0] == '\0')
@@ -127,7 +129,7 @@ kcmd(int *sock,
return (-1);
}
sin.sin_family = hp->h_addrtype;
- memcpy (&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
+ memcpy (&sin.sin_addr, h_addr_list[0], sizeof(sin.sin_addr));
sin.sin_port = rport;
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
break;
@@ -144,12 +146,12 @@ kcmd(int *sock,
timo *= 2;
continue;
}
- if (hp->h_addr_list[1] != NULL) {
+ if (h_addr_list[1] != NULL) {
warn ("kcmd: connect (%s)",
inet_ntoa(sin.sin_addr));
- hp->h_addr_list++;
+ h_addr_list++;
memcpy(&sin.sin_addr,
- hp->h_addr_list[0],
+ *h_addr_list,
sizeof(sin.sin_addr));
fprintf(stderr, "Trying %s...\n",
inet_ntoa(sin.sin_addr));
diff --git a/crypto/kerberosIV/appl/bsd/klogin.c b/crypto/kerberosIV/appl/bsd/klogin.c
index 321da64..41002dc 100644
--- a/crypto/kerberosIV/appl/bsd/klogin.c
+++ b/crypto/kerberosIV/appl/bsd/klogin.c
@@ -33,7 +33,7 @@
#include "bsd_locl.h"
-RCSID("$Id: klogin.c,v 1.20 1997/05/02 14:27:42 assar Exp $");
+RCSID("$Id: klogin.c,v 1.24 1999/03/15 13:34:12 bg Exp $");
#ifdef KERBEROS
@@ -44,6 +44,63 @@ extern char *krbtkfile_env;
static char tkt_location[MaxPathLen];
+static int
+multiple_get_tkt(char *name,
+ char *instance,
+ char *realm,
+ char *service,
+ char *sinstance,
+ int life,
+ char *password)
+{
+ int n;
+ char rlm[256];
+#define ERICSSON_COMPAT 1
+#ifdef ERICSSON_COMPAT
+ FILE *f;
+
+ f = fopen("/etc/krb.localrealms", "r");
+ if (f != NULL) {
+ while (fgets(rlm, sizeof(rlm), f) != NULL) {
+ if (rlm[strlen(rlm) - 1] == '\n')
+ rlm[strlen(rlm) - 1] = '\0';
+
+ if (krb_get_pw_in_tkt(name,
+ instance,
+ rlm,
+ service,
+ realm,
+ life,
+ password) == KSUCCESS) {
+ fclose(f);
+ return KSUCCESS;
+ }
+ }
+ return krb_get_pw_in_tkt(name,
+ instance,
+ realm,
+ service,
+ realm,
+ life,
+ password);
+ }
+#endif
+ /* First try to verify against the supplied realm. */
+ if (krb_get_pw_in_tkt(name, instance, realm, service, realm, life, password)
+ == KSUCCESS)
+ return KSUCCESS;
+
+ /* Verify all local realms, except the supplied realm. */
+ for (n = 1; krb_get_lrealm(rlm, n) == KSUCCESS; n++)
+ if (strcmp(rlm, realm) != 0)
+ if (krb_get_pw_in_tkt(name, instance, rlm,service, realm, life, password)
+ == KSUCCESS)
+ return KSUCCESS;
+
+ return KFAILURE;
+
+}
+
/*
* Attempt to log the user in using Kerberos authentication
*
@@ -73,7 +130,7 @@ klogin(struct passwd *pw, char *instance, char *localhost, char *password)
* without issuing any tickets.
*/
if (strcmp(pw->pw_name, "root") == 0 ||
- krb_get_lrealm(realm, 0) != KSUCCESS)
+ krb_get_lrealm(realm, 1) != KSUCCESS)
return (1);
noticketsdontcomplain = 0; /* enable warning message */
@@ -96,9 +153,25 @@ klogin(struct passwd *pw, char *instance, char *localhost, char *password)
krbtkfile_env = tkt_location;
krb_set_tkt_string(tkt_location);
- kerror = krb_get_pw_in_tkt(pw->pw_name, instance,
- realm, KRB_TICKET_GRANTING_TICKET, realm,
- DEFAULT_TKT_LIFE, password);
+ /*
+ * Set real as well as effective ID to 0 for the moment,
+ * to make the kerberos library do the right thing.
+ */
+ if (setuid(0) < 0) {
+ warnx("setuid");
+ return (1);
+ }
+
+ /*
+ * Get ticket
+ */
+ kerror = multiple_get_tkt(pw->pw_name,
+ instance,
+ realm,
+ KRB_TICKET_GRANTING_TICKET,
+ realm,
+ DEFAULT_TKT_LIFE,
+ password);
/*
* If we got a TGT, get a local "rcmd" ticket and check it so as to
@@ -121,8 +194,7 @@ klogin(struct passwd *pw, char *instance, char *localhost, char *password)
if (chown(TKT_FILE, pw->pw_uid, pw->pw_gid) < 0)
syslog(LOG_ERR, "chown tkfile (%s): %m", TKT_FILE);
- strncpy(savehost, krb_get_phost(localhost), sizeof(savehost));
- savehost[sizeof(savehost)-1] = '\0';
+ strcpy_truncate(savehost, krb_get_phost(localhost), sizeof(savehost));
#ifdef KLOGIN_PARANOID
/*
diff --git a/crypto/kerberosIV/appl/bsd/login.c b/crypto/kerberosIV/appl/bsd/login.c
index c436f8d..702c5ff 100644
--- a/crypto/kerberosIV/appl/bsd/login.c
+++ b/crypto/kerberosIV/appl/bsd/login.c
@@ -38,10 +38,18 @@
*/
#include "bsd_locl.h"
+#ifdef HAVE_CAPABILITY_H
+#include <capability.h>
+#endif
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#endif
-RCSID("$Id: login.c,v 1.104 1997/05/20 20:35:06 assar Exp $");
+RCSID("$Id: login.c,v 1.120.2.2 1999/09/02 08:55:26 joda Exp $");
+#ifdef OTP
#include <otp.h>
+#endif
#include "sysv_default.h"
#ifdef SYSV_SHADOW
@@ -93,22 +101,20 @@ static char rusername[100], lusername[100];
static int
change_passwd(struct passwd *who)
{
- int status;
- int pid;
- int wpid;
+ int status;
+ pid_t pid;
- switch (pid = fork()) {
- case -1:
- warn("fork /bin/passwd");
- sleepexit(1);
- case 0:
- execlp("/bin/passwd", "passwd", who->pw_name, (char *) 0);
- _exit(1);
- default:
- while ((wpid = wait(&status)) != -1 && wpid != pid)
- /* void */ ;
- return (status);
- }
+ switch (pid = fork()) {
+ case -1:
+ warn("fork /bin/passwd");
+ sleepexit(1);
+ case 0:
+ execlp("/bin/passwd", "passwd", who->pw_name, (char *) 0);
+ _exit(1);
+ default:
+ waitpid(pid, &status, 0);
+ return (status);
+ }
}
#ifndef NO_MOTD /* message of the day stuff */
@@ -177,7 +183,9 @@ main(int argc, char **argv)
char localhost[MaxHostNameLen];
char full_hostname[MaxHostNameLen];
int auth_level = AUTH_NONE;
+#ifdef OTP
OtpContext otp_ctx;
+#endif
int mask = 022; /* Default umask (set below) */
int maxtrys = 5; /* Default number of allowed failed logins */
@@ -210,7 +218,7 @@ main(int argc, char **argv)
*full_hostname = '\0';
domain = NULL;
- if (k_gethostname(localhost, sizeof(localhost)) < 0)
+ if (gethostname(localhost, sizeof(localhost)) < 0)
syslog(LOG_ERR, "couldn't get local hostname: %m");
else
domain = strchr(localhost, '.');
@@ -222,8 +230,10 @@ main(int argc, char **argv)
case 'a':
if (strcmp (optarg, "none") == 0)
auth_level = AUTH_NONE;
+#ifdef OTP
else if (strcmp (optarg, "otp") == 0)
auth_level = AUTH_OTP;
+#endif
else
warnx ("bad value for -a: %s", optarg);
break;
@@ -240,7 +250,9 @@ main(int argc, char **argv)
if (uid)
errx(1, "-h option: %s", strerror(EPERM));
hflag = 1;
- strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
+ strcpy_truncate(full_hostname,
+ optarg,
+ sizeof(full_hostname));
if (domain && (p = strchr(optarg, '.')) &&
strcasecmp(p, domain) == 0)
*p = 0;
@@ -263,7 +275,9 @@ main(int argc, char **argv)
exit(1);
}
rflag = 1;
- strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
+ strcpy_truncate(full_hostname,
+ optarg,
+ sizeof(full_hostname));
if (domain && (p = strchr(optarg, '.')) &&
strcasecmp(p, domain) == 0)
*p = 0;
@@ -275,8 +289,11 @@ main(int argc, char **argv)
if (!uid)
syslog(LOG_ERR, "invalid flag %c", ch);
fprintf(stderr,
- "usage: login [-fp] [-a otp]"
- "[-h hostname | -r hostname] [username]\n");
+ "usage: login [-fp]"
+#ifdef OTP
+ " [-a otp]"
+#endif
+ " [-h hostname | -r hostname] [username]\n");
exit(1);
}
argc -= optind;
@@ -366,7 +383,7 @@ main(int argc, char **argv)
badlogin(tbuf);
failures = 0;
}
- strcpy(tbuf, username);
+ strcpy_truncate(tbuf, username, sizeof(tbuf));
pwd = paranoid_getpwnam (username);
@@ -394,11 +411,14 @@ main(int argc, char **argv)
setpriority(PRIO_PROCESS, 0, -4);
+#ifdef OTP
if (otp_challenge (&otp_ctx, username,
ss, sizeof(ss)) == 0)
snprintf (prompt, sizeof(prompt), "%s's %s Password: ",
username, ss);
- else {
+ else
+#endif
+ {
if (auth_level == AUTH_NONE)
snprintf(prompt, sizeof(prompt), "%s's Password: ",
username);
@@ -406,9 +426,11 @@ main(int argc, char **argv)
char *s;
rval = 1;
+#ifdef OTP
s = otp_error(&otp_ctx);
if(s)
printf ("OTP: %s\n", s);
+#endif
continue;
}
}
@@ -419,9 +441,12 @@ main(int argc, char **argv)
/* Verify it somehow */
+#ifdef OTP
if (otp_verify_user (&otp_ctx, passwd) == 0)
rval = 0;
- else if (pwd == NULL)
+ else
+#endif
+ if (pwd == NULL)
;
else if (auth_level == AUTH_NONE) {
uid_t pwd_uid = pwd->pw_uid;
@@ -445,8 +470,10 @@ main(int argc, char **argv)
char *s;
rval = 1;
+#ifdef OTP
if ((s = otp_error(&otp_ctx)))
printf ("OTP: %s\n", s);
+#endif
}
memset (passwd, 0, sizeof(passwd));
@@ -507,28 +534,45 @@ main(int argc, char **argv)
struct udb *udb;
long t;
const long maxcpu = 46116860184; /* some random constant */
+
+ if(setjob(pwd->pw_uid, 0) < 0)
+ warn("setjob");
+
udb = getudbnam(pwd->pw_name);
- if(udb == UDB_NULL){
- warnx("Failed to get UDB entry.");
- exit(1);
- }
+ if(udb == UDB_NULL)
+ errx(1, "Failed to get UDB entry.");
+
+ /* per process cpu limit */
t = udb->ue_pcpulim[UDBRC_INTER];
if(t == 0 || t > maxcpu)
t = CPUUNLIM;
else
- t *= 100 * CLOCKS_PER_SEC;
+ t *= CLK_TCK;
if(limit(C_PROC, 0, L_CPU, t) < 0)
- warn("limit C_PROC");
+ warn("limit process cpu");
+ /* per process memory limit */
+ if(limit(C_PROC, 0, L_MEM, udb->ue_pmemlim[UDBRC_INTER]) < 0)
+ warn("limit process memory");
+
+ /* per job cpu limit */
t = udb->ue_jcpulim[UDBRC_INTER];
if(t == 0 || t > maxcpu)
t = CPUUNLIM;
else
- t *= 100 * CLOCKS_PER_SEC;
+ t *= CLK_TCK;
+
+ if(limit(C_JOB, 0, L_CPU, t) < 0)
+ warn("limit job cpu");
+
+ /* per job processor limit */
+ if(limit(C_JOB, 0, L_CPROC, udb->ue_jproclim[UDBRC_INTER]) < 0)
+ warn("limit job processors");
- if(limit(C_JOBPROCS, 0, L_CPU, t) < 0)
- warn("limit C_JOBPROCS");
+ /* per job memory limit */
+ if(limit(C_JOB, 0, L_MEM, udb->ue_jmemlim[UDBRC_INTER]) < 0)
+ warn("limit job memory");
nice(udb->ue_nice[UDBRC_INTER]);
}
@@ -590,9 +634,11 @@ main(int argc, char **argv)
*/
login_fbtab(tty, pwd->pw_uid, pwd->pw_gid);
- chown(ttyn, pwd->pw_uid,
- (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
- chmod(ttyn, S_IRUSR | S_IWUSR | S_IWGRP);
+ if (chown(ttyn, pwd->pw_uid,
+ (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid) < 0)
+ err(1, "chown tty failed");
+ if (chmod(ttyn, S_IRUSR | S_IWUSR | S_IWGRP) < 0)
+ err(1, "chmod tty failed");
setgid(pwd->pw_gid);
initgroups(username, pwd->pw_gid);
@@ -608,7 +654,7 @@ main(int argc, char **argv)
* that LD_* and IFS are never preserved.
*/
if (term[0] == '\0')
- strncpy(term, stypeof(tty), sizeof(term));
+ strcpy_truncate(term, stypeof(tty), sizeof(term));
/* set up a somewhat censored environment. */
sysv_newenv(argc, argv, pwd, term, pflag);
#ifdef KERBEROS
@@ -620,12 +666,13 @@ main(int argc, char **argv)
syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
/* If fflag is on, assume caller/authenticator has logged root login. */
- if (rootlogin && fflag == 0)
+ if (rootlogin && fflag == 0) {
if (hostname)
syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
username, tty, hostname);
else
syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
+ }
#ifdef KERBEROS
if (!quietlog && notickets == 1 && !noticketsdontcomplain)
@@ -668,7 +715,7 @@ main(int argc, char **argv)
#endif /* NO_MOTD */
#ifdef LOGIN_ACCESS
- if (login_access(pwd->pw_name, hostname ? full_hostname : tty) == 0) {
+ if (login_access(pwd, hostname ? full_hostname : tty) == 0) {
printf("Permission denied\n");
if (hostname)
syslog(LOG_NOTICE, "%s LOGIN REFUSED FROM %s",
@@ -683,11 +730,12 @@ main(int argc, char **argv)
signal(SIGALRM, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGINT, SIG_DFL);
+#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN);
+#endif
- tbuf[0] = '-';
- strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
- p + 1 : pwd->pw_shell);
+ p = strrchr(pwd->pw_shell, '/');
+ snprintf (tbuf, sizeof(tbuf), "-%s", p ? p + 1 : pwd->pw_shell);
#ifdef HAVE_SETLOGIN
if (setlogin(pwd->pw_name) < 0)
@@ -703,6 +751,35 @@ main(int argc, char **argv)
spwd = getspnam (username);
endspent ();
#endif
+ /* perhaps work some magic */
+ if(do_osfc2_magic(pwd->pw_uid))
+ sleepexit(1);
+#if defined(HAVE_SGI_GETCAPABILITYBYNAME) && defined(HAVE_CAP_SET_PROC)
+ /* XXX SGI capability hack IRIX 6.x (x >= 0?) has something
+ called capabilities, that allow you to give away
+ permissions (such as chown) to specific processes. From 6.5
+ this is default on, and the default capability set seems to
+ not always be the empty set. The problem is that the
+ runtime linker refuses to do just about anything if the
+ process has *any* capabilities set, so we have to remove
+ them here (unless otherwise instructed by /etc/capability).
+ In IRIX < 6.5, these functions was called sgi_cap_setproc,
+ etc, but we ignore this fact (it works anyway). */
+ {
+ struct user_cap *ucap = sgi_getcapabilitybyname(pwd->pw_name);
+ cap_t cap;
+ if(ucap == NULL)
+ cap = cap_from_text("all=");
+ else
+ cap = cap_from_text(ucap->ca_default);
+ if(cap == NULL)
+ err(1, "cap_from_text");
+ if(cap_set_proc(cap) < 0)
+ err(1, "cap_set_proc");
+ cap_free(cap);
+ free(ucap);
+ }
+#endif
/* Discard permissions last so can't get killed and drop core. */
{
int uid = rootlogin ? 0 : pwd->pw_uid;
@@ -742,10 +819,18 @@ main(int argc, char **argv)
if (k_hasafs()) {
char cell[64];
+#ifdef _AIX
+ /* XXX this is a fix for a bug in AFS for AIX 4.3, w/o
+ this hack the kernel crashes on the following
+ pioctl... */
+ char *pw_dir = strdup(pwd->pw_dir);
+#else
+ char *pw_dir = pwd->pw_dir;
+#endif
k_setpag();
- if(k_afs_cell_of_file(pwd->pw_dir, cell, sizeof(cell)) == 0)
- k_afsklog(cell, 0);
- k_afsklog(0, 0);
+ if(k_afs_cell_of_file(pw_dir, cell, sizeof(cell)) == 0)
+ krb_afslog(cell, 0);
+ krb_afslog(0, 0);
}
execlp(pwd->pw_shell, tbuf, 0);
@@ -768,46 +853,77 @@ main(int argc, char **argv)
static void
getloginname(int prompt)
{
- int ch;
- char *p;
- static char nbuf[NBUFSIZ];
-
- for (;;) {
- if (prompt)
- if (ttyprompt && *ttyprompt)
- printf("%s", ttyprompt);
- else
- printf("login: ");
- prompt = 1;
- for (p = nbuf; (ch = getchar()) != '\n'; ) {
- if (ch == EOF) {
- badlogin(username);
- exit(0);
- }
- if (p < nbuf + (NBUFSIZ - 1))
- *p++ = ch;
- }
- if (p > nbuf)
- if (nbuf[0] == '-')
- warnx("login names may not start with '-'.");
- else {
- *p = '\0';
- username = nbuf;
- break;
- }
+ int ch;
+ char *p;
+ static char nbuf[NBUFSIZ];
+
+ for (;;) {
+ if (prompt) {
+ if (ttyprompt && *ttyprompt)
+ printf("%s", ttyprompt);
+ else
+ printf("login: ");
+ }
+ prompt = 1;
+ for (p = nbuf; (ch = getchar()) != '\n'; ) {
+ if (ch == EOF) {
+ badlogin(username);
+ exit(0);
+ }
+ if (p < nbuf + (NBUFSIZ - 1))
+ *p++ = ch;
+ }
+ if (p > nbuf) {
+ if (nbuf[0] == '-')
+ warnx("login names may not start with '-'.");
+ else {
+ *p = '\0';
+ username = nbuf;
+ break;
+ }
}
+ }
+}
+
+static int
+find_in_etc_securetty (char *ttyn)
+{
+ FILE *f;
+ char buf[128];
+ int ret = 0;
+
+ f = fopen (_PATH_ETC_SECURETTY, "r");
+ if (f == NULL)
+ return 0;
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ if(buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+ if (strcmp (buf, ttyn) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ fclose(f);
+ return ret;
}
static int
rootterm(char *ttyn)
{
-#ifndef HAVE_TTYENT_H
- return (default_console == 0 || strcmp(default_console, ttyname(0)) == 0);
-#else
+#ifdef HAVE_TTYENT_H
+ {
struct ttyent *t;
- return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
+ t = getttynam (ttyn);
+ if (t && t->ty_status & TTY_SECURE)
+ return 1;
+ }
#endif
+ if (find_in_etc_securetty(ttyn))
+ return 1;
+ if (default_console == 0 || strcmp(default_console, ttyn) == 0)
+ return 1;
+ return 0;
}
static RETSIGTYPE
diff --git a/crypto/kerberosIV/appl/bsd/login_access.c b/crypto/kerberosIV/appl/bsd/login_access.c
index 0e017b1..7b79dc8 100644
--- a/crypto/kerberosIV/appl/bsd/login_access.c
+++ b/crypto/kerberosIV/appl/bsd/login_access.c
@@ -9,7 +9,7 @@
#include "bsd_locl.h"
-RCSID("$Id: login_access.c,v 1.15 1997/06/01 03:12:28 assar Exp $");
+RCSID("$Id: login_access.c,v 1.19 1999/05/14 22:02:14 assar Exp $");
#ifdef LOGIN_ACCESS
@@ -23,15 +23,26 @@ static char sep[] = ", \t"; /* list-element separator */
#define YES 1
#define NO 0
-static int list_match(char *list, char *item, int (*match_fn)(char *, char *));
-static int user_match(char *tok, char *string);
-static int from_match(char *tok, char *string);
+ /*
+ * A structure to bundle up all login-related information to keep the
+ * functional interfaces as generic as possible.
+ */
+struct login_info {
+ struct passwd *user;
+ char *from;
+};
+
+static int list_match(char *list, struct login_info *item,
+ int (*match_fn)(char *, struct login_info *));
+static int user_match(char *tok, struct login_info *item);
+static int from_match(char *tok, struct login_info *item);
static int string_match(char *tok, char *string);
/* login_access - match username/group and host/tty with access control file */
-int login_access(char *user, char *from)
+int login_access(struct passwd *user, char *from)
{
+ struct login_info item;
FILE *fp;
char line[BUFSIZ];
char *perm; /* becomes permission field */
@@ -43,6 +54,12 @@ int login_access(char *user, char *from)
char *foo;
/*
+ * Bundle up the arguments to avoid unnecessary clumsiness lateron.
+ */
+ item.user = user;
+ item.from = from;
+
+ /*
* Process the table one line at a time and stop at the first match.
* Blank lines and lines that begin with a '#' character are ignored.
* Non-comment lines are broken at the ':' character. All fields are
@@ -60,7 +77,7 @@ int login_access(char *user, char *from)
}
if (line[0] == '#')
continue; /* comment line */
- while (end > 0 && isspace(line[end - 1]))
+ while (end > 0 && isspace((unsigned char)line[end - 1]))
end--;
line[end] = 0; /* strip trailing whitespace */
if (line[0] == 0) /* skip blank lines */
@@ -81,8 +98,8 @@ int login_access(char *user, char *from)
lineno);
continue;
}
- match = (list_match(froms, from, from_match)
- && list_match(users, user, user_match));
+ match = (list_match(froms, &item, from_match)
+ && list_match(users, &item, user_match));
}
fclose(fp);
} else if (errno != ENOENT) {
@@ -94,7 +111,9 @@ int login_access(char *user, char *from)
/* list_match - match an item against a list of tokens with exceptions */
static int
-list_match(char *list, char *item, int (*match_fn)(char *, char *))
+list_match(char *list,
+ struct login_info *item,
+ int (*match_fn)(char *, struct login_info *))
{
char *tok;
int match = NO;
@@ -126,6 +145,19 @@ list_match(char *list, char *item, int (*match_fn)(char *, char *))
return (NO);
}
+/* myhostname - figure out local machine name */
+
+static char *myhostname(void)
+{
+ static char name[MAXHOSTNAMELEN + 1] = "";
+
+ if (name[0] == 0) {
+ gethostname(name, sizeof(name));
+ name[MAXHOSTNAMELEN] = 0;
+ }
+ return (name);
+}
+
/* netgroup_match - match group against machine or user */
static int netgroup_match(char *group, char *machine, char *user)
@@ -144,22 +176,32 @@ static int netgroup_match(char *group, char *machine, char *user)
/* user_match - match a username against one token */
-static int user_match(char *tok, char *string)
+static int user_match(char *tok, struct login_info *item)
{
+ char *string = item->user->pw_name;
+ struct login_info fake_item;
struct group *group;
int i;
+ char *at;
/*
* If a token has the magic value "ALL" the match always succeeds.
- * Otherwise, return YES if the token fully matches the username, or if
- * the token is a group that contains the username.
+ * Otherwise, return YES if the token fully matches the username, if the
+ * token is a group that contains the username, or if the token is the
+ * name of the user's primary group.
*/
- if (tok[0] == '@') { /* netgroup */
+ if ((at = strchr(tok + 1, '@')) != 0) { /* split user@host pattern */
+ *at = 0;
+ fake_item.from = myhostname();
+ return (user_match(tok, item) && from_match(at + 1, &fake_item));
+ } else if (tok[0] == '@') { /* netgroup */
return (netgroup_match(tok + 1, (char *) 0, string));
} else if (string_match(tok, string)) { /* ALL or exact match */
return (YES);
} else if ((group = getgrnam(tok)) != 0) { /* try group membership */
+ if (item->user->pw_gid == group->gr_gid)
+ return (YES);
for (i = 0; group->gr_mem[i]; i++)
if (strcasecmp(string, group->gr_mem[i]) == 0)
return (YES);
@@ -169,8 +211,9 @@ static int user_match(char *tok, char *string)
/* from_match - match a host or tty against a list of tokens */
-static int from_match(char *tok, char *string)
+static int from_match(char *tok, struct login_info *item)
{
+ char *string = item->from;
int tok_len;
int str_len;
diff --git a/crypto/kerberosIV/appl/bsd/login_fbtab.c b/crypto/kerberosIV/appl/bsd/login_fbtab.c
index f7f53aa..f831909 100644
--- a/crypto/kerberosIV/appl/bsd/login_fbtab.c
+++ b/crypto/kerberosIV/appl/bsd/login_fbtab.c
@@ -58,7 +58,7 @@
#include "bsd_locl.h"
-RCSID("$Id: login_fbtab.c,v 1.10 1997/06/01 03:12:54 assar Exp $");
+RCSID("$Id: login_fbtab.c,v 1.13 1999/01/14 00:37:59 assar Exp $");
void login_protect (char *, char *, int, uid_t, gid_t);
void login_fbtab (char *tty, uid_t uid, gid_t gid);
@@ -126,15 +126,25 @@ login_protect(char *table, char *path, int mask, uid_t uid, gid_t gid)
if (chown(path, uid, gid) && errno != ENOENT)
syslog(LOG_ERR, "%s: chown(%s): %m", table, path);
} else {
- strcpy(buf, path);
- buf[pathlen - 1] = 0;
+ strcpy_truncate (buf, path, sizeof(buf));
+ if (sizeof(buf) > pathlen)
+ buf[pathlen - 2] = '\0';
+ /* Solaris evidently operates on the directory as well */
+ login_protect(table, buf, mask | ((mask & 0444) >> 2), uid, gid);
if ((dir = opendir(buf)) == 0) {
syslog(LOG_ERR, "%s: opendir(%s): %m", table, path);
} else {
+ if (sizeof(buf) > pathlen) {
+ buf[pathlen - 2] = '/';
+ buf[pathlen - 1] = '\0';
+ }
+
while ((ent = readdir(dir)) != 0) {
if (strcmp(ent->d_name, ".") != 0
&& strcmp(ent->d_name, "..") != 0) {
- strcpy(buf + pathlen - 1, ent->d_name);
+ strcpy_truncate (buf + pathlen - 1,
+ ent->d_name,
+ sizeof(buf) - (pathlen + 1));
login_protect(table, buf, mask, uid, gid);
}
}
diff --git a/crypto/kerberosIV/appl/bsd/osfc2.c b/crypto/kerberosIV/appl/bsd/osfc2.c
new file mode 100644
index 0000000..78f2e6e
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/osfc2.c
@@ -0,0 +1,84 @@
+/*
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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 "bsd_locl.h"
+RCSID("$Id: osfc2.c,v 1.1 1998/09/28 11:47:36 joda Exp $");
+
+int
+do_osfc2_magic(uid_t uid)
+{
+#ifdef HAVE_OSFC2
+ struct es_passwd *epw;
+ char *argv[2];
+
+ /* fake */
+ argv[0] = (char*)__progname;
+ argv[1] = NULL;
+ set_auth_parameters(1, argv);
+
+ epw = getespwuid(uid);
+ if(epw == NULL) {
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "getespwuid failed for %d", uid);
+ printf("Sorry.\n");
+ return 1;
+ }
+ /* We don't check for auto-retired, foo-retired,
+ bar-retired, or any other kind of retired accounts
+ here; neither do we check for time-locked accounts, or
+ any other kind of serious C2 mumbo-jumbo. We do,
+ however, call setluid, since failing to do so it not
+ very good (take my word for it). */
+
+ if(!epw->uflg->fg_uid) {
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "attempted login by %s (has no uid)", epw->ufld->fd_name);
+ printf("Sorry.\n");
+ return 1;
+ }
+ setluid(epw->ufld->fd_uid);
+ if(getluid() != epw->ufld->fd_uid) {
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "failed to set LUID for %s (%d)",
+ epw->ufld->fd_name, epw->ufld->fd_uid);
+ printf("Sorry.\n");
+ return 1;
+ }
+#endif /* HAVE_OSFC2 */
+ return 0;
+}
diff --git a/crypto/kerberosIV/appl/bsd/pathnames.h b/crypto/kerberosIV/appl/bsd/pathnames.h
index 3c10bff..671f663 100644
--- a/crypto/kerberosIV/appl/bsd/pathnames.h
+++ b/crypto/kerberosIV/appl/bsd/pathnames.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 5.2 (Berkeley) 4/9/90
- * $Id: pathnames.h,v 1.23 1996/11/17 06:36:42 joda Exp $
+ * $Id: pathnames.h,v 1.25 1998/02/03 23:29:30 assar Exp $
*/
/******* First fix default path, we stick to _PATH_DEFPATH everywhere */
@@ -65,6 +65,9 @@
#undef _PATH_RSH /* Redifine rsh */
#define _PATH_RSH BINDIR "/rsh"
+#undef _PATH_RCP /* Redifine rcp */
+#define _PATH_RCP BINDIR "/rcp"
+
#undef _PATH_LOGIN
#define _PATH_LOGIN BINDIR "/login"
@@ -175,6 +178,10 @@
#define _PATH_ETC_ENVIRONMENT "/etc/environment"
#endif
+#ifndef _PATH_ETC_SECURETTY
+#define _PATH_ETC_SECURETTY "/etc/securetty"
+#endif
+
/*
* NeXT KLUDGE ALERT!!!!!!!!!!!!!!!!!!
* Some sort of bug in the NEXTSTEP cpp.
@@ -186,6 +193,8 @@
#define _PATH_RLOGIN "/usr/athena/bin/rlogin"
#undef _PATH_RSH
#define _PATH_RSH "/usr/athena/bin/rsh"
+#undef _PATH_RCP
+#define _PATH_RCP "/usr/athena/bin/rcp"
#undef _PATH_LOGIN
#define _PATH_LOGIN "/usr/athena/bin/login"
#endif
diff --git a/crypto/kerberosIV/appl/bsd/rcmd_util.c b/crypto/kerberosIV/appl/bsd/rcmd_util.c
index 4669009..1884133 100644
--- a/crypto/kerberosIV/appl/bsd/rcmd_util.c
+++ b/crypto/kerberosIV/appl/bsd/rcmd_util.c
@@ -38,7 +38,7 @@
#include "bsd_locl.h"
-RCSID("$Id: rcmd_util.c,v 1.15 1997/05/02 14:27:44 assar Exp $");
+RCSID("$Id: rcmd_util.c,v 1.17 1997/09/24 21:14:23 assar Exp $");
int
get_login_port(int kerberos, int encryption)
@@ -240,7 +240,7 @@ warning(const char *fmt, ...)
if (strncmp(rstar_no_warn, "yes", 3) != 0) {
/* XXX */
fprintf(stderr, "%s: warning, using standard ", __progname);
- warnx(fmt, args);
+ vwarnx(fmt, args);
}
va_end(args);
}
diff --git a/crypto/kerberosIV/appl/bsd/rcp.c b/crypto/kerberosIV/appl/bsd/rcp.c
index 6dfb472..39fd36e 100644
--- a/crypto/kerberosIV/appl/bsd/rcp.c
+++ b/crypto/kerberosIV/appl/bsd/rcp.c
@@ -33,7 +33,7 @@
#include "bsd_locl.h"
-RCSID("$Id: rcp.c,v 1.43 1997/05/13 09:41:26 bg Exp $");
+RCSID("$Id: rcp.c,v 1.49 1999/07/06 03:17:58 assar Exp $");
/* Globals */
static char dst_realm_buf[REALM_SZ];
@@ -49,6 +49,9 @@ static u_short port;
static uid_t userid;
static int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+static int argc_copy;
+static char **argv_copy;
+
#define CMDNEEDS 64
static char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
@@ -58,7 +61,7 @@ void rsource(char *name, struct stat *statp);
CREDENTIALS cred;
MSG_DAT msg_data;
-struct sockaddr_in foreign, local;
+struct sockaddr_in foreign_addr, local_addr;
Key_schedule schedule;
KTEXT_ST ticket;
@@ -71,18 +74,18 @@ send_auth(char *h, char *r)
long opts;
lslen = sizeof(struct sockaddr_in);
- if (getsockname(rem, (struct sockaddr *)&local, &lslen) < 0)
+ if (getsockname(rem, (struct sockaddr *)&local_addr, &lslen) < 0)
err(1, "getsockname");
fslen = sizeof(struct sockaddr_in);
- if (getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0)
+ if (getpeername(rem, (struct sockaddr *)&foreign_addr, &fslen) < 0)
err(1, "getpeername");
if ((r == NULL) || (*r == '\0'))
r = krb_realmofhost(h);
opts = KOPT_DO_MUTUAL;
if ((status = krb_sendauth(opts, rem, &ticket, SERVICE_NAME, h, r,
(unsigned long)getpid(), &msg_data, &cred,
- schedule, &local,
- &foreign, "KCMDV0.1")) != KSUCCESS)
+ schedule, &local_addr,
+ &foreign_addr, "KCMDV0.1")) != KSUCCESS)
errx(1, "krb_sendauth failure: %s", krb_get_err_text(status));
}
@@ -94,15 +97,15 @@ answer_auth(void)
char inst[INST_SZ], v[9];
lslen = sizeof(struct sockaddr_in);
- if (getsockname(rem, (struct sockaddr *)&local, &lslen) < 0)
+ if (getsockname(rem, (struct sockaddr *)&local_addr, &lslen) < 0)
err(1, "getsockname");
fslen = sizeof(struct sockaddr_in);
- if(getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0)
+ if(getpeername(rem, (struct sockaddr *)&foreign_addr, &fslen) < 0)
err(1, "getperrname");
k_getsockinst(rem, inst, sizeof(inst));
opts = KOPT_DO_MUTUAL;
if ((status = krb_recvauth(opts, rem, &ticket, SERVICE_NAME, inst,
- &foreign, &local,
+ &foreign_addr, &local_addr,
&kdata, "", schedule, v)) != KSUCCESS)
errx(1, "krb_recvauth failure: %s", krb_get_err_text(status));
}
@@ -143,10 +146,11 @@ run_err(const char *fmt, ...)
va_start(args, fmt);
++errs;
#define RCPERR "\001rcp: "
- strcpy (errbuf, RCPERR);
- vsnprintf (errbuf + strlen(RCPERR), sizeof(errbuf) - strlen(RCPERR),
+ strcpy_truncate (errbuf, RCPERR, sizeof(errbuf));
+ vsnprintf (errbuf + strlen(errbuf),
+ sizeof(errbuf) - strlen(errbuf),
fmt, args);
- strcat (errbuf, "\n");
+ strcat_truncate (errbuf, "\n", sizeof(errbuf));
des_write (rem, errbuf, strlen(errbuf));
if (!iamremote)
vwarnx(fmt, args);
@@ -351,11 +355,15 @@ rsource(char *name, struct stat *statp)
DIR *dirp;
struct dirent *dp;
char *last, *vect[1], path[MaxPathLen];
+ char *p;
if (!(dirp = opendir(name))) {
run_err("%s: %s", name, strerror(errno));
return;
}
+ for (p = name + strlen(name) - 1; p >= name && *p == '/'; --p)
+ *p = '\0';
+
last = strrchr(name, '/');
if (last == 0)
last = name;
@@ -403,8 +411,9 @@ static int
kerberos(char **host, char *bp, char *locuser, char *user)
{
int sock = -1, err;
-again:
+
if (use_kerberos) {
+ setuid(getuid());
rem = KSUCCESS;
errno = 0;
if (dest_realm == NULL)
@@ -439,13 +448,11 @@ again:
rem = sock;
#endif
if (rem < 0) {
- use_kerberos = 0;
- port = get_shell_port(use_kerberos, 0);
if (errno == ECONNREFUSED)
oldw("remote host doesn't support Kerberos");
else if (errno == ENOENT)
oldw("can't provide Kerberos authentication data");
- goto again;
+ execv(_PATH_RCP, argv_copy);
}
} else {
if (doencrypt)
@@ -493,29 +500,24 @@ toremote(char *targ, int argc, char **argv)
if (*src == 0)
src = ".";
host = strchr(argv[i], '@');
- len = strlen(_PATH_RSH) + strlen(argv[i]) +
- strlen(src) + (tuser ? strlen(tuser) : 0) +
- strlen(thost) + strlen(targ) + CMDNEEDS + 20;
- if (!(bp = malloc(len)))
- err(1, " ");
if (host) {
- *host++ = 0;
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
- continue;
- snprintf(bp, len,
- "%s %s -l %s -n %s %s '%s%s%s:%s'",
- _PATH_RSH, host, suser, cmd, src,
- tuser ? tuser : "", tuser ? "@" : "",
- thost, targ);
+ *host++ = 0;
+ suser = argv[i];
+ if (*suser == '\0')
+ suser = pwd->pw_name;
+ else if (!okname(suser))
+ continue;
+ asprintf(&bp, "%s %s -l %s -n %s %s '%s%s%s:%s'",
+ _PATH_RSH, host, suser, cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
} else
- snprintf(bp, len,
- "exec %s %s -n %s %s '%s%s%s:%s'",
- _PATH_RSH, argv[i], cmd, src,
- tuser ? tuser : "", tuser ? "@" : "",
- thost, targ);
+ asprintf(&bp, "exec %s %s -n %s %s '%s%s%s:%s'",
+ _PATH_RSH, argv[i], cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
+ if(bp == NULL)
+ errx(1, "out of memory");
susystem(bp, userid);
free(bp);
} else { /* local to remote */
@@ -623,7 +625,13 @@ sink(int argc, char **argv)
if (ch == '\n')
*--cp = 0;
-#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
+#define getnum(t) \
+ do { \
+ (t) = 0; \
+ while (isdigit((unsigned char)*cp)) \
+ (t) = (t) * 10 + (*cp++ - '0'); \
+ } while(0)
+
cp = buf;
if (*cp == 'T') {
setimes++;
@@ -666,7 +674,7 @@ sink(int argc, char **argv)
if (*cp++ != ' ')
SCREWUP("mode not delimited");
- for (size = 0; isdigit(*cp);)
+ for (size = 0; isdigit((unsigned char)*cp);)
size = size * 10 + (*cp++ - '0');
if (*cp++ != ' ')
SCREWUP("size not delimited");
@@ -906,8 +914,28 @@ main(int argc, char **argv)
{
int ch, fflag, tflag;
char *targ;
+ int i;
set_progname(argv[0]);
+
+ /*
+ * Prepare for execing ourselves.
+ */
+
+ argc_copy = argc + 1;
+ argv_copy = malloc((argc_copy + 1) * sizeof(*argv_copy));
+ if (argv_copy == NULL)
+ err(1, "malloc");
+ argv_copy[0] = argv[0];
+ argv_copy[1] = "-K";
+ for(i = 1; i < argc; ++i) {
+ argv_copy[i + 1] = strdup(argv[i]);
+ if (argv_copy[i + 1] == NULL)
+ errx(1, "strdup: out of memory");
+ }
+ argv_copy[argc + 1] = NULL;
+
+
fflag = tflag = 0;
while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
switch(ch) { /* User-visible flags. */
@@ -916,7 +944,7 @@ main(int argc, char **argv)
break;
case 'k':
dest_realm = dst_realm_buf;
- strncpy(dst_realm_buf, optarg, REALM_SZ);
+ strcpy_truncate(dst_realm_buf, optarg, REALM_SZ);
break;
case 'x':
doencrypt = 1;
@@ -951,47 +979,40 @@ main(int argc, char **argv)
* kshell service, pass 0 for no encryption */
port = get_shell_port(use_kerberos, 0);
+ userid = getuid();
+
#ifndef __CYGWIN32__
- if ((pwd = k_getpwuid(userid = getuid())) == NULL)
+ if ((pwd = k_getpwuid(userid)) == NULL)
errx(1, "unknown user %d", (int)userid);
#endif
rem = STDIN_FILENO; /* XXX */
- if (fflag) { /* Follow "protocol", send data. */
- if (doencrypt)
- answer_auth();
+ if (fflag || tflag) {
+ if (doencrypt)
+ answer_auth();
+ if(fflag)
response();
- setuid(userid);
- if (k_hasafs()) {
- /* Sometimes we will need cell specific tokens
- * to be able to read and write files, thus,
- * the token stuff done in rshd might not
- * suffice.
- */
- char cell[64];
- if (k_afs_cell_of_file(pwd->pw_dir,
- cell, sizeof(cell)) == 0)
- k_afsklog(cell, 0);
- k_afsklog(0, 0);
- }
+ if(do_osfc2_magic(pwd->pw_uid))
+ exit(1);
+ setuid(userid);
+ if (k_hasafs()) {
+ /* Sometimes we will need cell specific tokens
+ * to be able to read and write files, thus,
+ * the token stuff done in rshd might not
+ * suffice.
+ */
+ char cell[64];
+ if (k_afs_cell_of_file(pwd->pw_dir,
+ cell, sizeof(cell)) == 0)
+ krb_afslog(cell, 0);
+ krb_afslog(0, 0);
+ }
+ if(fflag)
source(argc, argv);
- exit(errs);
- }
-
- if (tflag) { /* Receive data. */
- if (doencrypt)
- answer_auth();
- setuid(userid);
- if (k_hasafs()) {
- char cell[64];
- if (k_afs_cell_of_file(pwd->pw_dir,
- cell, sizeof(cell)) == 0)
- k_afsklog(cell, 0);
- k_afsklog(0, 0);
- }
+ else
sink(argc, argv);
- exit(errs);
+ exit(errs);
}
if (argc < 2)
diff --git a/crypto/kerberosIV/appl/bsd/rcp_util.c b/crypto/kerberosIV/appl/bsd/rcp_util.c
index 6f0c5f0..54233af 100644
--- a/crypto/kerberosIV/appl/bsd/rcp_util.c
+++ b/crypto/kerberosIV/appl/bsd/rcp_util.c
@@ -33,7 +33,7 @@
#include "bsd_locl.h"
-RCSID("$Id: rcp_util.c,v 1.7 1996/11/17 20:23:05 assar Exp $");
+RCSID("$Id: rcp_util.c,v 1.8 1998/09/28 11:45:21 joda Exp $");
char *
colon(char *cp)
@@ -73,25 +73,27 @@ bad: warnx("%s: invalid user name", cp0);
int
susystem(char *s, int userid)
{
- RETSIGTYPE (*istat)(), (*qstat)();
- int status;
- pid_t pid;
+ RETSIGTYPE (*istat)(), (*qstat)();
+ int status;
+ pid_t pid;
- pid = fork();
- switch (pid) {
- case -1:
- return (127);
+ pid = fork();
+ switch (pid) {
+ case -1:
+ return (127);
- case 0:
- setuid(userid);
- 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;
- signal(SIGINT, istat);
- signal(SIGQUIT, qstat);
- return (status);
+ case 0:
+ if(do_osfc2_magic(userid))
+ exit(1);
+ setuid(userid);
+ 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;
+ signal(SIGINT, istat);
+ signal(SIGQUIT, qstat);
+ return (status);
}
diff --git a/crypto/kerberosIV/appl/bsd/rlogin.c b/crypto/kerberosIV/appl/bsd/rlogin.c
index 27aa8f0..5bc6196 100644
--- a/crypto/kerberosIV/appl/bsd/rlogin.c
+++ b/crypto/kerberosIV/appl/bsd/rlogin.c
@@ -36,7 +36,7 @@
*/
#include "bsd_locl.h"
-RCSID("$Id: rlogin.c,v 1.61 1997/05/25 01:14:47 assar Exp $");
+RCSID("$Id: rlogin.c,v 1.65 1999/03/13 21:13:54 assar Exp $");
CREDENTIALS cred;
Key_schedule schedule;
@@ -406,13 +406,14 @@ writer(void)
continue;
}
#endif /* VDSUSP */
- if (c != escapechar)
+ if (c != escapechar) {
#ifndef NOENCRYPTION
if (doencrypt)
des_enc_write(rem, &escapechar,1, schedule, &cred.session);
else
#endif
write(rem, &escapechar, 1);
+ }
}
if (doencrypt) {
@@ -578,7 +579,7 @@ main(int argc, char **argv)
break;
case 'k':
dest_realm = dst_realm_buf;
- strncpy(dest_realm, optarg, REALM_SZ);
+ strcpy_truncate(dest_realm, optarg, REALM_SZ);
break;
case 'l':
user = optarg;
@@ -586,22 +587,26 @@ main(int argc, char **argv)
case 'x':
doencrypt = 1;
break;
- case 'p':
- user_port = htons(atoi(optarg));
- break;
+ case 'p': {
+ char *endptr;
+
+ user_port = strtol (optarg, &endptr, 0);
+ if (user_port == 0 && optarg == endptr)
+ errx (1, "Bad port `%s'", optarg);
+ user_port = htons(user_port);
+ break;
+ }
case '?':
default:
usage();
}
optind += argoff;
- argc -= optind;
- argv += optind;
/* if haven't gotten a host yet, do so */
- if (!host && !(host = *argv++))
+ if (!host && !(host = argv[optind++]))
usage();
- if (*argv)
+ if (argv[optind])
usage();
if (!(pw = k_getpwuid(uid = getuid())))
@@ -609,7 +614,6 @@ main(int argc, char **argv)
if (!user)
user = pw->pw_name;
-
if (user_port)
sv_port = user_port;
else
@@ -636,17 +640,8 @@ main(int argc, char **argv)
get_window_size(0, &winsize);
- try_connect:
if (use_kerberos) {
- struct hostent *hp;
-
- /* Fully qualify hostname (needed for krb_realmofhost). */
- hp = gethostbyname(host);
- if (hp != NULL && !(host = strdup(hp->h_name))) {
- errno = ENOMEM;
- err(1, NULL);
- }
-
+ setuid(getuid());
rem = KSUCCESS;
errno = 0;
if (dest_realm == NULL)
@@ -656,18 +651,25 @@ main(int argc, char **argv)
rem = krcmd_mutual(&host, sv_port, user, term, 0,
dest_realm, &cred, schedule);
else
- rem = krcmd(&host, sv_port, user, term, 0,
- dest_realm);
+ rem = krcmd(&host, sv_port, user, term, 0,
+ dest_realm);
if (rem < 0) {
- use_kerberos = 0;
- if (user_port == 0)
- sv_port = get_login_port(use_kerberos,
- doencrypt);
- if (errno == ECONNREFUSED)
- warning("remote host doesn't support Kerberos");
- if (errno == ENOENT)
- warning("can't provide Kerberos auth data");
- goto try_connect;
+ int i;
+ char **newargv;
+
+ if (errno == ECONNREFUSED)
+ warning("remote host doesn't support Kerberos");
+ if (errno == ENOENT)
+ warning("can't provide Kerberos auth data");
+ newargv = malloc((argc + 2) * sizeof(*newargv));
+ if (newargv == NULL)
+ err(1, "malloc");
+ newargv[0] = argv[0];
+ newargv[1] = "-K";
+ for(i = 1; i < argc; ++i)
+ newargv[i + 1] = argv[i];
+ newargv[argc + 1] = NULL;
+ execv(_PATH_RLOGIN, newargv);
}
} else {
if (doencrypt)
diff --git a/crypto/kerberosIV/appl/bsd/rlogind.c b/crypto/kerberosIV/appl/bsd/rlogind.c
index c5d80774..d36df92 100644
--- a/crypto/kerberosIV/appl/bsd/rlogind.c
+++ b/crypto/kerberosIV/appl/bsd/rlogind.c
@@ -42,7 +42,7 @@
#include "bsd_locl.h"
-RCSID("$Id: rlogind.c,v 1.100 1997/05/25 01:15:20 assar Exp $");
+RCSID("$Id: rlogind.c,v 1.107.2.1 1999/07/22 03:14:39 assar Exp $");
extern int __check_rhosts_file;
@@ -187,7 +187,7 @@ readstream(int p, char *ibuf, int bufsize)
#ifdef HAVE_UTMPX_H
static int
-logout(const char *line)
+rlogind_logout(const char *line)
{
struct utmpx utmpx, *utxp;
int ret = 1;
@@ -198,8 +198,9 @@ logout(const char *line)
strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
utxp = getutxline(&utmpx);
if (utxp) {
- strcpy(utxp->ut_user, "");
+ utxp->ut_user[0] = '\0';
utxp->ut_type = DEAD_PROCESS;
+#ifdef HAVE_STRUCT_UTMPX_UT_EXIT
#ifdef _STRUCT___EXIT_STATUS
utxp->ut_exit.__e_termination = 0;
utxp->ut_exit.__e_exit = 0;
@@ -210,6 +211,7 @@ logout(const char *line)
utxp->ut_exit.e_termination = 0;
utxp->ut_exit.e_exit = 0;
#endif
+#endif
gettimeofday(&utxp->ut_tv, NULL);
pututxline(utxp);
#ifdef WTMPX_FILE
@@ -223,7 +225,7 @@ logout(const char *line)
}
#else
static int
-logout(const char *line)
+rlogind_logout(const char *line)
{
FILE *fp;
struct utmp ut;
@@ -237,9 +239,24 @@ logout(const char *line)
strncmp(ut.ut_line, line, sizeof(ut.ut_line)))
continue;
memset(ut.ut_name, 0, sizeof(ut.ut_name));
-#ifdef HAVE_UT_HOST
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
memset(ut.ut_host, 0, sizeof(ut.ut_host));
#endif
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ ut.ut_type = DEAD_PROCESS;
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_EXIT
+#ifdef _STRUCT___EXIT_STATUS
+ ut.ut_exit.__e_termination = 0;
+ ut.ut_exit.__e_exit = 0;
+#elif defined(__osf__) /* XXX */
+ ut.ut_exit.ut_termination = 0;
+ ut.ut_exit.ut_exit = 0;
+#else
+ ut.ut_exit.e_termination = 0;
+ ut.ut_exit.e_exit = 0;
+#endif
+#endif
time(&ut.ut_time);
fseek(fp, (long)-sizeof(struct utmp), SEEK_CUR);
fwrite(&ut, sizeof(struct utmp), 1, fp);
@@ -265,13 +282,16 @@ logwtmp(const char *line, const char *name, const char *host)
if (!fstat(fd, &buf)) {
strncpy(ut.ut_line, line, sizeof(ut.ut_line));
strncpy(ut.ut_name, name, sizeof(ut.ut_name));
-#ifdef HAVE_UT_HOST
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+ strncpy(ut.ut_id, make_id((char *)line), sizeof(ut.ut_id));
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
strncpy(ut.ut_host, host, sizeof(ut.ut_host));
#endif
-#ifdef HAVE_UT_PID
+#ifdef HAVE_STRUCT_UTMP_UT_PID
ut.ut_pid = getpid();
#endif
-#ifdef HAVE_UT_TYPE
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
if(name[0])
ut.ut_type = USER_PROCESS;
else
@@ -440,7 +460,11 @@ doit(int f, struct sockaddr_in *fromp)
write(f, INSECURE_MESSAGE, strlen(INSECURE_MESSAGE));
netf = f;
+#ifdef HAVE_FORKPTY
pid = forkpty(&master, line, NULL, NULL);
+#else
+ pid = forkpty_truncate(&master, line, sizeof(line), NULL, NULL);
+#endif
if (pid < 0) {
if (errno == ENOENT)
fatal(f, "Out of ptys", 0);
@@ -482,7 +506,9 @@ doit(int f, struct sockaddr_in *fromp)
ioctl(f, FIONBIO, &on);
ioctl(master, FIONBIO, &on);
ioctl(master, TIOCPKT, &on);
+#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN);
+#endif
signal(SIGCHLD, cleanup);
setsid();
protocol(f, master);
@@ -532,7 +558,7 @@ send_oob(int fd, char c)
{
static char last_oob = 0xFF;
-#if (SunOS == 5) || defined(__hpux)
+#if (SunOS >= 50) || defined(__hpux)
/*
* PSoriasis and HP-UX always send TIOCPKT_DOSTOP at startup so we
* can avoid sending OOB data and thus not break on Linux by merging
@@ -571,12 +597,14 @@ protocol(int f, int master)
char cntl;
unsigned char oob_queue = 0;
+#ifdef SIGTTOU
/*
* Must ignore SIGTTOU, otherwise we'll stop
* when we try and set slave pty's window shape
* (our controlling tty is the master pty).
*/
signal(SIGTTOU, SIG_IGN);
+#endif
send_oob(f, TIOCPKT_WINDOW); /* indicate new rlogin */
@@ -600,12 +628,13 @@ protocol(int f, int master)
omask = &obits;
} else
FD_SET(f, &ibits);
- if (pcc >= 0)
+ if (pcc >= 0) {
if (pcc) {
FD_SET(f, &obits);
omask = &obits;
} else
FD_SET(master, &ibits);
+ }
FD_SET(master, &ebits);
if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) {
if (errno == EINTR)
@@ -735,7 +764,7 @@ cleanup(int signo)
{
char *p = clean_ttyname (line);
- if (logout(p) == 0)
+ if (rlogind_logout(p) == 0)
logwtmp(p, "", "");
chmod(line, 0666);
chown(line, 0, 0);
diff --git a/crypto/kerberosIV/appl/bsd/rsh.c b/crypto/kerberosIV/appl/bsd/rsh.c
index 329ebf7..be2dfea 100644
--- a/crypto/kerberosIV/appl/bsd/rsh.c
+++ b/crypto/kerberosIV/appl/bsd/rsh.c
@@ -33,7 +33,7 @@
#include "bsd_locl.h"
-RCSID("$Id: rsh.c,v 1.35 1997/03/30 18:20:22 joda Exp $");
+RCSID("$Id: rsh.c,v 1.41 1999/06/17 18:49:18 assar Exp $");
CREDENTIALS cred;
Key_schedule schedule;
@@ -49,7 +49,7 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: rsh [-ndKx] [-k realm] [-l login] host [command]\n");
+ "usage: rsh [-ndKx] [-k realm] [-p port] [-l login] host [command]\n");
exit(1);
}
@@ -63,11 +63,13 @@ copyargs(char **argv)
cc = 0;
for (ap = argv; *ap; ++ap)
cc += strlen(*ap) + 1;
- if (!(args = malloc(cc)))
+ args = malloc(cc);
+ if (args == NULL)
errx(1, "Out of memory.");
for (p = args, ap = argv; *ap; ++ap) {
strcpy(p, *ap);
- for (p = strcpy(p, *ap); *p; ++p);
+ while(*p)
+ ++p;
if (ap[1])
*p++ = ' ';
}
@@ -92,7 +94,7 @@ talk(int nflag, sigset_t omask, int pid, int rem)
int cc, wc;
char *bp;
fd_set readfrom, ready, rembits;
- char buf[BUFSIZ];
+ char buf[DES_RW_MAXWRITE];
if (pid == 0) {
if (nflag)
@@ -107,7 +109,7 @@ talk(int nflag, sigset_t omask, int pid, int rem)
rewrite: FD_ZERO(&rembits);
FD_SET(rem, &rembits);
- if (select(16, 0, &rembits, 0, 0) < 0) {
+ if (select(rem + 1, 0, &rembits, 0, 0) < 0) {
if (errno != EINTR)
err(1, "select");
goto rewrite;
@@ -142,7 +144,7 @@ talk(int nflag, sigset_t omask, int pid, int rem)
FD_SET(rfd2, &readfrom);
do {
ready = readfrom;
- if (select(16, &ready, 0, 0, 0) < 0) {
+ if (select(max(rem,rfd2)+1, &ready, 0, 0, 0) < 0) {
if (errno != EINTR)
err(1, "select");
continue;
@@ -184,7 +186,7 @@ int
main(int argc, char **argv)
{
struct passwd *pw;
- int sv_port;
+ int sv_port, user_port = 0;
sigset_t omask;
int argoff, ch, dflag, nflag, nfork, one, pid, rem, uid;
char *args, *host, *user, *local_user;
@@ -197,12 +199,12 @@ main(int argc, char **argv)
set_progname(argv[0]);
/* handle "rsh host flags" */
- if (!host && argc > 2 && argv[1][0] != '-') {
+ if (argc > 2 && argv[1][0] != '-') {
host = argv[1];
argoff = 1;
}
-#define OPTIONS "+8KLde:k:l:nwx"
+#define OPTIONS "+8KLde:k:l:np:wx"
while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
switch(ch) {
case 'K':
@@ -221,7 +223,7 @@ main(int argc, char **argv)
break;
case 'k':
dest_realm = dst_realm_buf;
- strncpy(dest_realm, optarg, REALM_SZ);
+ strcpy_truncate(dest_realm, optarg, REALM_SZ);
break;
case 'n':
nflag = nfork = 1;
@@ -229,6 +231,15 @@ main(int argc, char **argv)
case 'x':
doencrypt = 1;
break;
+ case 'p': {
+ char *endptr;
+
+ user_port = strtol (optarg, &endptr, 0);
+ if (user_port == 0 && optarg == endptr)
+ errx (1, "Bad port `%s'", optarg);
+ user_port = htons(user_port);
+ break;
+ }
case '?':
default:
usage();
@@ -247,9 +258,6 @@ main(int argc, char **argv)
err(1, "can't exec %s", _PATH_RLOGIN);
}
- argc -= optind;
- argv += optind;
-
#ifndef __CYGWIN32__
if (!(pw = k_getpwuid(uid = getuid())))
errx(1, "unknown user id.");
@@ -266,12 +274,15 @@ main(int argc, char **argv)
if (doencrypt)
nfork = 0;
- args = copyargs(argv);
+ args = copyargs(argv+optind);
- sv_port=get_shell_port(use_kerberos, doencrypt);
+ if (user_port)
+ sv_port = user_port;
+ else
+ sv_port = get_shell_port(use_kerberos, doencrypt);
-try_connect:
if (use_kerberos) {
+ setuid(getuid());
rem = KSUCCESS;
errno = 0;
if (dest_realm == NULL)
@@ -284,13 +295,27 @@ try_connect:
rem = krcmd(&host, sv_port, user, args, &rfd2,
dest_realm);
if (rem < 0) {
+ int i = 0;
+ char **newargv;
+
if (errno == ECONNREFUSED)
warning("remote host doesn't support Kerberos");
if (errno == ENOENT)
warning("can't provide Kerberos auth data");
- use_kerberos = 0;
- sv_port=get_shell_port(use_kerberos, doencrypt);
- goto try_connect;
+ newargv = malloc((argc + 2) * sizeof(*newargv));
+ if (newargv == NULL)
+ err(1, "malloc");
+ newargv[i] = argv[i];
+ ++i;
+ if (argv[i][0] != '-') {
+ newargv[i] = argv[i];
+ ++i;
+ }
+ newargv[i++] = "-K";
+ for(; i <= argc; ++i)
+ newargv[i] = argv[i - 1];
+ newargv[argc + 1] = NULL;
+ execv(_PATH_RSH, newargv);
}
} else {
if (doencrypt)
diff --git a/crypto/kerberosIV/appl/bsd/rshd.c b/crypto/kerberosIV/appl/bsd/rshd.c
index 75ca1df..1a30793 100644
--- a/crypto/kerberosIV/appl/bsd/rshd.c
+++ b/crypto/kerberosIV/appl/bsd/rshd.c
@@ -42,7 +42,7 @@
#include "bsd_locl.h"
-RCSID("$Id: rshd.c,v 1.51 1997/05/13 09:42:39 bg Exp $");
+RCSID("$Id: rshd.c,v 1.58 1999/06/17 18:49:43 assar Exp $");
extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
extern int __check_rhosts_file;
@@ -197,7 +197,7 @@ doit(struct sockaddr_in *fromp)
int one = 1;
const char *errorhost = "";
char *errorstr;
- char *cp, sig, buf[BUFSIZ];
+ char *cp, sig, buf[DES_RW_MAXWRITE];
char cmdbuf[NCARGS+1], locuser[16], remuser[16];
char remotehost[2 * MaxHostNameLen + 1];
@@ -279,7 +279,7 @@ doit(struct sockaddr_in *fromp)
}
if (vacuous) {
- error("rshd: remote host requires Kerberos authentication\n");
+ error("rshd: Remote host requires Kerberos authentication.\n");
exit(1);
}
@@ -298,7 +298,7 @@ doit(struct sockaddr_in *fromp)
if (getsockname(0, (struct sockaddr *)&local_addr,
&rc) < 0) {
syslog(LOG_ERR, "getsockname: %m");
- error("rlogind: getsockname: %m");
+ error("rshd: getsockname: %m");
exit(1);
}
authopts = KOPT_DO_MUTUAL;
@@ -369,9 +369,9 @@ doit(struct sockaddr_in *fromp)
} else
if (errorstr ||
- pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
+ (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0,
- remuser, locuser) < 0) {
+ remuser, locuser) < 0)) {
if (__rcmd_errstr)
syslog(LOG_INFO|LOG_AUTH,
"%s@%s as %s: permission denied (%s). cmd='%.80s'",
@@ -560,19 +560,18 @@ doit(struct sockaddr_in *fromp)
if (setpcred (pwd->pw_name, NULL) == -1)
syslog(LOG_ERR, "setpcred() failure: %m");
#endif /* HAVE_SETPCRED */
+ if(do_osfc2_magic(pwd->pw_uid))
+ exit(1);
setgid((gid_t)pwd->pw_gid);
initgroups(pwd->pw_name, pwd->pw_gid);
setuid((uid_t)pwd->pw_uid);
- strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
+ strcat_truncate(homedir, pwd->pw_dir, sizeof(homedir));
- /* Need to extend path to find rcp */
- strncat(path, BINDIR, sizeof(path)-1);
- strncat(path, ":", sizeof(path)-1);
- strncat(path, _PATH_DEFPATH, sizeof(path)-1);
- path[sizeof(path)-1] = '\0';
+ /* Need to prepend path with BINDIR (/usr/athena/bin) to find rcp */
+ snprintf(path, sizeof(path), "PATH=%s:%s", BINDIR, _PATH_DEFPATH);
- strncat(shell, pwd->pw_shell, sizeof(shell)-7);
- strncat(username, pwd->pw_name, sizeof(username)-6);
+ strcat_truncate(shell, pwd->pw_shell, sizeof(shell));
+ strcat_truncate(username, pwd->pw_name, sizeof(username));
cp = strrchr(pwd->pw_shell, '/');
if (cp)
cp++;
@@ -594,7 +593,7 @@ doit(struct sockaddr_in *fromp)
if (k_hasafs()) {
if (new_pag)
k_setpag(); /* Put users process in an new pag */
- k_afsklog(0, 0);
+ krb_afslog(0, 0);
}
execle(pwd->pw_shell, cp, "-c", cmdbuf, 0, envinit);
err(1, pwd->pw_shell);
@@ -620,8 +619,8 @@ error(const char *fmt, ...)
len = 1;
} else
len = 0;
- len = vsnprintf (bp, sizeof(buf) - len, fmt, ap);
- write (STDERR_FILENO, buf, len);
+ len += vsnprintf(bp, sizeof(buf) - len, fmt, ap);
+ write(STDERR_FILENO, buf, len);
va_end(ap);
}
diff --git a/crypto/kerberosIV/appl/bsd/su.c b/crypto/kerberosIV/appl/bsd/su.c
index 8c610e1..d0da21d 100644
--- a/crypto/kerberosIV/appl/bsd/su.c
+++ b/crypto/kerberosIV/appl/bsd/su.c
@@ -33,7 +33,7 @@
#include "bsd_locl.h"
-RCSID ("$Id: su.c,v 1.59 1997/05/26 17:45:54 bg Exp $");
+RCSID ("$Id: su.c,v 1.66 1999/03/11 13:57:58 joda Exp $");
#ifdef SYSV_SHADOW
#include "sysv_shadow.h"
@@ -112,7 +112,7 @@ main (int argc, char **argv)
if (errno)
prio = 0;
setpriority (PRIO_PROCESS, 0, -2);
- openlog ("su", LOG_CONS, 0);
+ openlog ("su", LOG_CONS, LOG_AUTH);
/* get current login name and shell */
ruid = getuid ();
@@ -123,13 +123,17 @@ main (int argc, char **argv)
if (pwd == NULL)
errx (1, "who are you?");
username = strdup (pwd->pw_name);
- if (asme)
- if (pwd->pw_shell && *pwd->pw_shell)
- shell = strcpy (shellbuf, pwd->pw_shell);
- else {
+ if (username == NULL)
+ errx (1, "strdup: out of memory");
+ if (asme) {
+ if (pwd->pw_shell && *pwd->pw_shell) {
+ strcpy_truncate (shellbuf, pwd->pw_shell, sizeof(shellbuf));
+ shell = shellbuf;
+ } else {
shell = _PATH_BSHELL;
iscsh = NO;
}
+ }
/* get target login information, default to root */
user = *argv ? *argv : "root";
@@ -229,6 +233,8 @@ main (int argc, char **argv)
char *t = getenv ("TERM");
environ = malloc (10 * sizeof (char *));
+ if (environ == NULL)
+ err (1, "malloc");
environ[0] = NULL;
setenv ("PATH", _PATH_DEFPATH, 1);
if (t)
@@ -250,13 +256,13 @@ main (int argc, char **argv)
*np-- = "-m";
}
if (asthem) {
- avshellbuf[0] = '-';
- strcpy (avshellbuf + 1, avshell);
+ snprintf (avshellbuf, sizeof(avshellbuf),
+ "-%s", avshell);
avshell = avshellbuf;
} else if (iscsh == YES) {
/* csh strips the first character... */
- avshellbuf[0] = '_';
- strcpy (avshellbuf + 1, avshell);
+ snprintf (avshellbuf, sizeof(avshellbuf),
+ "_%s", avshell);
avshell = avshellbuf;
}
*np = avshell;
@@ -272,7 +278,7 @@ main (int argc, char **argv)
if (k_setpag () != 0)
warn ("setpag");
- code = k_afsklog (0, 0);
+ code = krb_afslog (0, 0);
if (code != KSUCCESS && code != KDC_PR_UNKNOWN)
warnx ("afsklog: %s", krb_get_err_text (code));
}
@@ -334,6 +340,15 @@ kerberos (char *username, char *user, int uid)
setenv ("KRBTKFILE", krbtkfile, 1);
krb_set_tkt_string (krbtkfile);
/*
+ * Set real as well as effective ID to 0 for the moment,
+ * to make the kerberos library do the right thing.
+ */
+ if (setuid(0) < 0) {
+ warn("setuid");
+ return (1);
+ }
+
+ /*
* Little trick here -- if we are su'ing to root, we need to get a ticket
* for "xxx.root", where xxx represents the name of the person su'ing.
* Otherwise (non-root case), we need to get a ticket for "yyy.", where
@@ -388,13 +403,12 @@ kerberos (char *username, char *user, int uid)
}
setpriority (PRIO_PROCESS, 0, -2);
- if (k_gethostname (hostname, sizeof (hostname)) == -1) {
+ if (gethostname (hostname, sizeof (hostname)) == -1) {
warn ("gethostname");
dest_tkt ();
return (1);
}
- strncpy (savehost, krb_get_phost (hostname), sizeof (savehost));
- savehost[sizeof (savehost) - 1] = '\0';
+ strcpy_truncate (savehost, krb_get_phost (hostname), sizeof (savehost));
kerno = krb_mk_req (&ticket, "rcmd", savehost, lrealm, 33);
diff --git a/crypto/kerberosIV/appl/bsd/sysv_default.c b/crypto/kerberosIV/appl/bsd/sysv_default.c
index cb36b84..e6b28a7 100644
--- a/crypto/kerberosIV/appl/bsd/sysv_default.c
+++ b/crypto/kerberosIV/appl/bsd/sysv_default.c
@@ -2,7 +2,7 @@
#include "bsd_locl.h"
-RCSID("$Id: sysv_default.c,v 1.9 1997/03/31 01:47:59 assar Exp $");
+RCSID("$Id: sysv_default.c,v 1.11 1999/03/13 21:15:24 assar Exp $");
#include "sysv_default.h"
@@ -21,7 +21,7 @@ char *default_hz = 0;
char *default_path = _PATH_DEFPATH;
char *default_supath = _PATH_DEFSUPATH;
char *default_ulimit = 0;
-char *default_timeout = "60";
+char *default_timeout = "180";
char *default_umask = default_umask_value;
char *default_sleep = "4";
char *default_maxtrys = "5";
@@ -48,7 +48,7 @@ static struct sysv_default {
#define trim(s) { \
char *cp = s + strlen(s); \
- while (cp > s && isspace(cp[-1])) \
+ while (cp > s && isspace((unsigned char)cp[-1])) \
cp--; \
*cp = 0; \
}
diff --git a/crypto/kerberosIV/appl/bsd/sysv_environ.c b/crypto/kerberosIV/appl/bsd/sysv_environ.c
index f5e782d..3df800e 100644
--- a/crypto/kerberosIV/appl/bsd/sysv_environ.c
+++ b/crypto/kerberosIV/appl/bsd/sysv_environ.c
@@ -2,7 +2,7 @@
#include "bsd_locl.h"
-RCSID("$Id: sysv_environ.c,v 1.21 1997/05/14 17:34:15 joda Exp $");
+RCSID("$Id: sysv_environ.c,v 1.23 1997/12/14 23:50:44 assar Exp $");
#ifdef HAVE_ULIMIT_H
#include <ulimit.h>
@@ -86,7 +86,6 @@ void sysv_newenv(int argc, char **argv, struct passwd *pwd,
char *term, int pflag)
{
unsigned umask_val;
- long limit_val;
char buf[BUFSIZ];
int count = 0;
struct censored *cp;
@@ -153,7 +152,7 @@ void sysv_newenv(int argc, char **argv, struct passwd *pwd,
char *sep = "/";
if(KRB4_MAILDIR[strlen(KRB4_MAILDIR) - 1] == '/')
sep = "";
- k_concat(buf, sizeof(buf), KRB4_MAILDIR, sep, pwd->pw_name, NULL);
+ roken_concat(buf, sizeof(buf), KRB4_MAILDIR, sep, pwd->pw_name, NULL);
}
setenv("MAIL", buf, 1);
setenv("LOGNAME", pwd->pw_name, 1);
@@ -182,6 +181,8 @@ void sysv_newenv(int argc, char **argv, struct passwd *pwd,
}
#ifdef HAVE_ULIMIT
if (default_ulimit) {
+ long limit_val;
+
if (sscanf(default_ulimit, "%ld", &limit_val) == 1 && limit_val)
if (ulimit(UL_SETFSIZE, limit_val) < 0)
warn ("ulimit(UL_SETFSIZE, %ld)", limit_val);
diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.c b/crypto/kerberosIV/appl/bsd/sysv_shadow.c
index 6839441..99794bd 100644
--- a/crypto/kerberosIV/appl/bsd/sysv_shadow.c
+++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.c
@@ -2,7 +2,7 @@
#include "bsd_locl.h"
-RCSID("$Id: sysv_shadow.c,v 1.7 1997/03/23 04:56:05 assar Exp $");
+RCSID("$Id: sysv_shadow.c,v 1.8 1997/12/29 19:56:07 bg Exp $");
#ifdef SYSV_SHADOW
@@ -16,7 +16,7 @@ sysv_expire(struct spwd *spwd)
long today;
tzset();
- today = time(0);
+ today = time(0)/(60*60*24); /* In days since Jan. 1, 1970 */
if (spwd->sp_expire > 0) {
if (today > spwd->sp_expire) {
diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.h b/crypto/kerberosIV/appl/bsd/sysv_shadow.h
index 4f07b49..339035b 100644
--- a/crypto/kerberosIV/appl/bsd/sysv_shadow.h
+++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.h
@@ -1,5 +1,5 @@
-/* $Id: sysv_shadow.h,v 1.6 1997/03/23 04:55:51 assar Exp $ */
+/* $Id: sysv_shadow.h,v 1.7 1999/03/13 21:15:43 assar Exp $ */
#include <shadow.h>
-extern sysv_expire(struct spwd *);
+int sysv_expire(struct spwd *);
diff --git a/crypto/kerberosIV/appl/bsd/utmp_login.c b/crypto/kerberosIV/appl/bsd/utmp_login.c
index da3f96a..8c1a2d3 100644
--- a/crypto/kerberosIV/appl/bsd/utmp_login.c
+++ b/crypto/kerberosIV/appl/bsd/utmp_login.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -38,8 +38,9 @@
#include "bsd_locl.h"
-RCSID("$Id: utmp_login.c,v 1.13 1997/05/20 13:46:21 assar Exp $");
+RCSID("$Id: utmp_login.c,v 1.15 1999/03/29 17:57:16 joda Exp $");
+#ifdef HAVE_UTMP_H
void
prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname)
{
@@ -50,11 +51,11 @@ prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname)
strncpy(utmp->ut_line, ttyx, sizeof(utmp->ut_line));
strncpy(utmp->ut_name, username, sizeof(utmp->ut_name));
-# ifdef HAVE_UT_USER
+# ifdef HAVE_STRUCT_UTMP_UT_USER
strncpy(utmp->ut_user, username, sizeof(utmp->ut_user));
# endif
-# ifdef HAVE_UT_ADDR
+# ifdef HAVE_STRUCT_UTMP_UT_ADDR
if (hostname[0]) {
struct hostent *he;
if ((he = gethostbyname(hostname)))
@@ -63,22 +64,23 @@ prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname)
}
# endif
-# ifdef HAVE_UT_HOST
+# ifdef HAVE_STRUCT_UTMP_UT_HOST
strncpy(utmp->ut_host, hostname, sizeof(utmp->ut_host));
# endif
-# ifdef HAVE_UT_TYPE
+# ifdef HAVE_STRUCT_UTMP_UT_TYPE
utmp->ut_type = USER_PROCESS;
# endif
-# ifdef HAVE_UT_PID
+# ifdef HAVE_STRUCT_UTMP_UT_PID
utmp->ut_pid = getpid();
# endif
-# ifdef HAVE_UT_ID
+# ifdef HAVE_STRUCT_UTMP_UT_ID
strncpy(utmp->ut_id, make_id(ttyx), sizeof(utmp->ut_id));
# endif
}
+#endif
#ifdef HAVE_UTMPX_H
void utmp_login(char *tty, char *username, char *hostname) { return; }
diff --git a/crypto/kerberosIV/appl/bsd/utmpx_login.c b/crypto/kerberosIV/appl/bsd/utmpx_login.c
index 005eca5..acc6a154 100644
--- a/crypto/kerberosIV/appl/bsd/utmpx_login.c
+++ b/crypto/kerberosIV/appl/bsd/utmpx_login.c
@@ -2,7 +2,7 @@
#include "bsd_locl.h"
-RCSID("$Id: utmpx_login.c,v 1.20 1997/06/01 03:13:15 assar Exp $");
+RCSID("$Id: utmpx_login.c,v 1.21 1999/03/29 17:57:31 joda Exp $");
/* utmpx_login - update utmp and wtmp after login */
@@ -17,12 +17,12 @@ utmpx_update(struct utmpx *ut, char *line, char *user, char *host)
char *clean_tty = clean_ttyname(line);
strncpy(ut->ut_line, clean_tty, sizeof(ut->ut_line));
-#ifdef HAVE_UT_ID
+#ifdef HAVE_STRUCT_UTMPX_UT_ID
strncpy(ut->ut_id, make_id(clean_tty), sizeof(ut->ut_id));
#endif
strncpy(ut->ut_user, user, sizeof(ut->ut_user));
strncpy(ut->ut_host, host, sizeof(ut->ut_host));
-#ifdef HAVE_UT_SYSLEN
+#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN
ut->ut_syslen = strlen(host) + 1;
if (ut->ut_syslen > sizeof(ut->ut_host))
ut->ut_syslen = sizeof(ut->ut_host);
diff --git a/crypto/kerberosIV/appl/ftp/ChangeLog b/crypto/kerberosIV/appl/ftp/ChangeLog
new file mode 100644
index 0000000..422f4a5
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ChangeLog
@@ -0,0 +1,196 @@
+1999-08-18 Assar Westerlund <assar@sics.se>
+
+ * ftp/cmds.c (getit): be more suspicious when parsing the result
+ of MDTM. Do the comparison of timestamps correctly.
+
+1999-06-15 Assar Westerlund <assar@sics.se>
+
+ * ftp/krb4.c (krb4_auth): type correctness
+
+1999-06-02 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftp/ftp.c (sendrequest): lmode != rmode
+
+1999-05-21 Assar Westerlund <assar@sics.se>
+
+ * ftp/extern.h (sendrequest): update prototype
+
+ * ftp/cmds.c: update calls to sendrequest and recvrequest to send
+ "b" when appropriate
+
+ * ftp/ftp.c (sendrequest): add argument for mode to open file in.
+
+1999-05-08 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y: rename getline -> ftpd_getline
+
+ * ftp/main.c (makeargv): fill in unused slots with NULL
+
+Thu Apr 8 15:06:40 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/ftpd.c: remove definition of KRB_VERIFY_USER (moved to
+ config.h)
+
+Wed Apr 7 16:15:21 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftp/gssapi.c (gss_auth): call gss_display_status to get a sane
+ error message; return AUTH_{CONTINUE,ERROR}, where appropriate
+
+ * ftp/krb4.c: return AUTH_{CONTINUE,ERROR}, where appropriate
+
+ * ftp/security.c (sec_login): if mechanism returns AUTH_CONTINUE,
+ just continue with the next mechanism, this fixes the case of
+ having GSSAPI fail because of non-existant of expired tickets
+
+ * ftp/security.h: add AUTH_{OK,CONTINUE,ERROR}
+
+Thu Apr 1 16:59:04 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/Makefile.am: don't run check-local
+
+ * ftp/Makefile.am: don't run check-local
+
+Mon Mar 22 22:15:18 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (pass): fall-back for KRB_VERIFY_SECURE
+
+ * ftpd/ftpd.c (pass): 1 -> KRB_VERIFY_SECURE
+
+Thu Mar 18 12:07:09 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/Makefile.am: clean ftpcmd.c
+
+ * ftpd/ftpd_locl.h: remove krb5.h (breaks in ftpcmd.y)
+
+ * ftpd/ftpd.c: move include of krb5.h here
+
+ * ftpd/Makefile.am: include Makefile.am.common
+
+ * Makefile.am: include Makefile.am.common
+
+ * ftp/Makefile.am: include Makefile.am.common
+
+ * common/Makefile.am: include Makefile.am.common
+
+Tue Mar 16 22:28:37 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd_locl.h: add krb5.h to get heimdal_version
+
+ * ftpd/ftpd.c: krb_verify_user_multiple -> krb_verify_user
+
+Thu Mar 11 14:54:59 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftp/Makefile.in: WFLAGS
+
+ * ftp/ruserpass.c: add some if-braces
+
+Wed Mar 10 20:02:55 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/ftpd_locl.h: remove ifdef HAVE_FNMATCH
+
+Mon Mar 8 21:29:24 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/ftpd.c: re-add version in greeting message
+
+Mon Mar 1 10:49:38 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/logwtmp.c: HAVE_UT_* -> HAVE_STRUCT_UTMP*_UT_*
+
+Mon Feb 22 19:20:51 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * common/Makefile.in: remove glob
+
+Sat Feb 13 17:19:35 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (match): remove #ifdef HAVE_FNMATCH. We have a
+ fnmatch implementation in roken and therefore always have it.
+
+ * ftp/ftp.c (copy_stream): initialize `werr'
+
+Wed Jan 13 23:52:57 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y: moved all check_login and check_login_no_guest to
+ the end of the rules to ensure we don't generate several
+ (independent) error messages. once again, having a yacc-grammar
+ for FTP with embedded actions doesn't strike me as the most
+ optimal way of doing it.
+
+Tue Dec 1 14:44:29 1998 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/Makefile.am: link with extra libs for aix
+
+Sun Nov 22 10:28:20 1998 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (retrying): support on-the-fly decompression
+
+ * ftpd/Makefile.in (WFLAGS): set
+
+ * ftp/ruserpass.c (guess_domain): new function
+ (ruserpass): use it
+
+ * common/Makefile.in (WFLAGS): set
+
+ * Makefile.in (WFLAGS): set
+
+Sat Nov 21 23:13:03 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/security.c: some more type correctness.
+
+ * ftp/gssapi.c (gss_adat): more braces to shut up warnings
+
+Wed Nov 18 21:47:55 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/main.c (main): new option `-p' for enable passive mode.
+
+Mon Nov 2 01:57:49 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/ftp.c (getreply): remove extra `break'
+
+ * ftp/gssapi.c (gss_auth): fixo typo(copyo?)
+
+ * ftp/security.c (sec_login): fix loop and return value
+
+Tue Sep 1 16:56:42 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/cmds.c (quote1): fix % quoting bug
+
+Fri Aug 14 17:10:06 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/krb4.c: krb_put_int -> KRB_PUT_INT
+
+Tue Jun 30 18:07:15 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/security.c (auth): free `app_data'
+ (sec_end): only destroy if it was initialized
+
+Tue Jun 9 21:01:59 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/krb4.c: pass client address to krb_rd_req
+
+Sat May 16 00:02:07 1998 Assar Westerlund <assar@sics.se>
+
+ * ftpd/Makefile.am: link with DBLIB
+
+Tue May 12 14:15:32 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/gssapi.c: Save client name for userok().
+
+ * ftpd/gss_userok.c: Userok for gssapi.
+
+Fri May 1 07:15:01 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/ftp.c: unifdef -DHAVE_H_ERRNO
+
+Fri Mar 27 00:46:07 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * Make compile w/o krb4.
+
+Thu Mar 26 03:49:12 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/*, ftpd/*: Changes for new framework.
+
+ * ftp/gssapi.c: GSS-API backend for the new security framework.
+
+ * ftp/krb4.c: Updated for new framework.
+
+ * ftp/security.{c,h}: New unified security framework.
diff --git a/crypto/kerberosIV/appl/ftp/Makefile.am b/crypto/kerberosIV/appl/ftp/Makefile.am
new file mode 100644
index 0000000..f8831a3
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/Makefile.am
@@ -0,0 +1,5 @@
+# $Id: Makefile.am,v 1.5 1999/03/20 13:58:14 joda Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+SUBDIRS = common ftp ftpd
diff --git a/crypto/kerberosIV/appl/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/Makefile.in
index 6d0c420..68546ab 100644
--- a/crypto/kerberosIV/appl/ftp/Makefile.in
+++ b/crypto/kerberosIV/appl/ftp/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.9 1997/03/23 13:03:54 assar Exp $
+# $Id: Makefile.in,v 1.12 1999/03/10 19:01:11 joda Exp $
srcdir = @srcdir@
top_srcdir = @top_srcdir@
@@ -11,7 +11,8 @@ SHELL = /bin/sh
CC = @CC@
RANLIB = @RANLIB@
DEFS = @DEFS@
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
INSTALL = @INSTALL@
@@ -39,3 +40,5 @@ distclean:
for i in $(SUBDIRS); \
do (cd $$i && $(MAKE) $(MFLAGS) distclean); done
rm -f Makefile *~
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/ftp/common/Makefile.am b/crypto/kerberosIV/appl/ftp/common/Makefile.am
new file mode 100644
index 0000000..2ab5801
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/Makefile.am
@@ -0,0 +1,12 @@
+# $Id: Makefile.am,v 1.7 1999/03/20 13:58:14 joda Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += $(INCLUDE_krb4)
+
+noinst_LIBRARIES = libcommon.a
+
+libcommon_a_SOURCES = \
+ sockbuf.c \
+ buffer.c \
+ common.h
diff --git a/crypto/kerberosIV/appl/ftp/common/Makefile.in b/crypto/kerberosIV/appl/ftp/common/Makefile.in
index 9ce1aa5..b00bd0a 100644
--- a/crypto/kerberosIV/appl/ftp/common/Makefile.in
+++ b/crypto/kerberosIV/appl/ftp/common/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.17 1997/05/18 20:00:06 assar Exp $
+# $Id: Makefile.in,v 1.23 1999/03/10 19:01:11 joda Exp $
SHELL = /bin/sh
@@ -10,16 +10,17 @@ CC = @CC@
AR = ar
RANLIB = @RANLIB@
DEFS = @DEFS@
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
INSTALL = @INSTALL@
prefix = @prefix@
-SOURCES = base64.c glob.c sockbuf.c buffer.c
+SOURCES = sockbuf.c buffer.c
OBJECTS = $(libcommon_OBJS)
-libcommon_OBJS = base64.o glob.o sockbuf.o buffer.o
+libcommon_OBJS = sockbuf.o buffer.o
LIBNAME = $(LIBPREFIX)common
LIBEXT = a
@@ -29,7 +30,7 @@ LIB = $(LIBNAME).$(LIBEXT)
all: $(LIB)
.c.o:
- $(CC) -c $(CFLAGS) -I$(srcdir) -I../../../include $(DEFS) $<
+ $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $<
$(LIB): $(libcommon_OBJS)
rm -f $@
@@ -50,3 +51,5 @@ distclean:
rm -f Makefile
$(OBJECTS): ../../../include/config.h
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/ftp/common/buffer.c b/crypto/kerberosIV/appl/ftp/common/buffer.c
index 5b7829a..97e2815 100644
--- a/crypto/kerberosIV/appl/ftp/common/buffer.c
+++ b/crypto/kerberosIV/appl/ftp/common/buffer.c
@@ -38,9 +38,10 @@
#include "common.h"
#include <stdio.h>
+#include <err.h>
#include "roken.h"
-RCSID("$Id: buffer.c,v 1.1 1997/05/18 19:59:24 assar Exp $");
+RCSID("$Id: buffer.c,v 1.2 1997/12/14 23:51:45 assar Exp $");
/*
* Allocate a buffer enough to handle st->st_blksize, if
diff --git a/crypto/kerberosIV/appl/ftp/ftp/Makefile.am b/crypto/kerberosIV/appl/ftp/ftp/Makefile.am
new file mode 100644
index 0000000..081465a
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.am
@@ -0,0 +1,44 @@
+# $Id: Makefile.am,v 1.12 1999/04/09 18:22:08 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += -I$(srcdir)/../common $(INCLUDE_readline) $(INCLUDE_krb4)
+
+bin_PROGRAMS = ftp
+
+CHECK_LOCAL =
+
+if KRB4
+krb4_sources = krb4.c kauth.c
+endif
+if KRB5
+krb5_sources = gssapi.c
+endif
+
+ftp_SOURCES = \
+ cmds.c \
+ cmdtab.c \
+ extern.h \
+ ftp.c \
+ ftp_locl.h \
+ ftp_var.h \
+ main.c \
+ pathnames.h \
+ ruserpass.c \
+ domacro.c \
+ globals.c \
+ security.c \
+ security.h \
+ $(krb4_sources) \
+ $(krb5_sources)
+
+EXTRA_ftp_SOURCES = krb4.c kauth.c gssapi.c
+
+LDADD = \
+ ../common/libcommon.a \
+ $(LIB_gssapi) \
+ $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_roken) \
+ $(LIB_readline)
diff --git a/crypto/kerberosIV/appl/ftp/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in
index 62bde3b..637d553 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/Makefile.in
+++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in
@@ -1,5 +1,5 @@
#
-# $Id: Makefile.in,v 1.24 1997/03/23 13:03:55 assar Exp $
+# $Id: Makefile.in,v 1.32 1999/03/11 13:58:09 joda Exp $
#
SHELL = /bin/sh
@@ -8,13 +8,14 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
-topdir = ../../..
+top_builddir = ../../..
CC = @CC@
RANLIB = @RANLIB@
DEFS = @DEFS@
-CFLAGS = @CFLAGS@
-CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I$(topdir) -I$(top_srcdir) -I$(topdir)/include -I$(top_srcdir)/include -I$(srcdir)/../common @INCLUDE_readline@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir)/../common @INCLUDE_readline@
LD_FLAGS = @LD_FLAGS@
LIB_tgetent = @LIB_tgetent@
LIBS = @LIBS@ @LIB_readline@
@@ -30,17 +31,35 @@ libdir = @libdir@
transform=@program_transform_name@
EXECSUFFIX=@EXECSUFFIX@
-INCTOP = $(topdir)/include
+INCTOP = $(top_builddir)/include
-LIBTOP = $(topdir)/lib
+LIBTOP = $(top_builddir)/lib
PROGS = ftp$(EXECSUFFIX)
-ftp_OBJS = cmds.o cmdtab.o ftp.o krb4.o main.o ruserpass.o domacro.o \
- globals.o kauth.o
-
-ftp_SOURCES = cmds.c cmdtab.c ftp.c krb4.c main.c ruserpass.c \
- domacro.c globals.c kauth.c
+ftp_SOURCES = \
+ cmds.c \
+ cmdtab.c \
+ domacro.c \
+ ftp.c \
+ globals.c \
+ kauth.c \
+ krb4.c \
+ main.c \
+ ruserpass.c \
+ security.c
+
+ftp_OBJS = \
+ cmds.o \
+ cmdtab.o \
+ domacro.o \
+ ftp.o \
+ globals.o \
+ kauth.o \
+ krb4.o \
+ main.o \
+ ruserpass.o \
+ security.o
OBJECTS = $(ftp_OBJS)
SOURCES = $(ftp_SOURCES)
@@ -48,29 +67,36 @@ SOURCES = $(ftp_SOURCES)
all: $(PROGS)
.c.o:
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(DEFS) $<
+ $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $<
install: all
- $(MKINSTALLDIRS) $(bindir)
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
for x in $(PROGS); do \
- $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
done
uninstall:
for x in $(PROGS); do \
- rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
done
-ftp$(EXECSUFFIX): $(ftp_OBJS) # ../common/libcommon.a
+ftp$(EXECSUFFIX): $(ftp_OBJS)
$(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(ftp_OBJS) -L../common -lcommon -L$(LIBTOP)/krb -lkrb -L$(LIBTOP)/des -ldes -L$(LIBTOP)/roken -lroken $(LIBS) -L$(LIBTOP)/roken -lroken
-TAGS: $(SOURCES)
+TAGS: $(SOURCES)
etags $(SOURCES)
-clean cleandir:
- rm -f *~ *.o core ftp \#*
+clean:
+ rm -f *~ *.o core ftp$(EXECSUFFIX) \#*
+
+mostlyclean: clean
-distclean:
+distclean: clean
rm -f Makefile
+realclean: distclean
+ rm -f TAGS
+
$(OBJECTS): ../../../include/config.h
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/ftp/ftp/cmds.c b/crypto/kerberosIV/appl/ftp/ftp/cmds.c
index 5e1980b..1571fc8 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/cmds.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/cmds.c
@@ -36,7 +36,7 @@
*/
#include "ftp_locl.h"
-RCSID("$Id: cmds.c,v 1.23 1997/06/01 22:52:37 assar Exp $");
+RCSID("$Id: cmds.c,v 1.34.2.1 1999/08/18 18:19:44 assar Exp $");
typedef void (*sighand)(int);
@@ -119,12 +119,17 @@ setpeer(int argc, char **argv)
/*
* Set up defaults for FTP.
*/
- strcpy(typename, "ascii"), type = TYPE_A;
+ strcpy_truncate(typename, "ascii", sizeof(typename));
+ type = TYPE_A;
curtype = TYPE_A;
- strcpy(formname, "non-print"), form = FORM_N;
- strcpy(modename, "stream"), mode = MODE_S;
- strcpy(structname, "file"), stru = STRU_F;
- strcpy(bytename, "8"), bytesize = 8;
+ strcpy_truncate(formname, "non-print", sizeof(formname));
+ form = FORM_N;
+ strcpy_truncate(modename, "stream", sizeof(modename));
+ mode = MODE_S;
+ strcpy_truncate(structname, "file", sizeof(structname));
+ stru = STRU_F;
+ strcpy_truncate(bytename, "8", sizeof(bytename));
+ bytesize = 8;
if (autologin)
login(argv[1]);
@@ -165,7 +170,7 @@ setpeer(int argc, char **argv)
* for text files unless changed by the user.
*/
type = 0;
- strcpy(typename, "binary");
+ strcpy_truncate(typename, "binary", sizeof(typename));
if (overbose)
printf("Using %s mode to transfer files.\n",
typename);
@@ -238,7 +243,7 @@ settype(int argc, char **argv)
else
comret = command("TYPE %s", p->t_mode);
if (comret == COMPLETE) {
- strcpy(typename, p->t_name);
+ strcpy_truncate(typename, p->t_name, sizeof(typename));
curtype = type = p->t_type;
}
}
@@ -398,7 +403,8 @@ usage:
argv[2] = domap(argv[2]);
}
sendrequest(cmd, argv[1], argv[2],
- argv[1] != oldargv1 || argv[2] != oldargv2);
+ curtype == TYPE_I ? "rb" : "r",
+ argv[1] != oldargv1 || argv[2] != oldargv2);
}
/* ARGSUSED */
@@ -428,133 +434,150 @@ mabort(int signo)
void
mput(int argc, char **argv)
{
- int i;
- RETSIGTYPE (*oldintr)();
- int ointer;
- char *tp;
+ int i;
+ RETSIGTYPE (*oldintr)();
+ int ointer;
+ char *tp;
- if (argc < 2 && !another(&argc, &argv, "local-files")) {
- printf("usage: %s local-files\n", argv[0]);
- code = -1;
- return;
- }
- mname = argv[0];
- mflag = 1;
- oldintr = signal(SIGINT, mabort);
- setjmp(jabort);
- if (proxy) {
- char *cp, *tp2, tmpbuf[MaxPathLen];
+ if (argc < 2 && !another(&argc, &argv, "local-files")) {
+ printf("usage: %s local-files\n", argv[0]);
+ code = -1;
+ return;
+ }
+ mname = argv[0];
+ mflag = 1;
+ oldintr = signal(SIGINT, mabort);
+ setjmp(jabort);
+ if (proxy) {
+ char *cp, *tp2, tmpbuf[MaxPathLen];
- while ((cp = remglob(argv,0)) != NULL) {
- if (*cp == 0) {
- mflag = 0;
- continue;
- }
- if (mflag && confirm(argv[0], cp)) {
- tp = cp;
- if (mcase) {
- while (*tp && !islower(*tp)) {
- tp++;
- }
- if (!*tp) {
- tp = cp;
- tp2 = tmpbuf;
- while ((*tp2 = *tp) != '\0') {
- if (isupper(*tp2)) {
- *tp2 = 'a' + *tp2 - 'A';
- }
- tp++;
- tp2++;
- }
- }
- tp = tmpbuf;
- }
- if (ntflag) {
- tp = dotrans(tp);
- }
- if (mapflag) {
- tp = domap(tp);
- }
- sendrequest((sunique) ? "STOU" : "STOR",
- cp, tp, cp != tp || !interactive);
- if (!mflag && fromatty) {
- ointer = interactive;
- interactive = 1;
- if (confirm("Continue with","mput")) {
- mflag++;
- }
- interactive = ointer;
- }
- }
- }
- signal(SIGINT, oldintr);
+ while ((cp = remglob(argv,0)) != NULL) {
+ if (*cp == 0) {
mflag = 0;
- return;
- }
- for (i = 1; i < argc; i++) {
- char **cpp;
- glob_t gl;
- int flags;
-
- if (!doglob) {
- if (mflag && confirm(argv[0], argv[i])) {
- tp = (ntflag) ? dotrans(argv[i]) : argv[i];
- tp = (mapflag) ? domap(tp) : tp;
- sendrequest((sunique) ? "STOU" : "STOR",
- argv[i], tp, tp != argv[i] || !interactive);
- if (!mflag && fromatty) {
- ointer = interactive;
- interactive = 1;
- if (confirm("Continue with","mput")) {
- mflag++;
- }
- interactive = ointer;
- }
+ continue;
+ }
+ if (mflag && confirm(argv[0], cp)) {
+ tp = cp;
+ if (mcase) {
+ while (*tp && !islower(*tp)) {
+ tp++;
+ }
+ if (!*tp) {
+ tp = cp;
+ tp2 = tmpbuf;
+ while ((*tp2 = *tp) != '\0') {
+ if (isupper(*tp2)) {
+ *tp2 = 'a' + *tp2 - 'A';
+ }
+ tp++;
+ tp2++;
}
- continue;
+ }
+ tp = tmpbuf;
}
-
- memset(&gl, 0, sizeof(gl));
- flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
- if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
- warnx("%s: not found", argv[i]);
- globfree(&gl);
- continue;
+ if (ntflag) {
+ tp = dotrans(tp);
}
- for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
- if (mflag && confirm(argv[0], *cpp)) {
- tp = (ntflag) ? dotrans(*cpp) : *cpp;
- tp = (mapflag) ? domap(tp) : tp;
- sendrequest((sunique) ? "STOU" : "STOR",
- *cpp, tp, *cpp != tp || !interactive);
- if (!mflag && fromatty) {
- ointer = interactive;
- interactive = 1;
- if (confirm("Continue with","mput")) {
- mflag++;
- }
- interactive = ointer;
- }
- }
+ if (mapflag) {
+ tp = domap(tp);
}
- globfree(&gl);
+ sendrequest((sunique) ? "STOU" : "STOR",
+ cp, tp,
+ curtype == TYPE_I ? "rb" : "r",
+ cp != tp || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
}
signal(SIGINT, oldintr);
mflag = 0;
+ return;
+ }
+ for (i = 1; i < argc; i++) {
+ char **cpp;
+ glob_t gl;
+ int flags;
+
+ if (!doglob) {
+ if (mflag && confirm(argv[0], argv[i])) {
+ tp = (ntflag) ? dotrans(argv[i]) : argv[i];
+ tp = (mapflag) ? domap(tp) : tp;
+ sendrequest((sunique) ? "STOU" : "STOR",
+ argv[i],
+ curtype == TYPE_I ? "rb" : "r",
+ tp, tp != argv[i] || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ continue;
+ }
+
+ memset(&gl, 0, sizeof(gl));
+ flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+ if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
+ warnx("%s: not found", argv[i]);
+ globfree(&gl);
+ continue;
+ }
+ for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
+ if (mflag && confirm(argv[0], *cpp)) {
+ tp = (ntflag) ? dotrans(*cpp) : *cpp;
+ tp = (mapflag) ? domap(tp) : tp;
+ sendrequest((sunique) ? "STOU" : "STOR",
+ *cpp, tp,
+ curtype == TYPE_I ? "rb" : "r",
+ *cpp != tp || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ globfree(&gl);
+ }
+ signal(SIGINT, oldintr);
+ mflag = 0;
}
void
reget(int argc, char **argv)
{
-
- getit(argc, argv, 1, "r+w");
+ getit(argc, argv, 1, curtype == TYPE_I ? "r+wb" : "r+w");
}
void
get(int argc, char **argv)
{
+ char *mode;
- getit(argc, argv, 0, restart_point ? "r+w" : "w" );
+ if (restart_point)
+ if (curtype == TYPE_I)
+ mode = "r+wb";
+ else
+ mode = "r+w";
+ else
+ if (curtype == TYPE_I)
+ mode = "wb";
+ else
+ mode = "w";
+
+ getit(argc, argv, 0, mode);
}
/*
@@ -564,17 +587,17 @@ int
getit(int argc, char **argv, int restartit, char *mode)
{
int loc = 0;
+ int local_given = 1;
char *oldargv1, *oldargv2;
if (argc == 2) {
argc++;
+ local_given = 0;
argv[2] = argv[1];
loc++;
}
- if (argc < 2 && !another(&argc, &argv, "remote-file"))
- goto usage;
- if (argc < 3 && !another(&argc, &argv, "local-file")) {
-usage:
+ if ((argc < 2 && !another(&argc, &argv, "remote-file")) ||
+ (argc < 3 && !another(&argc, &argv, "local-file"))) {
printf("usage: %s remote-file [ local-file ]\n", argv[0]);
code = -1;
return (0);
@@ -619,50 +642,60 @@ usage:
return (0);
}
restart_point = stbuf.st_size;
- } else {
- if (ret == 0) {
- int overbose;
-
- overbose = verbose;
- if (debug == 0)
- verbose = -1;
- if (command("MDTM %s", argv[1]) == COMPLETE) {
- int yy, mo, day, hour, min, sec;
- struct tm *tm;
- verbose = overbose;
- sscanf(reply_string,
- "%*s %04d%02d%02d%02d%02d%02d",
- &yy, &mo, &day, &hour, &min, &sec);
- tm = gmtime(&stbuf.st_mtime);
- tm->tm_mon++;
- if (tm->tm_year > yy%100)
- return (1);
- if ((tm->tm_year == yy%100 &&
- tm->tm_mon > mo) ||
- (tm->tm_mon == mo &&
- tm->tm_mday > day) ||
- (tm->tm_mday == day &&
- tm->tm_hour > hour) ||
- (tm->tm_hour == hour &&
- tm->tm_min > min) ||
- (tm->tm_min == min &&
- tm->tm_sec > sec))
- return (1);
- } else {
- printf("%s\n", reply_string);
- verbose = overbose;
- return (0);
- }
+ } else if (ret == 0) {
+ int overbose;
+ int cmdret;
+ int yy, mo, day, hour, min, sec;
+ struct tm *tm;
+
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+ cmdret = command("MDTM %s", argv[1]);
+ verbose = overbose;
+ if (cmdret != COMPLETE) {
+ printf("%s\n", reply_string);
+ return (0);
+ }
+ if (sscanf(reply_string,
+ "%*s %04d%02d%02d%02d%02d%02d",
+ &yy, &mo, &day, &hour, &min, &sec)
+ != 6) {
+ printf ("bad MDTM result\n");
+ return (0);
}
+
+ tm = gmtime(&stbuf.st_mtime);
+ tm->tm_mon++;
+ tm->tm_year += 1900;
+
+ if ((tm->tm_year > yy) ||
+ (tm->tm_year == yy &&
+ tm->tm_mon > mo) ||
+ (tm->tm_mon == mo &&
+ tm->tm_mday > day) ||
+ (tm->tm_mday == day &&
+ tm->tm_hour > hour) ||
+ (tm->tm_hour == hour &&
+ tm->tm_min > min) ||
+ (tm->tm_min == min &&
+ tm->tm_sec > sec))
+ return (1);
}
}
recvrequest("RETR", argv[2], argv[1], mode,
- argv[1] != oldargv1 || argv[2] != oldargv2);
+ argv[1] != oldargv1 || argv[2] != oldargv2, local_given);
restart_point = 0;
return (0);
}
+static int
+suspicious_filename(const char *fn)
+{
+ return strstr(fn, "../") != NULL || *fn == '/';
+}
+
/*
* Get multiple files.
*/
@@ -687,6 +720,8 @@ mget(int argc, char **argv)
mflag = 0;
continue;
}
+ if (mflag && suspicious_filename(cp))
+ printf("*** Suspicious filename: %s\n", cp);
if (mflag && confirm(argv[0], cp)) {
tp = cp;
if (mcase) {
@@ -701,8 +736,9 @@ mget(int argc, char **argv)
if (mapflag) {
tp = domap(tp);
}
- recvrequest("RETR", tp, cp, "w",
- tp != cp || !interactive);
+ recvrequest("RETR", tp, cp,
+ curtype == TYPE_I ? "wb" : "w",
+ tp != cp || !interactive, 0);
if (!mflag && fromatty) {
ointer = interactive;
interactive = 1;
@@ -720,61 +756,71 @@ mget(int argc, char **argv)
char *
remglob(char **argv, int doswitch)
{
- char temp[16];
- static char buf[MaxPathLen];
- static FILE *ftemp = NULL;
- static char **args;
- int oldverbose, oldhash;
- char *cp, *mode;
+ char temp[16];
+ static char buf[MaxPathLen];
+ static FILE *ftemp = NULL;
+ static char **args;
+ int oldverbose, oldhash;
+ char *cp, *mode;
- if (!mflag) {
- if (!doglob) {
- args = NULL;
- }
- else {
- if (ftemp) {
- fclose(ftemp);
- ftemp = NULL;
- }
- }
- return (NULL);
- }
+ if (!mflag) {
if (!doglob) {
- if (args == NULL)
- args = argv;
- if ((cp = *++args) == NULL)
- args = NULL;
- return (cp);
+ args = NULL;
}
- if (ftemp == NULL) {
- strcpy(temp, _PATH_TMP_XXX);
- mktemp(temp);
- oldverbose = verbose, verbose = 0;
- oldhash = hash, hash = 0;
- if (doswitch) {
- pswitch(!proxy);
- }
- for (mode = "w"; *++argv != NULL; mode = "a")
- recvrequest ("NLST", temp, *argv, mode, 0);
- if (doswitch) {
- pswitch(!proxy);
- }
- verbose = oldverbose; hash = oldhash;
- ftemp = fopen(temp, "r");
- unlink(temp);
- if (ftemp == NULL) {
- printf("can't find list of remote files, oops\n");
- return (NULL);
- }
- }
- if (fgets(buf, sizeof (buf), ftemp) == NULL) {
+ else {
+ if (ftemp) {
fclose(ftemp);
ftemp = NULL;
- return (NULL);
+ }
}
+ return (NULL);
+ }
+ if (!doglob) {
+ if (args == NULL)
+ args = argv;
+ if ((cp = *++args) == NULL)
+ args = NULL;
+ return (cp);
+ }
+ if (ftemp == NULL) {
+ int fd;
+ strcpy_truncate(temp, _PATH_TMP_XXX, sizeof(temp));
+ fd = mkstemp(temp);
+ if(fd < 0){
+ warn("unable to create temporary file %s", temp);
+ return NULL;
+ }
+ close(fd);
+ oldverbose = verbose, verbose = 0;
+ oldhash = hash, hash = 0;
+ if (doswitch) {
+ pswitch(!proxy);
+ }
+ for (mode = "w"; *++argv != NULL; mode = "a")
+ recvrequest ("NLST", temp, *argv, mode, 0, 0);
+ if (doswitch) {
+ pswitch(!proxy);
+ }
+ verbose = oldverbose; hash = oldhash;
+ ftemp = fopen(temp, "r");
+ unlink(temp);
+ if (ftemp == NULL) {
+ printf("can't find list of remote files, oops\n");
+ return (NULL);
+ }
+ }
+ while(fgets(buf, sizeof (buf), ftemp)) {
if ((cp = strchr(buf, '\n')) != NULL)
- *cp = '\0';
- return (buf);
+ *cp = '\0';
+ if(!interactive && suspicious_filename(buf)){
+ printf("Ignoring remote globbed file `%s'\n", buf);
+ continue;
+ }
+ return buf;
+ }
+ fclose(ftemp);
+ ftemp = NULL;
+ return (NULL);
}
char *
@@ -1036,38 +1082,38 @@ delete(int argc, char **argv)
void
mdelete(int argc, char **argv)
{
- sighand oldintr;
- int ointer;
- char *cp;
+ sighand oldintr;
+ int ointer;
+ char *cp;
- if (argc < 2 && !another(&argc, &argv, "remote-files")) {
- printf("usage: %s remote-files\n", argv[0]);
- code = -1;
- return;
- }
- mname = argv[0];
- mflag = 1;
- oldintr = signal(SIGINT, mabort);
- setjmp(jabort);
- while ((cp = remglob(argv,0)) != NULL) {
- if (*cp == '\0') {
- mflag = 0;
- continue;
- }
- if (mflag && confirm(argv[0], cp)) {
- command("DELE %s", cp);
- if (!mflag && fromatty) {
- ointer = interactive;
- interactive = 1;
- if (confirm("Continue with", "mdelete")) {
- mflag++;
- }
- interactive = ointer;
- }
+ if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+ printf("usage: %s remote-files\n", argv[0]);
+ code = -1;
+ return;
+ }
+ mname = argv[0];
+ mflag = 1;
+ oldintr = signal(SIGINT, mabort);
+ setjmp(jabort);
+ while ((cp = remglob(argv,0)) != NULL) {
+ if (*cp == '\0') {
+ mflag = 0;
+ continue;
+ }
+ if (mflag && confirm(argv[0], cp)) {
+ command("DELE %s", cp);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", "mdelete")) {
+ mflag++;
}
+ interactive = ointer;
+ }
}
- signal(SIGINT, oldintr);
- mflag = 0;
+ }
+ signal(SIGINT, oldintr);
+ mflag = 0;
}
/*
@@ -1113,11 +1159,12 @@ ls(int argc, char **argv)
return;
}
if (strcmp(argv[2], "-") && *argv[2] != '|')
- if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) {
- code = -1;
- return;
- }
- recvrequest(cmd, argv[2], argv[1], "w", 0);
+ if (!globulize(&argv[2]) || !confirm("output to local-file:",
+ argv[2])) {
+ code = -1;
+ return;
+ }
+ recvrequest(cmd, argv[2], argv[1], "w", 0, 1);
}
/*
@@ -1154,7 +1201,7 @@ usage:
setjmp(jabort);
for (i = 1; mflag && i < argc-1; ++i) {
*mode = (i == 1) ? 'w' : 'a';
- recvrequest(cmd, dest, argv[i], mode, 0);
+ recvrequest(cmd, dest, argv[i], mode, 0, 1);
if (!mflag && fromatty) {
ointer = interactive;
interactive = 1;
@@ -1193,8 +1240,8 @@ shell(int argc, char **argv)
namep = strrchr(shell,'/');
if (namep == NULL)
namep = shell;
- strcpy(shellnam,"-");
- strcat(shellnam, ++namep);
+ snprintf (shellnam, sizeof(shellnam),
+ "-%s", ++namep);
if (strcmp(namep, "sh") != 0)
shellnam[0] = '+';
if (debug) {
@@ -1369,22 +1416,19 @@ site(int argc, char **argv)
void
quote1(char *initial, int argc, char **argv)
{
- int i, len;
- char buf[BUFSIZ]; /* must be >= sizeof(line) */
+ int i;
+ char buf[BUFSIZ]; /* must be >= sizeof(line) */
- strcpy(buf, initial);
- if (argc > 1) {
- len = strlen(buf);
- len += strlen(strcpy(&buf[len], argv[1]));
- for (i = 2; i < argc; i++) {
- buf[len++] = ' ';
- len += strlen(strcpy(&buf[len], argv[i]));
- }
- }
- if (command(buf) == PRELIM) {
- while (getreply(0) == PRELIM)
- continue;
- }
+ strcpy_truncate(buf, initial, sizeof(buf));
+ for(i = 1; i < argc; i++) {
+ if(i > 1)
+ strcat_truncate(buf, " ", sizeof(buf));
+ strcat_truncate(buf, argv[i], sizeof(buf));
+ }
+ if (command("%s", buf) == PRELIM) {
+ while (getreply(0) == PRELIM)
+ continue;
+ }
}
void
@@ -1467,7 +1511,7 @@ disconnect(int argc, char **argv)
}
cout = NULL;
connected = 0;
- krb4_quit();
+ sec_end();
data = -1;
if (!proxy) {
macnum = 0;
@@ -1485,7 +1529,7 @@ confirm(char *cmd, char *file)
fflush(stdout);
if (fgets(line, sizeof line, stdin) == NULL)
return (0);
- return (*line != 'n' && *line != 'N');
+ return (*line == 'y' || *line == 'Y');
}
void
@@ -1531,12 +1575,11 @@ account(int argc, char **argv)
if (argc > 1) {
++argv;
--argc;
- strncpy(acct,*argv,49);
- acct[49] = '\0';
+ strcpy_truncate (acct, *argv, sizeof(acct));
while (argc > 1) {
--argc;
++argv;
- strncat(acct,*argv, 49-strlen(acct));
+ strcat_truncate(acct, *argv, sizeof(acct));
}
}
else {
@@ -1648,14 +1691,12 @@ setntrans(int argc, char **argv)
}
ntflag++;
code = ntflag;
- strncpy(ntin, argv[1], 16);
- ntin[16] = '\0';
+ strcpy_truncate (ntin, argv[1], 17);
if (argc == 2) {
ntout[0] = '\0';
return;
}
- strncpy(ntout, argv[2], 16);
- ntout[16] = '\0';
+ strcpy_truncate (ntout, argv[2], 17);
}
char *
@@ -1712,10 +1753,10 @@ setnmap(int argc, char **argv)
cp = strchr(altarg, ' ');
}
*cp = '\0';
- strncpy(mapin, altarg, MaxPathLen - 1);
+ strcpy_truncate(mapin, altarg, MaxPathLen);
while (*++cp == ' ')
continue;
- strncpy(mapout, cp, MaxPathLen - 1);
+ strcpy_truncate(mapout, cp, MaxPathLen);
}
char *
@@ -1967,7 +2008,9 @@ macdef(int argc, char **argv)
if (interactive) {
printf("Enter macro line by line, terminating it with a null line\n");
}
- strncpy(macros[macnum].mac_name, argv[1], 8);
+ strcpy_truncate(macros[macnum].mac_name,
+ argv[1],
+ sizeof(macros[macnum].mac_name));
if (macnum == 0) {
macros[macnum].mac_start = macbuf;
}
@@ -2067,7 +2110,7 @@ void
newer(int argc, char **argv)
{
- if (getit(argc, argv, -1, "w"))
+ if (getit(argc, argv, -1, curtype == TYPE_I ? "wb" : "w"))
printf("Local file \"%s\" is newer than remote file \"%s\"\n",
argv[2], argv[1]);
}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c
index 9567e3c..5dc96ef 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c
@@ -105,9 +105,13 @@ char userhelp[] = "send new user information";
char verbosehelp[] = "toggle verbose mode";
char prothelp[] = "set protection level";
+#ifdef KRB4
char kauthhelp[] = "get remote tokens";
char klisthelp[] = "show remote tickets";
-char aklog[] = "obtain remote AFS tokens";
+char kdestroyhelp[] = "destroy remote tickets";
+char krbtkfilehelp[] = "set filename of remote tickets";
+char afsloghelp[] = "obtain remote AFS tokens";
+#endif
struct cmd cmdtab[] = {
{ "!", shellhelp, 0, 0, 0, shell },
@@ -184,8 +188,13 @@ struct cmd cmdtab[] = {
{ "?", helphelp, 0, 0, 1, help },
{ "prot", prothelp, 0, 1, 0, sec_prot },
+#ifdef KRB4
{ "kauth", kauthhelp, 0, 1, 0, kauth },
{ "klist", klisthelp, 0, 1, 0, klist },
+ { "kdestroy", kdestroyhelp, 0, 1, 0, kdestroy },
+ { "krbtkfile", krbtkfilehelp, 0, 1, 0, krbtkfile },
+ { "afslog", afsloghelp, 0, 1, 0, afslog },
+#endif
{ 0 },
};
diff --git a/crypto/kerberosIV/appl/ftp/ftp/domacro.c b/crypto/kerberosIV/appl/ftp/ftp/domacro.c
index f5a89b9..432e3e5 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/domacro.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/domacro.c
@@ -32,7 +32,7 @@
*/
#include "ftp_locl.h"
-RCSID("$Id: domacro.c,v 1.5 1996/11/17 20:23:10 assar Exp $");
+RCSID("$Id: domacro.c,v 1.6 1998/06/09 19:24:21 joda Exp $");
void
domacro(int argc, char **argv)
@@ -56,7 +56,7 @@ domacro(int argc, char **argv)
code = -1;
return;
}
- strcpy(line2, line);
+ strcpy_truncate(line2, line, sizeof(line2));
TOP:
cp1 = macros[i].mac_start;
while (cp1 != macros[i].mac_end) {
diff --git a/crypto/kerberosIV/appl/ftp/ftp/extern.h b/crypto/kerberosIV/appl/ftp/ftp/extern.h
index b830999..5efe918 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/extern.h
+++ b/crypto/kerberosIV/appl/ftp/ftp/extern.h
@@ -33,7 +33,7 @@
* @(#)extern.h 8.3 (Berkeley) 10/9/94
*/
-/* $Id: extern.h,v 1.13 1997/04/20 05:46:48 assar Exp $ */
+/* $Id: extern.h,v 1.16 1999/05/21 09:21:51 assar Exp $ */
#include <setjmp.h>
#include <stdlib.h>
@@ -107,7 +107,7 @@ void pwd (int, char **);
void quit (int, char **);
void quote (int, char **);
void quote1 (char *, int, char **);
-void recvrequest (char *, char *, char *, char *, int);
+void recvrequest (char *, char *, char *, char *, int, int);
void reget (int, char **);
char *remglob (char **, int);
void removedir (int, char **);
@@ -117,7 +117,7 @@ void restart (int, char **);
void rmthelp (int, char **);
void rmtstatus (int, char **);
int ruserpass (char *, char **, char **, char **);
-void sendrequest (char *, char *, char *, int);
+void sendrequest (char *, char *, char *, char *, int);
void setascii (int, char **);
void setbell (int, char **);
void setbinary (int, char **);
@@ -165,3 +165,9 @@ extern int NCMDS;
extern char username[32];
extern char myhostname[];
extern char *mydomain;
+
+void afslog (int, char **);
+void kauth (int, char **);
+void kdestroy (int, char **);
+void klist (int, char **);
+void krbtkfile (int, char **);
diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp.c b/crypto/kerberosIV/appl/ftp/ftp/ftp.c
index cfabda6..3021a19 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/ftp.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/ftp.c
@@ -32,42 +32,38 @@
*/
#include "ftp_locl.h"
-RCSID("$Id: ftp.c,v 1.44 1997/05/18 20:00:31 assar Exp $");
+RCSID ("$Id: ftp.c,v 1.55 1999/06/02 20:12:22 joda Exp $");
-struct sockaddr_in hisctladdr;
-struct sockaddr_in data_addr;
-int data = -1;
-int abrtflag = 0;
-jmp_buf ptabort;
-int ptabflg;
-int ptflag = 0;
-struct sockaddr_in myctladdr;
-off_t restart_point = 0;
+struct sockaddr_in hisctladdr;
+struct sockaddr_in data_addr;
+int data = -1;
+int abrtflag = 0;
+jmp_buf ptabort;
+int ptabflg;
+int ptflag = 0;
+struct sockaddr_in myctladdr;
+off_t restart_point = 0;
-FILE *cin, *cout;
+FILE *cin, *cout;
-typedef void (*sighand)(int);
+typedef void (*sighand) (int);
char *
-hookup(char *host, int port)
+hookup (char *host, int port)
{
struct hostent *hp = 0;
- int s, len, tos;
- static char hostnamebuf[80];
+ int s, len;
+ static char hostnamebuf[MaxHostNameLen];
- memset(&hisctladdr, 0, sizeof (hisctladdr));
- if(inet_aton(host, &hisctladdr.sin_addr)){
+ memset (&hisctladdr, 0, sizeof (hisctladdr));
+ if (inet_aton (host, &hisctladdr.sin_addr)) {
hisctladdr.sin_family = AF_INET;
- strncpy(hostnamebuf, host, sizeof(hostnamebuf));
+ strcpy_truncate (hostnamebuf, host, sizeof (hostnamebuf));
} else {
- hp = gethostbyname(host);
+ hp = gethostbyname (host);
if (hp == NULL) {
-#ifdef HAVE_H_ERRNO
warnx("%s: %s", host, hstrerror(h_errno));
-#else
- warnx("%s: %s", host, "unknown error");
-#endif
code = -1;
return NULL;
}
@@ -75,73 +71,75 @@ hookup(char *host, int port)
memmove(&hisctladdr.sin_addr,
hp->h_addr_list[0],
sizeof(hisctladdr.sin_addr));
- strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
- hostnamebuf[sizeof(hostnamebuf) - 1] = '\0';
+ strcpy_truncate (hostnamebuf, hp->h_name, sizeof (hostnamebuf));
}
hostname = hostnamebuf;
- s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
+ s = socket (hisctladdr.sin_family, SOCK_STREAM, 0);
if (s < 0) {
- warn("socket");
+ warn ("socket");
code = -1;
return (0);
}
hisctladdr.sin_port = port;
- while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
+ while (connect (s, (struct sockaddr *) & hisctladdr, sizeof (hisctladdr)) < 0) {
if (hp && hp->h_addr_list[1]) {
int oerrno = errno;
char *ia;
- ia = inet_ntoa(hisctladdr.sin_addr);
+ ia = inet_ntoa (hisctladdr.sin_addr);
errno = oerrno;
- warn("connect to address %s", ia);
+ warn ("connect to address %s", ia);
hp->h_addr_list++;
- memmove(&hisctladdr.sin_addr,
- hp->h_addr_list[0],
- sizeof(hisctladdr.sin_addr));
- fprintf(stdout, "Trying %s...\n",
- inet_ntoa(hisctladdr.sin_addr));
- close(s);
- s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
+ memmove (&hisctladdr.sin_addr,
+ hp->h_addr_list[0],
+ sizeof (hisctladdr.sin_addr));
+ fprintf (stdout, "Trying %s...\n",
+ inet_ntoa (hisctladdr.sin_addr));
+ close (s);
+ s = socket (hisctladdr.sin_family, SOCK_STREAM, 0);
if (s < 0) {
- warn("socket");
+ warn ("socket");
code = -1;
return (0);
}
continue;
}
- warn("connect");
+ warn ("connect");
code = -1;
goto bad;
}
len = sizeof (myctladdr);
- if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
- warn("getsockname");
+ if (getsockname (s, (struct sockaddr *) & myctladdr, &len) < 0) {
+ warn ("getsockname");
code = -1;
goto bad;
}
#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
- tos = IPTOS_LOWDELAY;
+ {
+ int tos = IPTOS_LOWDELAY;
+
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
+ }
#endif
- cin = fdopen(s, "r");
- cout = fdopen(s, "w");
+ cin = fdopen (s, "r");
+ cout = fdopen (s, "w");
if (cin == NULL || cout == NULL) {
- warnx("fdopen failed.");
+ warnx ("fdopen failed.");
if (cin)
- fclose(cin);
+ fclose (cin);
if (cout)
- fclose(cout);
+ fclose (cout);
code = -1;
goto bad;
}
if (verbose)
- printf("Connected to %s.\n", hostname);
- if (getreply(0) > 2) { /* read startup message from server */
+ printf ("Connected to %s.\n", hostname);
+ if (getreply (0) > 2) { /* read startup message from server */
if (cin)
- fclose(cin);
+ fclose (cin);
if (cout)
- fclose(cout);
+ fclose (cout);
code = -1;
goto bad;
}
@@ -149,21 +147,21 @@ hookup(char *host, int port)
{
int on = 1;
- if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
+ if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on))
< 0 && debug) {
- warn("setsockopt");
+ warn ("setsockopt");
}
}
-#endif /* SO_OOBINLINE */
+#endif /* SO_OOBINLINE */
return (hostname);
bad:
- close(s);
+ close (s);
return NULL;
}
int
-login(char *host)
+login (char *host)
{
char tmp[80];
char defaultpass[128];
@@ -172,94 +170,97 @@ login(char *host)
char *myname = NULL;
struct passwd *pw = k_getpwuid(getuid());
+
if (pw != NULL)
myname = pw->pw_name;
user = pass = acct = 0;
- if(do_klogin(host))
+ if(sec_login(host))
printf("\n*** Using plaintext user and password ***\n\n");
else{
- printf("Kerberos authentication successful.\n\n");
+ printf("Authentication successful.\n\n");
}
- if (ruserpass(host, &user, &pass, &acct) < 0) {
+ if (ruserpass (host, &user, &pass, &acct) < 0) {
code = -1;
return (0);
}
while (user == NULL) {
if (myname)
- printf("Name (%s:%s): ", host, myname);
+ printf ("Name (%s:%s): ", host, myname);
else
- printf("Name (%s): ", host);
- fgets(tmp, sizeof(tmp) - 1, stdin);
- tmp[strlen(tmp) - 1] = '\0';
+ printf ("Name (%s): ", host);
+ fgets (tmp, sizeof (tmp) - 1, stdin);
+ tmp[strlen (tmp) - 1] = '\0';
if (*tmp == '\0')
user = myname;
else
user = tmp;
}
- strcpy(username, user);
+ strcpy_truncate(username, user, sizeof(username));
n = command("USER %s", user);
if (n == CONTINUE) {
- if(auth_complete)
+ if(sec_complete)
pass = myname;
else if (pass == NULL) {
char prompt[128];
if(myname &&
(!strcmp(user, "ftp") || !strcmp(user, "anonymous"))){
- snprintf(defaultpass, sizeof(defaultpass), "%s@%s", myname, mydomain);
- snprintf(prompt, sizeof(prompt), "Password (%s): ", defaultpass);
+ snprintf(defaultpass, sizeof(defaultpass),
+ "%s@%s", myname, mydomain);
+ snprintf(prompt, sizeof(prompt),
+ "Password (%s): ", defaultpass);
}else{
- strcpy(defaultpass, "");
+ *defaultpass = '\0';
snprintf(prompt, sizeof(prompt), "Password: ");
}
pass = defaultpass;
- des_read_pw_string (tmp, sizeof(tmp), prompt, 0);
- if(tmp[0])
+ des_read_pw_string (tmp, sizeof (tmp), prompt, 0);
+ if (tmp[0])
pass = tmp;
}
- n = command("PASS %s", pass);
+ n = command ("PASS %s", pass);
}
if (n == CONTINUE) {
aflag++;
acct = tmp;
- des_read_pw_string(acct, 128, "Account:", 0);
- n = command("ACCT %s", acct);
+ des_read_pw_string (acct, 128, "Account:", 0);
+ n = command ("ACCT %s", acct);
}
if (n != COMPLETE) {
- warnx("Login failed.");
+ warnx ("Login failed.");
return (0);
}
if (!aflag && acct != NULL)
- command("ACCT %s", acct);
+ command ("ACCT %s", acct);
if (proxy)
return (1);
for (n = 0; n < macnum; ++n) {
if (!strcmp("init", macros[n].mac_name)) {
- strcpy(line, "$init");
+ strcpy_truncate (line, "$init", sizeof (line));
makeargv();
domacro(margc, margv);
break;
}
}
- sec_set_protection_level();
+ sec_set_protection_level ();
return (1);
}
void
-cmdabort(int sig)
+cmdabort (int sig)
{
- printf("\n");
- fflush(stdout);
+ printf ("\n");
+ fflush (stdout);
abrtflag++;
if (ptflag)
- longjmp(ptabort,1);
+ longjmp (ptabort, 1);
}
int
-command(char *fmt, ...)
+command (char *fmt,...)
{
va_list ap;
int r;
@@ -267,7 +268,7 @@ command(char *fmt, ...)
abrtflag = 0;
if (cout == NULL) {
- warn("No control connection for command");
+ warn ("No control connection for command");
code = -1;
return (0);
}
@@ -281,29 +282,26 @@ command(char *fmt, ...)
vfprintf(stdout, fmt, ap);
va_start(ap, fmt);
}
- if(auth_complete)
- krb4_write_enc(cout, fmt, ap);
- else
- vfprintf(cout, fmt, ap);
+ sec_vfprintf(cout, fmt, ap);
va_end(ap);
if(debug){
printf("\n");
fflush(stdout);
}
- fprintf(cout, "\r\n");
- fflush(cout);
+ fprintf (cout, "\r\n");
+ fflush (cout);
cpend = 1;
- r = getreply(!strcmp(fmt, "QUIT"));
+ r = getreply (!strcmp (fmt, "QUIT"));
if (abrtflag && oldintr != SIG_IGN)
- (*oldintr)(SIGINT);
- signal(SIGINT, oldintr);
+ (*oldintr) (SIGINT);
+ signal (SIGINT, oldintr);
return (r);
}
-char reply_string[BUFSIZ]; /* last line of previous reply */
+char reply_string[BUFSIZ]; /* last line of previous reply */
int
-getreply(int expecteof)
+getreply (int expecteof)
{
char *p;
char *lead_string;
@@ -311,80 +309,82 @@ getreply(int expecteof)
struct sigaction sa, osa;
char buf[1024];
- sigemptyset(&sa.sa_mask);
+ sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = cmdabort;
- sigaction(SIGINT, &sa, &osa);
-
+ sigaction (SIGINT, &sa, &osa);
+
p = buf;
- while(1){
- c = getc(cin);
- switch(c){
+ while (1) {
+ c = getc (cin);
+ switch (c) {
case EOF:
if (expecteof) {
- sigaction(SIGINT,&osa, NULL);
+ sigaction (SIGINT, &osa, NULL);
code = 221;
return 0;
}
- lostpeer(0);
+ lostpeer (0);
if (verbose) {
- printf("421 Service not available, "
- "remote server has closed connection\n");
- fflush(stdout);
+ printf ("421 Service not available, "
+ "remote server has closed connection\n");
+ fflush (stdout);
}
code = 421;
return (4);
- break;
case IAC:
- c = getc(cin);
- if(c == WILL || c == WONT)
- fprintf(cout, "%c%c%c", IAC, DONT, getc(cin));
- if(c == DO || c == DONT)
- fprintf(cout, "%c%c%c", IAC, WONT, getc(cin));
+ c = getc (cin);
+ if (c == WILL || c == WONT)
+ fprintf (cout, "%c%c%c", IAC, DONT, getc (cin));
+ if (c == DO || c == DONT)
+ fprintf (cout, "%c%c%c", IAC, WONT, getc (cin));
continue;
case '\n':
- *p++ = 0;
+ *p++ = '\0';
if(isdigit(buf[0])){
sscanf(buf, "%d", &code);
if(code == 631){
- krb4_read_mic(buf);
+ sec_read_msg(buf, prot_safe);
sscanf(buf, "%d", &code);
lead_string = "S:";
} else if(code == 632){
- krb4_read_enc(buf);
+ sec_read_msg(buf, prot_private);
sscanf(buf, "%d", &code);
lead_string = "P:";
}else if(code == 633){
- printf("Received confidential reply!\n");
- }else if(auth_complete)
+ sec_read_msg(buf, prot_confidential);
+ sscanf(buf, "%d", &code);
+ lead_string = "C:";
+ }else if(sec_complete)
lead_string = "!!";
else
lead_string = "";
- if(verbose > 0 || (verbose > -1 && code > 499))
- fprintf(stdout, "%s%s\n", lead_string, buf);
- if(buf[3] == ' '){
- strcpy(reply_string, buf);
+ if (verbose > 0 || (verbose > -1 && code > 499))
+ fprintf (stdout, "%s%s\n", lead_string, buf);
+ if (buf[3] == ' ') {
+ strcpy (reply_string, buf);
if (code >= 200)
cpend = 0;
- sigaction(SIGINT, &osa, NULL);
+ sigaction (SIGINT, &osa, NULL);
if (code == 421)
- lostpeer(0);
+ lostpeer (0);
#if 1
- if (abrtflag &&
- osa.sa_handler != cmdabort &&
+ if (abrtflag &&
+ osa.sa_handler != cmdabort &&
osa.sa_handler != SIG_IGN)
- osa.sa_handler(SIGINT);
+ osa.sa_handler (SIGINT);
#endif
- if(code == 227){
+ if (code == 227) {
char *p, *q;
+
pasv[0] = 0;
- p = strchr(reply_string, '(');
- if(p){
+ p = strchr (reply_string, '(');
+ if (p) {
p++;
q = strchr(p, ')');
if(q){
- strncpy(pasv, p, q - p);
+ memcpy (pasv, p, q - p);
pasv[q - p] = 0;
}
}
@@ -393,7 +393,7 @@ getreply(int expecteof)
}
}else{
if(verbose > 0 || (verbose > -1 && code > 499)){
- if(auth_complete)
+ if(sec_complete)
fprintf(stdout, "!!");
fprintf(stdout, "%s\n", buf);
}
@@ -404,13 +404,13 @@ getreply(int expecteof)
*p++ = c;
}
}
-
+
}
#if 0
int
-getreply(int expecteof)
+getreply (int expecteof)
{
int c, n;
int dig;
@@ -419,24 +419,24 @@ getreply(int expecteof)
int pflag = 0;
char *cp, *pt = pasv;
- oldintr = signal(SIGINT, cmdabort);
+ oldintr = signal (SIGINT, cmdabort);
for (;;) {
dig = n = code = 0;
cp = reply_string;
- while ((c = getc(cin)) != '\n') {
- if (c == IAC) { /* handle telnet commands */
- switch (c = getc(cin)) {
+ while ((c = getc (cin)) != '\n') {
+ if (c == IAC) { /* handle telnet commands */
+ switch (c = getc (cin)) {
case WILL:
case WONT:
- c = getc(cin);
- fprintf(cout, "%c%c%c", IAC, DONT, c);
- fflush(cout);
+ c = getc (cin);
+ fprintf (cout, "%c%c%c", IAC, DONT, c);
+ fflush (cout);
break;
case DO:
case DONT:
- c = getc(cin);
- fprintf(cout, "%c%c%c", IAC, WONT, c);
- fflush(cout);
+ c = getc (cin);
+ fprintf (cout, "%c%c%c", IAC, WONT, c);
+ fflush (cout);
break;
default:
break;
@@ -446,14 +446,14 @@ getreply(int expecteof)
dig++;
if (c == EOF) {
if (expecteof) {
- signal(SIGINT,oldintr);
+ signal (SIGINT, oldintr);
code = 221;
return (0);
}
- lostpeer(0);
+ lostpeer (0);
if (verbose) {
- printf("421 Service not available, remote server has closed connection\n");
- fflush(stdout);
+ printf ("421 Service not available, remote server has closed connection\n");
+ fflush (stdout);
}
code = 421;
return (4);
@@ -462,14 +462,14 @@ getreply(int expecteof)
(verbose > -1 && n == '5' && dig > 4))) {
if (proxflag &&
(dig == 1 || dig == 5 && verbose == 0))
- printf("%s:",hostname);
- putchar(c);
+ printf ("%s:", hostname);
+ putchar (c);
}
- if (dig < 4 && isdigit(c))
+ if (dig < 4 && isdigit (c))
code = code * 10 + (c - '0');
if (!pflag && code == 227)
pflag = 1;
- if (dig > 4 && pflag == 1 && isdigit(c))
+ if (dig > 4 && pflag == 1 && isdigit (c))
pflag = 2;
if (pflag == 2) {
if (c != '\r' && c != ')')
@@ -486,11 +486,11 @@ getreply(int expecteof)
}
if (n == 0)
n = c;
- if (cp < &reply_string[sizeof(reply_string) - 1])
+ if (cp < &reply_string[sizeof (reply_string) - 1])
*cp++ = c;
}
if (verbose > 0 || verbose > -1 && n == '5') {
- putchar(c);
+ putchar (c);
fflush (stdout);
}
if (continuation && code != originalcode) {
@@ -499,112 +499,114 @@ getreply(int expecteof)
continue;
}
*cp = '\0';
- if(auth_complete){
+ if(sec_complete){
if(code == 631)
- krb4_read_mic(reply_string);
- else
- krb4_read_enc(reply_string);
+ sec_read_msg(reply_string, prot_safe);
+ else if(code == 632)
+ sec_read_msg(reply_string, prot_private);
+ else if(code == 633)
+ sec_read_msg(reply_string, prot_confidential);
n = code / 100 + '0';
}
-
if (n != '1')
cpend = 0;
- signal(SIGINT,oldintr);
+ signal (SIGINT, oldintr);
if (code == 421 || originalcode == 421)
- lostpeer(0);
+ lostpeer (0);
if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
- (*oldintr)(SIGINT);
+ (*oldintr) (SIGINT);
return (n - '0');
}
}
+
#endif
int
-empty(fd_set *mask, int sec)
+empty (fd_set * mask, int sec)
{
struct timeval t;
t.tv_sec = (long) sec;
t.tv_usec = 0;
- return (select(32, mask, NULL, NULL, &t));
+ return (select (32, mask, NULL, NULL, &t));
}
-jmp_buf sendabort;
+jmp_buf sendabort;
static RETSIGTYPE
-abortsend(int sig)
+abortsend (int sig)
{
mflag = 0;
abrtflag = 0;
- printf("\nsend aborted\nwaiting for remote to finish abort\n");
- fflush(stdout);
- longjmp(sendabort, 1);
+ printf ("\nsend aborted\nwaiting for remote to finish abort\n");
+ fflush (stdout);
+ longjmp (sendabort, 1);
}
#define HASHBYTES 1024
static int
-copy_stream(FILE *from, FILE *to)
+copy_stream (FILE * from, FILE * to)
{
static size_t bufsize;
static char *buf;
int n;
int bytes = 0;
- int werr;
+ int werr = 0;
int hashbytes = HASHBYTES;
struct stat st;
-
-#ifdef HAVE_MMAP
+
+#if defined(HAVE_MMAP) && !defined(NO_MMAP)
void *chunk;
#ifndef MAP_FAILED
#define MAP_FAILED (-1)
#endif
- if(fstat(fileno(from), &st) == 0 && S_ISREG(st.st_mode)){
- chunk = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(from), 0);
- if (chunk != (void *)MAP_FAILED) {
+ if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) {
+ chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0);
+ if (chunk != (void *) MAP_FAILED) {
int res;
- res = sec_write(fileno(to), chunk, st.st_size);
- if (munmap(chunk, st.st_size) < 0)
+ res = sec_write (fileno (to), chunk, st.st_size);
+ if (munmap (chunk, st.st_size) < 0)
warn ("munmap");
- sec_fflush(to);
+ sec_fflush (to);
return res;
}
}
#endif
buf = alloc_buffer (buf, &bufsize,
- fstat(fileno(from), &st) >= 0 ? &st : NULL);
+ fstat (fileno (from), &st) >= 0 ? &st : NULL);
if (buf == NULL)
return -1;
- while((n = read(fileno(from), buf, bufsize)) > 0){
- werr = sec_write(fileno(to), buf, n);
- if(werr < 0)
+ while ((n = read (fileno (from), buf, bufsize)) > 0) {
+ werr = sec_write (fileno (to), buf, n);
+ if (werr < 0)
break;
bytes += werr;
- while(hash && bytes > hashbytes){
- putchar('#');
+ while (hash && bytes > hashbytes) {
+ putchar ('#');
hashbytes += HASHBYTES;
}
}
- sec_fflush(to);
- if(n < 0)
- warn("local");
+ sec_fflush (to);
+ if (n < 0)
+ warn ("local");
- if(werr < 0){
- if(errno != EPIPE)
- warn("netout");
+ if (werr < 0) {
+ if (errno != EPIPE)
+ warn ("netout");
bytes = -1;
}
return bytes;
}
void
-sendrequest(char *cmd, char *local, char *remote, int printnames)
+sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
{
struct stat st;
struct timeval start, stop;
@@ -613,124 +615,123 @@ sendrequest(char *cmd, char *local, char *remote, int printnames)
int (*closefunc) (FILE *);
RETSIGTYPE (*oldintr)(), (*oldintp)();
long bytes = 0, hashbytes = HASHBYTES;
- char *lmode;
+ char *rmode = "w";
if (verbose && printnames) {
- if (local && *local != '-')
- printf("local: %s ", local);
+ if (local && strcmp (local, "-") != 0)
+ printf ("local: %s ", local);
if (remote)
- printf("remote: %s\n", remote);
+ printf ("remote: %s\n", remote);
}
if (proxy) {
- proxtrans(cmd, local, remote);
+ proxtrans (cmd, local, remote);
return;
}
if (curtype != type)
- changetype(type, 0);
+ changetype (type, 0);
closefunc = NULL;
oldintr = NULL;
oldintp = NULL;
- lmode = "w";
- if (setjmp(sendabort)) {
+
+ if (setjmp (sendabort)) {
while (cpend) {
- getreply(0);
+ getreply (0);
}
if (data >= 0) {
- close(data);
+ close (data);
data = -1;
}
if (oldintr)
- signal(SIGINT,oldintr);
+ signal (SIGINT, oldintr);
if (oldintp)
- signal(SIGPIPE,oldintp);
+ signal (SIGPIPE, oldintp);
code = -1;
return;
}
- oldintr = signal(SIGINT, abortsend);
- if (strcmp(local, "-") == 0)
+ oldintr = signal (SIGINT, abortsend);
+ if (strcmp (local, "-") == 0)
fin = stdin;
else if (*local == '|') {
- oldintp = signal(SIGPIPE,SIG_IGN);
- fin = popen(local + 1, "r");
+ oldintp = signal (SIGPIPE, SIG_IGN);
+ fin = popen (local + 1, lmode);
if (fin == NULL) {
- warn("%s", local + 1);
- signal(SIGINT, oldintr);
- signal(SIGPIPE, oldintp);
+ warn ("%s", local + 1);
+ signal (SIGINT, oldintr);
+ signal (SIGPIPE, oldintp);
code = -1;
return;
}
closefunc = pclose;
} else {
- fin = fopen(local, "r");
+ fin = fopen (local, lmode);
if (fin == NULL) {
- warn("local: %s", local);
- signal(SIGINT, oldintr);
+ warn ("local: %s", local);
+ signal (SIGINT, oldintr);
code = -1;
return;
}
closefunc = fclose;
- if (fstat(fileno(fin), &st) < 0 ||
- (st.st_mode&S_IFMT) != S_IFREG) {
- fprintf(stdout, "%s: not a plain file.\n", local);
- signal(SIGINT, oldintr);
- fclose(fin);
+ if (fstat (fileno (fin), &st) < 0 ||
+ (st.st_mode & S_IFMT) != S_IFREG) {
+ fprintf (stdout, "%s: not a plain file.\n", local);
+ signal (SIGINT, oldintr);
+ fclose (fin);
code = -1;
return;
}
}
- if (initconn()) {
- signal(SIGINT, oldintr);
+ if (initconn ()) {
+ signal (SIGINT, oldintr);
if (oldintp)
- signal(SIGPIPE, oldintp);
+ signal (SIGPIPE, oldintp);
code = -1;
if (closefunc != NULL)
- (*closefunc)(fin);
+ (*closefunc) (fin);
return;
}
- if (setjmp(sendabort))
+ if (setjmp (sendabort))
goto abort;
if (restart_point &&
- (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
+ (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) {
int rc;
switch (curtype) {
case TYPE_A:
- rc = fseek(fin, (long) restart_point, SEEK_SET);
+ rc = fseek (fin, (long) restart_point, SEEK_SET);
break;
case TYPE_I:
case TYPE_L:
- rc = lseek(fileno(fin), restart_point, SEEK_SET);
+ rc = lseek (fileno (fin), restart_point, SEEK_SET);
break;
}
if (rc < 0) {
- warn("local: %s", local);
+ warn ("local: %s", local);
restart_point = 0;
if (closefunc != NULL)
- (*closefunc)(fin);
+ (*closefunc) (fin);
return;
}
- if (command("REST %ld", (long) restart_point)
+ if (command ("REST %ld", (long) restart_point)
!= CONTINUE) {
restart_point = 0;
if (closefunc != NULL)
- (*closefunc)(fin);
+ (*closefunc) (fin);
return;
}
restart_point = 0;
- lmode = "r+w";
+ rmode = "r+w";
}
if (remote) {
- if (command("%s %s", cmd, remote) != PRELIM) {
- signal(SIGINT, oldintr);
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
if (oldintp)
- signal(SIGPIPE, oldintp);
+ signal (SIGPIPE, oldintp);
if (closefunc != NULL)
- (*closefunc)(fin);
+ (*closefunc) (fin);
return;
}
- } else
- if (command("%s", cmd) != PRELIM) {
+ } else if (command ("%s", cmd) != PRELIM) {
signal(SIGINT, oldintr);
if (oldintp)
signal(SIGPIPE, oldintp);
@@ -738,101 +739,102 @@ sendrequest(char *cmd, char *local, char *remote, int printnames)
(*closefunc)(fin);
return;
}
- dout = dataconn(lmode);
+ dout = dataconn(rmode);
if (dout == NULL)
goto abort;
- set_buffer_size(fileno(dout), 0);
- gettimeofday(&start, (struct timezone *)0);
- oldintp = signal(SIGPIPE, SIG_IGN);
+ set_buffer_size (fileno (dout), 0);
+ gettimeofday (&start, (struct timezone *) 0);
+ oldintp = signal (SIGPIPE, SIG_IGN);
switch (curtype) {
case TYPE_I:
case TYPE_L:
errno = d = c = 0;
- bytes = copy_stream(fin, dout);
+ bytes = copy_stream (fin, dout);
break;
case TYPE_A:
- while ((c = getc(fin)) != EOF) {
+ while ((c = getc (fin)) != EOF) {
if (c == '\n') {
while (hash && (bytes >= hashbytes)) {
- putchar('#');
- fflush(stdout);
+ putchar ('#');
+ fflush (stdout);
hashbytes += HASHBYTES;
}
- if (ferror(dout))
+ if (ferror (dout))
break;
- sec_putc('\r', dout);
+ sec_putc ('\r', dout);
bytes++;
}
- sec_putc(c, dout);
+ sec_putc (c, dout);
bytes++;
}
- sec_fflush(dout);
+ sec_fflush (dout);
if (hash) {
if (bytes < hashbytes)
- putchar('#');
- putchar('\n');
- fflush(stdout);
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
}
- if (ferror(fin))
- warn("local: %s", local);
- if (ferror(dout)) {
+ if (ferror (fin))
+ warn ("local: %s", local);
+ if (ferror (dout)) {
if (errno != EPIPE)
- warn("netout");
+ warn ("netout");
bytes = -1;
}
break;
}
if (closefunc != NULL)
- (*closefunc)(fin);
- fclose(dout);
- gettimeofday(&stop, (struct timezone *)0);
- getreply(0);
- signal(SIGINT, oldintr);
+ (*closefunc) (fin);
+ fclose (dout);
+ gettimeofday (&stop, (struct timezone *) 0);
+ getreply (0);
+ signal (SIGINT, oldintr);
if (oldintp)
- signal(SIGPIPE, oldintp);
+ signal (SIGPIPE, oldintp);
if (bytes > 0)
- ptransfer("sent", bytes, &start, &stop);
+ ptransfer ("sent", bytes, &start, &stop);
return;
abort:
- signal(SIGINT, oldintr);
+ signal (SIGINT, oldintr);
if (oldintp)
- signal(SIGPIPE, oldintp);
+ signal (SIGPIPE, oldintp);
if (!cpend) {
code = -1;
return;
}
if (data >= 0) {
- close(data);
+ close (data);
data = -1;
}
if (dout)
- fclose(dout);
- getreply(0);
+ fclose (dout);
+ getreply (0);
code = -1;
if (closefunc != NULL && fin != NULL)
- (*closefunc)(fin);
- gettimeofday(&stop, (struct timezone *)0);
+ (*closefunc) (fin);
+ gettimeofday (&stop, (struct timezone *) 0);
if (bytes > 0)
- ptransfer("sent", bytes, &start, &stop);
+ ptransfer ("sent", bytes, &start, &stop);
}
-jmp_buf recvabort;
+jmp_buf recvabort;
void
-abortrecv(int sig)
+abortrecv (int sig)
{
mflag = 0;
abrtflag = 0;
- printf("\nreceive aborted\nwaiting for remote to finish abort\n");
- fflush(stdout);
- longjmp(recvabort, 1);
+ printf ("\nreceive aborted\nwaiting for remote to finish abort\n");
+ fflush (stdout);
+ longjmp (recvabort, 1);
}
void
-recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames)
+recvrequest (char *cmd, char *local, char *remote,
+ char *lmode, int printnames, int local_given)
{
FILE *fout, *din = 0;
int (*closefunc) (FILE *);
@@ -844,72 +846,71 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames)
struct timeval start, stop;
struct stat st;
- is_retr = strcmp(cmd, "RETR") == 0;
+ is_retr = strcmp (cmd, "RETR") == 0;
if (is_retr && verbose && printnames) {
- if (local && *local != '-')
- printf("local: %s ", local);
+ if (local && strcmp (local, "-") != 0)
+ printf ("local: %s ", local);
if (remote)
- printf("remote: %s\n", remote);
+ printf ("remote: %s\n", remote);
}
if (proxy && is_retr) {
- proxtrans(cmd, local, remote);
+ proxtrans (cmd, local, remote);
return;
}
closefunc = NULL;
oldintr = NULL;
oldintp = NULL;
tcrflag = !crflag && is_retr;
- if (setjmp(recvabort)) {
+ if (setjmp (recvabort)) {
while (cpend) {
- getreply(0);
+ getreply (0);
}
if (data >= 0) {
- close(data);
+ close (data);
data = -1;
}
if (oldintr)
- signal(SIGINT, oldintr);
+ signal (SIGINT, oldintr);
code = -1;
return;
}
- oldintr = signal(SIGINT, abortrecv);
- if (strcmp(local, "-") && *local != '|') {
- if (access(local, 2) < 0) {
- char *dir = strrchr(local, '/');
+ oldintr = signal (SIGINT, abortrecv);
+ if (!local_given || (strcmp (local, "-") && *local != '|')) {
+ if (access (local, 2) < 0) {
+ char *dir = strrchr (local, '/');
if (errno != ENOENT && errno != EACCES) {
- warn("local: %s", local);
- signal(SIGINT, oldintr);
+ warn ("local: %s", local);
+ signal (SIGINT, oldintr);
code = -1;
return;
}
if (dir != NULL)
*dir = 0;
- d = access(dir ? local : ".", 2);
+ d = access (dir ? local : ".", 2);
if (dir != NULL)
*dir = '/';
if (d < 0) {
- warn("local: %s", local);
- signal(SIGINT, oldintr);
+ warn ("local: %s", local);
+ signal (SIGINT, oldintr);
code = -1;
return;
}
if (!runique && errno == EACCES &&
- chmod(local, 0600) < 0) {
- warn("local: %s", local);
- signal(SIGINT, oldintr);
- signal(SIGINT, oldintr);
+ chmod (local, 0600) < 0) {
+ warn ("local: %s", local);
+ signal (SIGINT, oldintr);
+ signal (SIGINT, oldintr);
code = -1;
return;
}
if (runique && errno == EACCES &&
- (local = gunique(local)) == NULL) {
- signal(SIGINT, oldintr);
+ (local = gunique (local)) == NULL) {
+ signal (SIGINT, oldintr);
code = -1;
return;
}
- }
- else if (runique && (local = gunique(local)) == NULL) {
+ } else if (runique && (local = gunique (local)) == NULL) {
signal(SIGINT, oldintr);
code = -1;
return;
@@ -917,98 +918,98 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames)
}
if (!is_retr) {
if (curtype != TYPE_A)
- changetype(TYPE_A, 0);
+ changetype (TYPE_A, 0);
} else if (curtype != type)
- changetype(type, 0);
- if (initconn()) {
- signal(SIGINT, oldintr);
+ changetype (type, 0);
+ if (initconn ()) {
+ signal (SIGINT, oldintr);
code = -1;
return;
}
- if (setjmp(recvabort))
+ if (setjmp (recvabort))
goto abort;
if (is_retr && restart_point &&
- command("REST %ld", (long) restart_point) != CONTINUE)
+ command ("REST %ld", (long) restart_point) != CONTINUE)
return;
if (remote) {
- if (command("%s %s", cmd, remote) != PRELIM) {
- signal(SIGINT, oldintr);
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
return;
}
} else {
- if (command("%s", cmd) != PRELIM) {
- signal(SIGINT, oldintr);
+ if (command ("%s", cmd) != PRELIM) {
+ signal (SIGINT, oldintr);
return;
}
}
- din = dataconn("r");
+ din = dataconn ("r");
if (din == NULL)
goto abort;
- set_buffer_size(fileno(din), 1);
- if (strcmp(local, "-") == 0)
+ set_buffer_size (fileno (din), 1);
+ if (local_given && strcmp (local, "-") == 0)
fout = stdout;
- else if (*local == '|') {
- oldintp = signal(SIGPIPE, SIG_IGN);
- fout = popen(local + 1, "w");
+ else if (local_given && *local == '|') {
+ oldintp = signal (SIGPIPE, SIG_IGN);
+ fout = popen (local + 1, "w");
if (fout == NULL) {
- warn("%s", local+1);
+ warn ("%s", local + 1);
goto abort;
}
closefunc = pclose;
} else {
- fout = fopen(local, lmode);
+ fout = fopen (local, lmode);
if (fout == NULL) {
- warn("local: %s", local);
+ warn ("local: %s", local);
goto abort;
}
closefunc = fclose;
}
buf = alloc_buffer (buf, &bufsize,
- fstat(fileno(fout), &st) >= 0 ? &st : NULL);
+ fstat (fileno (fout), &st) >= 0 ? &st : NULL);
if (buf == NULL)
goto abort;
- gettimeofday(&start, (struct timezone *)0);
+ gettimeofday (&start, (struct timezone *) 0);
switch (curtype) {
case TYPE_I:
case TYPE_L:
if (restart_point &&
- lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
- warn("local: %s", local);
+ lseek (fileno (fout), restart_point, SEEK_SET) < 0) {
+ warn ("local: %s", local);
if (closefunc != NULL)
- (*closefunc)(fout);
+ (*closefunc) (fout);
return;
}
errno = d = 0;
- while ((c = sec_read(fileno(din), buf, bufsize)) > 0) {
- if ((d = write(fileno(fout), buf, c)) != c)
+ while ((c = sec_read (fileno (din), buf, bufsize)) > 0) {
+ if ((d = write (fileno (fout), buf, c)) != c)
break;
bytes += c;
if (hash) {
while (bytes >= hashbytes) {
- putchar('#');
+ putchar ('#');
hashbytes += HASHBYTES;
}
- fflush(stdout);
+ fflush (stdout);
}
}
if (hash && bytes > 0) {
if (bytes < HASHBYTES)
- putchar('#');
- putchar('\n');
- fflush(stdout);
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
}
if (c < 0) {
if (errno != EPIPE)
- warn("netin");
+ warn ("netin");
bytes = -1;
}
if (d < c) {
if (d < 0)
- warn("local: %s", local);
+ warn ("local: %s", local);
else
- warnx("%s: short write", local);
+ warnx ("%s: short write", local);
}
break;
@@ -1016,38 +1017,37 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames)
if (restart_point) {
int i, n, ch;
- if (fseek(fout, 0L, SEEK_SET) < 0)
+ if (fseek (fout, 0L, SEEK_SET) < 0)
goto done;
n = restart_point;
for (i = 0; i++ < n;) {
- if ((ch = sec_getc(fout)) == EOF)
+ if ((ch = sec_getc (fout)) == EOF)
goto done;
if (ch == '\n')
i++;
}
- if (fseek(fout, 0L, SEEK_CUR) < 0) {
- done:
- warn("local: %s", local);
+ if (fseek (fout, 0L, SEEK_CUR) < 0) {
+ done:
+ warn ("local: %s", local);
if (closefunc != NULL)
- (*closefunc)(fout);
+ (*closefunc) (fout);
return;
}
}
-
while ((c = sec_getc(din)) != EOF) {
if (c == '\n')
bare_lfs++;
while (c == '\r') {
while (hash && (bytes >= hashbytes)) {
- putchar('#');
- fflush(stdout);
+ putchar ('#');
+ fflush (stdout);
hashbytes += HASHBYTES;
}
bytes++;
- if ((c = sec_getc(din)) != '\n' || tcrflag) {
- if (ferror(fout))
+ if ((c = sec_getc (din)) != '\n' || tcrflag) {
+ if (ferror (fout))
goto break2;
- putc('\r', fout);
+ putc ('\r', fout);
if (c == '\0') {
bytes++;
goto contin2;
@@ -1056,69 +1056,68 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames)
goto contin2;
}
}
- putc(c, fout);
+ putc (c, fout);
bytes++;
- contin2: ;
+ contin2:;
}
- break2:
+break2:
if (bare_lfs) {
- printf("WARNING! %d bare linefeeds received in ASCII mode\n",
- bare_lfs);
- printf("File may not have transferred correctly.\n");
+ printf ("WARNING! %d bare linefeeds received in ASCII mode\n",
+ bare_lfs);
+ printf ("File may not have transferred correctly.\n");
}
if (hash) {
if (bytes < hashbytes)
- putchar('#');
- putchar('\n');
- fflush(stdout);
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
}
- if (ferror(din)) {
+ if (ferror (din)) {
if (errno != EPIPE)
- warn("netin");
+ warn ("netin");
bytes = -1;
}
- if (ferror(fout))
- warn("local: %s", local);
+ if (ferror (fout))
+ warn ("local: %s", local);
break;
}
if (closefunc != NULL)
- (*closefunc)(fout);
- signal(SIGINT, oldintr);
+ (*closefunc) (fout);
+ signal (SIGINT, oldintr);
if (oldintp)
- signal(SIGPIPE, oldintp);
- fclose(din);
- gettimeofday(&stop, (struct timezone *)0);
- getreply(0);
+ signal (SIGPIPE, oldintp);
+ fclose (din);
+ gettimeofday (&stop, (struct timezone *) 0);
+ getreply (0);
if (bytes > 0 && is_retr)
- ptransfer("received", bytes, &start, &stop);
+ ptransfer ("received", bytes, &start, &stop);
return;
abort:
/* abort using RFC959 recommended IP,SYNC sequence */
if (oldintp)
- signal(SIGPIPE, oldintr);
- signal(SIGINT, SIG_IGN);
+ signal (SIGPIPE, oldintr);
+ signal (SIGINT, SIG_IGN);
if (!cpend) {
code = -1;
- signal(SIGINT, oldintr);
+ signal (SIGINT, oldintr);
return;
}
-
abort_remote(din);
code = -1;
if (data >= 0) {
- close(data);
+ close (data);
data = -1;
}
if (closefunc != NULL && fout != NULL)
- (*closefunc)(fout);
+ (*closefunc) (fout);
if (din)
- fclose(din);
- gettimeofday(&stop, (struct timezone *)0);
+ fclose (din);
+ gettimeofday (&stop, (struct timezone *) 0);
if (bytes > 0)
- ptransfer("received", bytes, &start, &stop);
- signal(SIGINT, oldintr);
+ ptransfer ("received", bytes, &start, &stop);
+ signal (SIGINT, oldintr);
}
/*
@@ -1126,112 +1125,110 @@ abort:
* otherwise the server's connect may fail.
*/
int
-initconn(void)
+initconn (void)
{
int result, len, tmpno = 0;
int on = 1;
int a0, a1, a2, a3, p0, p1;
if (passivemode) {
- data = socket(AF_INET, SOCK_STREAM, 0);
+ data = socket (AF_INET, SOCK_STREAM, 0);
if (data < 0) {
- perror("ftp: socket");
- return(1);
+ perror ("ftp: socket");
+ return (1);
}
#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
if ((options & SO_DEBUG) &&
- setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
- sizeof (on)) < 0)
- perror("ftp: setsockopt (ignored)");
+ setsockopt (data, SOL_SOCKET, SO_DEBUG, (char *) &on,
+ sizeof (on)) < 0)
+ perror ("ftp: setsockopt (ignored)");
#endif
- if (command("PASV") != COMPLETE) {
- printf("Passive mode refused.\n");
+ if (command ("PASV") != COMPLETE) {
+ printf ("Passive mode refused.\n");
goto bad;
}
/*
- * What we've got at this point is a string of comma
- * separated one-byte unsigned integer values.
- * The first four are the an IP address. The fifth is
- * the MSB of the port number, the sixth is the LSB.
- * From that we'll prepare a sockaddr_in.
+ * What we've got at this point is a string of comma separated
+ * one-byte unsigned integer values. The first four are the an IP
+ * address. The fifth is the MSB of the port number, the sixth is the
+ * LSB. From that we'll prepare a sockaddr_in.
*/
- if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",
- &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
- printf("Passive mode address scan failure. "
- "Shouldn't happen!\n");
+ if (sscanf (pasv, "%d,%d,%d,%d,%d,%d",
+ &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
+ printf ("Passive mode address scan failure. "
+ "Shouldn't happen!\n");
goto bad;
}
- if(a0 < 0 || a0 > 255 ||
- a1 < 0 || a1 > 255 ||
- a2 < 0 || a2 > 255 ||
- a3 < 0 || a3 > 255 ||
- p0 < 0 || p0 > 255 ||
- p1 < 0 || p1 > 255){
- printf("Can't parse passive mode string.\n");
+ if (a0 < 0 || a0 > 255 ||
+ a1 < 0 || a1 > 255 ||
+ a2 < 0 || a2 > 255 ||
+ a3 < 0 || a3 > 255 ||
+ p0 < 0 || p0 > 255 ||
+ p1 < 0 || p1 > 255) {
+ printf ("Can't parse passive mode string.\n");
goto bad;
}
-
memset(&data_addr, 0, sizeof(data_addr));
data_addr.sin_family = AF_INET;
- data_addr.sin_addr.s_addr = htonl((a0 << 24) | (a1 << 16) |
- (a2 << 8) | a3);
- data_addr.sin_port = htons((p0 << 8) | p1);
+ data_addr.sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) |
+ (a2 << 8) | a3);
+ data_addr.sin_port = htons ((p0 << 8) | p1);
- if (connect(data, (struct sockaddr *)&data_addr,
- sizeof(data_addr)) < 0) {
- perror("ftp: connect");
+ if (connect (data, (struct sockaddr *) & data_addr,
+ sizeof (data_addr)) < 0) {
+ perror ("ftp: connect");
goto bad;
}
#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
on = IPTOS_THROUGHPUT;
- if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
- sizeof(int)) < 0)
- perror("ftp: setsockopt TOS (ignored)");
+ if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on,
+ sizeof (int)) < 0)
+ perror ("ftp: setsockopt TOS (ignored)");
#endif
- return(0);
+ return (0);
}
-
noport:
data_addr = myctladdr;
if (sendport)
- data_addr.sin_port = 0; /* let system pick one */
+ data_addr.sin_port = 0; /* let system pick one */
if (data != -1)
- close(data);
- data = socket(AF_INET, SOCK_STREAM, 0);
+ close (data);
+ data = socket (AF_INET, SOCK_STREAM, 0);
if (data < 0) {
- warn("socket");
+ warn ("socket");
if (tmpno)
sendport = 1;
return (1);
}
#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
if (!sendport)
- if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
- warn("setsockopt (reuse address)");
+ if (setsockopt (data, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
+ warn ("setsockopt (reuse address)");
goto bad;
}
#endif
- if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
- warn("bind");
+ if (bind (data, (struct sockaddr *) & data_addr, sizeof (data_addr)) < 0) {
+ warn ("bind");
goto bad;
}
#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
if (options & SO_DEBUG &&
- setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
- warn("setsockopt (ignored)");
+ setsockopt (data, SOL_SOCKET, SO_DEBUG, (char *) &on, sizeof (on)) < 0)
+ warn ("setsockopt (ignored)");
#endif
len = sizeof (data_addr);
- if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
- warn("getsockname");
+ if (getsockname (data, (struct sockaddr *) & data_addr, &len) < 0) {
+ warn ("getsockname");
goto bad;
}
- if (listen(data, 1) < 0)
- warn("listen");
+ if (listen (data, 1) < 0)
+ warn ("listen");
if (sendport) {
unsigned int a = ntohl(data_addr.sin_addr.s_addr);
unsigned int p = ntohs(data_addr.sin_port);
+
result = command("PORT %d,%d,%d,%d,%d,%d",
(a >> 24) & 0xff,
(a >> 16) & 0xff,
@@ -1250,88 +1247,88 @@ noport:
sendport = 1;
#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
on = IPTOS_THROUGHPUT;
- if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
- warn("setsockopt TOS (ignored)");
+ if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, sizeof (int)) < 0)
+ warn ("setsockopt TOS (ignored)");
#endif
return (0);
bad:
- close(data), data = -1;
+ close (data), data = -1;
if (tmpno)
sendport = 1;
return (1);
}
FILE *
-dataconn(char *lmode)
+dataconn (char *lmode)
{
struct sockaddr_in from;
int s, fromlen = sizeof (from), tos;
if (passivemode)
- return (fdopen(data, lmode));
+ return (fdopen (data, lmode));
- s = accept(data, (struct sockaddr *) &from, &fromlen);
+ s = accept (data, (struct sockaddr *) & from, &fromlen);
if (s < 0) {
- warn("accept");
- close(data), data = -1;
+ warn ("accept");
+ close (data), data = -1;
return (NULL);
}
- close(data);
+ close (data);
data = s;
#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
tos = IPTOS_THROUGHPUT;
- if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
- warn("setsockopt TOS (ignored)");
+ if (setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0)
+ warn ("setsockopt TOS (ignored)");
#endif
- return (fdopen(data, lmode));
+ return (fdopen (data, lmode));
}
void
-ptransfer(char *direction, long int bytes,
- struct timeval *t0, struct timeval *t1)
+ptransfer (char *direction, long int bytes,
+ struct timeval * t0, struct timeval * t1)
{
struct timeval td;
float s;
float bs;
int prec;
char *unit;
-
+
if (verbose) {
td.tv_sec = t1->tv_sec - t0->tv_sec;
td.tv_usec = t1->tv_usec - t0->tv_usec;
- if(td.tv_usec < 0){
+ if (td.tv_usec < 0) {
td.tv_sec--;
td.tv_usec += 1000000;
}
s = td.tv_sec + (td.tv_usec / 1000000.);
- bs = bytes / (s?s:1);
- if(bs >= 1048576){
+ bs = bytes / (s ? s : 1);
+ if (bs >= 1048576) {
bs /= 1048576;
unit = "M";
prec = 2;
- }else if(bs >= 1024){
+ } else if (bs >= 1024) {
bs /= 1024;
unit = "k";
prec = 1;
- }else{
+ } else {
unit = "";
prec = 0;
}
-
- printf("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
- bytes, direction, s, prec, bs, unit);
+
+ printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
+ bytes, direction, s, prec, bs, unit);
}
}
void
-psabort(int sig)
+psabort (int sig)
{
abrtflag++;
}
void
-pswitch(int flag)
+pswitch (int flag)
{
sighand oldintr;
static struct comvars {
@@ -1357,7 +1354,7 @@ pswitch(int flag)
struct comvars *ip, *op;
abrtflag = 0;
- oldintr = signal(SIGINT, psabort);
+ oldintr = signal (SIGINT, psabort);
if (flag) {
if (proxy)
return;
@@ -1374,8 +1371,7 @@ pswitch(int flag)
ip->connect = connected;
connected = op->connect;
if (hostname) {
- strncpy(ip->name, hostname, sizeof(ip->name) - 1);
- ip->name[strlen(ip->name)] = '\0';
+ strcpy_truncate (ip->name, hostname, sizeof (ip->name));
} else
ip->name[0] = 0;
hostname = op->name;
@@ -1401,48 +1397,44 @@ pswitch(int flag)
mcase = op->mcse;
ip->ntflg = ntflag;
ntflag = op->ntflg;
- strncpy(ip->nti, ntin, 16);
- (ip->nti)[strlen(ip->nti)] = '\0';
- strcpy(ntin, op->nti);
- strncpy(ip->nto, ntout, 16);
- (ip->nto)[strlen(ip->nto)] = '\0';
- strcpy(ntout, op->nto);
+ strcpy_truncate (ip->nti, ntin, sizeof (ip->nti));
+ strcpy_truncate (ntin, op->nti, 17);
+ strcpy_truncate (ip->nto, ntout, sizeof (ip->nto));
+ strcpy_truncate (ntout, op->nto, 17);
ip->mapflg = mapflag;
mapflag = op->mapflg;
- strncpy(ip->mi, mapin, MaxPathLen - 1);
- (ip->mi)[strlen(ip->mi)] = '\0';
- strcpy(mapin, op->mi);
- strncpy(ip->mo, mapout, MaxPathLen - 1);
- (ip->mo)[strlen(ip->mo)] = '\0';
- strcpy(mapout, op->mo);
+ strcpy_truncate (ip->mi, mapin, MaxPathLen);
+ strcpy_truncate (mapin, op->mi, MaxPathLen);
+ strcpy_truncate (ip->mo, mapout, MaxPathLen);
+ strcpy_truncate (mapout, op->mo, MaxPathLen);
signal(SIGINT, oldintr);
if (abrtflag) {
abrtflag = 0;
- (*oldintr)(SIGINT);
+ (*oldintr) (SIGINT);
}
}
void
-abortpt(int sig)
+abortpt (int sig)
{
- printf("\n");
- fflush(stdout);
+ printf ("\n");
+ fflush (stdout);
ptabflg++;
mflag = 0;
abrtflag = 0;
- longjmp(ptabort, 1);
+ longjmp (ptabort, 1);
}
void
-proxtrans(char *cmd, char *local, char *remote)
+proxtrans (char *cmd, char *local, char *remote)
{
sighand oldintr;
int secndflag = 0, prox_type, nfnd;
char *cmd2;
fd_set mask;
- if (strcmp(cmd, "RETR"))
+ if (strcmp (cmd, "RETR"))
cmd2 = "RETR";
else
cmd2 = runique ? "STOU" : "STOR";
@@ -1453,148 +1445,147 @@ proxtrans(char *cmd, char *local, char *remote)
prox_type = TYPE_A;
}
if (curtype != prox_type)
- changetype(prox_type, 1);
- if (command("PASV") != COMPLETE) {
- printf("proxy server does not support third party transfers.\n");
+ changetype (prox_type, 1);
+ if (command ("PASV") != COMPLETE) {
+ printf ("proxy server does not support third party transfers.\n");
return;
}
- pswitch(0);
+ pswitch (0);
if (!connected) {
- printf("No primary connection\n");
- pswitch(1);
+ printf ("No primary connection\n");
+ pswitch (1);
code = -1;
return;
}
if (curtype != prox_type)
- changetype(prox_type, 1);
- if (command("PORT %s", pasv) != COMPLETE) {
- pswitch(1);
+ changetype (prox_type, 1);
+ if (command ("PORT %s", pasv) != COMPLETE) {
+ pswitch (1);
return;
}
- if (setjmp(ptabort))
+ if (setjmp (ptabort))
goto abort;
- oldintr = signal(SIGINT, abortpt);
- if (command("%s %s", cmd, remote) != PRELIM) {
- signal(SIGINT, oldintr);
- pswitch(1);
+ oldintr = signal (SIGINT, abortpt);
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
+ pswitch (1);
return;
}
- sleep(2);
- pswitch(1);
+ sleep (2);
+ pswitch (1);
secndflag++;
- if (command("%s %s", cmd2, local) != PRELIM)
+ if (command ("%s %s", cmd2, local) != PRELIM)
goto abort;
ptflag++;
- getreply(0);
- pswitch(0);
- getreply(0);
- signal(SIGINT, oldintr);
- pswitch(1);
+ getreply (0);
+ pswitch (0);
+ getreply (0);
+ signal (SIGINT, oldintr);
+ pswitch (1);
ptflag = 0;
- printf("local: %s remote: %s\n", local, remote);
+ printf ("local: %s remote: %s\n", local, remote);
return;
abort:
- signal(SIGINT, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
ptflag = 0;
- if (strcmp(cmd, "RETR") && !proxy)
- pswitch(1);
- else if (!strcmp(cmd, "RETR") && proxy)
- pswitch(0);
- if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
- if (command("%s %s", cmd2, local) != PRELIM) {
- pswitch(0);
+ if (strcmp (cmd, "RETR") && !proxy)
+ pswitch (1);
+ else if (!strcmp (cmd, "RETR") && proxy)
+ pswitch (0);
+ if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
+ if (command ("%s %s", cmd2, local) != PRELIM) {
+ pswitch (0);
if (cpend)
- abort_remote((FILE *) NULL);
+ abort_remote ((FILE *) NULL);
}
- pswitch(1);
+ pswitch (1);
if (ptabflg)
code = -1;
- signal(SIGINT, oldintr);
+ signal (SIGINT, oldintr);
return;
}
if (cpend)
- abort_remote((FILE *) NULL);
- pswitch(!proxy);
- if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
- if (command("%s %s", cmd2, local) != PRELIM) {
- pswitch(0);
+ abort_remote ((FILE *) NULL);
+ pswitch (!proxy);
+ if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
+ if (command ("%s %s", cmd2, local) != PRELIM) {
+ pswitch (0);
if (cpend)
- abort_remote((FILE *) NULL);
- pswitch(1);
+ abort_remote ((FILE *) NULL);
+ pswitch (1);
if (ptabflg)
code = -1;
- signal(SIGINT, oldintr);
+ signal (SIGINT, oldintr);
return;
}
}
if (cpend)
- abort_remote((FILE *) NULL);
- pswitch(!proxy);
+ abort_remote ((FILE *) NULL);
+ pswitch (!proxy);
if (cpend) {
- FD_ZERO(&mask);
- FD_SET(fileno(cin), &mask);
- if ((nfnd = empty(&mask, 10)) <= 0) {
+ FD_ZERO (&mask);
+ FD_SET (fileno (cin), &mask);
+ if ((nfnd = empty (&mask, 10)) <= 0) {
if (nfnd < 0) {
- warn("abort");
+ warn ("abort");
}
if (ptabflg)
code = -1;
- lostpeer(0);
+ lostpeer (0);
}
- getreply(0);
- getreply(0);
+ getreply (0);
+ getreply (0);
}
if (proxy)
- pswitch(0);
- pswitch(1);
+ pswitch (0);
+ pswitch (1);
if (ptabflg)
code = -1;
- signal(SIGINT, oldintr);
+ signal (SIGINT, oldintr);
}
void
-reset(int argc, char **argv)
+reset (int argc, char **argv)
{
fd_set mask;
int nfnd = 1;
- FD_ZERO(&mask);
+ FD_ZERO (&mask);
while (nfnd > 0) {
- FD_SET(fileno(cin), &mask);
- if ((nfnd = empty(&mask,0)) < 0) {
- warn("reset");
+ FD_SET (fileno (cin), &mask);
+ if ((nfnd = empty (&mask, 0)) < 0) {
+ warn ("reset");
code = -1;
lostpeer(0);
- }
- else if (nfnd) {
+ } else if (nfnd) {
getreply(0);
}
}
}
char *
-gunique(char *local)
+gunique (char *local)
{
static char new[MaxPathLen];
- char *cp = strrchr(local, '/');
- int d, count=0;
+ char *cp = strrchr (local, '/');
+ int d, count = 0;
char ext = '1';
if (cp)
*cp = '\0';
- d = access(cp ? local : ".", 2);
+ d = access (cp ? local : ".", 2);
if (cp)
*cp = '/';
if (d < 0) {
- warn("local: %s", local);
+ warn ("local: %s", local);
return NULL;
}
- strcpy(new, local);
+ strcpy_truncate (new, local, sizeof(new));
cp = new + strlen(new);
*cp++ = '.';
while (!d) {
if (++count == 100) {
- printf("runique: can't find unique file name.\n");
+ printf ("runique: can't find unique file name.\n");
return NULL;
}
*cp++ = ext;
@@ -1603,7 +1594,7 @@ gunique(char *local)
ext = '0';
else
ext++;
- if ((d = access(new, 0)) < 0)
+ if ((d = access (new, 0)) < 0)
break;
if (ext != '0')
cp--;
@@ -1618,7 +1609,7 @@ gunique(char *local)
}
void
-abort_remote(FILE *din)
+abort_remote (FILE * din)
{
char buf[BUFSIZ];
int nfnd;
@@ -1628,31 +1619,31 @@ abort_remote(FILE *din)
* send IAC in urgent mode instead of DM because 4.3BSD places oob mark
* after urgent byte rather than before as is protocol now
*/
- snprintf(buf, sizeof(buf), "%c%c%c", IAC, IP, IAC);
- if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
- warn("abort");
- fprintf(cout,"%cABOR\r\n", DM);
- fflush(cout);
- FD_ZERO(&mask);
- FD_SET(fileno(cin), &mask);
- if (din) {
- FD_SET(fileno(din), &mask);
- }
- if ((nfnd = empty(&mask, 10)) <= 0) {
+ snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC);
+ if (send (fileno (cout), buf, 3, MSG_OOB) != 3)
+ warn ("abort");
+ fprintf (cout, "%cABOR\r\n", DM);
+ fflush (cout);
+ FD_ZERO (&mask);
+ FD_SET (fileno (cin), &mask);
+ if (din) {
+ FD_SET (fileno (din), &mask);
+ }
+ if ((nfnd = empty (&mask, 10)) <= 0) {
if (nfnd < 0) {
- warn("abort");
+ warn ("abort");
}
if (ptabflg)
code = -1;
- lostpeer(0);
+ lostpeer (0);
}
- if (din && FD_ISSET(fileno(din), &mask)) {
- while (read(fileno(din), buf, BUFSIZ) > 0)
- /* LOOP */;
+ if (din && FD_ISSET (fileno (din), &mask)) {
+ while (read (fileno (din), buf, BUFSIZ) > 0)
+ /* LOOP */ ;
}
- if (getreply(0) == ERROR && code == 552) {
+ if (getreply (0) == ERROR && code == 552) {
/* 552 needed for nic style abort */
- getreply(0);
+ getreply (0);
}
- getreply(0);
+ getreply (0);
}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h
index 6ead793..5ae44b1 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h
+++ b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*/
-/* $Id: ftp_locl.h,v 1.29 1997/05/20 18:40:28 bg Exp $ */
+/* $Id: ftp_locl.h,v 1.33 1998/06/13 00:06:40 assar Exp $ */
#ifndef __FTP_LOCL_H__
#define __FTP_LOCL_H__
@@ -45,8 +45,6 @@
#include <config.h>
#endif
-#include <sys/cdefs.h>
-
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -121,7 +119,12 @@
#ifdef SOCKS
#include <socks.h>
-extern int LIBPREFIX(fclose) __P((FILE *));
+extern int LIBPREFIX(fclose) (FILE *);
+
+/* This doesn't belong here. */
+struct tm *localtime(const time_t *);
+struct hostent *gethostbyname(const char *);
+
#endif
#include "ftp_var.h"
@@ -129,13 +132,9 @@ extern int LIBPREFIX(fclose) __P((FILE *));
#include "common.h"
#include "pathnames.h"
-#include <des.h>
-
-#include <krb.h>
-
-#include "krb4.h"
-
#include "roken.h"
+#include "security.h"
+#include <des.h> /* for des_read_pw_string */
#if defined(__sun__) && !defined(__svr4)
int fclose(FILE*);
diff --git a/crypto/kerberosIV/appl/ftp/ftp/gssapi.c b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c
new file mode 100644
index 0000000..bc001a4
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 1998, 1999 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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.
+ */
+
+#ifdef FTP_SERVER
+#include "ftpd_locl.h"
+#else
+#include "ftp_locl.h"
+#endif
+#include <gssapi.h>
+
+RCSID("$Id: gssapi.c,v 1.7 1999/04/10 15:08:39 assar Exp $");
+
+struct gss_data {
+ gss_ctx_id_t context_hdl;
+ char *client_name;
+};
+
+static int
+gss_init(void *app_data)
+{
+ struct gss_data *d = app_data;
+ d->context_hdl = GSS_C_NO_CONTEXT;
+ return 0;
+}
+
+static int
+gss_check_prot(void *app_data, int level)
+{
+ if(level == prot_confidential)
+ return -1;
+ return 0;
+}
+
+static int
+gss_decode(void *app_data, void *buf, int len, int level)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc input, output;
+ gss_qop_t qop_state;
+ int conf_state;
+ struct gss_data *d = app_data;
+
+ input.length = len;
+ input.value = buf;
+ maj_stat = gss_unwrap (&min_stat,
+ d->context_hdl,
+ &input,
+ &output,
+ &conf_state,
+ &qop_state);
+ if(GSS_ERROR(maj_stat))
+ return -1;
+ memmove(buf, output.value, output.length);
+ return output.length;
+}
+
+static int
+gss_overhead(void *app_data, int level, int len)
+{
+ return 100; /* dunno? */
+}
+
+
+static int
+gss_encode(void *app_data, void *from, int length, int level, void **to)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc input, output;
+ int conf_state;
+ struct gss_data *d = app_data;
+
+ input.length = length;
+ input.value = from;
+ maj_stat = gss_wrap (&min_stat,
+ d->context_hdl,
+ level == prot_private,
+ GSS_C_QOP_DEFAULT,
+ &input,
+ &conf_state,
+ &output);
+ *to = output.value;
+ return output.length;
+}
+
+/* end common stuff */
+
+#ifdef FTP_SERVER
+
+static int
+gss_adat(void *app_data, void *buf, size_t len)
+{
+ char *p = NULL;
+ gss_buffer_desc input_token, output_token;
+ OM_uint32 maj_stat, min_stat;
+ gss_name_t client_name;
+ struct gss_data *d = app_data;
+
+ gss_channel_bindings_t bindings = malloc(sizeof(*bindings));
+ bindings->initiator_addrtype = GSS_C_AF_INET;
+ bindings->initiator_address.length = 4;
+ bindings->initiator_address.value = &his_addr.sin_addr;
+ bindings->acceptor_addrtype = GSS_C_AF_INET;
+ bindings->acceptor_address.length = 4;
+ bindings->acceptor_address.value = &ctrl_addr.sin_addr;
+ bindings->application_data.length = 0;
+ bindings->application_data.value = NULL;
+
+ input_token.value = buf;
+ input_token.length = len;
+
+ maj_stat = gss_accept_sec_context (&min_stat,
+ &d->context_hdl,
+ GSS_C_NO_CREDENTIAL,
+ &input_token,
+ bindings,
+ &client_name,
+ NULL,
+ &output_token,
+ NULL,
+ NULL,
+ NULL);
+
+ if(output_token.length) {
+ if(base64_encode(output_token.value, output_token.length, &p) < 0) {
+ reply(535, "Out of memory base64-encoding.");
+ return -1;
+ }
+ }
+ if(maj_stat == GSS_S_COMPLETE){
+ char *name;
+ gss_buffer_desc export_name;
+ maj_stat = gss_export_name(&min_stat, client_name, &export_name);
+ if(maj_stat != 0) {
+ reply(500, "Error exporting name");
+ goto out;
+ }
+ name = realloc(export_name.value, export_name.length + 1);
+ if(name == NULL) {
+ reply(500, "Out of memory");
+ free(export_name.value);
+ goto out;
+ }
+ name[export_name.length] = '\0';
+ d->client_name = name;
+ if(p)
+ reply(235, "ADAT=%s", p);
+ else
+ reply(235, "ADAT Complete");
+ sec_complete = 1;
+
+ } else if(maj_stat == GSS_S_CONTINUE_NEEDED) {
+ if(p)
+ reply(335, "ADAT=%s", p);
+ else
+ reply(335, "OK, need more data");
+ } else
+ reply(535, "foo?");
+out:
+ free(p);
+ return 0;
+}
+
+int gss_userok(void*, char*);
+
+struct sec_server_mech gss_server_mech = {
+ "GSSAPI",
+ sizeof(struct gss_data),
+ gss_init, /* init */
+ NULL, /* end */
+ gss_check_prot,
+ gss_overhead,
+ gss_encode,
+ gss_decode,
+ /* */
+ NULL,
+ gss_adat,
+ NULL, /* pbsz */
+ NULL, /* ccc */
+ gss_userok
+};
+
+#else /* FTP_SERVER */
+
+extern struct sockaddr_in hisctladdr, myctladdr;
+
+static int
+gss_auth(void *app_data, char *host)
+{
+
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc name;
+ gss_name_t target_name;
+ gss_buffer_desc input, output_token;
+ int context_established = 0;
+ char *p;
+ int n;
+ gss_channel_bindings_t bindings;
+ struct gss_data *d = app_data;
+
+ name.length = asprintf((char**)&name.value, "ftp@%s", host);
+ maj_stat = gss_import_name(&min_stat,
+ &name,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ &target_name);
+ free(name.value);
+
+
+ input.length = 0;
+ input.value = NULL;
+
+ bindings = malloc(sizeof(*bindings));
+ bindings->initiator_addrtype = GSS_C_AF_INET;
+ bindings->initiator_address.length = 4;
+ bindings->initiator_address.value = &myctladdr.sin_addr;
+ bindings->acceptor_addrtype = GSS_C_AF_INET;
+ bindings->acceptor_address.length = 4;
+ bindings->acceptor_address.value = &hisctladdr.sin_addr;
+ bindings->application_data.length = 0;
+ bindings->application_data.value = NULL;
+
+ while(!context_established) {
+ maj_stat = gss_init_sec_context(&min_stat,
+ GSS_C_NO_CREDENTIAL,
+ &d->context_hdl,
+ target_name,
+ GSS_C_NO_OID,
+ GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
+ 0,
+ bindings,
+ &input,
+ NULL,
+ &output_token,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat)) {
+ int new_stat;
+ int msg_ctx = 0;
+ gss_buffer_desc status_string;
+
+ gss_display_status(&new_stat,
+ min_stat,
+ GSS_C_MECH_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &status_string);
+ printf("Error initializing security context: %s\n",
+ (char*)status_string.value);
+ gss_release_buffer(&new_stat, &status_string);
+ return AUTH_CONTINUE;
+ }
+
+ gss_release_buffer(&min_stat, &input);
+ if (output_token.length != 0) {
+ base64_encode(output_token.value, output_token.length, &p);
+ gss_release_buffer(&min_stat, &output_token);
+ n = command("ADAT %s", p);
+ free(p);
+ }
+ if (GSS_ERROR(maj_stat)) {
+ if (d->context_hdl != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context (&min_stat,
+ &d->context_hdl,
+ GSS_C_NO_BUFFER);
+ break;
+ }
+ if (maj_stat & GSS_S_CONTINUE_NEEDED) {
+ p = strstr(reply_string, "ADAT=");
+ if(p == NULL){
+ printf("Error: expected ADAT in reply.\n");
+ return AUTH_ERROR;
+ } else {
+ p+=5;
+ input.value = malloc(strlen(p));
+ input.length = base64_decode(p, input.value);
+ }
+ } else {
+ if(code != 235) {
+ printf("Unrecognized response code: %d\n", code);
+ return AUTH_ERROR;
+ }
+ context_established = 1;
+ }
+ }
+ return AUTH_OK;
+}
+
+struct sec_client_mech gss_client_mech = {
+ "GSSAPI",
+ sizeof(struct gss_data),
+ gss_init,
+ gss_auth,
+ NULL, /* end */
+ gss_check_prot,
+ gss_overhead,
+ gss_encode,
+ gss_decode,
+};
+
+#endif /* FTP_SERVER */
diff --git a/crypto/kerberosIV/appl/ftp/ftp/kauth.c b/crypto/kerberosIV/appl/ftp/ftp/kauth.c
index 8bc9b9b..434dfb8 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/kauth.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/kauth.c
@@ -37,9 +37,11 @@
*/
#include "ftp_locl.h"
-RCSID("$Id: kauth.c,v 1.14 1997/05/11 04:08:04 assar Exp $");
+#include <krb.h>
+RCSID("$Id: kauth.c,v 1.17 1998/03/26 02:55:38 joda Exp $");
-void kauth(int argc, char **argv)
+void
+kauth(int argc, char **argv)
{
int ret;
char buf[1024];
@@ -120,7 +122,11 @@ void kauth(int argc, char **argv)
memset(key, 0, sizeof(key));
memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd));
- base64_encode(tktcopy.dat, tktcopy.length, &p);
+ if(base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
+ printf("Out of memory base64-encoding.\n");
+ code = -1;
+ return;
+ }
memset (tktcopy.dat, 0, tktcopy.length);
ret = command("SITE KAUTH %s %s", name, p);
free(p);
@@ -131,7 +137,8 @@ void kauth(int argc, char **argv)
code = 0;
}
-void klist(int argc, char **argv)
+void
+klist(int argc, char **argv)
{
int ret;
if(argc != 1){
@@ -143,3 +150,45 @@ void klist(int argc, char **argv)
ret = command("SITE KLIST");
code = (ret == COMPLETE);
}
+
+void
+kdestroy(int argc, char **argv)
+{
+ int ret;
+ if (argc != 1) {
+ printf("usage: %s\n", argv[0]);
+ code = -1;
+ return;
+ }
+ ret = command("SITE KDESTROY");
+ code = (ret == COMPLETE);
+}
+
+void
+krbtkfile(int argc, char **argv)
+{
+ int ret;
+ if(argc != 2) {
+ printf("usage: %s tktfile\n", argv[0]);
+ code = -1;
+ return;
+ }
+ ret = command("SITE KRBTKFILE %s", argv[1]);
+ code = (ret == COMPLETE);
+}
+
+void
+afslog(int argc, char **argv)
+{
+ int ret;
+ if(argc > 2) {
+ printf("usage: %s [cell]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if(argc == 2)
+ ret = command("SITE AFSLOG %s", argv[1]);
+ else
+ ret = command("SITE AFSLOG");
+ code = (ret == COMPLETE);
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/krb4.c b/crypto/kerberosIV/appl/ftp/ftp/krb4.c
index 872c5bc..5b9b9b8 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/krb4.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/krb4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -36,532 +36,260 @@
* SUCH DAMAGE.
*/
+#ifdef FTP_SERVER
+#include "ftpd_locl.h"
+#else
#include "ftp_locl.h"
-
-RCSID("$Id: krb4.c,v 1.18 1997/05/11 04:08:05 assar Exp $");
-
-static KTEXT_ST krb4_adat;
-
-static des_cblock key;
-static des_key_schedule schedule;
-
-static char *data_buffer;
-
-extern struct sockaddr_in hisctladdr, myctladdr;
-
-int auth_complete;
-
-static int command_prot;
-
-static int auth_pbsz;
-static int data_prot;
-
-static int request_data_prot;
-
-
-static struct {
- int level;
- char *name;
-} level_names[] = {
- { prot_clear, "clear" },
- { prot_safe, "safe" },
- { prot_confidential, "confidential" },
- { prot_private, "private" }
+#endif
+#include <krb.h>
+
+RCSID("$Id: krb4.c,v 1.30 1999/06/15 03:50:28 assar Exp $");
+
+#ifdef FTP_SERVER
+#define LOCAL_ADDR ctrl_addr
+#define REMOTE_ADDR his_addr
+#else
+#define LOCAL_ADDR myctladdr
+#define REMOTE_ADDR hisctladdr
+#endif
+extern struct sockaddr_in LOCAL_ADDR, REMOTE_ADDR;
+
+struct krb4_data {
+ des_cblock key;
+ des_key_schedule schedule;
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ char realm[REALM_SZ];
};
-static char *level_to_name(int level)
-{
- int i;
- for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
- if(level_names[i].level == level)
- return level_names[i].name;
- return "unknown";
-}
-
-static int name_to_level(char *name)
-{
- int i;
- for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
- if(!strncasecmp(level_names[i].name, name, strlen(name)))
- return level_names[i].level;
- return -1;
-}
-
-void sec_status(void)
-{
- if(auth_complete){
- printf("Using KERBEROS_V4 for authentication.\n");
-
- command_prot = prot_private; /* this variable is not used */
-
- printf("Using %s command channel.\n",
- level_to_name(command_prot));
-
- printf("Using %s data channel.\n",
- level_to_name(data_prot));
- if(auth_pbsz > 0)
- printf("Protection buffer size: %d.\n", auth_pbsz);
- }else{
- printf("Not using any security mechanism.\n");
- }
-}
-
static int
-sec_prot_internal(int level)
+krb4_check_prot(void *app_data, int level)
{
- int ret;
- char *p;
- int s = 1048576;
-
- int old_verbose = verbose;
- verbose = 0;
-
- if(!auth_complete){
- printf("No security data exchange has taken place.\n");
+ if(level == prot_confidential)
return -1;
- }
-
- if(level){
- ret = command("PBSZ %d", s);
- if(ret != COMPLETE){
- printf("Failed to set protection buffer size.\n");
- return -1;
- }
- auth_pbsz = s;
- p = strstr(reply_string, "PBSZ=");
- if(p)
- sscanf(p, "PBSZ=%d", &s);
- if(s < auth_pbsz)
- auth_pbsz = s;
- if(data_buffer)
- free(data_buffer);
- data_buffer = malloc(auth_pbsz);
- }
- verbose = old_verbose;
- ret = command("PROT %c", level["CSEP"]); /* XXX :-) */
- if(ret != COMPLETE){
- printf("Failed to set protection level.\n");
- return -1;
- }
-
- data_prot = level;
return 0;
}
-
-void
-sec_prot(int argc, char **argv)
+static int
+krb4_decode(void *app_data, void *buf, int len, int level)
{
- int level = -1;
-
- if(argc != 2){
- printf("usage: %s (clear | safe | confidential | private)\n",
- argv[0]);
- code = -1;
- return;
- }
- if(!auth_complete){
- printf("No security data exchange has taken place.\n");
- code = -1;
- return;
- }
- level = name_to_level(argv[1]);
-
- if(level == -1){
- printf("usage: %s (clear | safe | confidential | private)\n",
- argv[0]);
- code = -1;
- return;
- }
+ MSG_DAT m;
+ int e;
+ struct krb4_data *d = app_data;
- if(level == prot_confidential){
- printf("Confidential protection is not defined with Kerberos.\n");
- code = -1;
- return;
- }
-
- if(sec_prot_internal(level) < 0){
- code = -1;
- return;
- }
- code = 0;
-}
-
-void
-sec_set_protection_level(void)
-{
- if(auth_complete && data_prot != request_data_prot)
- sec_prot_internal(request_data_prot);
-}
-
-
-int
-sec_request_prot(char *level)
-{
- int l = name_to_level(level);
- if(l == -1)
- return -1;
- request_data_prot = l;
- return 0;
-}
-
-
-int sec_getc(FILE *F)
-{
- if(auth_complete && data_prot)
- return krb4_getc(F);
+ if(level == prot_safe)
+ e = krb_rd_safe(buf, len, &d->key, &REMOTE_ADDR, &LOCAL_ADDR, &m);
else
- return getc(F);
+ e = krb_rd_priv(buf, len, d->schedule, &d->key,
+ &REMOTE_ADDR, &LOCAL_ADDR, &m);
+ if(e){
+ return -1;
+ }
+ memmove(buf, m.app_data, m.app_length);
+ return m.app_length;
}
-int sec_read(int fd, void *data, int length)
+static int
+krb4_overhead(void *app_data, int level, int len)
{
- if(auth_complete && data_prot)
- return krb4_read(fd, data, length);
- else
- return read(fd, data, length);
+ return 31;
}
static int
-krb4_recv(int fd)
+krb4_encode(void *app_data, void *from, int length, int level, void **to)
{
- int len;
- MSG_DAT m;
- int kerror;
-
- krb_net_read(fd, &len, sizeof(len));
- len = ntohl(len);
- krb_net_read(fd, data_buffer, len);
- if(data_prot == prot_safe)
- kerror = krb_rd_safe(data_buffer, len, &key,
- &hisctladdr, &myctladdr, &m);
+ struct krb4_data *d = app_data;
+ *to = malloc(length + 31);
+ if(level == prot_safe)
+ return krb_mk_safe(from, *to, length, &d->key,
+ &LOCAL_ADDR, &REMOTE_ADDR);
+ else if(level == prot_private)
+ return krb_mk_priv(from, *to, length, d->schedule, &d->key,
+ &LOCAL_ADDR, &REMOTE_ADDR);
else
- kerror = krb_rd_priv(data_buffer, len, schedule, &key,
- &hisctladdr, &myctladdr, &m);
- if(kerror){
return -1;
- }
- memmove(data_buffer, m.app_data, m.app_length);
- return m.app_length;
}
+#ifdef FTP_SERVER
-int krb4_getc(FILE *F)
+static int
+krb4_adat(void *app_data, void *buf, size_t len)
{
- static int bytes;
- static int index;
- if(bytes == 0){
- bytes = krb4_recv(fileno(F));
- index = 0;
- }
- if(bytes){
- bytes--;
- return (unsigned char)data_buffer[index++];
+ KTEXT_ST tkt;
+ AUTH_DAT auth_dat;
+ char *p;
+ int kerror;
+ u_int32_t cs;
+ char msg[35]; /* size of encrypted block */
+ int tmp_len;
+ struct krb4_data *d = app_data;
+ char inst[INST_SZ];
+
+ memcpy(tkt.dat, buf, len);
+ tkt.length = len;
+
+ k_getsockinst(0, inst, sizeof(inst));
+ kerror = krb_rd_req(&tkt, "ftp", inst,
+ his_addr.sin_addr.s_addr, &auth_dat, "");
+ if(kerror == RD_AP_UNDEC){
+ k_getsockinst(0, inst, sizeof(inst));
+ kerror = krb_rd_req(&tkt, "rcmd", inst,
+ his_addr.sin_addr.s_addr, &auth_dat, "");
}
- return EOF;
-}
-
-int krb4_read(int fd, char *data, int length)
-{
- static int left;
- static int index;
- static int eof;
- int len = left;
- int rx = 0;
- if(eof){
- eof = 0;
- return 0;
+ if(kerror){
+ reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
+ return -1;
}
- if(left){
- if(length < len)
- len = length;
- memmove(data, data_buffer + index, len);
- length -= len;
- index += len;
- rx += len;
- left -= len;
+ memcpy(d->key, auth_dat.session, sizeof(d->key));
+ des_set_key(&d->key, d->schedule);
+
+ strcpy_truncate(d->name, auth_dat.pname, sizeof(d->name));
+ strcpy_truncate(d->instance, auth_dat.pinst, sizeof(d->instance));
+ strcpy_truncate(d->realm, auth_dat.prealm, sizeof(d->instance));
+
+ cs = auth_dat.checksum + 1;
+ {
+ unsigned char tmp[4];
+ KRB_PUT_INT(cs, tmp, 4, sizeof(tmp));
+ tmp_len = krb_mk_safe(tmp, msg, 4, &d->key, &LOCAL_ADDR, &REMOTE_ADDR);
}
-
- while(length){
- len = krb4_recv(fd);
- if(len == 0){
- if(rx)
- eof = 1;
- return rx;
- }
- if(len > length){
- left = len - length;
- len = index = length;
- }
- memmove(data, data_buffer, len);
- length -= len;
- data += len;
- rx += len;
+ if(tmp_len < 0){
+ reply(535, "Error creating reply: %s.", strerror(errno));
+ return -1;
}
- return rx;
-}
-
-
-static int
-krb4_encode(char *from, char *to, int length)
-{
- if(data_prot == prot_safe)
- return krb_mk_safe(from, to, length, &key,
- &myctladdr, &hisctladdr);
- else
- return krb_mk_priv(from, to, length, schedule, &key,
- &myctladdr, &hisctladdr);
-}
-
-static int
-krb4_overhead(int len)
-{
- if(data_prot == prot_safe)
- return 31;
- else
- return 26;
-}
-
-static char p_buf[1024];
-static int p_index;
-
-int
-sec_putc(int c, FILE *F)
-{
- if(data_prot){
- if((c == '\n' && p_index) || p_index == sizeof(p_buf)){
- sec_write(fileno(F), p_buf, p_index);
- p_index = 0;
- }
- p_buf[p_index++] = c;
- return c;
+ len = tmp_len;
+ if(base64_encode(msg, len, &p) < 0) {
+ reply(535, "Out of memory base64-encoding.");
+ return -1;
}
- return putc(c, F);
+ reply(235, "ADAT=%s", p);
+ sec_complete = 1;
+ free(p);
+ return 0;
}
static int
-sec_send(int fd, char *from, int length)
+krb4_userok(void *app_data, char *user)
{
- int bytes;
- bytes = krb4_encode(from, data_buffer, length);
- bytes = htonl(bytes);
- krb_net_write(fd, &bytes, sizeof(bytes));
- krb_net_write(fd, data_buffer, ntohl(bytes));
- return length;
+ struct krb4_data *d = app_data;
+ return krb_kuserok(d->name, d->instance, d->realm, user);
}
-int
-sec_fflush(FILE *F)
-{
- if(data_prot){
- if(p_index){
- sec_write(fileno(F), p_buf, p_index);
- p_index = 0;
- }
- sec_send(fileno(F), NULL, 0);
- }
- fflush(F);
- return 0;
-}
+struct sec_server_mech krb4_server_mech = {
+ "KERBEROS_V4",
+ sizeof(struct krb4_data),
+ NULL, /* init */
+ NULL, /* end */
+ krb4_check_prot,
+ krb4_overhead,
+ krb4_encode,
+ krb4_decode,
+ /* */
+ NULL,
+ krb4_adat,
+ NULL, /* pbsz */
+ NULL, /* ccc */
+ krb4_userok
+};
-int
-sec_write(int fd, char *data, int length)
-{
- int len = auth_pbsz;
- int tx = 0;
-
- if(data_prot == prot_clear)
- return write(fd, data, length);
-
- len -= krb4_overhead(len);
- while(length){
- if(length < len)
- len = length;
- sec_send(fd, data, len);
- length -= len;
- data += len;
- tx += len;
- }
- return tx;
-}
+#else /* FTP_SERVER */
static int
-do_auth(char *service, char *host, int checksum)
+mk_auth(struct krb4_data *d, KTEXT adat,
+ char *service, char *host, int checksum)
{
int ret;
CREDENTIALS cred;
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
- strcpy(sname, service);
- strcpy(inst, krb_get_phost(host));
- strcpy(realm, krb_realmofhost(host));
- ret = krb_mk_req(&krb4_adat, sname, inst, realm, checksum);
+
+ strcpy_truncate(sname, service, sizeof(sname));
+ strcpy_truncate(inst, krb_get_phost(host), sizeof(inst));
+ strcpy_truncate(realm, krb_realmofhost(host), sizeof(realm));
+ ret = krb_mk_req(adat, sname, inst, realm, checksum);
if(ret)
return ret;
- strcpy(sname, service);
- strcpy(inst, krb_get_phost(host));
- strcpy(realm, krb_realmofhost(host));
+ strcpy_truncate(sname, service, sizeof(sname));
+ strcpy_truncate(inst, krb_get_phost(host), sizeof(inst));
+ strcpy_truncate(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_get_cred(sname, inst, realm, &cred);
- memmove(&key, &cred.session, sizeof(des_cblock));
- des_key_sched(&key, schedule);
+ memmove(&d->key, &cred.session, sizeof(des_cblock));
+ des_key_sched(&d->key, d->schedule);
memset(&cred, 0, sizeof(cred));
return ret;
}
-
-int
-do_klogin(char *host)
+static int
+krb4_auth(void *app_data, char *host)
{
int ret;
char *p;
int len;
- char adat[1024];
+ KTEXT_ST adat;
MSG_DAT msg_data;
int checksum;
-
- int old_verbose = verbose;
-
- verbose = 0;
- printf("Trying KERBEROS_V4...\n");
- ret = command("AUTH KERBEROS_V4");
- if(ret != CONTINUE){
- if(code == 504){
- printf("Kerberos 4 is not supported by the server.\n");
- }else if(code == 534){
- printf("KERBEROS_V4 rejected as security mechanism.\n");
- }else if(ret == ERROR)
- printf("The server doesn't understand the FTP "
- "security extensions.\n");
- verbose = old_verbose;
- return -1;
- }
+ u_int32_t cs;
+ struct krb4_data *d = app_data;
checksum = getpid();
- ret = do_auth("ftp", host, checksum);
+ ret = mk_auth(d, &adat, "ftp", host, checksum);
if(ret == KDC_PR_UNKNOWN)
- ret = do_auth("rcmd", host, checksum);
+ ret = mk_auth(d, &adat, "rcmd", host, checksum);
if(ret){
printf("%s\n", krb_get_err_text(ret));
- verbose = old_verbose;
- return ret;
+ return AUTH_CONTINUE;
}
- base64_encode(krb4_adat.dat, krb4_adat.length, &p);
+ if(base64_encode(adat.dat, adat.length, &p) < 0) {
+ printf("Out of memory base64-encoding.\n");
+ return AUTH_CONTINUE;
+ }
ret = command("ADAT %s", p);
free(p);
if(ret != COMPLETE){
printf("Server didn't accept auth data.\n");
- verbose = old_verbose;
- return -1;
+ return AUTH_ERROR;
}
p = strstr(reply_string, "ADAT=");
if(!p){
printf("Remote host didn't send adat reply.\n");
- verbose = old_verbose;
- return -1;
+ return AUTH_ERROR;
}
- p+=5;
- len = base64_decode(p, adat);
+ p += 5;
+ len = base64_decode(p, adat.dat);
if(len < 0){
printf("Failed to decode base64 from server.\n");
- verbose = old_verbose;
- return -1;
+ return AUTH_ERROR;
}
- ret = krb_rd_safe(adat, len, &key,
+ adat.length = len;
+ ret = krb_rd_safe(adat.dat, adat.length, &d->key,
&hisctladdr, &myctladdr, &msg_data);
if(ret){
printf("Error reading reply from server: %s.\n",
krb_get_err_text(ret));
- verbose = old_verbose;
- return -1;
+ return AUTH_ERROR;
}
- {
- /* the draft doesn't tell what size the return has */
- int i;
- u_int32_t cs = 0;
- for(i = 0; i < msg_data.app_length; i++)
- cs = (cs<<8) + msg_data.app_data[i];
- if(cs - checksum != 1){
- printf("Bad checksum returned from server.\n");
- verbose = old_verbose;
- return -1;
- }
+ krb_get_int(msg_data.app_data, &cs, 4, 0);
+ if(cs - checksum != 1){
+ printf("Bad checksum returned from server.\n");
+ return AUTH_ERROR;
}
- auth_complete = 1;
- verbose = old_verbose;
- return 0;
-}
-
-void
-krb4_quit(void)
-{
- auth_complete = 0;
-}
-
-int krb4_write_enc(FILE *F, char *fmt, va_list ap)
-{
- int len;
- char *p;
- char buf[1024];
- char enc[1024];
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
- len = krb_mk_priv(buf, enc, strlen(buf), schedule, &key,
- &myctladdr, &hisctladdr);
- base64_encode(enc, len, &p);
-
- fprintf(F, "ENC %s", p);
- free (p);
- return 0;
+ return AUTH_OK;
}
+struct sec_client_mech krb4_client_mech = {
+ "KERBEROS_V4",
+ sizeof(struct krb4_data),
+ NULL, /* init */
+ krb4_auth,
+ NULL, /* end */
+ krb4_check_prot,
+ krb4_overhead,
+ krb4_encode,
+ krb4_decode
+};
-int krb4_read_msg(char *s, int priv)
-{
- int len;
- int ret;
- char buf[1024];
- MSG_DAT m;
- int code;
-
- len = base64_decode(s + 4, buf);
- if(priv)
- ret = krb_rd_priv(buf, len, schedule, &key,
- &hisctladdr, &myctladdr, &m);
- else
- ret = krb_rd_safe(buf, len, &key, &hisctladdr, &myctladdr, &m);
- if(ret){
- printf("%s\n", krb_get_err_text(ret));
- return -1;
- }
-
- m.app_data[m.app_length] = 0;
- if(m.app_data[3] == '-')
- code = 0;
- else
- sscanf((char*)m.app_data, "%d", &code);
- strncpy(s, (char*)m.app_data, strlen((char*)m.app_data));
-
- s[m.app_length] = 0;
- len = strlen(s);
- if(s[len-1] == '\n')
- s[len-1] = 0;
-
- return code;
-}
-
-int
-krb4_read_mic(char *s)
-{
- return krb4_read_msg(s, 0);
-}
-
-int
-krb4_read_enc(char *s)
-{
- return krb4_read_msg(s, 1);
-}
-
+#endif /* FTP_SERVER */
diff --git a/crypto/kerberosIV/appl/ftp/ftp/main.c b/crypto/kerberosIV/appl/ftp/ftp/main.c
index 4d1b6a5..5b0fe36 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/main.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/main.c
@@ -36,7 +36,7 @@
*/
#include "ftp_locl.h"
-RCSID("$Id: main.c,v 1.20 1997/04/20 16:14:55 joda Exp $");
+RCSID("$Id: main.c,v 1.25 1999/05/08 02:22:09 assar Exp $");
int
main(int argc, char **argv)
@@ -54,8 +54,9 @@ main(int argc, char **argv)
doglob = 1;
interactive = 1;
autologin = 1;
+ passivemode = 0; /* passive mode not active */
- while ((ch = getopt(argc, argv, "dgintv")) != EOF) {
+ while ((ch = getopt(argc, argv, "dginptv")) != EOF) {
switch (ch) {
case 'd':
options |= SO_DEBUG;
@@ -74,6 +75,9 @@ main(int argc, char **argv)
autologin = 0;
break;
+ case 'p':
+ passivemode = 1;
+ break;
case 't':
trace++;
break;
@@ -84,7 +88,7 @@ main(int argc, char **argv)
default:
fprintf(stderr,
- "usage: ftp [-dgintv] [host [port]]\n");
+ "usage: ftp [-dginptv] [host [port]]\n");
exit(1);
}
}
@@ -96,7 +100,6 @@ main(int argc, char **argv)
verbose++;
cpend = 0; /* no pending replies */
proxy = 0; /* proxy not active */
- passivemode = 0; /* passive mode not active */
crflag = 1; /* strip c.r. on ascii gets */
sendport = -1; /* not using ports */
/*
@@ -104,8 +107,8 @@ main(int argc, char **argv)
*/
pw = k_getpwuid(getuid());
if (pw != NULL) {
+ strcpy_truncate(homedir, pw->pw_dir, sizeof(homedir));
home = homedir;
- strcpy(home, pw->pw_dir);
}
if (argc > 0) {
char *xargv[5];
@@ -174,6 +177,7 @@ lostpeer(int sig)
}
proxflag = 0;
pswitch(0);
+ sec_end();
SIGRETURN(0);
}
@@ -242,8 +246,7 @@ cmdscanner(int top)
p = readline("ftp> ");
if(p == NULL)
quit(0, 0);
- strncpy(line, p, sizeof(line));
- line[sizeof(line) - 1] = 0;
+ strcpy_truncate(line, p, sizeof(line));
add_history(p);
free(p);
} else{
@@ -337,12 +340,16 @@ makeargv(void)
for (margc = 0; ; margc++) {
/* Expand array if necessary */
if (margc == margvlen) {
+ int i;
+
margv = (margvlen == 0)
? (char **)malloc(20 * sizeof(char *))
: (char **)realloc(margv,
(margvlen + 20)*sizeof(char *));
if (margv == NULL)
errx(1, "cannot realloc argv array");
+ for(i = margvlen; i < margvlen + 20; ++i)
+ margv[i] = NULL;
margvlen += 20;
argp = margv + margc;
}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c
index 8cea6d4..043e6fb 100644
--- a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c
+++ b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c
@@ -32,7 +32,7 @@
*/
#include "ftp_locl.h"
-RCSID("$Id: ruserpass.c,v 1.10 1997/05/02 14:27:55 assar Exp $");
+RCSID("$Id: ruserpass.c,v 1.15 1999/03/11 13:54:58 joda Exp $");
static int token (void);
static FILE *cfile;
@@ -63,175 +63,213 @@ static struct toktab {
{ NULL, 0 }
};
+/*
+ * Write a copy of the hostname into `hostname, sz' and return a guess
+ * as to the `domain' of that hostname.
+ */
+
+static char *
+guess_domain (char *hostname, size_t sz)
+{
+ struct hostent *he;
+ char *dot;
+ char *a;
+ char **aliases;
+
+ if (gethostname (hostname, sz) < 0) {
+ strcpy_truncate (hostname, "", sz);
+ return "";
+ }
+ dot = strchr (hostname, '.');
+ if (dot != NULL)
+ return dot + 1;
+
+ he = gethostbyname (hostname);
+ if (he == NULL)
+ return hostname;
+
+ dot = strchr (he->h_name, '.');
+ if (dot != NULL) {
+ strcpy_truncate (hostname, he->h_name, sz);
+ return dot + 1;
+ }
+ for (aliases = he->h_aliases; (a = *aliases) != NULL; ++aliases) {
+ dot = strchr (a, '.');
+ if (dot != NULL) {
+ strcpy_truncate (hostname, a, sz);
+ return dot + 1;
+ }
+ }
+ return hostname;
+}
+
int
ruserpass(char *host, char **aname, char **apass, char **aacct)
{
- char *hdir, buf[BUFSIZ], *tmp;
- int t, i, c, usedefault = 0;
- struct stat stb;
+ char *hdir, buf[BUFSIZ], *tmp;
+ int t, i, c, usedefault = 0;
+ struct stat stb;
- if(k_gethostname(myhostname, MaxHostNameLen) < 0)
- strcpy(myhostname, "");
- if((mydomain = strchr(myhostname, '.')) == NULL)
- mydomain = myhostname;
- else
- mydomain++;
- hdir = getenv("HOME");
- if (hdir == NULL)
- hdir = ".";
- snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
- cfile = fopen(buf, "r");
- if (cfile == NULL) {
- if (errno != ENOENT)
- warn("%s", buf);
- return (0);
- }
+ mydomain = guess_domain (myhostname, MaxHostNameLen);
+
+ hdir = getenv("HOME");
+ if (hdir == NULL)
+ hdir = ".";
+ snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
+ cfile = fopen(buf, "r");
+ if (cfile == NULL) {
+ if (errno != ENOENT)
+ warn("%s", buf);
+ return (0);
+ }
next:
- while ((t = token())) switch(t) {
+ while ((t = token())) switch(t) {
- case DEFAULT:
- usedefault = 1;
- /* FALL THROUGH */
+ case DEFAULT:
+ usedefault = 1;
+ /* FALL THROUGH */
- case MACH:
- if (!usedefault) {
- if (token() != ID)
- continue;
- /*
- * Allow match either for user's input host name
- * or official hostname. Also allow match of
- * incompletely-specified host in local domain.
- */
- if (strcasecmp(host, tokval) == 0)
- goto match;
- if (strcasecmp(hostname, tokval) == 0)
- goto match;
- if ((tmp = strchr(hostname, '.')) != NULL &&
- tmp++ &&
- strcasecmp(tmp, mydomain) == 0 &&
- strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
- tokval[tmp - hostname] == '\0')
- goto match;
- if ((tmp = strchr(host, '.')) != NULL &&
- tmp++ &&
- strcasecmp(tmp, mydomain) == 0 &&
- strncasecmp(host, tokval, tmp - host) == 0 &&
- tokval[tmp - host] == '\0')
- goto match;
- continue;
- }
- match:
- while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
+ case MACH:
+ if (!usedefault) {
+ if (token() != ID)
+ continue;
+ /*
+ * Allow match either for user's input host name
+ * or official hostname. Also allow match of
+ * incompletely-specified host in local domain.
+ */
+ if (strcasecmp(host, tokval) == 0)
+ goto match;
+ if (strcasecmp(hostname, tokval) == 0)
+ goto match;
+ if ((tmp = strchr(hostname, '.')) != NULL &&
+ tmp++ &&
+ strcasecmp(tmp, mydomain) == 0 &&
+ strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
+ tokval[tmp - hostname] == '\0')
+ goto match;
+ if ((tmp = strchr(host, '.')) != NULL &&
+ tmp++ &&
+ strcasecmp(tmp, mydomain) == 0 &&
+ strncasecmp(host, tokval, tmp - host) == 0 &&
+ tokval[tmp - host] == '\0')
+ goto match;
+ continue;
+ }
+ match:
+ while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
- case LOGIN:
- if (token())
- if (*aname == 0) {
- *aname = strdup(tokval);
- } else {
- if (strcmp(*aname, tokval))
- goto next;
- }
- break;
- case PASSWD:
- if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
- fstat(fileno(cfile), &stb) >= 0 &&
- (stb.st_mode & 077) != 0) {
- warnx("Error: .netrc file is readable by others.");
- warnx("Remove password or make file unreadable by others.");
- goto bad;
- }
- if (token() && *apass == 0) {
- *apass = strdup(tokval);
- }
- break;
- case ACCOUNT:
- if (fstat(fileno(cfile), &stb) >= 0
- && (stb.st_mode & 077) != 0) {
- warnx("Error: .netrc file is readable by others.");
- warnx("Remove account or make file unreadable by others.");
- goto bad;
- }
- if (token() && *aacct == 0) {
- *aacct = strdup(tokval);
- }
- break;
- case MACDEF:
- if (proxy) {
- fclose(cfile);
- return (0);
- }
- while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t');
- if (c == EOF || c == '\n') {
- printf("Missing macdef name argument.\n");
- goto bad;
- }
- if (macnum == 16) {
- printf("Limit of 16 macros have already been defined\n");
- goto bad;
- }
- tmp = macros[macnum].mac_name;
- *tmp++ = c;
- for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
- !isspace(c); ++i) {
- *tmp++ = c;
- }
- if (c == EOF) {
- printf("Macro definition missing null line terminator.\n");
- goto bad;
- }
- *tmp = '\0';
- if (c != '\n') {
- while ((c=getc(cfile)) != EOF && c != '\n');
- }
- if (c == EOF) {
- printf("Macro definition missing null line terminator.\n");
- goto bad;
- }
- if (macnum == 0) {
- macros[macnum].mac_start = macbuf;
- }
- else {
- macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
- }
- tmp = macros[macnum].mac_start;
- while (tmp != macbuf + 4096) {
- if ((c=getc(cfile)) == EOF) {
- printf("Macro definition missing null line terminator.\n");
- goto bad;
- }
- *tmp = c;
- if (*tmp == '\n') {
- if (*(tmp-1) == '\0') {
- macros[macnum++].mac_end = tmp - 1;
- break;
- }
- *tmp = '\0';
- }
- tmp++;
- }
- if (tmp == macbuf + 4096) {
- printf("4K macro buffer exceeded\n");
- goto bad;
- }
- break;
- case PROT:
- token();
- if(sec_request_prot(tokval) < 0)
- warnx("Unknown protection level \"%s\"", tokval);
- break;
- default:
- warnx("Unknown .netrc keyword %s", tokval);
+ case LOGIN:
+ if (token()) {
+ if (*aname == 0) {
+ *aname = strdup(tokval);
+ } else {
+ if (strcmp(*aname, tokval))
+ goto next;
+ }
+ }
+ break;
+ case PASSWD:
+ if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
+ fstat(fileno(cfile), &stb) >= 0 &&
+ (stb.st_mode & 077) != 0) {
+ warnx("Error: .netrc file is readable by others.");
+ warnx("Remove password or make file unreadable by others.");
+ goto bad;
+ }
+ if (token() && *apass == 0) {
+ *apass = strdup(tokval);
+ }
+ break;
+ case ACCOUNT:
+ if (fstat(fileno(cfile), &stb) >= 0
+ && (stb.st_mode & 077) != 0) {
+ warnx("Error: .netrc file is readable by others.");
+ warnx("Remove account or make file unreadable by others.");
+ goto bad;
+ }
+ if (token() && *aacct == 0) {
+ *aacct = strdup(tokval);
+ }
+ break;
+ case MACDEF:
+ if (proxy) {
+ fclose(cfile);
+ return (0);
+ }
+ while ((c=getc(cfile)) != EOF &&
+ (c == ' ' || c == '\t'));
+ if (c == EOF || c == '\n') {
+ printf("Missing macdef name argument.\n");
+ goto bad;
+ }
+ if (macnum == 16) {
+ printf("Limit of 16 macros have already been defined\n");
+ goto bad;
+ }
+ tmp = macros[macnum].mac_name;
+ *tmp++ = c;
+ for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
+ !isspace(c); ++i) {
+ *tmp++ = c;
+ }
+ if (c == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ *tmp = '\0';
+ if (c != '\n') {
+ while ((c=getc(cfile)) != EOF && c != '\n');
+ }
+ if (c == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ if (macnum == 0) {
+ macros[macnum].mac_start = macbuf;
+ }
+ else {
+ macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
+ }
+ tmp = macros[macnum].mac_start;
+ while (tmp != macbuf + 4096) {
+ if ((c=getc(cfile)) == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ *tmp = c;
+ if (*tmp == '\n') {
+ if (*(tmp-1) == '\0') {
+ macros[macnum++].mac_end = tmp - 1;
break;
+ }
+ *tmp = '\0';
}
- goto done;
+ tmp++;
+ }
+ if (tmp == macbuf + 4096) {
+ printf("4K macro buffer exceeded\n");
+ goto bad;
+ }
+ break;
+ case PROT:
+ token();
+ if(sec_request_prot(tokval) < 0)
+ warnx("Unknown protection level \"%s\"", tokval);
+ break;
+ default:
+ warnx("Unknown .netrc keyword %s", tokval);
+ break;
}
+ goto done;
+ }
done:
- fclose(cfile);
- return (0);
+ fclose(cfile);
+ return (0);
bad:
- fclose(cfile);
- return (-1);
+ fclose(cfile);
+ return (-1);
}
static int
diff --git a/crypto/kerberosIV/appl/ftp/ftp/security.c b/crypto/kerberosIV/appl/ftp/ftp/security.c
new file mode 100644
index 0000000..96d598f
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/security.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (c) 1998, 1999 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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.
+ */
+
+#ifdef FTP_SERVER
+#include "ftpd_locl.h"
+#else
+#include "ftp_locl.h"
+#endif
+
+RCSID("$Id: security.c,v 1.8 1999/04/07 14:16:48 joda Exp $");
+
+static enum protection_level command_prot;
+static enum protection_level data_prot;
+static size_t buffer_size;
+
+struct buffer {
+ void *data;
+ size_t size;
+ size_t index;
+ int eof_flag;
+};
+
+static struct buffer in_buffer, out_buffer;
+int sec_complete;
+
+static struct {
+ enum protection_level level;
+ const char *name;
+} level_names[] = {
+ { prot_clear, "clear" },
+ { prot_safe, "safe" },
+ { prot_confidential, "confidential" },
+ { prot_private, "private" }
+};
+
+static const char *
+level_to_name(enum protection_level level)
+{
+ int i;
+ for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
+ if(level_names[i].level == level)
+ return level_names[i].name;
+ return "unknown";
+}
+
+#ifndef FTP_SERVER /* not used in server */
+static enum protection_level
+name_to_level(const char *name)
+{
+ int i;
+ for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
+ if(!strncasecmp(level_names[i].name, name, strlen(name)))
+ return level_names[i].level;
+ return (enum protection_level)-1;
+}
+#endif
+
+#ifdef FTP_SERVER
+
+static struct sec_server_mech *mechs[] = {
+#ifdef KRB5
+ &gss_server_mech,
+#endif
+#ifdef KRB4
+ &krb4_server_mech,
+#endif
+ NULL
+};
+
+static struct sec_server_mech *mech;
+
+#else
+
+static struct sec_client_mech *mechs[] = {
+#ifdef KRB5
+ &gss_client_mech,
+#endif
+#ifdef KRB4
+ &krb4_client_mech,
+#endif
+ NULL
+};
+
+static struct sec_client_mech *mech;
+
+#endif
+
+static void *app_data;
+
+int
+sec_getc(FILE *F)
+{
+ if(sec_complete && data_prot) {
+ char c;
+ if(sec_read(fileno(F), &c, 1) == 0)
+ return EOF;
+ return c;
+ } else
+ return getc(F);
+}
+
+static int
+block_read(int fd, void *buf, size_t len)
+{
+ unsigned char *p = buf;
+ int b;
+ while(len) {
+ b = read(fd, p, len);
+ if(b <= 0)
+ return -1;
+ len -= b;
+ p += b;
+ }
+ return p - (unsigned char*)buf;
+}
+
+static int
+block_write(int fd, void *buf, size_t len)
+{
+ unsigned char *p = buf;
+ int b;
+ while(len) {
+ b = write(fd, p, len);
+ if(b < 0)
+ return -1;
+ len -= b;
+ p += b;
+ }
+ return p - (unsigned char*)buf;
+}
+
+static int
+sec_get_data(int fd, struct buffer *buf, int level)
+{
+ int len;
+
+ if(block_read(fd, &len, sizeof(len)) < 0)
+ return -1;
+ len = ntohl(len);
+ buf->data = realloc(buf->data, len);
+ if(block_read(fd, buf->data, len) < 0)
+ return -1;
+ buf->size = (*mech->decode)(app_data, buf->data, len, data_prot);
+ buf->index = 0;
+ return 0;
+}
+
+static size_t
+buffer_read(struct buffer *buf, void *data, size_t len)
+{
+ len = min(len, buf->size - buf->index);
+ memcpy(data, (char*)buf->data + buf->index, len);
+ buf->index += len;
+ return len;
+}
+
+static size_t
+buffer_write(struct buffer *buf, void *data, size_t len)
+{
+ if(buf->index + len > buf->size) {
+ void *tmp;
+ if(buf->data == NULL)
+ tmp = malloc(1024);
+ else
+ tmp = realloc(buf->data, buf->index + len);
+ if(tmp == NULL)
+ return -1;
+ buf->data = tmp;
+ buf->size = buf->index + len;
+ }
+ memcpy((char*)buf->data + buf->index, data, len);
+ buf->index += len;
+ return len;
+}
+
+int
+sec_read(int fd, void *data, int length)
+{
+ size_t len;
+ int rx = 0;
+
+ if(sec_complete == 0 || data_prot == 0)
+ return read(fd, data, length);
+
+ if(in_buffer.eof_flag){
+ in_buffer.eof_flag = 0;
+ return 0;
+ }
+
+ len = buffer_read(&in_buffer, data, length);
+ length -= len;
+ rx += len;
+ data = (char*)data + len;
+
+ while(length){
+ if(sec_get_data(fd, &in_buffer, data_prot) < 0)
+ return -1;
+ if(in_buffer.size == 0) {
+ if(rx)
+ in_buffer.eof_flag = 1;
+ return rx;
+ }
+ len = buffer_read(&in_buffer, data, length);
+ length -= len;
+ rx += len;
+ data = (char*)data + len;
+ }
+ return rx;
+}
+
+static int
+sec_send(int fd, char *from, int length)
+{
+ int bytes;
+ void *buf;
+ bytes = (*mech->encode)(app_data, from, length, data_prot, &buf);
+ bytes = htonl(bytes);
+ block_write(fd, &bytes, sizeof(bytes));
+ block_write(fd, buf, ntohl(bytes));
+ free(buf);
+ return length;
+}
+
+int
+sec_fflush(FILE *F)
+{
+ if(data_prot != prot_clear) {
+ if(out_buffer.index > 0){
+ sec_write(fileno(F), out_buffer.data, out_buffer.index);
+ out_buffer.index = 0;
+ }
+ sec_send(fileno(F), NULL, 0);
+ }
+ fflush(F);
+ return 0;
+}
+
+int
+sec_write(int fd, char *data, int length)
+{
+ int len = buffer_size;
+ int tx = 0;
+
+ if(data_prot == prot_clear)
+ return write(fd, data, length);
+
+ len -= (*mech->overhead)(app_data, data_prot, len);
+ while(length){
+ if(length < len)
+ len = length;
+ sec_send(fd, data, len);
+ length -= len;
+ data += len;
+ tx += len;
+ }
+ return tx;
+}
+
+int
+sec_putc(int c, FILE *F)
+{
+ char ch = c;
+ if(data_prot == prot_clear)
+ return putc(c, F);
+
+ buffer_write(&out_buffer, &ch, 1);
+ if(c == '\n' || out_buffer.index >= 1024 /* XXX */) {
+ sec_write(fileno(F), out_buffer.data, out_buffer.index);
+ out_buffer.index = 0;
+ }
+ return c;
+}
+
+int
+sec_read_msg(char *s, int level)
+{
+ int len;
+ char *buf;
+ int code;
+
+ buf = malloc(strlen(s));
+ len = base64_decode(s + 4, buf); /* XXX */
+
+ len = (*mech->decode)(app_data, buf, len, level);
+ if(len < 0)
+ return -1;
+
+ buf[len] = '\0';
+
+ if(buf[3] == '-')
+ code = 0;
+ else
+ sscanf(buf, "%d", &code);
+ if(buf[len-1] == '\n')
+ buf[len-1] = '\0';
+ strcpy(s, buf);
+ free(buf);
+ return code;
+}
+
+int
+sec_vfprintf(FILE *f, const char *fmt, va_list ap)
+{
+ char *buf;
+ void *enc;
+ int len;
+ if(!sec_complete)
+ return vfprintf(f, fmt, ap);
+
+ vasprintf(&buf, fmt, ap);
+ len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc);
+ free(buf);
+ if(len < 0) {
+ printf("Failed to encode command.\n");
+ return -1;
+ }
+ if(base64_encode(enc, len, &buf) < 0){
+ printf("Out of memory base64-encoding.\n");
+ return -1;
+ }
+#ifdef FTP_SERVER
+ if(command_prot == prot_safe)
+ fprintf(f, "631 %s\r\n", buf);
+ else if(command_prot == prot_private)
+ fprintf(f, "632 %s\r\n", buf);
+ else if(command_prot == prot_confidential)
+ fprintf(f, "633 %s\r\n", buf);
+#else
+ if(command_prot == prot_safe)
+ fprintf(f, "MIC %s", buf);
+ else if(command_prot == prot_private)
+ fprintf(f, "ENC %s", buf);
+ else if(command_prot == prot_confidential)
+ fprintf(f, "CONF %s", buf);
+#endif
+ free(buf);
+ return 0;
+}
+
+int
+sec_fprintf(FILE *f, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ va_start(ap, fmt);
+ ret = sec_vfprintf(f, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+/* end common stuff */
+
+#ifdef FTP_SERVER
+
+void
+auth(char *auth_name)
+{
+ int i;
+ for(i = 0; (mech = mechs[i]) != NULL; i++){
+ if(!strcasecmp(auth_name, mech->name)){
+ app_data = realloc(app_data, mech->size);
+ if(mech->init && (*mech->init)(app_data) != 0) {
+ reply(431, "Unable to accept %s at this time", mech->name);
+ return;
+ }
+ if(mech->auth) {
+ (*mech->auth)(app_data);
+ return;
+ }
+ if(mech->adat)
+ reply(334, "Send authorization data.");
+ else
+ reply(234, "Authorization complete.");
+ return;
+ }
+ }
+ free (app_data);
+ reply(504, "%s is unknown to me", auth_name);
+}
+
+void
+adat(char *auth_data)
+{
+ if(mech && !sec_complete) {
+ void *buf = malloc(strlen(auth_data));
+ size_t len;
+ len = base64_decode(auth_data, buf);
+ (*mech->adat)(app_data, buf, len);
+ free(buf);
+ } else
+ reply(503, "You must %sissue an AUTH first.", mech ? "re-" : "");
+}
+
+void pbsz(int size)
+{
+ size_t new = size;
+ if(!sec_complete)
+ reply(503, "Incomplete security data exchange.");
+ if(mech->pbsz)
+ new = (*mech->pbsz)(app_data, size);
+ if(buffer_size != new){
+ buffer_size = size;
+ }
+ if(new != size)
+ reply(200, "PBSZ=%lu", (unsigned long)new);
+ else
+ reply(200, "OK");
+}
+
+void
+prot(char *pl)
+{
+ int p = -1;
+
+ if(buffer_size == 0){
+ reply(503, "No protection buffer size negotiated.");
+ return;
+ }
+
+ if(!strcasecmp(pl, "C"))
+ p = prot_clear;
+ else if(!strcasecmp(pl, "S"))
+ p = prot_safe;
+ else if(!strcasecmp(pl, "E"))
+ p = prot_confidential;
+ else if(!strcasecmp(pl, "P"))
+ p = prot_private;
+ else {
+ reply(504, "Unrecognized protection level.");
+ return;
+ }
+
+ if(sec_complete){
+ if((*mech->check_prot)(app_data, p)){
+ reply(536, "%s does not support %s protection.",
+ mech->name, level_to_name(p));
+ }else{
+ data_prot = (enum protection_level)p;
+ reply(200, "Data protection is %s.", level_to_name(p));
+ }
+ }else{
+ reply(503, "Incomplete security data exchange.");
+ }
+}
+
+void ccc(void)
+{
+ if(sec_complete){
+ if(mech->ccc && (*mech->ccc)(app_data) == 0)
+ command_prot = data_prot = prot_clear;
+ else
+ reply(534, "You must be joking.");
+ }else
+ reply(503, "Incomplete security data exchange.");
+}
+
+void mec(char *msg, enum protection_level level)
+{
+ void *buf;
+ size_t len;
+ if(!sec_complete) {
+ reply(503, "Incomplete security data exchange.");
+ return;
+ }
+ buf = malloc(strlen(msg) + 2); /* XXX go figure out where that 2
+ comes from :-) */
+ len = base64_decode(msg, buf);
+ command_prot = level;
+ if(len == (size_t)-1) {
+ reply(501, "Failed to base64-decode command");
+ return;
+ }
+ len = (*mech->decode)(app_data, buf, len, level);
+ if(len == (size_t)-1) {
+ reply(535, "Failed to decode command");
+ return;
+ }
+ ((char*)buf)[len] = '\0';
+ if(strstr((char*)buf, "\r\n") == NULL)
+ strcat((char*)buf, "\r\n");
+ new_ftp_command(buf);
+}
+
+/* ------------------------------------------------------------ */
+
+int
+sec_userok(char *user)
+{
+ if(sec_complete)
+ return (*mech->userok)(app_data, user);
+ return 0;
+}
+
+char *ftp_command;
+
+void
+new_ftp_command(char *command)
+{
+ ftp_command = command;
+}
+
+void
+delete_ftp_command(void)
+{
+ free(ftp_command);
+ ftp_command = NULL;
+}
+
+int
+secure_command(void)
+{
+ return ftp_command != NULL;
+}
+
+#else /* FTP_SERVER */
+
+void
+sec_status(void)
+{
+ if(sec_complete){
+ printf("Using %s for authentication.\n", mech->name);
+ printf("Using %s command channel.\n", level_to_name(command_prot));
+ printf("Using %s data channel.\n", level_to_name(data_prot));
+ if(buffer_size > 0)
+ printf("Protection buffer size: %lu.\n",
+ (unsigned long)buffer_size);
+ }else{
+ printf("Not using any security mechanism.\n");
+ }
+}
+
+static int
+sec_prot_internal(int level)
+{
+ int ret;
+ char *p;
+ unsigned int s = 1048576;
+
+ int old_verbose = verbose;
+ verbose = 0;
+
+ if(!sec_complete){
+ printf("No security data exchange has taken place.\n");
+ return -1;
+ }
+
+ if(level){
+ ret = command("PBSZ %u", s);
+ if(ret != COMPLETE){
+ printf("Failed to set protection buffer size.\n");
+ return -1;
+ }
+ buffer_size = s;
+ p = strstr(reply_string, "PBSZ=");
+ if(p)
+ sscanf(p, "PBSZ=%u", &s);
+ if(s < buffer_size)
+ buffer_size = s;
+ }
+ verbose = old_verbose;
+ ret = command("PROT %c", level["CSEP"]); /* XXX :-) */
+ if(ret != COMPLETE){
+ printf("Failed to set protection level.\n");
+ return -1;
+ }
+
+ data_prot = (enum protection_level)level;
+ return 0;
+}
+
+void
+sec_prot(int argc, char **argv)
+{
+ int level = -1;
+
+ if(argc != 2){
+ printf("usage: %s (clear | safe | confidential | private)\n",
+ argv[0]);
+ code = -1;
+ return;
+ }
+ if(!sec_complete){
+ printf("No security data exchange has taken place.\n");
+ code = -1;
+ return;
+ }
+ level = name_to_level(argv[1]);
+
+ if(level == -1){
+ printf("usage: %s (clear | safe | confidential | private)\n",
+ argv[0]);
+ code = -1;
+ return;
+ }
+
+ if((*mech->check_prot)(app_data, level)) {
+ printf("%s does not implement %s protection.\n",
+ mech->name, level_to_name(level));
+ code = -1;
+ return;
+ }
+
+ if(sec_prot_internal(level) < 0){
+ code = -1;
+ return;
+ }
+ code = 0;
+}
+
+static enum protection_level request_data_prot;
+
+void
+sec_set_protection_level(void)
+{
+ if(sec_complete && data_prot != request_data_prot)
+ sec_prot_internal(request_data_prot);
+}
+
+
+int
+sec_request_prot(char *level)
+{
+ int l = name_to_level(level);
+ if(l == -1)
+ return -1;
+ request_data_prot = (enum protection_level)l;
+ return 0;
+}
+
+int
+sec_login(char *host)
+{
+ int ret;
+ struct sec_client_mech **m;
+ int old_verbose = verbose;
+
+ verbose = -1; /* shut up all messages this will produce (they
+ are usually not very user friendly) */
+
+ for(m = mechs; *m && (*m)->name; m++) {
+ app_data = realloc(app_data, (*m)->size);
+ if((*m)->init && (*(*m)->init)(app_data) != 0) {
+ printf("Skipping %s...\n", (*m)->name);
+ continue;
+ }
+ printf("Trying %s...\n", (*m)->name);
+ ret = command("AUTH %s", (*m)->name);
+ if(ret != CONTINUE){
+ if(code == 504){
+ printf("%s is not supported by the server.\n", (*m)->name);
+ }else if(code == 534){
+ printf("%s rejected as security mechanism.\n", (*m)->name);
+ }else if(ret == ERROR) {
+ printf("The server doesn't support the FTP "
+ "security extensions.\n");
+ verbose = old_verbose;
+ return -1;
+ }
+ continue;
+ }
+
+ ret = (*(*m)->auth)(app_data, host);
+
+ if(ret == AUTH_CONTINUE)
+ continue;
+ else if(ret != AUTH_OK){
+ /* mechanism is supposed to output error string */
+ verbose = old_verbose;
+ return -1;
+ }
+ mech = *m;
+ sec_complete = 1;
+ command_prot = prot_safe;
+ break;
+ }
+
+ verbose = old_verbose;
+ return *m == NULL;
+}
+
+void
+sec_end(void)
+{
+ if (mech != NULL) {
+ if(mech->end)
+ (*mech->end)(app_data);
+ memset(app_data, 0, mech->size);
+ free(app_data);
+ }
+ sec_complete = 0;
+ data_prot = (enum protection_level)0;
+}
+
+#endif /* FTP_SERVER */
+
diff --git a/crypto/kerberosIV/appl/ftp/ftp/security.h b/crypto/kerberosIV/appl/ftp/ftp/security.h
new file mode 100644
index 0000000..adac689
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/security.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1998, 1999 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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: security.h,v 1.3 1999/04/07 14:15:20 joda Exp $ */
+
+#ifndef __security_h__
+#define __security_h__
+
+enum protection_level {
+ prot_clear,
+ prot_safe,
+ prot_confidential,
+ prot_private
+};
+
+struct sec_client_mech {
+ char *name;
+ size_t size;
+ int (*init)(void *);
+ int (*auth)(void *, char*);
+ void (*end)(void *);
+ int (*check_prot)(void *, int);
+ int (*overhead)(void *, int, int);
+ int (*encode)(void *, void*, int, int, void**);
+ int (*decode)(void *, void*, int, int);
+};
+
+struct sec_server_mech {
+ char *name;
+ size_t size;
+ int (*init)(void *);
+ void (*end)(void *);
+ int (*check_prot)(void *, int);
+ int (*overhead)(void *, int, int);
+ int (*encode)(void *, void*, int, int, void**);
+ int (*decode)(void *, void*, int, int);
+
+ int (*auth)(void *);
+ int (*adat)(void *, void*, size_t);
+ size_t (*pbsz)(void *, size_t);
+ int (*ccc)(void*);
+ int (*userok)(void*, char*);
+};
+
+#define AUTH_OK 0
+#define AUTH_CONTINUE 1
+#define AUTH_ERROR 2
+
+#ifdef FTP_SERVER
+extern struct sec_server_mech krb4_server_mech, gss_server_mech;
+#else
+extern struct sec_client_mech krb4_client_mech, gss_client_mech;
+#endif
+
+extern int sec_complete;
+
+#ifdef FTP_SERVER
+extern char *ftp_command;
+void new_ftp_command(char*);
+void delete_ftp_command(void);
+#endif
+
+/* ---- */
+
+
+int sec_fflush (FILE *);
+int sec_fprintf (FILE *, const char *, ...);
+int sec_getc (FILE *);
+int sec_putc (int, FILE *);
+int sec_read (int, void *, int);
+int sec_read_msg (char *, int);
+int sec_vfprintf (FILE *, const char *, va_list);
+int sec_write (int, char *, int);
+
+#ifdef FTP_SERVER
+void adat (char *);
+void auth (char *);
+void ccc (void);
+void mec (char *, enum protection_level);
+void pbsz (int);
+void prot (char *);
+void delete_ftp_command (void);
+void new_ftp_command (char *);
+int sec_userok (char *);
+int secure_command (void);
+#else
+void sec_end (void);
+int sec_login (char *);
+void sec_prot (int, char **);
+int sec_request_prot (char *);
+void sec_set_protection_level (void);
+void sec_status (void);
+#endif
+
+#endif /* __security_h__ */
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am
new file mode 100644
index 0000000..187fca3
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am
@@ -0,0 +1,53 @@
+# $Id: Makefile.am,v 1.19 1999/04/25 13:24:55 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER
+
+libexec_PROGRAMS = ftpd
+
+CHECK_LOCAL =
+
+if KRB4
+krb4_sources = krb4.c kauth.c
+endif
+if KRB5
+krb5_sources = gssapi.c gss_userok.c
+endif
+
+ftpd_SOURCES = \
+ extern.h \
+ ftpcmd.y \
+ ftpd.c \
+ ftpd_locl.h \
+ logwtmp.c \
+ pathnames.h \
+ popen.c \
+ security.c \
+ $(krb4_sources) \
+ $(krb5_sources)
+
+EXTRA_ftpd_SOURCES = krb4.c kauth.c gssapi.c gss_userok.c
+
+$(ftpd_OBJECTS): security.h
+
+security.c:
+ @test -f security.c || $(LN_S) $(srcdir)/../ftp/security.c .
+security.h:
+ @test -f security.h || $(LN_S) $(srcdir)/../ftp/security.h .
+krb4.c:
+ @test -f krb4.c || $(LN_S) $(srcdir)/../ftp/krb4.c .
+gssapi.c:
+ @test -f gssapi.c || $(LN_S) $(srcdir)/../ftp/gssapi.c .
+
+CLEANFILES = security.c security.h krb4.c gssapi.c ftpcmd.c
+
+LDADD = ../common/libcommon.a \
+ $(LIB_kafs) \
+ $(LIB_gssapi) \
+ $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(LIB_otp) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_roken) \
+ $(DBLIB)
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in
index 55981de..3b555a6 100644
--- a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in
+++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in
@@ -1,12 +1,12 @@
#
-# $Id: Makefile.in,v 1.31 1997/05/02 17:49:27 assar Exp $
+# $Id: Makefile.in,v 1.40 1999/03/10 19:01:11 joda Exp $
#
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
-topdir = ../../..
+top_builddir = ../../..
SHELL = /bin/sh
@@ -14,7 +14,8 @@ CC = @CC@
YACC = @YACC@
RANLIB = @RANLIB@
DEFS = @DEFS@
-CFLAGS = @CFLAGS@
+WFLAGS = @WFLAGS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
LD_FLAGS = @LD_FLAGS@
LIBS = @LIBS@
LIB_DBM = @LIB_DBM@
@@ -23,6 +24,8 @@ MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LN_S = @LN_S@
+
prefix = @prefix@
exec_prefix = @exec_prefix@
libdir = @libdir@
@@ -39,31 +42,42 @@ LIBTOP = $(ATHENA)/lib
LIBKAFS = @KRB_KAFS_LIB@
LIBKRB = -L$(LIBTOP)/krb -lkrb
LIBDES = -L$(LIBTOP)/des -ldes
-LIBOTP = -L$(LIBTOP)/otp -lotp
+LIBOTP = @LIB_otp@
LIBROKEN= -L$(LIBTOP)/roken -lroken
PROGS = ftpd$(EXECSUFFIX)
-ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c popen.c auth.c krb4.c kauth.c
-ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o auth.o krb4.o kauth.o
+ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c popen.c security.c krb4.c kauth.c
+ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o security.o krb4.o kauth.o
SOURCES = $(ftpd_SOURCES)
OBJECTS = $(ftpd_OBJS)
all: $(PROGS)
+$(ftpd_OBJS): security.h
+
+security.c:
+ $(LN_S) $(srcdir)/../ftp/security.c .
+security.h:
+ $(LN_S) $(srcdir)/../ftp/security.h .
+krb4.c:
+ $(LN_S) $(srcdir)/../ftp/krb4.c .
+gssapi.c:
+ $(LN_S) $(srcdir)/../ftp/gssapi.c .
+
.c.o:
- $(CC) -c $(CFLAGS) -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $<
+ $(CC) -c -DFTP_SERVER -I. -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $(CFLAGS) $(CPPFLAGS) $<
install: all
- $(MKINSTALLDIRS) $(libexecdir)
+ $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir)
for x in $(PROGS); do \
- $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
done
uninstall:
for x in $(PROGS); do \
- rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
done
ftpd$(EXECSUFFIX): $(ftpd_OBJS)
@@ -77,8 +91,12 @@ ftpcmd.c: ftpcmd.y
TAGS: $(SOURCES)
etags $(SOURCES)
+CLEANFILES = ftpd$(EXECSUFFIX) ftpcmd.c security.c security.h krb4.c gssapi.c
+
clean cleandir:
- rm -f *~ *.o core ftpd ftpcmd.c \#*
+ rm -f *~ *.o core \#* $(CLEANFILES)
distclean:
rm -f Makefile
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/extern.h b/crypto/kerberosIV/appl/ftp/ftpd/extern.h
index f9b800f..e96809e 100644
--- a/crypto/kerberosIV/appl/ftp/ftpd/extern.h
+++ b/crypto/kerberosIV/appl/ftp/ftpd/extern.h
@@ -36,6 +36,9 @@
#ifndef _EXTERN_H_
#define _EXTERN_H_
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
@@ -49,8 +52,13 @@
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef NBBY
+#define NBBY CHAR_BIT
#endif
void abor(void);
@@ -63,8 +71,8 @@ void fatal(char *);
int filename_check(char *);
int ftpd_pclose(FILE *);
FILE *ftpd_popen(char *, char *, int, int);
-char *getline(char *, int);
-void logwtmp(char *, char *, char *);
+char *ftpd_getline(char *, int);
+void ftpd_logwtmp(char *, char *, char *);
void lreply(int, const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 2, 3)))
@@ -105,6 +113,11 @@ void yyerror(char *);
void kauth(char *, char*);
void klist(void);
+void cond_kdestroy(void);
+void kdestroy(void);
+void krbtkfile(const char *tkfile);
+void afslog(const char *cell);
+void afsunlog(void);
int find(char *);
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y
index 9368cdb..be36ea2 100644
--- a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y
+++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y
@@ -42,73 +42,15 @@
%{
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-RCSID("$Id: ftpcmd.y,v 1.35 1997/05/25 14:38:49 assar Exp $");
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_FTP_H
-#include <arpa/ftp.h>
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <glob.h>
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#include <setjmp.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_BSD_BSD_H
-#include <bsd/bsd.h>
-#endif
-
-#include <roken.h>
-
-#ifdef SOCKS
-#include <socks.h>
-extern int LIBPREFIX(fclose) __P((FILE *));
-#endif
-
-#include "extern.h"
-#include "auth.h"
+#include "ftpd_locl.h"
+RCSID("$Id: ftpcmd.y,v 1.48 1999/05/08 02:22:43 assar Exp $");
off_t restart_point;
static int cmd_type;
static int cmd_form;
static int cmd_bytesz;
-char cbuf[512];
+char cbuf[2048];
char *fromname;
struct tab {
@@ -122,13 +64,13 @@ struct tab {
extern struct tab cmdtab[];
extern struct tab sitetab[];
-static char *copy (char *);
-static void help (struct tab *, char *);
+static char *copy (char *);
+static void help (struct tab *, char *);
static struct tab *
- lookup (struct tab *, char *);
-static void sizecmd (char *);
-static void toolong (int);
-static int yylex (void);
+ lookup (struct tab *, char *);
+static void sizecmd (char *);
+static RETSIGTYPE toolong (int);
+static int yylex (void);
/* This is for bison */
@@ -154,7 +96,7 @@ static int yylex (void);
APPE MLFL MAIL MSND MSOM MSAM
MRSQ MRCP ALLO REST RNFR RNTO
ABOR DELE CWD LIST NLST SITE
- STAT HELP NOOP MKD RMD PWD
+ sTAT HELP NOOP MKD RMD PWD
CDUP STOU SMNT SYST SIZE MDTM
UMASK IDLE CHMOD
@@ -162,14 +104,15 @@ static int yylex (void);
AUTH ADAT PROT PBSZ CCC MIC
CONF ENC
- KAUTH KLIST FIND URL
+ KAUTH KLIST KDESTROY KRBTKFILE AFSLOG
+ FIND URL
LEXERR
%token <s> STRING
%token <i> NUMBER
-%type <i> check_login check_login_no_guest octal_number byte_size
+%type <i> check_login check_login_no_guest check_secure octal_number byte_size
%type <i> struct_code mode_code type_code form_code
%type <s> pathstring pathname password username
@@ -193,38 +136,6 @@ cmd
user($3);
free($3);
}
- | AUTH SP STRING CRLF
- {
- auth($3);
- free($3);
- }
- | ADAT SP STRING CRLF
- {
- adat($3);
- free($3);
- }
- | PBSZ SP NUMBER CRLF
- {
- pbsz($3);
- }
- | PROT SP STRING CRLF
- {
- prot($3);
- }
- | CCC CRLF
- {
- ccc();
- }
- | MIC SP STRING CRLF
- {
- mic($3);
- free($3);
- }
- | CONF SP STRING CRLF
- {
- conf($3);
- free($3);
- }
| PASS SP password CRLF
{
pass($3);
@@ -311,100 +222,102 @@ cmd
{
reply(202, "ALLO command ignored.");
}
- | RETR check_login SP pathname CRLF
+ | RETR SP pathname CRLF check_login
{
- if ($2 && $4 != NULL)
- retrieve((char *) 0, $4);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ retrieve(0, $3);
+ if ($3 != NULL)
+ free($3);
}
- | STOR check_login SP pathname CRLF
+ | STOR SP pathname CRLF check_login
{
- if ($2 && $4 != NULL)
- do_store($4, "w", 0);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ do_store($3, "w", 0);
+ if ($3 != NULL)
+ free($3);
}
- | APPE check_login SP pathname CRLF
+ | APPE SP pathname CRLF check_login
{
- if ($2 && $4 != NULL)
- do_store($4, "a", 0);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ do_store($3, "a", 0);
+ if ($3 != NULL)
+ free($3);
}
- | NLST check_login CRLF
+ | NLST CRLF check_login
{
- if ($2)
+ if ($3)
send_file_list(".");
}
- | NLST check_login SP STRING CRLF
+ | NLST SP STRING CRLF check_login
{
- if ($2 && $4 != NULL)
- send_file_list($4);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ send_file_list($3);
+ if ($3 != NULL)
+ free($3);
}
- | LIST check_login CRLF
+ | LIST CRLF check_login
{
#ifdef HAVE_LS_A
char *cmd = "/bin/ls -lA";
#else
char *cmd = "/bin/ls -la";
#endif
- if ($2)
+ if ($3)
retrieve(cmd, "");
}
- | LIST check_login SP pathname CRLF
+ | LIST SP pathname CRLF check_login
{
#ifdef HAVE_LS_A
char *cmd = "/bin/ls -lA %s";
#else
char *cmd = "/bin/ls -la %s";
#endif
- if ($2 && $4 != NULL)
- retrieve(cmd, $4);
- if ($4 != NULL)
- free($4);
- }
- | STAT check_login SP pathname CRLF
- {
- if ($2 && $4 != NULL)
- statfilecmd($4);
- if ($4 != NULL)
- free($4);
- }
- | STAT CRLF
- {
- if(oobflag){
- if (file_size != (off_t) -1)
- reply(213, "Status: %ld of %ld bytes transferred",
- byte_count, file_size);
- else
- reply(213, "Status: %ld bytes transferred", byte_count);
- }else
- statcmd();
+ if ($5 && $3 != NULL)
+ retrieve(cmd, $3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | sTAT SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ statfilecmd($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | sTAT CRLF
+ {
+ if(oobflag){
+ if (file_size != (off_t) -1)
+ reply(213, "Status: %lu of %lu bytes transferred",
+ (unsigned long)byte_count,
+ (unsigned long)file_size);
+ else
+ reply(213, "Status: %lu bytes transferred",
+ (unsigned long)byte_count);
+ }else
+ statcmd();
}
- | DELE check_login_no_guest SP pathname CRLF
+ | DELE SP pathname CRLF check_login_no_guest
{
- if ($2 && $4 != NULL)
- do_delete($4);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ do_delete($3);
+ if ($3 != NULL)
+ free($3);
}
- | RNTO check_login_no_guest SP pathname CRLF
+ | RNTO SP pathname CRLF check_login_no_guest
{
- if($2){
+ if($5){
if (fromname) {
- renamecmd(fromname, $4);
+ renamecmd(fromname, $3);
free(fromname);
fromname = (char *) 0;
} else {
reply(503, "Bad sequence of commands.");
}
}
- if ($4 != NULL)
- free($4);
+ if ($3 != NULL)
+ free($3);
}
| ABOR CRLF
{
@@ -416,17 +329,17 @@ cmd
}else
reply(225, "ABOR command successful.");
}
- | CWD check_login CRLF
+ | CWD CRLF check_login
{
- if ($2)
+ if ($3)
cwd(pw->pw_dir);
}
- | CWD check_login SP pathname CRLF
+ | CWD SP pathname CRLF check_login
{
- if ($2 && $4 != NULL)
- cwd($4);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ cwd($3);
+ if ($3 != NULL)
+ free($3);
}
| HELP CRLF
{
@@ -451,28 +364,28 @@ cmd
{
reply(200, "NOOP command successful.");
}
- | MKD check_login SP pathname CRLF
+ | MKD SP pathname CRLF check_login
{
- if ($2 && $4 != NULL)
- makedir($4);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ makedir($3);
+ if ($3 != NULL)
+ free($3);
}
- | RMD check_login_no_guest SP pathname CRLF
+ | RMD SP pathname CRLF check_login_no_guest
{
- if ($2 && $4 != NULL)
- removedir($4);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ removedir($3);
+ if ($3 != NULL)
+ free($3);
}
- | PWD check_login CRLF
+ | PWD CRLF check_login
{
- if ($2)
+ if ($3)
pwd();
}
- | CDUP check_login CRLF
+ | CDUP CRLF check_login
{
- if ($2)
+ if ($3)
cwd("..");
}
| SITE SP HELP CRLF
@@ -483,44 +396,40 @@ cmd
{
help(sitetab, $5);
}
- | SITE SP UMASK check_login CRLF
+ | SITE SP UMASK CRLF check_login
{
- int oldmask;
-
- if ($4) {
- oldmask = umask(0);
+ if ($5) {
+ int oldmask = umask(0);
umask(oldmask);
reply(200, "Current UMASK is %03o", oldmask);
}
}
- | SITE SP UMASK check_login_no_guest SP octal_number CRLF
+ | SITE SP UMASK SP octal_number CRLF check_login_no_guest
{
- int oldmask;
-
- if ($4) {
- if (($6 == -1) || ($6 > 0777)) {
+ if ($7) {
+ if (($5 == -1) || ($5 > 0777)) {
reply(501, "Bad UMASK value");
} else {
- oldmask = umask($6);
+ int oldmask = umask($5);
reply(200,
- "UMASK set to %03o (was %03o)",
- $6, oldmask);
+ "UMASK set to %03o (was %03o)",
+ $5, oldmask);
}
}
}
- | SITE SP CHMOD check_login_no_guest SP octal_number SP pathname CRLF
+ | SITE SP CHMOD SP octal_number SP pathname CRLF check_login_no_guest
{
- if ($4 && $8 != NULL) {
- if ($6 > 0777)
+ if ($9 && $7 != NULL) {
+ if ($5 > 0777)
reply(501,
"CHMOD: Mode value must be between 0 and 0777");
- else if (chmod($8, $6) < 0)
- perror_reply(550, $8);
+ else if (chmod($7, $5) < 0)
+ perror_reply(550, $7);
else
reply(200, "CHMOD command successful.");
}
- if ($8 != NULL)
- free($8);
+ if ($7 != NULL)
+ free($7);
}
| SITE SP IDLE CRLF
{
@@ -543,47 +452,102 @@ cmd
}
}
- | SITE SP KAUTH check_login SP STRING CRLF
+ | SITE SP KAUTH SP STRING CRLF check_login
{
+#ifdef KRB4
char *p;
if(guest)
reply(500, "Can't be done as guest.");
else{
- if($4 && $6 != NULL){
- p = strpbrk($6, " \t");
+ if($7 && $5 != NULL){
+ p = strpbrk($5, " \t");
if(p){
*p++ = 0;
- kauth($6, p + strspn(p, " \t"));
+ kauth($5, p + strspn(p, " \t"));
}else
- kauth($6, NULL);
+ kauth($5, NULL);
}
}
- if($6 != NULL)
- free($6);
+ if($5 != NULL)
+ free($5);
+#else
+ reply(500, "Command not implemented.");
+#endif
}
- | SITE SP KLIST check_login CRLF
+ | SITE SP KLIST CRLF check_login
{
- if($4)
+#ifdef KRB4
+ if($5)
klist();
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP KDESTROY CRLF check_login
+ {
+#ifdef KRB4
+ if($5)
+ kdestroy();
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP KRBTKFILE SP STRING CRLF check_login
+ {
+#ifdef KRB4
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else if($7 && $5)
+ krbtkfile($5);
+ if($5)
+ free($5);
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP AFSLOG CRLF check_login
+ {
+#ifdef KRB4
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else if($5)
+ afslog(NULL);
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP AFSLOG SP STRING CRLF check_login
+ {
+#ifdef KRB4
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else if($7){
+ afslog($5);
+ }
+ if($5)
+ free($5);
+#else
+ reply(500, "Command not implemented.");
+#endif
}
- | SITE SP FIND check_login SP STRING CRLF
+ | SITE SP FIND SP STRING CRLF check_login
{
- if($4 && $6 != NULL)
- find($6);
- if($6 != NULL)
- free($6);
+ if($7 && $5 != NULL)
+ find($5);
+ if($5 != NULL)
+ free($5);
}
| SITE SP URL CRLF
{
reply(200, "http://www.pdc.kth.se/kth-krb/");
}
- | STOU check_login SP pathname CRLF
+ | STOU SP pathname CRLF check_login
{
- if ($2 && $4 != NULL)
- do_store($4, "w", 1);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ do_store($3, "w", 1);
+ if ($3 != NULL)
+ free($3);
}
| SYST CRLF
{
@@ -601,12 +565,12 @@ cmd
* Return size of file in a format suitable for
* using with RESTART (we just count bytes).
*/
- | SIZE check_login SP pathname CRLF
+ | SIZE SP pathname CRLF check_login
{
- if ($2 && $4 != NULL)
- sizecmd($4);
- if ($4 != NULL)
- free($4);
+ if ($5 && $3 != NULL)
+ sizecmd($3);
+ if ($3 != NULL)
+ free($3);
}
/*
@@ -618,15 +582,16 @@ cmd
* where xxx is the fractional second (of any precision,
* not necessarily 3 digits)
*/
- | MDTM check_login SP pathname CRLF
+ | MDTM SP pathname CRLF check_login
{
- if ($2 && $4 != NULL) {
+ if ($5 && $3 != NULL) {
struct stat stbuf;
- if (stat($4, &stbuf) < 0)
+ if (stat($3, &stbuf) < 0)
reply(550, "%s: %s",
- $4, strerror(errno));
+ $3, strerror(errno));
else if (!S_ISREG(stbuf.st_mode)) {
- reply(550, "%s: not a plain file.", $4);
+ reply(550,
+ "%s: not a plain file.", $3);
} else {
struct tm *t;
t = gmtime(&stbuf.st_mtime);
@@ -640,8 +605,8 @@ cmd
t->tm_sec);
}
}
- if ($4 != NULL)
- free($4);
+ if ($3 != NULL)
+ free($3);
}
| QUIT CRLF
{
@@ -654,13 +619,13 @@ cmd
}
;
rcmd
- : RNFR check_login_no_guest SP pathname CRLF
+ : RNFR SP pathname CRLF check_login_no_guest
{
restart_point = (off_t) 0;
- if ($2 && $4) {
- fromname = renamefrom($4);
- if (fromname == (char *) 0 && $4) {
- free($4);
+ if ($5 && $3) {
+ fromname = renamefrom($3);
+ if (fromname == (char *) 0 && $3) {
+ free($3);
}
}
}
@@ -672,9 +637,41 @@ rcmd
(long)restart_point,
"Send STORE or RETRIEVE to initiate transfer.");
}
+ | AUTH SP STRING CRLF
+ {
+ auth($3);
+ free($3);
+ }
+ | ADAT SP STRING CRLF
+ {
+ adat($3);
+ free($3);
+ }
+ | PBSZ SP NUMBER CRLF
+ {
+ pbsz($3);
+ }
+ | PROT SP STRING CRLF
+ {
+ prot($3);
+ }
+ | CCC CRLF
+ {
+ ccc();
+ }
+ | MIC SP STRING CRLF
+ {
+ mec($3, prot_safe);
+ free($3);
+ }
+ | CONF SP STRING CRLF
+ {
+ mec($3, prot_confidential);
+ free($3);
+ }
| ENC SP STRING CRLF
{
- enc($3);
+ mec($3, prot_private);
free($3);
}
;
@@ -861,19 +858,24 @@ check_login_no_guest : check_login
}
;
-check_login
- : /* empty */
+check_login : check_secure
{
- if(auth_complete && prot_level == prot_clear){
- reply(533, "Command protection level denied for paranoid reasons.");
- $$ = 0;
- }else
- if (logged_in)
- $$ = 1;
- else {
+ if($1) {
+ if(($$ = logged_in) == 0)
reply(530, "Please login with USER and PASS.");
- $$ = 0;
- }
+ } else
+ $$ = 0;
+ }
+ ;
+
+check_secure : /* empty */
+ {
+ $$ = 1;
+ if(sec_complete && !secure_command()) {
+ $$ = 0;
+ reply(533, "Command protection level denied "
+ "for paranoid reasons.");
+ }
}
;
@@ -925,7 +927,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */
{ "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
{ "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
{ "SYST", SYST, ARGS, 1, "(get type of operating system)" },
- { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
+ { "STAT", sTAT, OSTR, 1, "[ <sp> path-name ]" },
{ "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
{ "NOOP", NOOP, ARGS, 1, "" },
{ "MKD", MKD, STR1, 1, "<sp> path-name" },
@@ -940,7 +942,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */
{ "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
{ "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
- /* extensions from draft-ietf-cat-ftpsec-08 */
+ /* extensions from RFC2228 */
{ "AUTH", AUTH, STR1, 1, "<sp> auth-type" },
{ "ADAT", ADAT, STR1, 1, "<sp> auth-data" },
{ "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" },
@@ -961,6 +963,9 @@ struct tab sitetab[] = {
{ "KAUTH", KAUTH, STR1, 1, "<sp> principal [ <sp> ticket ]" },
{ "KLIST", KLIST, ARGS, 1, "(show ticket file)" },
+ { "KDESTROY", KDESTROY, ARGS, 1, "(destroy tickets)" },
+ { "KRBTKFILE", KRBTKFILE, STR1, 1, "<sp> ticket-file" },
+ { "AFSLOG", AFSLOG, OSTR, 1, "[<sp> cell]" },
{ "FIND", FIND, STR1, 1, "<sp> globexpr" },
@@ -979,13 +984,11 @@ lookup(struct tab *p, char *cmd)
return (0);
}
-#include <arpa/telnet.h>
-
/*
- * getline - a hacked up version of fgets to ignore TELNET escape codes.
+ * ftpd_getline - a hacked up version of fgets to ignore TELNET escape codes.
*/
char *
-getline(char *s, int n)
+ftpd_getline(char *s, int n)
{
int c;
char *cs;
@@ -993,7 +996,7 @@ getline(char *s, int n)
cs = s;
/* tmpline may contain saved command from urgent mode interruption */
if(ftp_command){
- strncpy(s, ftp_command, n);
+ strcpy_truncate(s, ftp_command, n);
if (debug)
syslog(LOG_DEBUG, "command: %s", s);
#ifdef XXX
@@ -1001,7 +1004,6 @@ getline(char *s, int n)
#endif
return s;
}
- prot_level = prot_clear;
while ((c = getc(stdin)) != EOF) {
c &= 0377;
if (c == IAC) {
@@ -1087,15 +1089,15 @@ yylex(void)
case CMD:
signal(SIGALRM, toolong);
alarm((unsigned) ftpd_timeout);
- if (getline(cbuf, sizeof(cbuf)-1) == NULL) {
+ if (ftpd_getline(cbuf, sizeof(cbuf)-1) == NULL) {
reply(221, "You could at least say goodbye.");
dologout(0);
}
alarm(0);
-#ifdef HASSETPROCTITLE
+#ifdef HAVE_SETPROCTITLE
if (strncasecmp(cbuf, "PASS", 4) != NULL)
setproctitle("%s: %s", proctitle, cbuf);
-#endif /* HASSETPROCTITLE */
+#endif /* HAVE_SETPROCTITLE */
if ((cp = strchr(cbuf, '\r'))) {
*cp++ = '\n';
*cp = '\0';
@@ -1333,16 +1335,21 @@ help(struct tab *ctab, char *s)
columns = 1;
lines = (NCMDS + columns - 1) / columns;
for (i = 0; i < lines; i++) {
- strcpy (buf, " ");
+ strcpy_truncate (buf, " ", sizeof(buf));
for (j = 0; j < columns; j++) {
c = ctab + j * lines + i;
- snprintf (buf + strlen(buf), sizeof(buf) - strlen(buf),
- "%s%c", c->name, c->implemented ? ' ' : '*');
+ snprintf (buf + strlen(buf),
+ sizeof(buf) - strlen(buf),
+ "%s%c",
+ c->name,
+ c->implemented ? ' ' : '*');
if (c + lines >= &ctab[NCMDS])
break;
w = strlen(c->name) + 1;
while (w < width) {
- strcat(buf, " ");
+ strcat_truncate (buf,
+ " ",
+ sizeof(buf));
w++;
}
}
@@ -1375,11 +1382,12 @@ sizecmd(char *filename)
reply(550, "%s: not a plain file.", filename);
else
reply(213, "%lu", (unsigned long)stbuf.st_size);
- break; }
+ break;
+ }
case TYPE_A: {
FILE *fin;
int c;
- off_t count;
+ size_t count;
struct stat stbuf;
fin = fopen(filename, "r");
if (fin == NULL) {
@@ -1400,8 +1408,9 @@ sizecmd(char *filename)
}
fclose(fin);
- reply(213, "%ld", count);
- break; }
+ reply(213, "%lu", (unsigned long)count);
+ break;
+ }
default:
reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c
index 17cd3b9..fa87fc2 100644
--- a/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c
+++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c
@@ -31,122 +31,13 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-RCSID("$Id: ftpd.c,v 1.88 1997/06/01 03:13:48 assar Exp $");
-#endif
-
-/*
- * FTP server.
- */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
-#include <sys/ioctl.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_NETINET_IN_H
-#include <netinet/in.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_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
#define FTP_NAMES
-#include <arpa/ftp.h>
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_ARPA_TELNET_H
-#include <arpa/telnet.h>
+#include "ftpd_locl.h"
+#ifdef KRB5
+#include <krb5.h>
#endif
-#include <ctype.h>
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include <glob.h>
-#include <limits.h>
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#include <setjmp.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-
-#include <err.h>
-
-#include "pathnames.h"
-#include "extern.h"
-#include "common.h"
-
-#include "auth.h"
-
-#include <krb.h>
-
-#include <kafs.h>
-#include "roken.h"
-
-#include <otp.h>
-
-#ifdef SOCKS
-#include <socks.h>
-extern int LIBPREFIX(fclose) __P((FILE *));
-#endif
-
-void yyparse();
-
-#ifndef LOG_FTP
-#define LOG_FTP LOG_DAEMON
-#endif
+RCSID("$Id: ftpd.c,v 1.115 1999/06/15 03:51:47 assar Exp $");
static char version[] = "Version 6.00";
@@ -164,7 +55,7 @@ jmp_buf errcatch, urgcatch;
int oobflag;
int logged_in;
struct passwd *pw;
-int debug;
+int debug = 0;
int ftpd_timeout = 900; /* timeout after 15 minutes of inactivity */
int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
int logging;
@@ -248,12 +139,12 @@ static void usage(void);
static char *
curdir(void)
{
- static char path[MaxPathLen+1+1]; /* path + '/' + '\0' */
+ static char path[MaxPathLen+1]; /* path + '/' + '\0' */
- if (getcwd(path, sizeof(path)-2) == NULL)
+ if (getcwd(path, sizeof(path)-1) == NULL)
return ("");
if (path[1] != '\0') /* special case for root dir. */
- strcat(path, "/");
+ strcat_truncate(path, "/", sizeof(path));
/* For guest account, skip / since it's chrooted */
return (guest ? path+1 : path);
}
@@ -274,8 +165,10 @@ parse_auth_level(char *str)
p = strtok_r(NULL, ",", &foo)) {
if(strcmp(p, "user") == 0)
;
+#ifdef OTP
else if(strcmp(p, "otp") == 0)
ret |= AUTH_PLAIN|AUTH_OTP;
+#endif
else if(strcmp(p, "ftp") == 0 ||
strcmp(p, "safe") == 0)
ret |= AUTH_FTP;
@@ -313,18 +206,20 @@ main(int argc, char **argv)
int not_inetd = 0;
int port;
struct servent *sp;
- char tkfile[1024];
set_progname (argv[0]);
+#ifdef KRB4
/* detach from any tickets and tokens */
-
- snprintf(tkfile, sizeof(tkfile),
- "/tmp/ftp_%u", (unsigned)getpid());
- krb_set_tkt_string(tkfile);
- if(k_hasafs())
- k_setpag();
-
+ {
+ char tkfile[1024];
+ snprintf(tkfile, sizeof(tkfile),
+ "/tmp/ftp_%u", (unsigned)getpid());
+ krb_set_tkt_string(tkfile);
+ if(k_hasafs())
+ k_setpag();
+ }
+#endif
sp = getservbyname("ftp", "tcp");
if(sp)
port = sp->s_port;
@@ -426,7 +321,6 @@ main(int argc, char **argv)
syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
#endif
data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
- debug = 0;
/* set this here so it can be put in wtmp */
snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid());
@@ -440,8 +334,6 @@ main(int argc, char **argv)
syslog(LOG_ERR, "signal: %m");
#endif
- auth_init();
-
/* Try to handle urgent data inline */
#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on,
@@ -486,9 +378,22 @@ main(int argc, char **argv)
fclose(fd);
/* reply(220,) must follow */
}
- k_gethostname(hostname, sizeof(hostname));
- reply(220, "%s FTP server (%s+%s) ready.", hostname,
- version, krb4_version);
+ gethostname(hostname, sizeof(hostname));
+ reply(220, "%s FTP server (%s"
+#ifdef KRB5
+ "+%s"
+#endif
+#ifdef KRB4
+ "+%s"
+#endif
+ ") ready.", hostname, version
+#ifdef KRB5
+ ,heimdal_version
+#endif
+#ifdef KRB4
+ ,krb4_version
+#endif
+ );
setjmp(errcatch);
for (;;)
yyparse();
@@ -552,7 +457,9 @@ sgetpwnam(char *name)
static int login_attempts; /* number of failed login attempts */
static int askpasswd; /* had user command, ask for passwd */
static char curname[10]; /* current USER name */
+#ifdef OTP
OtpContext otp_ctx;
+#endif
/*
* USER command.
@@ -570,7 +477,7 @@ user(char *name)
{
char *cp, *shell;
- if(auth_level == 0 && !auth_complete){
+ if(auth_level == 0 && !sec_complete){
reply(530, "No login allowed without authorization.");
return;
}
@@ -605,7 +512,7 @@ user(char *name)
remotehost, inet_ntoa(his_addr.sin_addr));
return;
}
- if((auth_level & AUTH_PLAIN) == 0 && !auth_complete){
+ if((auth_level & AUTH_PLAIN) == 0 && !sec_complete){
reply(530, "Only authorized and anonymous login allowed.");
return;
}
@@ -630,26 +537,37 @@ user(char *name)
}
}
if (logging)
- strncpy(curname, name, sizeof(curname)-1);
- if(auth_ok())
- ct->userok(name);
- else {
+ strcpy_truncate(curname, name, sizeof(curname));
+ if(sec_complete) {
+ if(sec_userok(name) == 0)
+ do_login(232, name);
+ else
+ reply(530, "User %s access denied.", name);
+ } else {
char ss[256];
+#ifdef OTP
if (otp_challenge(&otp_ctx, name, ss, sizeof(ss)) == 0) {
reply(331, "Password %s for %s required.",
ss, name);
askpasswd = 1;
- } else if ((auth_level & AUTH_OTP) == 0) {
+ } else
+#endif
+ if ((auth_level & AUTH_OTP) == 0) {
reply(331, "Password required for %s.", name);
askpasswd = 1;
} else {
char *s;
- if (s = otp_error (&otp_ctx))
+#ifdef OTP
+ if ((s = otp_error (&otp_ctx)) != NULL)
lreply(530, "OTP: %s", s);
+#endif
reply(530,
- "Only authorized, anonymous and OTP "
+ "Only authorized, anonymous"
+#ifdef OTP
+ " and OTP "
+#endif
"login allowed.");
}
@@ -706,11 +624,7 @@ checkuser(char *fname, char *name)
static int
match(const char *pattern, const char *string)
{
-#ifdef HAVE_FNMATCH
return fnmatch(pattern, string, FNM_NOESCAPE);
-#else
- return strcmp(pattern, "*") != 0 && strcmp(pattern, string) != 0;
-#endif
}
static int
@@ -759,7 +673,7 @@ int do_login(int code, char *passwd)
initgroups(pw->pw_name, pw->pw_gid);
/* open wtmp before chroot */
- logwtmp(ttyline, pw->pw_name, remotehost);
+ ftpd_logwtmp(ttyline, pw->pw_name, remotehost);
logged_in = 1;
dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name);
@@ -842,7 +756,7 @@ end_login(void)
seteuid((uid_t)0);
if (logged_in)
- logwtmp(ttyline, "", "");
+ ftpd_logwtmp(ttyline, "", "");
pw = NULL;
logged_in = 0;
guest = 0;
@@ -869,23 +783,33 @@ pass(char *passwd)
if (!guest) { /* "ftp" is only account allowed no password */
if (pw == NULL)
rval = 1; /* failure below */
+#ifdef OTP
else if (otp_verify_user (&otp_ctx, passwd) == 0) {
rval = 0;
- } else if((auth_level & AUTH_OTP) == 0) {
+ }
+#endif
+ else if((auth_level & AUTH_OTP) == 0) {
+#ifdef KRB4
char realm[REALM_SZ];
if((rval = krb_get_lrealm(realm, 1)) == KSUCCESS)
- rval = krb_verify_user(pw->pw_name, "", realm,
- passwd, 1, NULL);
- if (rval == KSUCCESS ){
+ rval = krb_verify_user(pw->pw_name,
+ "", realm,
+ passwd,
+ KRB_VERIFY_SECURE, NULL);
+ if (rval == KSUCCESS ) {
+ chown (tkt_string(), pw->pw_uid, pw->pw_gid);
if(k_hasafs())
- k_afsklog(0, 0);
- }else
+ krb_afslog(0, 0);
+ } else
+#endif
rval = unix_verify_user(pw->pw_name, passwd);
} else {
char *s;
- if (s = otp_error(&otp_ctx))
+#ifdef OTP
+ if ((s = otp_error(&otp_ctx)) != NULL)
lreply(530, "OTP: %s", s);
+#endif
}
memset (passwd, 0, strlen(passwd));
@@ -935,14 +859,15 @@ retrieve(char *cmd, char *name)
st.st_size = 0;
if(fin == NULL){
struct cmds {
- char *ext;
- char *cmd;
+ const char *ext;
+ const char *cmd;
+ const char *rev_cmd;
} cmds[] = {
- {".tar", "/bin/gtar cPf - %s"},
- {".tar.gz", "/bin/gtar zcPf - %s"},
- {".tar.Z", "/bin/gtar ZcPf - %s"},
- {".gz", "/bin/gzip -c %s"},
- {".Z", "/bin/compress -c %s"},
+ {".tar", "/bin/gtar cPf - %s", NULL},
+ {".tar.gz", "/bin/gtar zcPf - %s", NULL},
+ {".tar.Z", "/bin/gtar ZcPf - %s", NULL},
+ {".gz", "/bin/gzip -c %s", "/bin/gzip -c -d %s"},
+ {".Z", "/bin/compress -c %s", "/bin/uncompress -c -d %s"},
{NULL, NULL}
};
struct cmds *p;
@@ -958,6 +883,21 @@ retrieve(char *cmd, char *name)
break;
}
*tail = c;
+ if (p->rev_cmd != NULL) {
+ char *ext;
+
+ asprintf(&ext, "%s%s", name, p->ext);
+ if (ext != NULL) {
+ if (access(ext, R_OK) == 0) {
+ snprintf (line, sizeof(line),
+ p->rev_cmd, ext);
+ free(ext);
+ break;
+ }
+ free(ext);
+ }
+ }
+
}
if(p->ext){
fin = ftpd_popen(line, "r", 0, 0);
@@ -1173,14 +1113,14 @@ dataconn(char *name, off_t size, char *mode)
{
char sizebuf[32];
FILE *file;
- int retry = 0, tos;
+ int retry = 0;
file_size = size;
byte_count = 0;
- if (size != (off_t) -1)
- snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", size);
+ if (size >= 0)
+ snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", (long)size);
else
- strcpy(sizebuf, "");
+ *sizebuf = '\0';
if (pdata >= 0) {
struct sockaddr_in from;
int s, fromlen = sizeof(from);
@@ -1195,9 +1135,12 @@ dataconn(char *name, off_t size, char *mode)
close(pdata);
pdata = s;
#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
- tos = IPTOS_THROUGHPUT;
- setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos,
- sizeof(int));
+ {
+ int tos = IPTOS_THROUGHPUT;
+
+ setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos,
+ sizeof(tos));
+ }
#endif
reply(150, "Opening %s mode data connection for '%s'%s.",
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
@@ -1249,8 +1192,6 @@ send_data(FILE *instr, FILE *outstr)
int c, cnt, filefd, netfd;
static char *buf;
static size_t bufsize;
- int i = 0;
- char s[1024];
transflag++;
if (setjmp(urgcatch)) {
@@ -1260,31 +1201,24 @@ send_data(FILE *instr, FILE *outstr)
switch (type) {
case TYPE_A:
- while ((c = getc(instr)) != EOF) {
- byte_count++;
- if(i > 1022){
- auth_write(fileno(outstr), s, i);
- i = 0;
- }
- if(c == '\n')
- s[i++] = '\r';
- s[i++] = c;
- }
- if(i)
- auth_write(fileno(outstr), s, i);
- auth_write(fileno(outstr), s, 0);
- fflush(outstr);
- transflag = 0;
- if (ferror(instr))
- goto file_err;
- if (ferror(outstr))
- goto data_err;
- reply(226, "Transfer complete.");
- return;
+ while ((c = getc(instr)) != EOF) {
+ byte_count++;
+ if(c == '\n')
+ sec_putc('\r', outstr);
+ sec_putc(c, outstr);
+ }
+ sec_fflush(outstr);
+ transflag = 0;
+ if (ferror(instr))
+ goto file_err;
+ if (ferror(outstr))
+ goto data_err;
+ reply(226, "Transfer complete.");
+ return;
case TYPE_I:
case TYPE_L:
-#ifdef HAVE_MMAP
+#if defined(HAVE_MMAP) && !defined(NO_MMAP)
#ifndef MAP_FAILED
#define MAP_FAILED (-1)
#endif
@@ -1294,13 +1228,13 @@ send_data(FILE *instr, FILE *outstr)
int in = fileno(instr);
if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)) {
chunk = mmap(0, st.st_size, PROT_READ, MAP_SHARED, in, 0);
- if(chunk != (void *)MAP_FAILED) {
+ if((void *)chunk != (void *)MAP_FAILED) {
cnt = st.st_size - restart_point;
- auth_write(fileno(outstr),
+ sec_write(fileno(outstr),
chunk + restart_point,
cnt);
munmap(chunk, st.st_size);
- auth_write(fileno(outstr), NULL, 0);
+ sec_fflush(outstr);
byte_count = cnt;
transflag = 0;
}
@@ -1321,9 +1255,9 @@ send_data(FILE *instr, FILE *outstr)
return;
}
while ((cnt = read(filefd, buf, bufsize)) > 0 &&
- auth_write(netfd, buf, cnt) == cnt)
+ sec_write(netfd, buf, cnt) == cnt)
byte_count += cnt;
- auth_write(netfd, buf, 0); /* to end an encrypted stream */
+ sec_fflush(outstr); /* to end an encrypted stream */
transflag = 0;
if (cnt != 0) {
if (cnt < 0)
@@ -1381,7 +1315,7 @@ receive_data(FILE *instr, FILE *outstr)
case TYPE_I:
case TYPE_L:
- while ((cnt = auth_read(fileno(instr), buf, bufsize)) > 0) {
+ while ((cnt = sec_read(fileno(instr), buf, bufsize)) > 0) {
if (write(fileno(outstr), buf, cnt) != cnt)
goto file_err;
byte_count += cnt;
@@ -1400,7 +1334,7 @@ receive_data(FILE *instr, FILE *outstr)
{
char *p, *q;
int cr_flag = 0;
- while ((cnt = auth_read(fileno(instr),
+ while ((cnt = sec_read(fileno(instr),
buf + cr_flag,
bufsize - cr_flag)) > 0){
byte_count += cnt;
@@ -1409,7 +1343,7 @@ receive_data(FILE *instr, FILE *outstr)
for(p = buf, q = buf; p < buf + cnt;) {
if(*p == '\n')
bare_lfs++;
- if(*p == '\r')
+ if(*p == '\r') {
if(p == buf + cnt - 1){
cr_flag = 1;
p++;
@@ -1419,6 +1353,7 @@ receive_data(FILE *instr, FILE *outstr)
p += 2;
continue;
}
+ }
*q++ = *p++;
}
fwrite(buf, q - buf, 1, outstr);
@@ -1563,21 +1498,21 @@ __attribute__ ((format (printf, 3, 0)))
static void
int_reply(int n, char *c, const char *fmt, va_list ap)
{
- char buf[10240];
- char *p;
- p=buf;
- if(n){
- snprintf(p, sizeof(buf), "%d%s", n, c);
- p+=strlen(p);
- }
- vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap);
- p+=strlen(p);
- snprintf(p, sizeof(buf) - strlen(p), "\r\n");
- p+=strlen(p);
- auth_printf("%s", buf);
- fflush(stdout);
- if (debug)
- syslog(LOG_DEBUG, "<--- %s- ", buf);
+ char buf[10240];
+ char *p;
+ p=buf;
+ if(n){
+ snprintf(p, sizeof(buf), "%d%s", n, c);
+ p+=strlen(p);
+ }
+ vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap);
+ p+=strlen(p);
+ snprintf(p, sizeof(buf) - strlen(p), "\r\n");
+ p+=strlen(p);
+ sec_fprintf(stdout, "%s", buf);
+ fflush(stdout);
+ if (debug)
+ syslog(LOG_DEBUG, "<--- %s- ", buf);
}
void
@@ -1698,7 +1633,7 @@ removedir(char *name)
void
pwd(void)
{
- char path[MaxPathLen + 1];
+ char path[MaxPathLen];
char *ret;
/* SunOS has a broken getcwd that does popen(pwd) (!!!), this
@@ -1762,10 +1697,10 @@ dologout(int status)
transflag = 0;
if (logged_in) {
seteuid((uid_t)0);
- logwtmp(ttyline, "", "");
- dest_tkt();
- if(k_hasafs())
- k_unlog();
+ ftpd_logwtmp(ttyline, "", "");
+#ifdef KRB4
+ cond_kdestroy();
+#endif
}
/* beware of flushing buffers after a SIGPIPE */
#ifdef XXX
@@ -1801,7 +1736,7 @@ myoob(int signo)
#if 0
cp = tmpline;
- if (getline(cp, 7) == NULL) {
+ if (ftpd_getline(cp, 7) == NULL) {
reply(221, "You could at least say goodbye.");
dologout(0);
}
@@ -1982,7 +1917,7 @@ send_file_list(char *whichf)
}
snprintf(buf, sizeof(buf), "%s%s\n", dirname,
type == TYPE_A ? "\r" : "");
- auth_write(fileno(dout), buf, strlen(buf));
+ sec_write(fileno(dout), buf, strlen(buf));
byte_count += strlen(dirname) + 1;
continue;
} else if (!S_ISDIR(st.st_mode))
@@ -2019,7 +1954,7 @@ send_file_list(char *whichf)
else
snprintf(buf, sizeof(buf), "%s%s\n", nbuf,
type == TYPE_A ? "\r" : "");
- auth_write(fileno(dout), buf, strlen(buf));
+ sec_write(fileno(dout), buf, strlen(buf));
byte_count += strlen(nbuf) + 1;
}
}
@@ -2034,7 +1969,7 @@ send_file_list(char *whichf)
transflag = 0;
if (dout != NULL){
- auth_write(fileno(dout), buf, 0); /* XXX flush */
+ sec_write(fileno(dout), buf, 0); /* XXX flush */
fclose(dout);
}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h
new file mode 100644
index 0000000..4bb3ad3
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1998, 1999 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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: ftpd_locl.h,v 1.5.2.1 1999/07/22 03:24:42 assar Exp $ */
+
+#ifndef __ftpd_locl_h__
+#define __ftpd_locl_h__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * FTP server.
+ */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.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_NETINET_IN_H
+#include <netinet/in.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_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include <arpa/ftp.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <glob.h>
+#include <limits.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#include <fnmatch.h>
+
+#ifdef HAVE_BSD_BSD_H
+#include <bsd/bsd.h>
+#endif
+
+#include <err.h>
+
+#include "pathnames.h"
+#include "extern.h"
+#include "common.h"
+
+#include "security.h"
+
+#include "roken.h"
+
+#ifdef KRB4
+#include <krb.h>
+#include <kafs.h>
+#endif
+
+#ifdef OTP
+#include <otp.h>
+#endif
+
+#ifdef SOCKS
+#include <socks.h>
+extern int LIBPREFIX(fclose) (FILE *);
+#endif
+
+int yyparse();
+
+#ifndef LOG_FTP
+#define LOG_FTP LOG_DAEMON
+#endif
+
+#endif /* __ftpd_locl_h__ */
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c
new file mode 100644
index 0000000..8a1a8e3
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c
@@ -0,0 +1,74 @@
+/*
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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 "ftpd_locl.h"
+#include <gssapi.h>
+#include <krb5.h>
+
+RCSID("$Id: gss_userok.c,v 1.1 1998/05/12 12:15:22 joda Exp $");
+
+/* XXX a bit too much of krb5 dependency here...
+ What is the correct way to do this?
+ */
+
+extern krb5_context gssapi_krb5_context;
+
+/* XXX sync with gssapi.c */
+struct gss_data {
+ gss_ctx_id_t context_hdl;
+ char *client_name;
+};
+
+int gss_userok(void*, char*); /* to keep gcc happy */
+
+int
+gss_userok(void *app_data, char *username)
+{
+ struct gss_data *data = app_data;
+ if(gssapi_krb5_context) {
+ krb5_principal client;
+ krb5_error_code ret;
+ ret = krb5_parse_name(gssapi_krb5_context, data->client_name, &client);
+ if(ret)
+ return 1;
+ ret = krb5_kuserok(gssapi_krb5_context, client, username);
+ krb5_free_principal(gssapi_krb5_context, client);
+ return !ret;
+ }
+ return 1;
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c
index 02d23d6..33795b6 100644
--- a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c
+++ b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -36,34 +36,9 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-RCSID("$Id: kauth.c,v 1.14 1997/05/07 02:21:30 assar Exp $");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <time.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <roken.h>
-
-#include <des.h>
-#include <krb.h>
-#include <kafs.h>
+#include "ftpd_locl.h"
-#include "extern.h"
-#include "krb4.h"
-#include "auth.h"
-#include "base64.h"
+RCSID("$Id: kauth.c,v 1.22 1999/06/29 21:19:33 bg Exp $");
static KTEXT_ST cip;
static unsigned int lifetime;
@@ -71,9 +46,15 @@ static time_t local_time;
static krb_principal pr;
+static int do_destroy_tickets = 1;
+
static int
-save_tkt(char *user, char *instance, char *realm, void *arg,
- int (*key_proc)(char*, char*, char*, void*, des_cblock*), KTEXT *cipp)
+save_tkt(const char *user,
+ const char *instance,
+ const char *realm,
+ const void *arg,
+ key_proc_t key_proc,
+ KTEXT *cipp)
{
local_time = time(0);
memmove(&cip, *cipp, sizeof(cip));
@@ -89,11 +70,9 @@ store_ticket(KTEXT cip)
unsigned char kvno;
KTEXT_ST tkt;
int left = cip->length;
-
+ int len;
int kerror;
- time_t kdc_time;
-
ptr = (char *) cip->dat;
/* extract session key */
@@ -101,29 +80,32 @@ store_ticket(KTEXT cip)
ptr += 8;
left -= 8;
- if (strnlen(ptr, left) == left)
+ len = strnlen(ptr, left);
+ if (len == left)
return(INTK_BADPW);
/* extract server's name */
- strcpy(sp.name, ptr);
- ptr += strlen(sp.name) + 1;
- left -= strlen(sp.name) + 1;
+ strcpy_truncate(sp.name, ptr, sizeof(sp.name));
+ ptr += len + 1;
+ left -= len + 1;
- if (strnlen(ptr, left) == left)
+ len = strnlen(ptr, left);
+ if (len == left)
return(INTK_BADPW);
-
+
/* extract server's instance */
- strcpy(sp.instance, ptr);
- ptr += strlen(sp.instance) + 1;
- left -= strlen(sp.instance) + 1;
+ strcpy_truncate(sp.instance, ptr, sizeof(sp.instance));
+ ptr += len + 1;
+ left -= len + 1;
- if (strnlen(ptr, left) == left)
+ len = strnlen(ptr, left);
+ if (len == left)
return(INTK_BADPW);
-
+
/* extract server's realm */
- strcpy(sp.realm,ptr);
- ptr += strlen(sp.realm) + 1;
- left -= strlen(sp.realm) + 1;
+ strcpy_truncate(sp.realm, ptr, sizeof(sp.realm));
+ ptr += len + 1;
+ left -= len + 1;
if(left < 3)
return INTK_BADPW;
@@ -154,14 +136,18 @@ store_ticket(KTEXT cip)
#if 0
/* check KDC time stamp */
- memmove(&kdc_time, ptr, sizeof(kdc_time));
- if (swap_bytes) swap_u_long(kdc_time);
+ {
+ time_t kdc_time;
- ptr += 4;
+ memmove(&kdc_time, ptr, sizeof(kdc_time));
+ if (swap_bytes) swap_u_long(kdc_time);
+
+ ptr += 4;
- if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) {
- return(RD_AP_TIME); /* XXX should probably be better
+ if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
code */
+ }
}
#endif
@@ -184,7 +170,8 @@ store_ticket(KTEXT cip)
return(kerror);
}
-void kauth(char *principal, char *ticket)
+void
+kauth(char *principal, char *ticket)
{
char *p;
int ret;
@@ -209,8 +196,10 @@ void kauth(char *principal, char *ticket)
memset(&cip, 0, sizeof(cip));
return;
}
+ do_destroy_tickets = 1;
+
if(k_hasafs())
- k_afsklog(0, 0);
+ krb_afslog(0, 0);
reply(200, "Tickets will be destroyed on exit.");
return;
}
@@ -226,7 +215,10 @@ void kauth(char *principal, char *ticket)
reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
return;
}
- base64_encode(cip.dat, cip.length, &p);
+ if(base64_encode(cip.dat, cip.length, &p) < 0) {
+ reply(500, "Out of memory while base64-encoding.");
+ return;
+ }
reply(300, "P=%s T=%s", krb_unparse_name(&pr), p);
free(p);
memset(&cip, 0, sizeof(cip));
@@ -245,7 +237,8 @@ short_date(int32_t dp)
return (cp);
}
-void klist(void)
+void
+klist(void)
{
int err;
@@ -302,6 +295,8 @@ void klist(void)
* it was done before tf_init.
*/
+ lreply(200, "Ticket file: %s", tkt_string());
+
lreply(200, "Principal: %s", krb_unparse_name(&pr));
while ((err = tf_get_cred(&c)) == KSUCCESS) {
if (header) {
@@ -309,17 +304,63 @@ void klist(void)
" Issued", " Expires", " Principal (kvno)");
header = 0;
}
- strcpy(buf1, short_date(c.issue_date));
+ strcpy_truncate(buf1, short_date(c.issue_date), sizeof(buf1));
c.issue_date = krb_life_to_time(c.issue_date, c.lifetime);
if (time(0) < (unsigned long) c.issue_date)
- strcpy(buf2, short_date(c.issue_date));
+ strcpy_truncate(buf2, short_date(c.issue_date), sizeof(buf2));
else
- strcpy(buf2, ">>> Expired <<< ");
+ strcpy_truncate(buf2, ">>> Expired <<< ", sizeof(buf2));
lreply(200, "%s %s %s (%d)", buf1, buf2,
krb_unparse_name_long(c.service, c.instance, c.realm), c.kvno);
}
if (header && err == EOF) {
lreply(200, "No tickets in file.");
}
- reply(200, "");
+ reply(200, " ");
+}
+
+/*
+ * Only destroy if we created the tickets
+ */
+
+void
+cond_kdestroy(void)
+{
+ if (do_destroy_tickets)
+ dest_tkt();
+ afsunlog();
+}
+
+void
+kdestroy(void)
+{
+ dest_tkt();
+ afsunlog();
+ reply(200, "Tickets destroyed");
+}
+
+void
+krbtkfile(const char *tkfile)
+{
+ do_destroy_tickets = 0;
+ krb_set_tkt_string(tkfile);
+ reply(200, "Using ticket file %s", tkfile);
+}
+
+void
+afslog(const char *cell)
+{
+ if(k_hasafs()) {
+ krb_afslog(cell, 0);
+ reply(200, "afslog done");
+ } else {
+ reply(200, "no AFS present");
+ }
+}
+
+void
+afsunlog(void)
+{
+ if(k_hasafs())
+ k_unlog();
}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c
index 95ab216..d948a5a 100644
--- a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c
+++ b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c
@@ -38,7 +38,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id: logwtmp.c,v 1.10 1997/05/25 15:17:56 assar Exp $");
+RCSID("$Id: logwtmp.c,v 1.13 1999/03/01 09:49:37 joda Exp $");
#endif
#include <stdio.h>
@@ -74,18 +74,20 @@ RCSID("$Id: logwtmp.c,v 1.10 1997/05/25 15:17:56 assar Exp $");
#endif
void
-logwtmp(char *line, char *name, char *host)
+ftpd_logwtmp(char *line, char *name, char *host)
{
static int init = 0;
- static int fd, fdx;
- struct timeval tv;
+ static int fd;
+#ifdef WTMPX_FILE
+ static int fdx;
+#endif
struct utmp ut;
#ifdef WTMPX_FILE
struct utmpx utx;
#endif
memset(&ut, 0, sizeof(struct utmp));
-#ifdef HAVE_UT_TYPE
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
if(name[0])
ut.ut_type = USER_PROCESS;
else
@@ -93,10 +95,10 @@ logwtmp(char *line, char *name, char *host)
#endif
strncpy(ut.ut_line, line, sizeof(ut.ut_line));
strncpy(ut.ut_name, name, sizeof(ut.ut_name));
-#ifdef HAVE_UT_PID
+#ifdef HAVE_STRUCT_UTMP_UT_PID
ut.ut_pid = getpid();
#endif
-#ifdef HAVE_UT_HOST
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
strncpy(ut.ut_host, host, sizeof(ut.ut_host));
#endif
ut.ut_time = time(NULL);
@@ -105,14 +107,18 @@ logwtmp(char *line, char *name, char *host)
strncpy(utx.ut_line, line, sizeof(utx.ut_line));
strncpy(utx.ut_user, name, sizeof(utx.ut_user));
strncpy(utx.ut_host, host, sizeof(utx.ut_host));
-#ifdef HAVE_UT_SYSLEN
+#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN
utx.ut_syslen = strlen(host) + 1;
if (utx.ut_syslen > sizeof(utx.ut_host))
utx.ut_syslen = sizeof(utx.ut_host);
#endif
- gettimeofday (&tv, 0);
- utx.ut_tv.tv_sec = tv.tv_sec;
- utx.ut_tv.tv_usec = tv.tv_usec;
+ {
+ struct timeval tv;
+
+ gettimeofday (&tv, 0);
+ utx.ut_tv.tv_sec = tv.tv_sec;
+ utx.ut_tv.tv_usec = tv.tv_usec;
+ }
if(name[0])
utx.ut_type = USER_PROCESS;
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/popen.c b/crypto/kerberosIV/appl/ftp/ftpd/popen.c
index 58c4985..4bd5e04 100644
--- a/crypto/kerberosIV/appl/ftp/ftpd/popen.c
+++ b/crypto/kerberosIV/appl/ftp/ftpd/popen.c
@@ -37,7 +37,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id: popen.c,v 1.16 1997/06/01 03:14:06 assar Exp $");
+RCSID("$Id: popen.c,v 1.18 1998/06/09 19:24:24 joda Exp $");
#endif
#include <sys/types.h>
@@ -89,10 +89,10 @@ ftp_rooted(const char *path)
if(!home[0])
if((pwd = k_getpwnam("ftp")))
- strcpy(home, pwd->pw_dir);
+ strcpy_truncate(home, pwd->pw_dir, sizeof(home));
snprintf(newpath, sizeof(newpath), "%s/%s", home, path);
if(access(newpath, X_OK))
- strcpy(newpath, path);
+ strcpy_truncate(newpath, path, sizeof(newpath));
return newpath;
}
@@ -125,8 +125,8 @@ ftpd_popen(char *program, char *type, int do_stderr, int no_glob)
return (NULL);
/* break up string into pieces */
+ foo = NULL;
for (argc = 0, cp = program;; cp = NULL) {
- foo = NULL;
if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo)))
break;
}
diff --git a/crypto/kerberosIV/appl/kauth/ChangeLog b/crypto/kerberosIV/appl/kauth/ChangeLog
new file mode 100644
index 0000000..ad849a2
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/ChangeLog
@@ -0,0 +1,24 @@
+Thu Apr 15 15:05:33 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * kauth.c: add `-v'
+
+Thu Mar 18 11:17:14 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: include Makefile.am.common
+
+Sun Nov 22 10:30:47 1998 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (WFLAGS): set
+
+Tue May 26 17:41:47 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * kauth.c: use krb_enable_debug
+
+Fri May 1 07:15:18 1998 Assar Westerlund <assar@sics.se>
+
+ * rkinit.c: unifdef -DHAVE_H_ERRNO
+
+Thu Mar 19 16:07:18 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * kauth.c: Check for negative return value from krb_afslog().
+
diff --git a/crypto/kerberosIV/appl/kauth/Makefile.am b/crypto/kerberosIV/appl/kauth/Makefile.am
new file mode 100644
index 0000000..a5bf0fdaca
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/Makefile.am
@@ -0,0 +1,42 @@
+# $Id: Makefile.am,v 1.7 1999/04/09 18:22:45 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += $(INCLUDE_krb4)
+
+bin_PROGRAMS = kauth
+bin_SCRIPTS = ksrvtgt
+libexec_PROGRAMS = kauthd
+
+EXTRA_DIST = zrefresh ksrvtgt.in
+
+kauth_SOURCES = \
+ kauth.c \
+ kauth.h \
+ rkinit.c \
+ marshall.c \
+ encdata.c
+
+kauthd_SOURCES = \
+ kauthd.c \
+ kauth.h \
+ marshall.c \
+ encdata.c
+
+ksrvtgt: ksrvtgt.in
+ sed -e "s!%bindir%!$(bindir)!" $(srcdir)/ksrvtgt.in > $@
+ chmod +x $@
+
+install-exec-local:
+ if test -f $(bindir)/zrefresh -o -r $(bindir)/zrefresh; then \
+ true; \
+ else \
+ $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(bindir)/`echo zrefresh | sed '$(transform)'`; \
+ fi
+
+LDADD = \
+ $(LIB_kafs) \
+ $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_roken)
diff --git a/crypto/kerberosIV/appl/kauth/Makefile.in b/crypto/kerberosIV/appl/kauth/Makefile.in
index 97bfdb4..278facc 100644
--- a/crypto/kerberosIV/appl/kauth/Makefile.in
+++ b/crypto/kerberosIV/appl/kauth/Makefile.in
@@ -1,17 +1,19 @@
-# $Id: Makefile.in,v 1.33 1997/04/05 21:24:35 assar Exp $
+# $Id: Makefile.in,v 1.40 1999/03/10 19:01:11 joda Exp $
SHELL = /bin/sh
srcdir = @srcdir@
VPATH = @srcdir@
-topdir = ../..
+top_builddir = ../..
CC = @CC@
+LINK = @LINK@
AR = ar
RANLIB = @RANLIB@
DEFS = @DEFS@ -DBINDIR='"$(bindir)"'
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
LD_FLAGS = @LD_FLAGS@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -49,28 +51,28 @@ Wall:
make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__"
.c.o:
- $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $<
+ $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $<
install: all
- $(MKINSTALLDIRS) $(bindir) $(libexecdir)
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir) $(DESTDIR)$(libexecdir)
for x in $(PROG_BIN); do \
- $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x| sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
done
- if test -f $(bindir)/zrefresh -o -r $(bindir)/zrefresh; then \
+ if test -f $(DESTDIR)$(bindir)/zrefresh -o -r $(DESTDIR)$(bindir)/zrefresh; then \
true; \
else \
- $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(bindir)/`echo zrefresh | sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(DESTDIR)$(bindir)/`echo zrefresh | sed '$(transform)'`; \
fi
for x in $(PROG_LIBEXEC); do \
- $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \
done
uninstall:
for x in $(PROG_BIN); do \
- rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
done
for x in $(PROG_LIBEXEC); do \
- rm -f $(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \
done
TAGS: $(SOURCES)
@@ -89,20 +91,14 @@ distclean: clean
realclean: distclean
rm -f TAGS
-dist: $(DISTFILES)
- for file in $(DISTFILES); do \
- ln $$file ../`cat ../.fname`/lib \
- || cp -p $$file ../`cat ../.fname`/lib; \
- done
-
KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
LIBROKEN=-L../../lib/roken -lroken
kauth$(EXECSUFFIX): $(OBJECTS_KAUTH) $(OBJECTS_COMMON)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTH) $(OBJECTS_COMMON) $(KRB_KAFS_LIB) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTH) $(OBJECTS_COMMON) $(KRB_KAFS_LIB) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
kauthd$(EXECSUFFIX): $(OBJECTS_KAUTHD) $(OBJECTS_COMMON)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
ksrvtgt: ksrvtgt.in
sed -e "s!%bindir%!$(bindir)!" $(srcdir)/ksrvtgt.in > $@
@@ -110,3 +106,5 @@ ksrvtgt: ksrvtgt.in
$(OBJECTS): ../../include/config.h
+
+.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/kauth/kauth.c b/crypto/kerberosIV/appl/kauth/kauth.c
index 84614b0..ae5454e 100644
--- a/crypto/kerberosIV/appl/kauth/kauth.c
+++ b/crypto/kerberosIV/appl/kauth/kauth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -46,12 +46,12 @@
#include "kauth.h"
-RCSID("$Id: kauth.c,v 1.75 1997/05/02 15:09:24 assar Exp $");
+RCSID("$Id: kauth.c,v 1.92 1999/06/29 21:19:35 bg Exp $");
krb_principal princ;
-static char srvtab[MaxPathLen + 1];
+static char srvtab[MaxPathLen];
static int lifetime = DEFAULT_TKT_LIFE;
-static char remote_tktfile[MaxPathLen + 1];
+static char remote_tktfile[MaxPathLen];
static char remoteuser[100];
static char *cell = 0;
@@ -59,41 +59,31 @@ static void
usage(void)
{
fprintf(stderr,
- "Usage: %s [-n <name>] [-r remoteuser] [-t remote ticketfile]"
- "[-l lifetime (in minutes) ] [-h hosts... ]"
- "[-f srvtab ] [-c AFS cell name ] [command ... ]\n",
+ "Usage: %s -n <name> [-r remoteuser] [-t remote ticketfile] "
+ "[-l lifetime (in minutes) ] [-f srvtab ] "
+ "[-c AFS cell name ] [-h hosts... [--]] [command ... ]\n",
__progname);
fprintf(stderr, "\nA fully qualified name can be given user[.instance][@realm]\nRealm is converted to uppercase!\n");
exit(1);
}
-static void
+#define EX_NOEXEC 126
+#define EX_NOTFOUND 127
+
+static int
doexec(int argc, char **argv)
{
- int status;
- pid_t ret;
-
- switch (fork()) {
- case -1:
- err (1, "fork");
- break;
- case 0:
- /* in child */
- execvp(argv[0], argv);
- err (1, "Can't exec program ``%s''", argv[0]);
- break;
- default:
- /* in parent */
- do {
- ret = wait(&status);
- } while ((ret > 0 && !WIFEXITED(status)) || (ret < 0 && errno == EINTR));
- if (ret < 0)
- perror("wait");
- dest_tkt();
- if (k_hasafs())
- k_unlog();
- break;
- }
+ int ret = simple_execvp(argv[0], argv);
+ if(ret == -2)
+ warn ("fork");
+ if(ret == -3)
+ warn("waitpid");
+ if(ret < 0)
+ return EX_NOEXEC;
+ if(ret == EX_NOEXEC || ret == EX_NOTFOUND)
+ warnx("Can't exec program ``%s''", argv[0]);
+
+ return ret;
}
static RETSIGTYPE
@@ -110,7 +100,7 @@ renew(int sig)
warnx ("%s", krb_get_err_text(code));
else if (k_hasafs())
{
- if ((code = k_afsklog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) {
+ if ((code = krb_afslog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) {
warnx ("%s", krb_get_err_text(code));
}
}
@@ -139,7 +129,10 @@ zrefresh(void)
}
static int
-key_to_key(char *user, char *instance, char *realm, void *arg,
+key_to_key(const char *user,
+ char *instance,
+ const char *realm,
+ const void *arg,
des_cblock *key)
{
memcpy(key, arg, sizeof(des_cblock));
@@ -154,6 +147,7 @@ main(int argc, char **argv)
int c;
char *file;
int pflag = 0;
+ int version_flag = 0;
char passwd[100];
des_cblock key;
char **host;
@@ -169,17 +163,31 @@ main(int argc, char **argv)
memset(srvtab, 0, sizeof(srvtab));
*remoteuser = '\0';
nhost = 0;
+ host = NULL;
- while ((c = getopt(argc, argv, "r:t:f:hl:n:c:")) != EOF)
+ /* Look for kerberos name */
+ if (argc > 1 &&
+ argv[1][0] != '-' &&
+ krb_parse_name(argv[1], &princ) == 0)
+ {
+ argc--; argv++;
+ strupr(princ.realm);
+ }
+
+ while ((c = getopt(argc, argv, "r:t:f:hdl:n:c:v")) != EOF)
switch (c) {
+ case 'd':
+ krb_enable_debug();
+ _kafs_debug = 1;
+ break;
case 'f':
- strncpy(srvtab, optarg, sizeof(srvtab));
+ strcpy_truncate(srvtab, optarg, sizeof(srvtab));
break;
case 't':
- strncpy(remote_tktfile, optarg, sizeof(remote_tktfile));
+ strcpy_truncate(remote_tktfile, optarg, sizeof(remote_tktfile));
break;
case 'r':
- strncpy(remoteuser, optarg, sizeof(remoteuser));
+ strcpy_truncate(remoteuser, optarg, sizeof(remoteuser));
break;
case 'l':
lifetime = atoi(optarg);
@@ -208,31 +216,38 @@ main(int argc, char **argv)
for(nhost = 0; optind < argc && *argv[optind] != '-'; ++optind)
++nhost;
break;
+ case 'v':
+ version_flag++;
+ print_version(NULL);
+ break;
case '?':
default:
usage();
break;
}
- /* Look for kerberos name */
- if (!pflag && optind < argc && krb_parse_name(argv[optind], &princ) == 0) {
- ++optind;
- strupr(princ.realm);
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
}
-
if (princ.name[0] == '\0' && krb_get_default_principal (princ.name,
princ.instance,
princ.realm) < 0)
errx (1, "Could not get default principal");
- if (*remoteuser == '\0')
- strcpy (remoteuser, princ.name);
+ /* With root tickets assume remote user is root */
+ if (*remoteuser == '\0') {
+ if (strcmp(princ.instance, "root") == 0)
+ strcpy_truncate(remoteuser, princ.instance, sizeof(remoteuser));
+ else
+ strcpy_truncate(remoteuser, princ.name, sizeof(remoteuser));
+ }
more_args = argc - optind;
if (princ.realm[0] == '\0')
if (krb_get_lrealm(princ.realm, 1) != KSUCCESS)
- strcpy(princ.realm, KRB_REALM);
+ strcpy_truncate(princ.realm, KRB_REALM, REALM_SZ);
if (more_args) {
int f;
@@ -271,18 +286,10 @@ main(int argc, char **argv)
memset(passwd, 0, sizeof(passwd));
exit(1);
}
- des_string_to_key (passwd, &key);
- code = krb_get_in_tkt (princ.name, princ.instance, princ.realm,
- KRB_TICKET_GRANTING_TICKET,
- princ.realm, lifetime,
- key_to_key, NULL, key);
- if(code == INTK_BADPW) {
- afs_string_to_key (passwd, princ.realm, &key);
- code = krb_get_in_tkt (princ.name, princ.instance, princ.realm,
- KRB_TICKET_GRANTING_TICKET,
- princ.realm, lifetime,
- key_to_key, NULL, key);
- }
+ code = krb_get_pw_in_tkt2(princ.name, princ.instance, princ.realm,
+ KRB_TICKET_GRANTING_TICKET, princ.realm,
+ lifetime, passwd, &key);
+
memset(passwd, 0, sizeof(passwd));
}
if (code) {
@@ -293,8 +300,12 @@ main(int argc, char **argv)
if (k_hasafs()) {
if (more_args)
k_setpag();
- if ((code = k_afsklog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN)
- warnx ("%s", krb_get_err_text(code));
+ if ((code = krb_afslog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) {
+ if(code > 0)
+ warnx ("%s", krb_get_err_text(code));
+ else
+ warnx ("failed to store AFS token");
+ }
}
for(ret = 0; nhost-- > 0; host++)
@@ -303,10 +314,14 @@ main(int argc, char **argv)
if (ret)
return ret;
- if (more_args)
- doexec(more_args, &argv[optind]);
+ if (more_args) {
+ ret = doexec(more_args, &argv[optind]);
+ dest_tkt();
+ if (k_hasafs())
+ k_unlog();
+ }
else
zrefresh();
- return 0;
+ return ret;
}
diff --git a/crypto/kerberosIV/appl/kauth/kauth.h b/crypto/kerberosIV/appl/kauth/kauth.h
index 2c48fcc..c5a4517 100644
--- a/crypto/kerberosIV/appl/kauth/kauth.h
+++ b/crypto/kerberosIV/appl/kauth/kauth.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*/
-/* $Id: kauth.h,v 1.18 1997/05/20 18:40:31 bg Exp $ */
+/* $Id: kauth.h,v 1.20 1998/06/13 00:06:45 assar Exp $ */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -92,6 +92,9 @@
#endif
#ifdef SOCKS
#include <socks.h>
+/* This doesn't belong here. */
+struct tm *localtime(const time_t *);
+struct hostent *gethostbyname(const char *);
#endif
#include <err.h>
@@ -113,6 +116,6 @@ int write_encrypted (int, void*, size_t, des_key_schedule,
int read_encrypted (int, void*, size_t, void **, des_key_schedule,
des_cblock*, struct sockaddr_in*, struct sockaddr_in*);
-unsigned pack_args (char *, krb_principal*, int, char*, char*);
+int pack_args (char *, size_t, krb_principal*, int, const char*, const char*);
-int unpack_args (char*, krb_principal*, int*, char*, char*);
+int unpack_args (const char*, krb_principal*, int*, char*, char*);
diff --git a/crypto/kerberosIV/appl/kauth/kauthd.c b/crypto/kerberosIV/appl/kauth/kauthd.c
index b6a40cf..0018a13 100644
--- a/crypto/kerberosIV/appl/kauth/kauthd.c
+++ b/crypto/kerberosIV/appl/kauth/kauthd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -38,12 +38,12 @@
#include "kauth.h"
-RCSID("$Id: kauthd.c,v 1.22 1997/05/18 20:37:55 assar Exp $");
+RCSID("$Id: kauthd.c,v 1.24 1999/06/29 21:19:35 bg Exp $");
krb_principal princ;
-static char locuser[SNAME_SZ + 1];
+static char locuser[SNAME_SZ];
static int lifetime;
-static char tktfile[MaxPathLen + 1];
+static char tktfile[MaxPathLen];
struct remote_args {
int sock;
@@ -53,8 +53,12 @@ struct remote_args {
};
static int
-decrypt_remote_tkt (char *user, char *inst, char *realm, void *varg,
- key_proc_t key_proc, KTEXT *cipp)
+decrypt_remote_tkt (const char *user,
+ const char *inst,
+ const char *realm,
+ const void *varg,
+ key_proc_t key_proc,
+ KTEXT *cipp)
{
char buf[BUFSIZ];
void *ptr;
@@ -78,7 +82,7 @@ doit(int sock)
int status;
KTEXT_ST ticket;
AUTH_DAT auth;
- char instance[INST_SZ + 1];
+ char instance[INST_SZ];
des_key_schedule schedule;
struct sockaddr_in thisaddr, thataddr;
int addrlen;
diff --git a/crypto/kerberosIV/appl/kauth/ksrvtgt.in b/crypto/kerberosIV/appl/kauth/ksrvtgt.in
index 30d9e15..c2f33bb 100644
--- a/crypto/kerberosIV/appl/kauth/ksrvtgt.in
+++ b/crypto/kerberosIV/appl/kauth/ksrvtgt.in
@@ -1,5 +1,5 @@
#! /bin/sh
-# $Id: ksrvtgt.in,v 1.2 1997/04/05 21:29:17 assar Exp $
+# $Id: ksrvtgt.in,v 1.3 1997/09/13 03:39:03 joda Exp $
usage="Usage: `basename $0` name instance [[realm] srvtab]"
@@ -11,4 +11,4 @@ fi
srvtab="${4-${3-/etc/srvtab}}"
realm="${4+@$3}"
-%bindir%/kauth -n "$1.$2$realm" -l 5 -f "$srvtab "
+%bindir%/kauth -n "$1.$2$realm" -l 5 -f "$srvtab"
diff --git a/crypto/kerberosIV/appl/kauth/marshall.c b/crypto/kerberosIV/appl/kauth/marshall.c
index 4f1bfeb..dc28ae5 100644
--- a/crypto/kerberosIV/appl/kauth/marshall.c
+++ b/crypto/kerberosIV/appl/kauth/marshall.c
@@ -38,60 +38,94 @@
#include "kauth.h"
-RCSID("$Id: marshall.c,v 1.7 1997/04/01 08:17:32 joda Exp $");
+RCSID("$Id: marshall.c,v 1.8 1998/06/09 19:24:26 joda Exp $");
-unsigned
-pack_args (char *buf, krb_principal *pr, int lifetime,
- char *locuser, char *tktfile)
+int
+pack_args (char *buf,
+ size_t sz,
+ krb_principal *pr,
+ int lifetime,
+ const char *locuser,
+ const char *tktfile)
{
- char *p;
+ char *p = buf;
+ int len;
p = buf;
- strcpy (p, pr->name);
- p += strlen (pr->name) + 1;
- strcpy (p, pr->instance);
- p += strlen (pr->instance) + 1;
- strcpy (p, pr->realm);
- p += strlen (pr->realm) + 1;
+
+ len = strlen(pr->name);
+ if (len >= sz)
+ return -1;
+ memcpy (p, pr->name, len + 1);
+ p += len + 1;
+ sz -= len + 1;
+
+ len = strlen(pr->instance);
+ if (len >= sz)
+ return -1;
+ memcpy (p, pr->instance, len + 1);
+ p += len + 1;
+ sz -= len + 1;
+
+ len = strlen(pr->realm);
+ if (len >= sz)
+ return -1;
+ memcpy(p, pr->realm, len + 1);
+ p += len + 1;
+ sz -= len + 1;
+
+ if (sz < 1)
+ return -1;
*p++ = (unsigned char)lifetime;
- strcpy(p, locuser);
- p += strlen (locuser) + 1;
- strcpy(p, tktfile);
- p += strlen(tktfile) + 1;
+
+ len = strlen(locuser);
+ if (len >= sz)
+ return -1;
+ memcpy (p, locuser, len + 1);
+ p += len + 1;
+ sz -= len + 1;
+
+ len = strlen(tktfile);
+ if (len >= sz)
+ return -1;
+ memcpy (p, tktfile, len + 1);
+ p += len + 1;
+ sz -= len + 1;
+
return p - buf;
}
int
-unpack_args (char *buf, krb_principal *pr, int *lifetime,
+unpack_args (const char *buf, krb_principal *pr, int *lifetime,
char *locuser, char *tktfile)
{
int len;
len = strlen(buf);
- if (len > SNAME_SZ)
+ if (len >= SNAME_SZ)
return -1;
- strncpy(pr->name, buf, len + 1);
+ strcpy_truncate (pr->name, buf, ANAME_SZ);
buf += len + 1;
len = strlen (buf);
- if (len > INST_SZ)
+ if (len >= INST_SZ)
return -1;
- strncpy (pr->instance, buf, len + 1);
+ strcpy_truncate (pr->instance, buf, INST_SZ);
buf += len + 1;
len = strlen (buf);
- if (len > REALM_SZ)
+ if (len >= REALM_SZ)
return -1;
- strncpy (pr->realm, buf, len + 1);
+ strcpy_truncate (pr->realm, buf, REALM_SZ);
buf += len + 1;
*lifetime = (unsigned char)*buf++;
len = strlen(buf);
- if (len > SNAME_SZ)
+ if (len >= SNAME_SZ)
return -1;
- strncpy (locuser, buf, len + 1);
+ strcpy_truncate (locuser, buf, SNAME_SZ);
buf += len + 1;
len = strlen(buf);
- if (len > MaxPathLen)
+ if (len >= MaxPathLen)
return -1;
- strncpy (tktfile, buf, len + 1);
+ strcpy_truncate (tktfile, buf, MaxPathLen);
buf += len + 1;
return 0;
}
diff --git a/crypto/kerberosIV/appl/kauth/rkinit.c b/crypto/kerberosIV/appl/kauth/rkinit.c
index ec75d46..d736ddc 100644
--- a/crypto/kerberosIV/appl/kauth/rkinit.c
+++ b/crypto/kerberosIV/appl/kauth/rkinit.c
@@ -38,7 +38,7 @@
#include "kauth.h"
-RCSID("$Id: rkinit.c,v 1.19 1997/04/01 08:17:33 joda Exp $");
+RCSID("$Id: rkinit.c,v 1.21 1998/06/09 19:24:26 joda Exp $");
static struct in_addr *
getalladdrs (char *hostname, unsigned *count)
@@ -53,12 +53,7 @@ getalladdrs (char *hostname, unsigned *count)
if (hostent == NULL) {
warnx ("gethostbyname '%s' failed: %s\n",
hostname,
-#ifdef HAVE_H_ERRNO
- hstrerror(h_errno)
-#else
- "unknown error"
-#endif
- );
+ hstrerror(h_errno));
return NULL;
}
maxaddr = 1;
@@ -126,7 +121,12 @@ doit_host (krb_principal *princ, int lifetime, char *locuser,
warnx ("%s: %s\n", hostname, krb_get_err_text(status));
return 1;
}
- inlen = pack_args (buf, princ, lifetime, locuser, tktfile);
+ inlen = pack_args (buf, sizeof(buf),
+ princ, lifetime, locuser, tktfile);
+ if (inlen < 0) {
+ warn ("cannot marshall arguments to %s", hostname);
+ return 1;
+ }
if (write_encrypted(s, buf, inlen, schedule, &cred.session,
&thisaddr, &thataddr) < 0) {
diff --git a/crypto/kerberosIV/appl/kip/Makefile.in b/crypto/kerberosIV/appl/kip/Makefile.in
index 690a661..801c3f9 100644
--- a/crypto/kerberosIV/appl/kip/Makefile.in
+++ b/crypto/kerberosIV/appl/kip/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.12 1997/03/23 13:04:03 assar Exp $
+# $Id: Makefile.in,v 1.18 1999/03/10 19:01:11 joda Exp $
SHELL = /bin/sh
@@ -6,9 +6,11 @@ srcdir = @srcdir@
VPATH = @srcdir@
CC = @CC@
+LINK = @LINK@
AR = ar
DEFS = @DEFS@
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
LD_FLAGS = @LD_FLAGS@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -43,23 +45,23 @@ Wall:
make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__"
.c.o:
- $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $<
+ $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $<
install: all
- $(MKINSTALLDIRS) $(bindir) $(libexecdir)
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir) $(DESTDIR)$(libexecdir)
for x in $(PROG_BIN); do \
- $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
done
for x in $(PROG_LIBEXEC); do \
- $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
done
uninstall:
for x in $(PROG_BIN); do \
- rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
done
for x in $(PROG_LIBEXEC); do \
- rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
done
TAGS: $(SOURCES)
@@ -78,19 +80,15 @@ distclean: clean
realclean: distclean
rm -f TAGS
-dist: $(DISTFILES)
- for file in $(DISTFILES); do \
- ln $$file ../`cat ../.fname`/lib \
- || cp -p $$file ../`cat ../.fname`/lib; \
- done
-
KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
LIBROKEN=-L../../lib/roken -lroken
kip$(EXECSUFFIX): $(OBJECTS_KIP)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIP) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIP) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
kipd$(EXECSUFFIX): $(OBJECTS_KIPD)
- $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIPD) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIPD) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
$(OBJECTS): ../../include/config.h
+
+.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/kip/kip.c b/crypto/kerberosIV/appl/kip/kip.c
index e324a28..990583b 100644
--- a/crypto/kerberosIV/appl/kip/kip.c
+++ b/crypto/kerberosIV/appl/kip/kip.c
@@ -38,10 +38,10 @@
#include "kip.h"
-RCSID("$Id: kip.c,v 1.15 1997/05/11 10:54:51 assar Exp $");
+RCSID("$Id: kip.c,v 1.17 1998/05/01 05:20:11 assar Exp $");
static void
-usage()
+usage(void)
{
fprintf (stderr, "Usage: %s host\n",
__progname);
@@ -69,12 +69,7 @@ connect_host (char *host, des_cblock *key, des_key_schedule schedule)
hostent = gethostbyname (host);
if (hostent == NULL) {
warnx ("gethostbyname '%s': %s", host,
-#ifdef HAVE_H_ERRNO
- hstrerror(h_errno)
-#else
- "unknown error"
-#endif
- );
+ hstrerror(h_errno));
return -1;
}
@@ -83,8 +78,6 @@ connect_host (char *host, des_cblock *key, des_key_schedule schedule)
thataddr.sin_port = k_getportbyname ("kip", "tcp", htons(KIPPORT));
for(p = hostent->h_addr_list; *p; ++p) {
- int one = 1;
-
memcpy (&thataddr.sin_addr, *p, sizeof(thataddr.sin_addr));
s = socket (AF_INET, SOCK_STREAM, 0);
@@ -94,7 +87,12 @@ connect_host (char *host, des_cblock *key, des_key_schedule schedule)
}
#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
- setsockopt (s, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one));
+ {
+ int one = 1;
+
+ setsockopt (s, IPPROTO_TCP, TCP_NODELAY,
+ (void *)&one, sizeof(one));
+ }
#endif
if (connect (s, (struct sockaddr *)&thataddr, sizeof(thataddr)) < 0) {
@@ -151,8 +149,6 @@ doit (char *host)
des_key_schedule schedule;
des_cblock iv;
int other, this;
- struct ifreq ifreq;
- int sock;
other = connect_host (host, &iv, schedule);
if (other < 0)
diff --git a/crypto/kerberosIV/appl/kip/kip.h b/crypto/kerberosIV/appl/kip/kip.h
index 94e30a5..ed9874a 100644
--- a/crypto/kerberosIV/appl/kip/kip.h
+++ b/crypto/kerberosIV/appl/kip/kip.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*/
-/* $Id: kip.h,v 1.16 1997/05/20 18:40:31 bg Exp $ */
+/* $Id: kip.h,v 1.17 1997/12/14 23:57:21 assar Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -73,6 +73,9 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
#include <netdb.h>
#include <sys/sockio.h>
#include <net/if.h>
diff --git a/crypto/kerberosIV/appl/kip/kipd.c b/crypto/kerberosIV/appl/kip/kipd.c
index 6d9d334..6990d05 100644
--- a/crypto/kerberosIV/appl/kip/kipd.c
+++ b/crypto/kerberosIV/appl/kip/kipd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -38,7 +38,7 @@
#include "kip.h"
-RCSID("$Id: kipd.c,v 1.13 1997/05/18 20:38:01 assar Exp $");
+RCSID("$Id: kipd.c,v 1.15 1999/03/10 18:33:24 joda Exp $");
static int
fatal (int fd, char *s)
@@ -58,7 +58,7 @@ recv_conn (int sock, des_cblock *key, des_key_schedule schedule,
int status;
KTEXT_ST ticket;
AUTH_DAT auth;
- char instance[INST_SZ + 1];
+ char instance[INST_SZ];
struct sockaddr_in thisaddr, thataddr;
int addrlen;
char version[KRB_SENDAUTH_VLEN + 1];
@@ -122,7 +122,7 @@ main (int argc, char **argv)
{
set_progname (argv[0]);
- openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON);
+ roken_openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON);
signal (SIGCHLD, childhandler);
return doit(0);
}
diff --git a/crypto/kerberosIV/appl/sample/Makefile.in b/crypto/kerberosIV/appl/sample/Makefile.in
new file mode 100644
index 0000000..d88023a
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/Makefile.in
@@ -0,0 +1,83 @@
+# $Id: Makefile.in,v 1.18 1999/03/10 19:01:13 joda Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+top_builddir = ../..
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS = @LD_FLAGS@
+INSTALL = @INSTALL@
+LIBS = @LIBS@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+libexecdir = @libexecdir@
+bindir = @bindir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+PROG_BIN = sample_client$(EXECSUFFIX) \
+ simple_client$(EXECSUFFIX)
+PROG_LIBEXEC = sample_server$(EXECSUFFIX) \
+ simple_server$(EXECSUFFIX)
+PROGS = $(PROG_BIN) $(PROG_LIBEXEC)
+
+OBJECTS = sample_client.o sample_server.o simple_client.o simple_server.o
+SOURCES = sample_client.c sample_server.c simple_client.c simple_server.c
+
+all: $(PROGS)
+
+Wall:
+ make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__"
+
+.c.o:
+ $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $<
+
+install: all
+
+uninstall:
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+check:
+
+clean:
+ rm -f *.a *.o $(PROGS)
+
+mostlyclean: clean
+
+distclean: clean
+ rm -f Makefile *.tab.c *~
+
+realclean: distclean
+ rm -f TAGS
+
+KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
+LIBROKEN=-L../../lib/roken -lroken
+
+sample_client$(EXECSUFFIX): sample_client.o
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ sample_client.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+simple_client$(EXECSUFFIX): simple_client.o
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ simple_client.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+sample_server$(EXECSUFFIX): sample_server.o
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ sample_server.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+simple_server$(EXECSUFFIX): simple_server.o
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ simple_server.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+$(OBJECTS): ../../include/config.h
+
+.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/sample/sample.h b/crypto/kerberosIV/appl/sample/sample.h
new file mode 100644
index 0000000..a5880ab
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/sample.h
@@ -0,0 +1,81 @@
+/*
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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: sample.h,v 1.10 1998/06/13 00:06:49 assar Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <errno.h>
+#ifdef SOCKS
+#include <socks.h>
+/* This doesn't belong here. */
+struct tm *localtime(const time_t *);
+struct hostent *gethostbyname(const char *);
+#endif
+
+#include <err.h>
+#include <krb.h>
+
+#include <roken.h>
+
+#define SAMPLE_PORT 6354
+
+#define SAMPLE_SERVICE "sample"
+#define SAMPLE_VERSION "VERSION9"
diff --git a/crypto/kerberosIV/appl/sample/sample_client.c b/crypto/kerberosIV/appl/sample/sample_client.c
new file mode 100644
index 0000000..8c45ae5
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/sample_client.c
@@ -0,0 +1,168 @@
+/*
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information,
+ * please see the file <mit-copyright.h>.
+ *
+ * sample_client:
+ * A sample Kerberos client, which connects to a server on a remote host,
+ * at port "sample" (be sure to define it in /etc/services)
+ * and authenticates itself to the server. The server then writes back
+ * (in ASCII) the authenticated name.
+ *
+ * Usage:
+ * sample_client <hostname> <checksum>
+ *
+ * <hostname> is the name of the foreign host to contact.
+ *
+ * <checksum> is an integer checksum to be used for the call to krb_mk_req()
+ * and mutual authentication
+ *
+ */
+
+#include "sample.h"
+
+RCSID("$Id: sample_client.c,v 1.19 1999/05/08 02:23:43 assar Exp $");
+
+static void
+usage (void)
+{
+ fprintf (stderr, "Usage: %s [-s service] [-p port] hostname checksum\n",
+ __progname);
+ exit (1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct hostent *hp;
+ struct sockaddr_in sin, lsin;
+ char *remote_host;
+ int status;
+ int namelen;
+ int sock = -1;
+ KTEXT_ST ticket;
+ char buf[512];
+ long authopts;
+ MSG_DAT msg_data;
+ CREDENTIALS cred;
+ des_key_schedule sched;
+ u_int32_t cksum;
+ int c;
+ char service[SNAME_SZ];
+ u_int16_t port;
+ struct servent *serv;
+ char **h_addr_list;
+
+ set_progname (argv[0]);
+ strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service));
+ port = 0;
+
+ while ((c = getopt(argc, argv, "s:p:")) != EOF)
+ switch(c) {
+ case 's' :
+ strcpy_truncate (service, optarg, sizeof(service));
+ break;
+ case 'p' :
+ serv = getservbyname (optarg, "tcp");
+ if (serv)
+ port = serv->s_port;
+ else
+ port = htons(atoi(optarg));
+ break;
+ case '?' :
+ default :
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage ();
+
+ /* convert cksum to internal rep */
+ cksum = atoi(argv[1]);
+
+ printf("Setting checksum to %ld\n", (long)cksum);
+
+ /* clear out the structure first */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (port)
+ sin.sin_port = port;
+ else
+ sin.sin_port = k_getportbyname (service, "tcp", htons(SAMPLE_PORT));
+
+ /* look up the server host */
+ hp = gethostbyname(argv[0]);
+ if (hp == NULL)
+ errx (1, "gethostbyname(%s): %s", argv[0],
+ hstrerror(h_errno));
+
+ /* copy the hostname into non-volatile storage */
+ remote_host = strdup(hp->h_name);
+ if (remote_host == NULL)
+ errx (1, "strdup: out of memory");
+
+ /* set up the address of the foreign socket for connect() */
+ sin.sin_family = hp->h_addrtype;
+
+ for (h_addr_list = hp->h_addr_list;
+ *h_addr_list;
+ ++h_addr_list) {
+ memcpy(&sin.sin_addr, *h_addr_list, sizeof(sin.sin_addr));
+ fprintf (stderr, "Trying %s...\n", inet_ntoa(sin.sin_addr));
+
+ /* open a TCP socket */
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ err (1, "socket");
+
+ /* connect to the server */
+ if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ break;
+ close (sock);
+ }
+
+ if (*h_addr_list == NULL)
+ err (1, "connect");
+
+ /* find out who I am, now that we are connected and therefore bound */
+ namelen = sizeof(lsin);
+ if (getsockname(sock, (struct sockaddr *) &lsin, &namelen) < 0) {
+ close (sock);
+ err (1, "getsockname");
+ }
+
+ /* call Kerberos library routine to obtain an authenticator,
+ pass it over the socket to the server, and obtain mutual
+ authentication. */
+
+ authopts = KOPT_DO_MUTUAL;
+ status = krb_sendauth(authopts, sock, &ticket,
+ service, remote_host,
+ NULL, cksum, &msg_data, &cred,
+ sched, &lsin, &sin, SAMPLE_VERSION);
+ if (status != KSUCCESS)
+ errx (1, "cannot authenticate to server: %s",
+ krb_get_err_text(status));
+
+ /* After we send the authenticator to the server, it will write
+ back the name we authenticated to. Read what it has to say. */
+ status = read(sock, buf, sizeof(buf));
+ if (status < 0)
+ errx(1, "read");
+
+ /* make sure it's null terminated before printing */
+ if (status < sizeof(buf))
+ buf[status] = '\0';
+ else
+ buf[sizeof(buf) - 1] = '\0';
+
+ printf("The server says:\n%s\n", buf);
+
+ close(sock);
+ return 0;
+}
diff --git a/crypto/kerberosIV/appl/sample/sample_server.c b/crypto/kerberosIV/appl/sample/sample_server.c
new file mode 100644
index 0000000..a1a92d1
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/sample_server.c
@@ -0,0 +1,153 @@
+/*
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information,
+ * please see the file <mit-copyright.h>.
+ *
+ * sample_server:
+ * A sample Kerberos server, which reads a ticket from a TCP socket,
+ * decodes it, and writes back the results (in ASCII) to the client.
+ *
+ * Usage:
+ * sample_server
+ *
+ * file descriptor 0 (zero) should be a socket connected to the requesting
+ * client (this will be correct if this server is started by inetd).
+ */
+
+#include "sample.h"
+
+RCSID("$Id: sample_server.c,v 1.12 1999/03/10 18:33:53 joda Exp $");
+
+static void
+usage (void)
+{
+ fprintf (stderr, "Usage: %s [-i] [-s service] [-t srvtab]\n",
+ __progname);
+ exit (1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sockaddr_in peername, myname;
+ int namelen = sizeof(peername);
+ int status, count, len;
+ long authopts;
+ AUTH_DAT auth_data;
+ KTEXT_ST clt_ticket;
+ des_key_schedule sched;
+ char instance[INST_SZ];
+ char service[ANAME_SZ];
+ char version[KRB_SENDAUTH_VLEN+1];
+ char retbuf[512];
+ char lname[ANAME_SZ];
+ char srvtab[MaxPathLen];
+ int c;
+ int no_inetd = 0;
+
+ /* open a log connection */
+
+ set_progname (argv[0]);
+
+ roken_openlog(__progname, LOG_ODELAY, LOG_DAEMON);
+
+ strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service));
+ *srvtab = '\0';
+
+ while ((c = getopt (argc, argv, "s:t:i")) != EOF)
+ switch (c) {
+ case 's' :
+ strcpy_truncate (service, optarg, sizeof(service));
+ break;
+ case 't' :
+ strcpy_truncate (srvtab, optarg, sizeof(srvtab));
+ break;
+ case 'i':
+ no_inetd = 1;
+ break;
+ case '?' :
+ default :
+ usage ();
+ }
+
+ if (no_inetd)
+ mini_inetd (htons(SAMPLE_PORT));
+
+ /*
+ * To verify authenticity, we need to know the address of the
+ * client.
+ */
+ if (getpeername(STDIN_FILENO,
+ (struct sockaddr *)&peername,
+ &namelen) < 0) {
+ syslog(LOG_ERR, "getpeername: %m");
+ return 1;
+ }
+
+ /* for mutual authentication, we need to know our address */
+ namelen = sizeof(myname);
+ if (getsockname(STDIN_FILENO, (struct sockaddr *)&myname, &namelen) < 0) {
+ syslog(LOG_ERR, "getsocknamename: %m");
+ return 1;
+ }
+
+ /* read the authenticator and decode it. Using `k_getsockinst' we
+ * always get the right instance on a multi-homed host.
+ */
+ k_getsockinst (STDIN_FILENO, instance, sizeof(instance));
+
+ /* we want mutual authentication */
+ authopts = KOPT_DO_MUTUAL;
+ status = krb_recvauth(authopts, STDIN_FILENO, &clt_ticket,
+ service, instance, &peername, &myname,
+ &auth_data, srvtab,
+ sched, version);
+ if (status != KSUCCESS) {
+ snprintf(retbuf, sizeof(retbuf),
+ "Kerberos error: %s\n",
+ krb_get_err_text(status));
+ syslog(LOG_ERR, retbuf);
+ } else {
+ /* Check the version string (KRB_SENDAUTH_VLEN chars) */
+ if (strncmp(version, SAMPLE_VERSION, KRB_SENDAUTH_VLEN)) {
+ /* didn't match the expected version */
+ /* could do something different, but we just log an error
+ and continue */
+ version[8] = '\0'; /* make sure null term */
+ syslog(LOG_ERR, "Version mismatch: '%s' isn't '%s'",
+ version, SAMPLE_VERSION);
+ }
+ /* now that we have decoded the authenticator, translate
+ the kerberos principal.instance@realm into a local name */
+ if (krb_kntoln(&auth_data, lname) != KSUCCESS)
+ strcpy_truncate(lname,
+ "*No local name returned by krb_kntoln*",
+ sizeof(lname));
+ /* compose the reply */
+ snprintf(retbuf, sizeof(retbuf),
+ "You are %s.%s@%s (local name %s),\n at address %s, version %s, cksum %ld\n",
+ auth_data.pname,
+ auth_data.pinst,
+ auth_data.prealm,
+ lname,
+ inet_ntoa(peername.sin_addr),
+ version,
+ (long)auth_data.checksum);
+ }
+
+ /* write back the response */
+ if ((count = write(0, retbuf, (len = strlen(retbuf) + 1))) < 0) {
+ syslog(LOG_ERR,"write: %m");
+ return 1;
+ } else if (count != len) {
+ syslog(LOG_ERR, "write count incorrect: %d != %d\n",
+ count, len);
+ return 1;
+ }
+
+ /* close up and exit */
+ close(0);
+ return 0;
+}
diff --git a/crypto/kerberosIV/appl/sample/simple.h b/crypto/kerberosIV/appl/sample/simple.h
new file mode 100644
index 0000000..17315b3
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/simple.h
@@ -0,0 +1,14 @@
+/*
+ * $Id: simple.h,v 1.3 1996/09/27 15:54:23 assar Exp $
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Common definitions for the simple UDP-based Kerberos-mediated
+ * server & client applications.
+ */
+
+#define SERVICE "sample"
+#define HOST "bach"
diff --git a/crypto/kerberosIV/appl/sample/simple_client.c b/crypto/kerberosIV/appl/sample/simple_client.c
new file mode 100644
index 0000000..8769725
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/simple_client.c
@@ -0,0 +1,202 @@
+/*
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Simple UDP-based sample client program. For demonstration.
+ * This program performs no useful function.
+ */
+
+#include "sample.h"
+RCSID("$Id: simple_client.c,v 1.13 1998/06/09 19:24:39 joda Exp $");
+
+#define MSG "hi, Jennifer!" /* message text */
+
+static int
+talkto(char *hostname, char *service, int port)
+{
+ int flags = 0; /* flags for sendto() */
+ long len;
+ u_long cksum = 0L; /* cksum not used */
+ char c_realm[REALM_SZ]; /* local Kerberos realm */
+ char *s_realm; /* server's Kerberos realm */
+
+ KTEXT_ST k; /* Kerberos data */
+ KTEXT ktxt = &k;
+
+ int sock, i;
+ struct hostent *host;
+ struct sockaddr_in s_sock; /* server address */
+ char myhostname[MaxHostNameLen]; /* local hostname */
+
+ /* for krb_mk_safe/priv */
+ struct sockaddr_in c_sock; /* client address */
+ CREDENTIALS c; /* ticket & session key */
+ CREDENTIALS *cred = &c;
+
+ /* for krb_mk_priv */
+ des_key_schedule sched; /* session key schedule */
+
+ /* Look up server host */
+ if ((host = gethostbyname(hostname)) == NULL) {
+ fprintf(stderr, "%s: unknown host \n", hostname);
+ return 1;
+ }
+
+ /* Set server's address */
+ memset(&s_sock, 0, sizeof(s_sock));
+ memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr));
+ s_sock.sin_family = AF_INET;
+ if (port)
+ s_sock.sin_port = port;
+ else
+ s_sock.sin_port = k_getportbyname (service, "tcp", htons(SAMPLE_PORT));
+
+ if (gethostname(myhostname, sizeof(myhostname)) < 0) {
+ warn("gethostname");
+ return 1;
+ }
+
+ if ((host = gethostbyname(myhostname)) == NULL) {
+ fprintf(stderr, "%s: unknown host\n", myhostname);
+ return 1;
+ }
+
+ /* Open a socket */
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ warn("socket SOCK_DGRAM");
+ return 1;
+ }
+
+ memset(&c_sock, 0, sizeof(c_sock));
+ memcpy(&c_sock.sin_addr, host->h_addr, sizeof(c_sock.sin_addr));
+ c_sock.sin_family = AF_INET;
+
+ /* Bind it to set the address; kernel will fill in port # */
+ if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) {
+ warn("bind");
+ return 1;
+ }
+
+ /* Get local realm, not needed, just an example */
+ if ((i = krb_get_lrealm(c_realm, 1)) != KSUCCESS) {
+ fprintf(stderr, "can't find local Kerberos realm\n");
+ return 1;
+ }
+ printf("Local Kerberos realm is %s\n", c_realm);
+
+ /* Get Kerberos realm of host */
+ s_realm = krb_realmofhost(hostname);
+
+ /* PREPARE KRB_MK_REQ MESSAGE */
+
+ /* Get credentials for server, create krb_mk_req message */
+ if ((i = krb_mk_req(ktxt, service, hostname, s_realm, cksum))
+ != KSUCCESS) {
+ fprintf(stderr, "%s\n", krb_get_err_text(i));
+ return 1;
+ }
+ printf("Got credentials for %s.\n", service);
+
+ /* Send authentication info to server */
+ i = sendto(sock, (char *)ktxt->dat, ktxt->length, flags,
+ (struct sockaddr *)&s_sock, sizeof(s_sock));
+ if (i < 0)
+ warn("sending datagram message");
+ printf("Sent authentication data: %d bytes\n", i);
+
+ /* PREPARE KRB_MK_SAFE MESSAGE */
+
+ /* Get my address */
+ memset(&c_sock, 0, sizeof(c_sock));
+ i = sizeof(c_sock);
+ if (getsockname(sock, (struct sockaddr *)&c_sock, &i) < 0) {
+ warn("getsockname");
+ return 1;
+ }
+
+ /* Get session key */
+ i = krb_get_cred(service, hostname, s_realm, cred);
+ if (i != KSUCCESS)
+ return 1;
+
+ /* Make the safe message */
+ len = krb_mk_safe(MSG, ktxt->dat, strlen(MSG)+1,
+ &cred->session, &c_sock, &s_sock);
+
+ /* Send it */
+ i = sendto(sock, (char *)ktxt->dat, (int) len, flags,
+ (struct sockaddr *)&s_sock, sizeof(s_sock));
+ if (i < 0)
+ warn("sending safe message");
+ printf("Sent checksummed message: %d bytes\n", i);
+
+ /* PREPARE KRB_MK_PRIV MESSAGE */
+
+#ifdef NOENCRYPTION
+ memset(sched, 0, sizeof(sched));
+#else
+ /* Get key schedule for session key */
+ des_key_sched(&cred->session, sched);
+#endif
+
+ /* Make the encrypted message */
+ len = krb_mk_priv(MSG, ktxt->dat, strlen(MSG)+1,
+ sched, &cred->session, &c_sock, &s_sock);
+
+ /* Send it */
+ i = sendto(sock, (char *)ktxt->dat, (int) len, flags,
+ (struct sockaddr *)&s_sock, sizeof(s_sock));
+ if (i < 0)
+ warn("sending encrypted message");
+ printf("Sent encrypted message: %d bytes\n", i);
+ return 0;
+}
+
+static void
+usage (void)
+{
+ fprintf (stderr, "Usage: %s [-s service] [-p port] hostname\n",
+ __progname);
+ exit (1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+ int port = 0;
+ char service[SNAME_SZ];
+ struct servent *serv;
+ int c;
+
+ set_progname (argv[0]);
+
+ strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service));
+
+ while ((c = getopt(argc, argv, "s:p:")) != EOF)
+ switch(c) {
+ case 's' :
+ strcpy_truncate (service, optarg, sizeof(service));
+ break;
+ case 'p' :
+ serv = getservbyname (optarg, "tcp");
+ if (serv)
+ port = serv->s_port;
+ else
+ port = htons(atoi(optarg));
+ break;
+ case '?' :
+ default :
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ while (argc-- > 0)
+ ret &= talkto (*argv++, service, port);
+ return ret;
+}
diff --git a/crypto/kerberosIV/appl/sample/simple_server.c b/crypto/kerberosIV/appl/sample/simple_server.c
new file mode 100644
index 0000000..2b950c7
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/simple_server.c
@@ -0,0 +1,140 @@
+/*
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Simple UDP-based server application. For demonstration.
+ * This program performs no useful function.
+ */
+
+#include "sample.h"
+
+RCSID("$Id: simple_server.c,v 1.9 1998/06/09 19:24:39 joda Exp $");
+
+static void
+usage (void)
+{
+ fprintf (stderr, "Usage: %s [-p port] [-s service] [-t srvtab]\n",
+ __progname);
+ exit (1);
+}
+
+int
+main(int argc, char **argv)
+{
+ char service[SNAME_SZ];
+ char instance[INST_SZ];
+ int port;
+ char srvtab[MaxPathLen];
+ struct sockaddr_in addr, otheraddr;
+ int c;
+ int sock;
+ int i;
+ int len;
+ KTEXT_ST k;
+ KTEXT ktxt = &k;
+ AUTH_DAT ad;
+ MSG_DAT msg_data;
+ des_key_schedule sched;
+
+ set_progname (argv[0]);
+ strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service));
+ strcpy_truncate (instance, "*", sizeof(instance));
+ *srvtab = '\0';
+ port = 0;
+
+ while ((c = getopt (argc, argv, "p:s:t:")) != EOF)
+ switch (c) {
+ case 'p' : {
+ struct servent *sp;
+
+ sp = getservbyname (optarg, "udp");
+ if (sp)
+ port = sp->s_port;
+ else
+ port = htons(atoi(optarg));
+ break;
+ }
+ case 's' :
+ strcpy_truncate (service, optarg, sizeof(service));
+ break;
+ case 't' :
+ strcpy_truncate (srvtab, optarg, sizeof(srvtab));
+ break;
+ case '?' :
+ default :
+ usage ();
+ }
+
+ if(port == 0)
+ port = k_getportbyname (SAMPLE_SERVICE, "udp", htons(SAMPLE_PORT));
+
+ memset (&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = port;
+
+ sock = socket (AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+ err (1, "socket");
+
+ if (bind (sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ err (1, "bind");
+
+ /* GET KRB_MK_REQ MESSAGE */
+
+ i = read(sock, ktxt->dat, MAX_KTXT_LEN);
+ if (i < 0)
+ err (1, "read");
+
+ printf("Received %d bytes\n", i);
+ ktxt->length = i;
+
+ /* Check authentication info */
+ i = krb_rd_req(ktxt, service, instance, 0, &ad, "");
+ if (i != KSUCCESS)
+ errx (1, "krb_rd_req: %s", krb_get_err_text(i));
+ printf("Got authentication info from %s%s%s@%s\n", ad.pname,
+ *ad.pinst ? "." : "", ad.pinst, ad.prealm);
+
+ /* GET KRB_MK_SAFE MESSAGE */
+
+ /* use "recvfrom" so we know client's address */
+ len = sizeof(otheraddr);
+ i = recvfrom(sock, ktxt->dat, MAX_KTXT_LEN, 0,
+ (struct sockaddr *)&otheraddr, &len);
+ if (i < 0)
+ err (1, "recvfrom");
+ printf("Received %d bytes\n", i);
+
+ /* Verify the checksummed message */
+ i = krb_rd_safe(ktxt->dat, i, &ad.session, &otheraddr,
+ &addr, &msg_data);
+ if (i != KSUCCESS)
+ errx (1, "krb_rd_safe: %s", krb_get_err_text(i));
+ printf("Safe message is: %s\n", msg_data.app_data);
+
+ /* NOW GET ENCRYPTED MESSAGE */
+
+#ifdef NOENCRYPTION
+ memset(sched, 0, sizeof(sched));
+#else
+ /* need key schedule for session key */
+ des_key_sched(&ad.session, sched);
+#endif
+
+ /* use "recvfrom" so we know client's address */
+ len = sizeof(otheraddr);
+ i = recvfrom(sock, ktxt->dat, MAX_KTXT_LEN, 0,
+ (struct sockaddr *)&otheraddr, &len);
+ if (i < 0)
+ err (1, "recvfrom");
+ printf("Received %d bytes\n", i);
+ i = krb_rd_priv(ktxt->dat, i, sched, &ad.session, &otheraddr,
+ &addr, &msg_data);
+ if (i != KSUCCESS)
+ errx (1, "krb_rd_priv: %s", krb_get_err_text(i));
+ printf("Decrypted message is: %s\n", msg_data.app_data);
+ return(0);
+}
diff --git a/crypto/kerberosIV/appl/telnet/ChangeLog b/crypto/kerberosIV/appl/telnet/ChangeLog
new file mode 100644
index 0000000..5681679
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/ChangeLog
@@ -0,0 +1,232 @@
+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
+
diff --git a/crypto/kerberosIV/appl/telnet/Makefile.am b/crypto/kerberosIV/appl/telnet/Makefile.am
new file mode 100644
index 0000000..eec013b
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/Makefile.am
@@ -0,0 +1,11 @@
+# $Id: Makefile.am,v 1.6 1999/03/20 13:58:15 joda Exp $
+
+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 = README.ORIG telnet.state
diff --git a/crypto/kerberosIV/appl/telnet/Makefile.in b/crypto/kerberosIV/appl/telnet/Makefile.in
new file mode 100644
index 0000000..840e757
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/Makefile.in
@@ -0,0 +1,42 @@
+# $Id: Makefile.in,v 1.20 1998/05/31 18:04:50 joda Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SHELL = /bin/sh
+
+@SET_MAKE@
+
+CC = @CC@
+LINK = @LINK@
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@
+
+INSTALL = @INSTALL@
+
+SUBDIRS=libtelnet telnet telnetd
+
+all:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) all); done
+
+install:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) install); done
+
+uninstall:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) uninstall); done
+
+clean cleandir:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) clean); done
+
+distclean:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) distclean); done
+ rm -f Makefile *~
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/telnet/README.ORIG b/crypto/kerberosIV/appl/telnet/README.ORIG
new file mode 100644
index 0000000..37b588f
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/README.ORIG
@@ -0,0 +1,743 @@
+
+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.
diff --git a/crypto/kerberosIV/appl/telnet/arpa/telnet.h b/crypto/kerberosIV/appl/telnet/arpa/telnet.h
new file mode 100644
index 0000000..5d9ef60
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/arpa/telnet.h
@@ -0,0 +1,323 @@
+/*
+ * 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_ */
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.am b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.am
new file mode 100644
index 0000000..8806f88
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.am
@@ -0,0 +1,24 @@
+# $Id: Makefile.am,v 1.8 1999/03/20 13:58:15 joda Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += -I$(srcdir)/.. $(INCLUDE_krb4)
+
+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 \
+ kerberos.c \
+ kerberos5.c \
+ misc-proto.h \
+ misc.c \
+ misc.h
+
+EXTRA_DIST = krb4encpwd.c rsaencpwd.c spx.c
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.in b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.in
new file mode 100644
index 0000000..b8ca629
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.in
@@ -0,0 +1,54 @@
+# $Id: Makefile.in,v 1.28 1999/03/11 13:50:00 joda Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SHELL = /bin/sh
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LIBNAME = $(LIBPREFIX)telnet
+LIBEXT = a
+LIBPREFIX = @LIBPREFIX@
+LIB = $(LIBNAME).$(LIBEXT)
+
+prefix = @prefix@
+
+SOURCES=auth.c encrypt.c genget.c enc_des.c misc.c kerberos.c kerberos5.c
+
+OBJECTS=auth.o encrypt.o genget.o enc_des.o misc.o kerberos.o kerberos5.o
+
+all: $(LIB)
+
+libtop = @libtop@
+
+.c.o:
+ $(CC) -c $(DEFS) -I../../../include -I$(srcdir)/.. $(CFLAGS) $(CPPFLAGS) $<
+
+$(LIB): $(OBJECTS)
+ rm -f $@
+ $(AR) cr $@ $(OBJECTS)
+ -$(RANLIB) $@
+
+install:
+ @true
+
+uninstall:
+ @true
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+clean cleandir:
+ rm -f *.o *.a \#* *~ core
+
+distclean: clean
+ rm -f Makefile *~
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/auth-proto.h b/crypto/kerberosIV/appl/telnet/libtelnet/auth-proto.h
new file mode 100644
index 0000000..bcc4c64
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/auth-proto.h
@@ -0,0 +1,122 @@
+/*-
+ * 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: auth-proto.h,v 1.9 1998/06/09 19:24:40 joda Exp $ */
+
+#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 *, int, unsigned char *, int);
+void auth_init (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*, int, unsigned char*, int);
+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);
+void auth_gen_printsub(unsigned char *data, int cnt,
+ unsigned char *buf, int buflen);
+
+#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 *, int, unsigned char *, int);
+#endif
+
+#ifdef SRA
+int sra_init (Authenticator *, int);
+int sra_send (Authenticator *);
+void sra_is (Authenticator *, unsigned char *, int);
+void sra_reply (Authenticator *, unsigned char *, int);
+int sra_status (Authenticator *, char *, int);
+void sra_printsub (unsigned char *, int, unsigned char *, int);
+#endif
+
+#ifdef KRB4
+int kerberos4_init (Authenticator *, int);
+int kerberos4_send_mutual (Authenticator *);
+int kerberos4_send_oneway (Authenticator *);
+void kerberos4_is (Authenticator *, unsigned char *, int);
+void kerberos4_reply (Authenticator *, unsigned char *, int);
+int kerberos4_status (Authenticator *, char *, size_t, int);
+void kerberos4_printsub (unsigned char *, int, unsigned char *, int);
+int kerberos4_forward(Authenticator *ap, void *);
+#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 *, int, unsigned char *, int);
+#endif
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/auth.c b/crypto/kerberosIV/appl/telnet/libtelnet/auth.c
new file mode 100644
index 0000000..31d3ede
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/auth.c
@@ -0,0 +1,657 @@
+/*-
+ * 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: auth.c,v 1.22 1999/03/11 13:48:52 joda Exp $");
+
+#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 KRB4_ENCPWD
+extern krb4encpwd_init();
+extern krb4encpwd_send();
+extern krb4encpwd_is();
+extern krb4encpwd_reply();
+extern krb4encpwd_status();
+extern krb4encpwd_printsub();
+#endif
+
+#ifdef RSA_ENCPWD
+extern rsaencpwd_init();
+extern rsaencpwd_send();
+extern rsaencpwd_is();
+extern rsaencpwd_reply();
+extern rsaencpwd_status();
+extern rsaencpwd_printsub();
+#endif
+
+int auth_debug_mode = 0;
+static char *Name = "Noname";
+static 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 KRB4
+ { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
+ kerberos4_init,
+ kerberos4_send_mutual,
+ kerberos4_is,
+ kerberos4_reply,
+ kerberos4_status,
+ kerberos4_printsub },
+ { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+ kerberos4_init,
+ kerberos4_send_oneway,
+ kerberos4_is,
+ kerberos4_reply,
+ kerberos4_status,
+ kerberos4_printsub },
+#endif
+#ifdef KRB4_ENCPWD
+ { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
+ krb4encpwd_init,
+ krb4encpwd_send,
+ krb4encpwd_is,
+ krb4encpwd_reply,
+ krb4encpwd_status,
+ krb4encpwd_printsub },
+#endif
+#ifdef RSA_ENCPWD
+ { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+ rsaencpwd_init,
+ rsaencpwd_send,
+ rsaencpwd_is,
+ rsaencpwd_reply,
+ rsaencpwd_status,
+ rsaencpwd_printsub },
+#endif
+ { 0, },
+};
+
+static Authenticator NoAuth = { 0 };
+
+static int i_support = 0;
+static int i_wont_support = 0;
+
+Authenticator *
+findauthenticator(int type, int way)
+{
+ Authenticator *ap = authenticators;
+
+ while (ap->type && (ap->type != type || ap->way != way))
+ ++ap;
+ return(ap->type ? ap : 0);
+}
+
+void
+auth_init(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);
+#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, int cnt, unsigned char *buf, int buflen)
+{
+ Authenticator *ap;
+
+ if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
+ (*ap->printsub)(data, cnt, buf, buflen);
+ else
+ auth_gen_printsub(data, cnt, buf, buflen);
+}
+
+void
+auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
+{
+ unsigned char *cp;
+ unsigned char tbuf[16];
+
+ cnt -= 3;
+ data += 3;
+ buf[buflen-1] = '\0';
+ buf[buflen-2] = '*';
+ buflen -= 2;
+ for (; cnt > 0; cnt--, data++) {
+ snprintf(tbuf, sizeof(tbuf), " %d", *data);
+ for (cp = tbuf; *cp && buflen > 0; --buflen)
+ *buf++ = *cp++;
+ if (buflen <= 0)
+ return;
+ }
+ *buf = '\0';
+}
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/auth.h b/crypto/kerberosIV/appl/telnet/libtelnet/auth.h
new file mode 100644
index 0000000..83dd701
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/auth.h
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)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: auth.h,v 1.4 1998/06/09 19:24:41 joda Exp $ */
+
+#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 *, int, unsigned char *, int);
+} Authenticator;
+
+#include "auth-proto.h"
+
+extern int auth_debug_mode;
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/enc-proto.h b/crypto/kerberosIV/appl/telnet/libtelnet/enc-proto.h
new file mode 100644
index 0000000..cb0077d
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/enc-proto.h
@@ -0,0 +1,132 @@
+/*-
+ * 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: enc-proto.h,v 1.9 1998/07/09 23:16:22 assar Exp $ */
+
+#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*, int, unsigned char*, int);
+void encrypt_init(char*, int);
+void encrypt_is(unsigned char*, int);
+void encrypt_list_types(void);
+void encrypt_not(void);
+void encrypt_printsub(unsigned char*, int, unsigned char*, int);
+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);
+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 *, int, unsigned char *, int);
+
+void ofb64_encrypt (unsigned char *, int);
+int ofb64_decrypt (int);
+void ofb64_init (int);
+int ofb64_start (int, int);
+int ofb64_is (unsigned char *, int);
+int ofb64_reply (unsigned char *, int);
+void ofb64_session (Session_Key *, int);
+int ofb64_keyid (int, unsigned char *, int *);
+void ofb64_printsub (unsigned char *, int, unsigned char *, int);
+
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c b/crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c
new file mode 100644
index 0000000..a24bfa7
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c
@@ -0,0 +1,671 @@
+/*-
+ * 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: enc_des.c,v 1.16 1998/07/09 23:16:23 assar Exp $");
+
+#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 <des.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];
+ int once;
+ 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 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.
+ */
+#ifndef OLD_DES_RANDOM_KEY
+ des_new_random_key(&fbp->temp_feed);
+#else
+ /*
+ * From des_cryp.man "If the des_check_key flag is non-zero,
+ * des_set_key will check that the key passed is
+ * of odd parity and is not a week or semi-weak key."
+ */
+ do {
+ des_random_key(fbp->temp_feed);
+ des_set_odd_parity(fbp->temp_feed);
+ } while (des_is_weak_key(fbp->temp_feed));
+#endif
+ des_ecb_encrypt(&fbp->temp_feed,
+ &fbp->temp_feed,
+ fbp->krbdes_sched, 1);
+ 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]);
+
+ if (fbp->once == 0) {
+#ifndef OLD_DES_RANDOM_KEY
+ des_init_random_number_generator(&fbp->krbdes_key);
+#endif
+ fbp->once = 1;
+ }
+ des_key_sched(&fbp->krbdes_key, fbp->krbdes_sched);
+ /*
+ * Now look to see if krbdes_start() was was waiting for
+ * the key to show up. If so, go ahead an call it now
+ * that we have the key.
+ */
+ if (fbp->need_start) {
+ fbp->need_start = 0;
+ fb64_start(fbp, DIR_ENCRYPT, server);
+ }
+}
+
+/*
+ * We only accept a keyid of 0. If we get a keyid of
+ * 0, then mark the state as SUCCESS.
+ */
+
+int cfb64_keyid(int dir, unsigned char *kp, int *lenp)
+{
+ return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
+}
+
+int ofb64_keyid(int dir, unsigned char *kp, int *lenp)
+{
+ return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
+}
+
+int fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp)
+{
+ int state = fbp->state[dir-1];
+
+ if (*lenp != 1 || (*kp != '\0')) {
+ *lenp = 0;
+ return(state);
+ }
+
+ if (state == FAILED)
+ state = IN_PROGRESS;
+
+ state &= ~NO_KEYID;
+
+ return(fbp->state[dir-1] = state);
+}
+
+void fb64_printsub(unsigned char *data, int cnt,
+ unsigned char *buf, int buflen, 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, int cnt,
+ unsigned char *buf, int buflen)
+{
+ fb64_printsub(data, cnt, buf, buflen, "CFB64");
+}
+
+void ofb64_printsub(unsigned char *data, int cnt,
+ unsigned char *buf, int buflen)
+{
+ fb64_printsub(data, cnt, buf, buflen, "OFB64");
+}
+
+void fb64_stream_iv(des_cblock seed, struct stinfo *stp)
+{
+
+ memcpy(stp->str_iv, seed,sizeof(des_cblock));
+ memcpy(stp->str_output, seed, sizeof(des_cblock));
+
+ des_key_sched(&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_key_sched((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
+
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.c b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.c
new file mode 100644
index 0000000..21f7a85
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.c
@@ -0,0 +1,995 @@
+/*-
+ * 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: encrypt.c,v 1.21 1998/07/09 23:16:25 assar Exp $");
+
+#if defined(ENCRYPTION)
+
+#define ENCRYPT_NAMES
+#include <arpa/telnet.h>
+
+#include "encrypt.h"
+#include "misc.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <roken.h>
+#ifdef SOCKS
+#include <socks.h>
+#endif
+
+
+/*
+ * These functions pointers point to the current routines
+ * for encrypting and decrypting data.
+ */
+void (*encrypt_output) (unsigned char *, int);
+int (*decrypt_input) (int);
+char *nclearto;
+
+int encrypt_debug_mode = 0;
+static int decrypt_mode = 0;
+static int encrypt_mode = 0;
+static int encrypt_verbose = 0;
+static int autoencrypt = 0;
+static int autodecrypt = 0;
+static int havesessionkey = 0;
+static int Server = 0;
+static char *Name = "Noname";
+
+#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0)
+
+static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64)
+ | typemask(ENCTYPE_DES_OFB64);
+ static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64)
+ | typemask(ENCTYPE_DES_OFB64);
+ static long i_wont_support_encrypt = 0;
+ static long i_wont_support_decrypt = 0;
+#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt)
+#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt)
+
+ static long remote_supports_encrypt = 0;
+ static long remote_supports_decrypt = 0;
+
+ static Encryptions encryptions[] = {
+#if defined(DES_ENCRYPTION)
+ { "DES_CFB64", ENCTYPE_DES_CFB64,
+ cfb64_encrypt,
+ cfb64_decrypt,
+ cfb64_init,
+ cfb64_start,
+ cfb64_is,
+ cfb64_reply,
+ cfb64_session,
+ cfb64_keyid,
+ cfb64_printsub },
+ { "DES_OFB64", ENCTYPE_DES_OFB64,
+ ofb64_encrypt,
+ ofb64_decrypt,
+ ofb64_init,
+ ofb64_start,
+ ofb64_is,
+ ofb64_reply,
+ ofb64_session,
+ ofb64_keyid,
+ ofb64_printsub },
+#endif
+ { 0, },
+ };
+
+static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
+ ENCRYPT_SUPPORT };
+static unsigned char str_suplen = 0;
+static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
+static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
+
+Encryptions *
+findencryption(int type)
+{
+ Encryptions *ep = encryptions;
+
+ if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))
+ return(0);
+ while (ep->type && ep->type != type)
+ ++ep;
+ return(ep->type ? ep : 0);
+}
+
+Encryptions *
+finddecryption(int type)
+{
+ Encryptions *ep = encryptions;
+
+ if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))
+ return(0);
+ while (ep->type && ep->type != type)
+ ++ep;
+ return(ep->type ? ep : 0);
+}
+
+#define MAXKEYLEN 64
+
+static struct key_info {
+ unsigned char keyid[MAXKEYLEN];
+ int keylen;
+ int dir;
+ int *modep;
+ Encryptions *(*getcrypt)();
+} ki[2] = {
+ { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
+ { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
+};
+
+void
+encrypt_init(char *name, int server)
+{
+ Encryptions *ep = encryptions;
+
+ Name = name;
+ Server = server;
+ i_support_encrypt = i_support_decrypt = 0;
+ remote_supports_encrypt = remote_supports_decrypt = 0;
+ encrypt_mode = 0;
+ decrypt_mode = 0;
+ encrypt_output = 0;
+ decrypt_input = 0;
+#ifdef notdef
+ encrypt_verbose = !server;
+#endif
+
+ str_suplen = 4;
+
+ while (ep->type) {
+ if (encrypt_debug_mode)
+ printf(">>>%s: I will support %s\r\n",
+ Name, ENCTYPE_NAME(ep->type));
+ i_support_encrypt |= typemask(ep->type);
+ i_support_decrypt |= typemask(ep->type);
+ if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
+ if ((str_send[str_suplen++] = ep->type) == IAC)
+ str_send[str_suplen++] = IAC;
+ if (ep->init)
+ (*ep->init)(Server);
+ ++ep;
+ }
+ str_send[str_suplen++] = IAC;
+ str_send[str_suplen++] = SE;
+}
+
+void
+encrypt_list_types(void)
+{
+ Encryptions *ep = encryptions;
+
+ printf("Valid encryption types:\n");
+ while (ep->type) {
+ printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
+ ++ep;
+ }
+}
+
+int
+EncryptEnable(char *type, char *mode)
+{
+ if (isprefix(type, "help") || isprefix(type, "?")) {
+ printf("Usage: encrypt enable <type> [input|output]\n");
+ encrypt_list_types();
+ return(0);
+ }
+ if (EncryptType(type, mode))
+ return(EncryptStart(mode));
+ return(0);
+}
+
+int
+EncryptDisable(char *type, char *mode)
+{
+ Encryptions *ep;
+ int ret = 0;
+
+ if (isprefix(type, "help") || isprefix(type, "?")) {
+ printf("Usage: encrypt disable <type> [input|output]\n");
+ encrypt_list_types();
+ } else if ((ep = (Encryptions *)genget(type, (char**)encryptions,
+ sizeof(Encryptions))) == 0) {
+ printf("%s: invalid encryption type\n", type);
+ } else if (Ambiguous(ep)) {
+ printf("Ambiguous type '%s'\n", type);
+ } else {
+ if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
+ if (decrypt_mode == ep->type)
+ EncryptStopInput();
+ i_wont_support_decrypt |= typemask(ep->type);
+ ret = 1;
+ }
+ if ((mode == 0) || (isprefix(mode, "output"))) {
+ if (encrypt_mode == ep->type)
+ EncryptStopOutput();
+ i_wont_support_encrypt |= typemask(ep->type);
+ ret = 1;
+ }
+ if (ret == 0)
+ printf("%s: invalid encryption mode\n", mode);
+ }
+ return(ret);
+}
+
+int
+EncryptType(char *type, char *mode)
+{
+ Encryptions *ep;
+ int ret = 0;
+
+ if (isprefix(type, "help") || isprefix(type, "?")) {
+ printf("Usage: encrypt type <type> [input|output]\n");
+ encrypt_list_types();
+ } else if ((ep = (Encryptions *)genget(type, (char**)encryptions,
+ sizeof(Encryptions))) == 0) {
+ printf("%s: invalid encryption type\n", type);
+ } else if (Ambiguous(ep)) {
+ printf("Ambiguous type '%s'\n", type);
+ } else {
+ if ((mode == 0) || isprefix(mode, "input")) {
+ decrypt_mode = ep->type;
+ i_wont_support_decrypt &= ~typemask(ep->type);
+ ret = 1;
+ }
+ if ((mode == 0) || isprefix(mode, "output")) {
+ encrypt_mode = ep->type;
+ i_wont_support_encrypt &= ~typemask(ep->type);
+ ret = 1;
+ }
+ if (ret == 0)
+ printf("%s: invalid encryption mode\n", mode);
+ }
+ return(ret);
+}
+
+int
+EncryptStart(char *mode)
+{
+ int ret = 0;
+ if (mode) {
+ if (isprefix(mode, "input"))
+ return(EncryptStartInput());
+ if (isprefix(mode, "output"))
+ return(EncryptStartOutput());
+ if (isprefix(mode, "help") || isprefix(mode, "?")) {
+ printf("Usage: encrypt start [input|output]\n");
+ return(0);
+ }
+ printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
+ return(0);
+ }
+ ret += EncryptStartInput();
+ ret += EncryptStartOutput();
+ return(ret);
+}
+
+int
+EncryptStartInput(void)
+{
+ if (decrypt_mode) {
+ encrypt_send_request_start();
+ return(1);
+ }
+ printf("No previous decryption mode, decryption not enabled\r\n");
+ return(0);
+}
+
+int
+EncryptStartOutput(void)
+{
+ if (encrypt_mode) {
+ encrypt_start_output(encrypt_mode);
+ return(1);
+ }
+ printf("No previous encryption mode, encryption not enabled\r\n");
+ return(0);
+}
+
+int
+EncryptStop(char *mode)
+{
+ int ret = 0;
+ if (mode) {
+ if (isprefix(mode, "input"))
+ return(EncryptStopInput());
+ if (isprefix(mode, "output"))
+ return(EncryptStopOutput());
+ if (isprefix(mode, "help") || isprefix(mode, "?")) {
+ printf("Usage: encrypt stop [input|output]\n");
+ return(0);
+ }
+ printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
+ return(0);
+ }
+ ret += EncryptStopInput();
+ ret += EncryptStopOutput();
+ return(ret);
+}
+
+int
+EncryptStopInput(void)
+{
+ encrypt_send_request_end();
+ return(1);
+}
+
+int
+EncryptStopOutput(void)
+{
+ encrypt_send_end();
+ return(1);
+}
+
+void
+encrypt_display(void)
+{
+ printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n",
+ autoencrypt?"on":"off", autodecrypt?"on":"off");
+
+ if (encrypt_output)
+ printf("Currently encrypting output with %s\r\n",
+ ENCTYPE_NAME(encrypt_mode));
+ else
+ printf("Currently not encrypting output\r\n");
+
+ if (decrypt_input)
+ printf("Currently decrypting input with %s\r\n",
+ ENCTYPE_NAME(decrypt_mode));
+ else
+ printf("Currently not decrypting input\r\n");
+}
+
+int
+EncryptStatus(void)
+{
+ printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n",
+ autoencrypt?"on":"off", autodecrypt?"on":"off");
+
+ if (encrypt_output)
+ printf("Currently encrypting output with %s\r\n",
+ ENCTYPE_NAME(encrypt_mode));
+ else if (encrypt_mode) {
+ printf("Currently output is clear text.\r\n");
+ printf("Last encryption mode was %s\r\n",
+ ENCTYPE_NAME(encrypt_mode));
+ } else
+ printf("Currently not encrypting output\r\n");
+
+ if (decrypt_input) {
+ printf("Currently decrypting input with %s\r\n",
+ ENCTYPE_NAME(decrypt_mode));
+ } else if (decrypt_mode) {
+ printf("Currently input is clear text.\r\n");
+ printf("Last decryption mode was %s\r\n",
+ ENCTYPE_NAME(decrypt_mode));
+ } else
+ printf("Currently not decrypting input\r\n");
+
+ return 1;
+}
+
+void
+encrypt_send_support(void)
+{
+ if (str_suplen) {
+ /*
+ * If the user has requested that decryption start
+ * immediatly, then send a "REQUEST START" before
+ * we negotiate the type.
+ */
+ if (!Server && autodecrypt)
+ encrypt_send_request_start();
+ telnet_net_write(str_send, str_suplen);
+ printsub('>', &str_send[2], str_suplen - 2);
+ str_suplen = 0;
+ }
+}
+
+int
+EncryptDebug(int on)
+{
+ if (on < 0)
+ encrypt_debug_mode ^= 1;
+ else
+ encrypt_debug_mode = on;
+ printf("Encryption debugging %s\r\n",
+ encrypt_debug_mode ? "enabled" : "disabled");
+ return(1);
+}
+
+/* turn on verbose encryption, but dont keep telling the whole world
+ */
+void encrypt_verbose_quiet(int on)
+{
+ if(on < 0)
+ encrypt_verbose ^= 1;
+ else
+ encrypt_verbose = on ? 1 : 0;
+}
+
+int
+EncryptVerbose(int on)
+{
+ encrypt_verbose_quiet(on);
+ printf("Encryption %s verbose\r\n",
+ encrypt_verbose ? "is" : "is not");
+ return(1);
+}
+
+int
+EncryptAutoEnc(int on)
+{
+ encrypt_auto(on);
+ printf("Automatic encryption of output is %s\r\n",
+ autoencrypt ? "enabled" : "disabled");
+ return(1);
+}
+
+int
+EncryptAutoDec(int on)
+{
+ decrypt_auto(on);
+ printf("Automatic decryption of input is %s\r\n",
+ autodecrypt ? "enabled" : "disabled");
+ return(1);
+}
+
+/* Called when we receive a WONT or a DONT ENCRYPT after we sent a DO
+ encrypt */
+void
+encrypt_not(void)
+{
+ if (encrypt_verbose)
+ printf("[ Connection is NOT encrypted ]\r\n");
+ else
+ printf("\r\n*** Connection not encrypted! "
+ "Communication may be eavesdropped. ***\r\n");
+}
+
+/*
+ * Called when ENCRYPT SUPPORT is received.
+ */
+void
+encrypt_support(unsigned char *typelist, int cnt)
+{
+ int type, use_type = 0;
+ Encryptions *ep;
+
+ /*
+ * Forget anything the other side has previously told us.
+ */
+ remote_supports_decrypt = 0;
+
+ while (cnt-- > 0) {
+ type = *typelist++;
+ if (encrypt_debug_mode)
+ printf(">>>%s: He is supporting %s (%d)\r\n",
+ Name,
+ ENCTYPE_NAME(type), type);
+ if ((type < ENCTYPE_CNT) &&
+ (I_SUPPORT_ENCRYPT & typemask(type))) {
+ remote_supports_decrypt |= typemask(type);
+ if (use_type == 0)
+ use_type = type;
+ }
+ }
+ if (use_type) {
+ ep = findencryption(use_type);
+ if (!ep)
+ return;
+ type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
+ if (encrypt_debug_mode)
+ printf(">>>%s: (*ep->start)() returned %d\r\n",
+ Name, type);
+ if (type < 0)
+ return;
+ encrypt_mode = use_type;
+ if (type == 0)
+ encrypt_start_output(use_type);
+ }
+}
+
+void
+encrypt_is(unsigned char *data, int cnt)
+{
+ Encryptions *ep;
+ int type, ret;
+
+ if (--cnt < 0)
+ return;
+ type = *data++;
+ if (type < ENCTYPE_CNT)
+ remote_supports_encrypt |= typemask(type);
+ if (!(ep = finddecryption(type))) {
+ if (encrypt_debug_mode)
+ printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
+ Name,
+ ENCTYPE_NAME_OK(type)
+ ? ENCTYPE_NAME(type) : "(unknown)",
+ type);
+ return;
+ }
+ if (!ep->is) {
+ if (encrypt_debug_mode)
+ printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
+ Name,
+ ENCTYPE_NAME_OK(type)
+ ? ENCTYPE_NAME(type) : "(unknown)",
+ type);
+ ret = 0;
+ } else {
+ ret = (*ep->is)(data, cnt);
+ if (encrypt_debug_mode)
+ printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
+ (ret < 0) ? "FAIL " :
+ (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
+ }
+ if (ret < 0) {
+ autodecrypt = 0;
+ } else {
+ decrypt_mode = type;
+ if (ret == 0 && autodecrypt)
+ encrypt_send_request_start();
+ }
+}
+
+void
+encrypt_reply(unsigned char *data, int cnt)
+{
+ Encryptions *ep;
+ int ret, type;
+
+ if (--cnt < 0)
+ return;
+ type = *data++;
+ if (!(ep = findencryption(type))) {
+ if (encrypt_debug_mode)
+ printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
+ Name,
+ ENCTYPE_NAME_OK(type)
+ ? ENCTYPE_NAME(type) : "(unknown)",
+ type);
+ return;
+ }
+ if (!ep->reply) {
+ if (encrypt_debug_mode)
+ printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
+ Name,
+ ENCTYPE_NAME_OK(type)
+ ? ENCTYPE_NAME(type) : "(unknown)",
+ type);
+ ret = 0;
+ } else {
+ ret = (*ep->reply)(data, cnt);
+ if (encrypt_debug_mode)
+ printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
+ data, cnt,
+ (ret < 0) ? "FAIL " :
+ (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
+ }
+ if (encrypt_debug_mode)
+ printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
+ if (ret < 0) {
+ autoencrypt = 0;
+ } else {
+ encrypt_mode = type;
+ if (ret == 0 && autoencrypt)
+ encrypt_start_output(type);
+ }
+}
+
+/*
+ * Called when a ENCRYPT START command is received.
+ */
+void
+encrypt_start(unsigned char *data, int cnt)
+{
+ Encryptions *ep;
+
+ if (!decrypt_mode) {
+ /*
+ * Something is wrong. We should not get a START
+ * command without having already picked our
+ * decryption scheme. Send a REQUEST-END to
+ * attempt to clear the channel...
+ */
+ printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
+ encrypt_send_request_end();
+ return;
+ }
+
+ if ((ep = finddecryption(decrypt_mode))) {
+ decrypt_input = ep->input;
+ if (encrypt_verbose)
+ printf("[ Input is now decrypted with type %s ]\r\n",
+ ENCTYPE_NAME(decrypt_mode));
+ if (encrypt_debug_mode)
+ printf(">>>%s: Start to decrypt input with type %s\r\n",
+ Name, ENCTYPE_NAME(decrypt_mode));
+ } else {
+ printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
+ Name,
+ ENCTYPE_NAME_OK(decrypt_mode)
+ ? ENCTYPE_NAME(decrypt_mode)
+ : "(unknown)",
+ decrypt_mode);
+ encrypt_send_request_end();
+ }
+}
+
+void
+encrypt_session_key(Session_Key *key, int server)
+{
+ Encryptions *ep = encryptions;
+
+ havesessionkey = 1;
+
+ while (ep->type) {
+ if (ep->session)
+ (*ep->session)(key, server);
+ ++ep;
+ }
+}
+
+/*
+ * Called when ENCRYPT END is received.
+ */
+void
+encrypt_end(void)
+{
+ decrypt_input = 0;
+ if (encrypt_debug_mode)
+ printf(">>>%s: Input is back to clear text\r\n", Name);
+ if (encrypt_verbose)
+ printf("[ Input is now clear text ]\r\n");
+}
+
+/*
+ * Called when ENCRYPT REQUEST-END is received.
+ */
+void
+encrypt_request_end(void)
+{
+ encrypt_send_end();
+}
+
+/*
+ * Called when ENCRYPT REQUEST-START is received. If we receive
+ * this before a type is picked, then that indicates that the
+ * other side wants us to start encrypting data as soon as we
+ * can.
+ */
+void
+encrypt_request_start(unsigned char *data, int cnt)
+{
+ if (encrypt_mode == 0) {
+ if (Server)
+ autoencrypt = 1;
+ return;
+ }
+ encrypt_start_output(encrypt_mode);
+}
+
+static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
+
+static void
+encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
+{
+ Encryptions *ep;
+ int dir = kp->dir;
+ int ret = 0;
+
+ if (!(ep = (*kp->getcrypt)(*kp->modep))) {
+ if (len == 0)
+ return;
+ kp->keylen = 0;
+ } else if (len == 0) {
+ /*
+ * Empty option, indicates a failure.
+ */
+ if (kp->keylen == 0)
+ return;
+ kp->keylen = 0;
+ if (ep->keyid)
+ (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
+
+ } else if ((len != kp->keylen) || (memcmp(keyid,kp->keyid,len) != 0)) {
+ /*
+ * Length or contents are different
+ */
+ kp->keylen = len;
+ memcpy(kp->keyid,keyid, len);
+ if (ep->keyid)
+ (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
+ } else {
+ if (ep->keyid)
+ ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
+ if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
+ encrypt_start_output(*kp->modep);
+ return;
+ }
+
+ encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
+}
+
+void encrypt_enc_keyid(unsigned char *keyid, int len)
+{
+ encrypt_keyid(&ki[1], keyid, len);
+}
+
+void encrypt_dec_keyid(unsigned char *keyid, int len)
+{
+ encrypt_keyid(&ki[0], keyid, len);
+}
+
+
+void encrypt_send_keyid(int dir, unsigned char *keyid, int keylen, int saveit)
+{
+ unsigned char *strp;
+
+ str_keyid[3] = (dir == DIR_ENCRYPT)
+ ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
+ if (saveit) {
+ struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
+ memcpy(kp->keyid,keyid, keylen);
+ kp->keylen = keylen;
+ }
+
+ for (strp = &str_keyid[4]; keylen > 0; --keylen) {
+ if ((*strp++ = *keyid++) == IAC)
+ *strp++ = IAC;
+ }
+ *strp++ = IAC;
+ *strp++ = SE;
+ telnet_net_write(str_keyid, strp - str_keyid);
+ printsub('>', &str_keyid[2], strp - str_keyid - 2);
+}
+
+void
+encrypt_auto(int on)
+{
+ if (on < 0)
+ autoencrypt ^= 1;
+ else
+ autoencrypt = on ? 1 : 0;
+}
+
+void
+decrypt_auto(int on)
+{
+ if (on < 0)
+ autodecrypt ^= 1;
+ else
+ autodecrypt = on ? 1 : 0;
+}
+
+void
+encrypt_start_output(int type)
+{
+ Encryptions *ep;
+ unsigned char *p;
+ int i;
+
+ if (!(ep = findencryption(type))) {
+ if (encrypt_debug_mode) {
+ printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
+ Name,
+ ENCTYPE_NAME_OK(type)
+ ? ENCTYPE_NAME(type) : "(unknown)",
+ type);
+ }
+ return;
+ }
+ if (ep->start) {
+ i = (*ep->start)(DIR_ENCRYPT, Server);
+ if (encrypt_debug_mode) {
+ printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
+ Name,
+ (i < 0) ? "failed" :
+ "initial negotiation in progress",
+ i, ENCTYPE_NAME(type));
+ }
+ if (i)
+ return;
+ }
+ p = str_start + 3;
+ *p++ = ENCRYPT_START;
+ for (i = 0; i < ki[0].keylen; ++i) {
+ if ((*p++ = ki[0].keyid[i]) == IAC)
+ *p++ = IAC;
+ }
+ *p++ = IAC;
+ *p++ = SE;
+ telnet_net_write(str_start, p - str_start);
+ net_encrypt();
+ printsub('>', &str_start[2], p - &str_start[2]);
+ /*
+ * If we are already encrypting in some mode, then
+ * encrypt the ring (which includes our request) in
+ * the old mode, mark it all as "clear text" and then
+ * switch to the new mode.
+ */
+ encrypt_output = ep->output;
+ encrypt_mode = type;
+ if (encrypt_debug_mode)
+ printf(">>>%s: Started to encrypt output with type %s\r\n",
+ Name, ENCTYPE_NAME(type));
+ if (encrypt_verbose)
+ printf("[ Output is now encrypted with type %s ]\r\n",
+ ENCTYPE_NAME(type));
+}
+
+void
+encrypt_send_end(void)
+{
+ if (!encrypt_output)
+ return;
+
+ str_end[3] = ENCRYPT_END;
+ telnet_net_write(str_end, sizeof(str_end));
+ net_encrypt();
+ printsub('>', &str_end[2], sizeof(str_end) - 2);
+ /*
+ * Encrypt the output buffer now because it will not be done by
+ * netflush...
+ */
+ encrypt_output = 0;
+ if (encrypt_debug_mode)
+ printf(">>>%s: Output is back to clear text\r\n", Name);
+ if (encrypt_verbose)
+ printf("[ Output is now clear text ]\r\n");
+}
+
+void
+encrypt_send_request_start(void)
+{
+ unsigned char *p;
+ int i;
+
+ p = &str_start[3];
+ *p++ = ENCRYPT_REQSTART;
+ for (i = 0; i < ki[1].keylen; ++i) {
+ if ((*p++ = ki[1].keyid[i]) == IAC)
+ *p++ = IAC;
+ }
+ *p++ = IAC;
+ *p++ = SE;
+ telnet_net_write(str_start, p - str_start);
+ printsub('>', &str_start[2], p - &str_start[2]);
+ if (encrypt_debug_mode)
+ printf(">>>%s: Request input to be encrypted\r\n", Name);
+}
+
+void
+encrypt_send_request_end(void)
+{
+ str_end[3] = ENCRYPT_REQEND;
+ telnet_net_write(str_end, sizeof(str_end));
+ printsub('>', &str_end[2], sizeof(str_end) - 2);
+
+ if (encrypt_debug_mode)
+ printf(">>>%s: Request input to be clear text\r\n", Name);
+}
+
+
+void encrypt_wait(void)
+{
+ if (encrypt_debug_mode)
+ printf(">>>%s: in encrypt_wait\r\n", Name);
+ if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
+ return;
+ while (autoencrypt && !encrypt_output)
+ if (telnet_spin())
+ return;
+}
+
+int
+encrypt_delay(void)
+{
+ if(!havesessionkey ||
+ (I_SUPPORT_ENCRYPT & remote_supports_decrypt) == 0 ||
+ (I_SUPPORT_DECRYPT & remote_supports_encrypt) == 0)
+ return 0;
+ if(!(encrypt_output && decrypt_input))
+ return 1;
+ return 0;
+}
+
+void
+encrypt_debug(int mode)
+{
+ encrypt_debug_mode = mode;
+}
+
+void encrypt_gen_printsub(unsigned char *data, int cnt,
+ unsigned char *buf, int buflen)
+{
+ char tbuf[16], *cp;
+
+ cnt -= 2;
+ data += 2;
+ buf[buflen-1] = '\0';
+ buf[buflen-2] = '*';
+ buflen -= 2;;
+ for (; cnt > 0; cnt--, data++) {
+ snprintf(tbuf, sizeof(tbuf), " %d", *data);
+ for (cp = tbuf; *cp && buflen > 0; --buflen)
+ *buf++ = *cp++;
+ if (buflen <= 0)
+ return;
+ }
+ *buf = '\0';
+}
+
+void
+encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
+{
+ Encryptions *ep;
+ int type = data[1];
+
+ for (ep = encryptions; ep->type && ep->type != type; ep++)
+ ;
+
+ if (ep->printsub)
+ (*ep->printsub)(data, cnt, buf, buflen);
+ else
+ encrypt_gen_printsub(data, cnt, buf, buflen);
+}
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.h b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.h
new file mode 100644
index 0000000..5919db5
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.h
@@ -0,0 +1,98 @@
+/*-
+ * 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: encrypt.h,v 1.4 1997/01/24 23:10:56 assar Exp $ */
+
+#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 *, int, unsigned char *, int);
+} Encryptions;
+
+#define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */
+
+#include "enc-proto.h"
+
+extern int encrypt_debug_mode;
+extern int (*decrypt_input) (int);
+extern void (*encrypt_output) (unsigned char *, int);
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/genget.c b/crypto/kerberosIV/appl/telnet/libtelnet/genget.c
new file mode 100644
index 0000000..c17a7bd
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/genget.c
@@ -0,0 +1,103 @@
+/*-
+ * 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>
+#include "misc-proto.h"
+
+RCSID("$Id: genget.c,v 1.6 1997/05/04 09:01:34 assar Exp $");
+
+#include <ctype.h>
+
+#define LOWER(x) (isupper(x) ? tolower(x) : (x))
+/*
+ * The prefix function returns 0 if *s1 is not a prefix
+ * of *s2. If *s1 exactly matches *s2, the negative of
+ * the length is returned. If *s1 is a prefix of *s2,
+ * the length of *s1 is returned.
+ */
+
+int
+isprefix(char *s1, char *s2)
+{
+ char *os1;
+ char c1, c2;
+
+ if (*s1 == '\0')
+ return(-1);
+ os1 = s1;
+ c1 = *s1;
+ c2 = *s2;
+ while (LOWER(c1) == LOWER(c2)) {
+ if (c1 == '\0')
+ break;
+ c1 = *++s1;
+ c2 = *++s2;
+ }
+ return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1)));
+}
+
+static char *ambiguous; /* special return value for command routines */
+
+char **
+genget(char *name, char **table, int stlen)
+ /* 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);
+}
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c
new file mode 100644
index 0000000..b5c0953
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c
@@ -0,0 +1,717 @@
+/*-
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$Id: kerberos.c,v 1.45 1999/03/13 21:18:55 assar Exp $");
+
+#ifdef KRB4
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+#include <stdio.h>
+#include <des.h> /* BSD wont include this in krb.h, so we do it here */
+#include <krb.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <roken.h>
+#ifdef SOCKS
+#include <socks.h>
+#endif
+
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+int kerberos4_cksum (unsigned char *, int);
+extern int auth_debug_mode;
+
+static unsigned char str_data[2048] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_KERBEROS_V4, };
+
+#define KRB_AUTH 0 /* Authentication data follows */
+#define KRB_REJECT 1 /* Rejected (reason might follow) */
+#define KRB_ACCEPT 2 /* Accepted */
+#define KRB_CHALLENGE 3 /* Challenge for mutual auth. */
+#define KRB_RESPONSE 4 /* Response for mutual auth. */
+
+#define KRB_FORWARD 5 /* */
+#define KRB_FORWARD_ACCEPT 6 /* */
+#define KRB_FORWARD_REJECT 7 /* */
+
+#define KRB_SERVICE_NAME "rcmd"
+
+static KTEXT_ST auth;
+static char name[ANAME_SZ];
+static AUTH_DAT adat;
+static des_cblock session_key;
+static des_cblock cred_session;
+static des_key_schedule sched;
+static des_cblock challenge;
+static int auth_done; /* XXX */
+
+static int pack_cred(CREDENTIALS *cred, unsigned char *buf);
+static int unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred);
+
+
+static int
+Data(Authenticator *ap, int type, const void *d, int c)
+{
+ unsigned char *p = str_data + 4;
+ const unsigned char *cd = (const unsigned char *)d;
+
+ if (c == -1)
+ c = strlen((const char *)cd);
+
+ if (auth_debug_mode) {
+ printf("%s:%d: [%d] (%d)",
+ str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
+ str_data[3],
+ type, c);
+ printd(d, c);
+ printf("\r\n");
+ }
+ *p++ = ap->type;
+ *p++ = ap->way;
+ *p++ = type;
+ while (c-- > 0) {
+ if ((*p++ = *cd++) == IAC)
+ *p++ = IAC;
+ }
+ *p++ = IAC;
+ *p++ = SE;
+ if (str_data[3] == TELQUAL_IS)
+ printsub('>', &str_data[2], p - (&str_data[2]));
+ return(telnet_net_write(str_data, p - str_data));
+}
+
+int
+kerberos4_init(Authenticator *ap, int server)
+{
+ FILE *fp;
+
+ if (server) {
+ str_data[3] = TELQUAL_REPLY;
+ if ((fp = fopen(KEYFILE, "r")) == NULL)
+ return(0);
+ fclose(fp);
+ } else {
+ str_data[3] = TELQUAL_IS;
+ }
+ return(1);
+}
+
+char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
+int dst_realm_sz = REALM_SZ;
+
+static int
+kerberos4_send(char *name, Authenticator *ap)
+{
+ KTEXT_ST auth;
+ char instance[INST_SZ];
+ char *realm;
+ CREDENTIALS cred;
+ int r;
+
+ printf("[ Trying %s ... ]\r\n", name);
+ if (!UserNameRequested) {
+ if (auth_debug_mode) {
+ printf("Kerberos V4: no user name supplied\r\n");
+ }
+ return(0);
+ }
+
+ memset(instance, 0, sizeof(instance));
+
+ strcpy_truncate (instance,
+ krb_get_phost(RemoteHostName),
+ INST_SZ);
+
+ realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
+
+ if (!realm) {
+ printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
+ return(0);
+ }
+ r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L);
+ if (r) {
+ printf("mk_req failed: %s\r\n", krb_get_err_text(r));
+ return(0);
+ }
+ r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred);
+ if (r) {
+ printf("get_cred failed: %s\r\n", krb_get_err_text(r));
+ return(0);
+ }
+ if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+ if (auth_debug_mode)
+ printf("Not enough room for user name\r\n");
+ return(0);
+ }
+ if (auth_debug_mode)
+ printf("Sent %d bytes of authentication data\r\n", auth.length);
+ if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) {
+ if (auth_debug_mode)
+ printf("Not enough room for authentication data\r\n");
+ return(0);
+ }
+#ifdef ENCRYPTION
+ /* create challenge */
+ if ((ap->way & AUTH_HOW_MASK)==AUTH_HOW_MUTUAL) {
+ int i;
+
+ des_key_sched(&cred.session, sched);
+ memcpy (&cred_session, &cred.session, sizeof(cred_session));
+ des_init_random_number_generator(&cred.session);
+ des_new_random_key(&session_key);
+ des_ecb_encrypt(&session_key, &session_key, sched, 0);
+ des_ecb_encrypt(&session_key, &challenge, sched, 0);
+
+ /*
+ old code
+ Some CERT Advisory thinks this is a bad thing...
+
+ des_init_random_number_generator(&cred.session);
+ des_new_random_key(&challenge);
+ des_ecb_encrypt(&challenge, &session_key, sched, 1);
+ */
+
+ /*
+ * Increment the challenge by 1, and encrypt it for
+ * later comparison.
+ */
+ for (i = 7; i >= 0; --i)
+ if(++challenge[i] != 0) /* No carry! */
+ break;
+ des_ecb_encrypt(&challenge, &challenge, sched, 1);
+ }
+
+#endif
+
+ if (auth_debug_mode) {
+ printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
+ printd(auth.dat, auth.length);
+ printf("\r\n");
+ printf("Sent Kerberos V4 credentials to server\r\n");
+ }
+ return(1);
+}
+int
+kerberos4_send_mutual(Authenticator *ap)
+{
+ return kerberos4_send("mutual KERBEROS4", ap);
+}
+
+int
+kerberos4_send_oneway(Authenticator *ap)
+{
+ return kerberos4_send("KERBEROS4", ap);
+}
+
+void
+kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
+{
+ struct sockaddr_in addr;
+ char realm[REALM_SZ];
+ char instance[INST_SZ];
+ int r;
+ int addr_len;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB_AUTH:
+ if (krb_get_lrealm(realm, 1) != KSUCCESS) {
+ Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
+ auth_finished(ap, AUTH_REJECT);
+ if (auth_debug_mode)
+ printf("No local realm\r\n");
+ return;
+ }
+ memmove(auth.dat, data, auth.length = cnt);
+ if (auth_debug_mode) {
+ printf("Got %d bytes of authentication data\r\n", cnt);
+ printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
+ printd(auth.dat, auth.length);
+ printf("\r\n");
+ }
+ k_getsockinst(0, instance, sizeof(instance));
+ addr_len = sizeof(addr);
+ if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) {
+ if(auth_debug_mode)
+ printf("getpeername failed\r\n");
+ Data(ap, KRB_REJECT, "getpeername failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ if (addr.sin_family != AF_INET) {
+ if (auth_debug_mode)
+ printf("unknown address family: %d\r\n", addr.sin_family);
+ Data(ap, KRB_REJECT, "bad address family", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+
+ r = krb_rd_req(&auth, KRB_SERVICE_NAME,
+ instance, addr.sin_addr.s_addr, &adat, "");
+ if (r) {
+ if (auth_debug_mode)
+ printf("Kerberos failed him as %s\r\n", name);
+ Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ /* save the session key */
+ memmove(session_key, adat.session, sizeof(adat.session));
+ krb_kntoln(&adat, name);
+
+ if (UserNameRequested && !kuserok(&adat, UserNameRequested)){
+ char ts[MaxPathLen];
+ struct passwd *pw = getpwnam(UserNameRequested);
+
+ if(pw){
+ snprintf(ts, sizeof(ts),
+ "%s%u",
+ TKT_ROOT,
+ (unsigned)pw->pw_uid);
+ setenv("KRBTKFILE", ts, 1);
+
+ if (pw->pw_uid == 0)
+ syslog(LOG_INFO|LOG_AUTH,
+ "ROOT Kerberos login from %s on %s\n",
+ krb_unparse_name_long(adat.pname,
+ adat.pinst,
+ adat.prealm),
+ RemoteHostName);
+ }
+ Data(ap, KRB_ACCEPT, NULL, 0);
+ } else {
+ char *msg;
+
+ asprintf (&msg, "user `%s' is not authorized to "
+ "login as `%s'",
+ krb_unparse_name_long(adat.pname,
+ adat.pinst,
+ adat.prealm),
+ UserNameRequested ? UserNameRequested : "<nobody>");
+ if (msg == NULL)
+ Data(ap, KRB_REJECT, NULL, 0);
+ else {
+ Data(ap, KRB_REJECT, (void *)msg, -1);
+ free(msg);
+ }
+ }
+ auth_finished(ap, AUTH_USER);
+ break;
+
+ case KRB_CHALLENGE:
+#ifndef ENCRYPTION
+ Data(ap, KRB_RESPONSE, NULL, 0);
+#else
+ if(!VALIDKEY(session_key)){
+ Data(ap, KRB_RESPONSE, NULL, 0);
+ break;
+ }
+ des_key_sched(&session_key, sched);
+ {
+ des_cblock d_block;
+ int i;
+ Session_Key skey;
+
+ memmove(d_block, data, sizeof(d_block));
+
+ /* make a session key for encryption */
+ des_ecb_encrypt(&d_block, &session_key, sched, 1);
+ skey.type=SK_DES;
+ skey.length=8;
+ skey.data=session_key;
+ encrypt_session_key(&skey, 1);
+
+ /* decrypt challenge, add one and encrypt it */
+ des_ecb_encrypt(&d_block, &challenge, sched, 0);
+ for (i = 7; i >= 0; i--)
+ if(++challenge[i] != 0)
+ break;
+ des_ecb_encrypt(&challenge, &challenge, sched, 1);
+ Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
+ }
+#endif
+ break;
+
+ case KRB_FORWARD:
+ {
+ des_key_schedule ks;
+ unsigned char netcred[sizeof(CREDENTIALS)];
+ CREDENTIALS cred;
+ int ret;
+ if(cnt > sizeof(cred))
+ abort();
+
+ memcpy (session_key, adat.session, sizeof(session_key));
+ des_set_key(&session_key, ks);
+ des_pcbc_encrypt((void*)data, (void*)netcred, cnt,
+ ks, &session_key, DES_DECRYPT);
+ unpack_cred(netcred, cnt, &cred);
+ {
+ if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) ||
+ strncmp(cred.instance, cred.realm, sizeof(cred.instance)) ||
+ cred.lifetime < 0 || cred.lifetime > 255 ||
+ cred.kvno < 0 || cred.kvno > 255 ||
+ cred.issue_date < 0 ||
+ cred.issue_date > time(0) + CLOCK_SKEW ||
+ strncmp(cred.pname, adat.pname, sizeof(cred.pname)) ||
+ strncmp(cred.pinst, adat.pinst, sizeof(cred.pinst))){
+ Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1);
+ }else{
+ if((ret = tf_setup(&cred,
+ cred.pname,
+ cred.pinst)) == KSUCCESS){
+ struct passwd *pw = getpwnam(UserNameRequested);
+
+ if (pw)
+ chown(tkt_string(), pw->pw_uid, pw->pw_gid);
+ Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
+ } else{
+ Data(ap, KRB_FORWARD_REJECT,
+ krb_get_err_text(ret), -1);
+ }
+ }
+ }
+ memset(data, 0, cnt);
+ memset(ks, 0, sizeof(ks));
+ memset(&cred, 0, sizeof(cred));
+ }
+
+ break;
+
+ default:
+ if (auth_debug_mode)
+ printf("Unknown Kerberos option %d\r\n", data[-1]);
+ Data(ap, KRB_REJECT, 0, 0);
+ break;
+ }
+}
+
+void
+kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt)
+{
+ Session_Key skey;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB_REJECT:
+ if(auth_done){ /* XXX Ick! */
+ printf("[ Kerberos V4 received unknown opcode ]\r\n");
+ }else{
+ printf("[ Kerberos V4 refuses authentication ");
+ if (cnt > 0)
+ printf("because %.*s ", cnt, data);
+ printf("]\r\n");
+ auth_send_retry();
+ }
+ return;
+ case KRB_ACCEPT:
+ printf("[ Kerberos V4 accepts you ]\r\n");
+ auth_done = 1;
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ /*
+ * Send over the encrypted challenge.
+ */
+ Data(ap, KRB_CHALLENGE, session_key,
+ sizeof(session_key));
+ des_ecb_encrypt(&session_key, &session_key, sched, 1);
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key;
+ encrypt_session_key(&skey, 0);
+#if 0
+ kerberos4_forward(ap, &cred_session);
+#endif
+ return;
+ }
+ auth_finished(ap, AUTH_USER);
+ return;
+ case KRB_RESPONSE:
+ /* make sure the response is correct */
+ if ((cnt != sizeof(des_cblock)) ||
+ (memcmp(data, challenge, sizeof(challenge)))){
+ printf("[ Kerberos V4 challenge failed!!! ]\r\n");
+ auth_send_retry();
+ return;
+ }
+ printf("[ Kerberos V4 challenge successful ]\r\n");
+ auth_finished(ap, AUTH_USER);
+ break;
+ case KRB_FORWARD_ACCEPT:
+ printf("[ Kerberos V4 accepted forwarded credentials ]\r\n");
+ break;
+ case KRB_FORWARD_REJECT:
+ printf("[ Kerberos V4 rejected forwarded credentials: `%.*s']\r\n",
+ cnt, data);
+ break;
+ default:
+ if (auth_debug_mode)
+ printf("Unknown Kerberos option %d\r\n", data[-1]);
+ return;
+ }
+}
+
+int
+kerberos4_status(Authenticator *ap, char *name, size_t name_sz, int level)
+{
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
+ strcpy_truncate(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
+kerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
+{
+ int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case KRB_REJECT: /* Rejected (reason might follow) */
+ strcpy_truncate((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB_ACCEPT: /* Accepted (name might follow) */
+ strcpy_truncate((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 */
+ strcpy_truncate((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB_CHALLENGE:
+ strcpy_truncate((char *)buf, " CHALLENGE", buflen);
+ goto common2;
+
+ case KRB_RESPONSE:
+ strcpy_truncate((char *)buf, " RESPONSE", 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
+kerberos4_cksum(unsigned char *d, int n)
+{
+ int ck = 0;
+
+ /*
+ * A comment is probably needed here for those not
+ * well versed in the "C" language. Yes, this is
+ * supposed to be a "switch" with the body of the
+ * "switch" being a "while" statement. The whole
+ * purpose of the switch is to allow us to jump into
+ * the middle of the while() loop, and then not have
+ * to do any more switch()s.
+ *
+ * Some compilers will spit out a warning message
+ * about the loop not being entered at the top.
+ */
+ switch (n&03)
+ while (n > 0) {
+ case 0:
+ ck ^= (int)*d++ << 24;
+ --n;
+ case 3:
+ ck ^= (int)*d++ << 16;
+ --n;
+ case 2:
+ ck ^= (int)*d++ << 8;
+ --n;
+ case 1:
+ ck ^= (int)*d++;
+ --n;
+ }
+ return(ck);
+}
+
+static int
+pack_cred(CREDENTIALS *cred, unsigned char *buf)
+{
+ unsigned char *p = buf;
+
+ memcpy (p, cred->service, ANAME_SZ);
+ p += ANAME_SZ;
+ memcpy (p, cred->instance, INST_SZ);
+ p += INST_SZ;
+ memcpy (p, cred->realm, REALM_SZ);
+ p += REALM_SZ;
+ memcpy(p, cred->session, 8);
+ p += 8;
+ p += KRB_PUT_INT(cred->lifetime, p, 4, 4);
+ p += KRB_PUT_INT(cred->kvno, p, 4, 4);
+ p += KRB_PUT_INT(cred->ticket_st.length, p, 4, 4);
+ memcpy(p, cred->ticket_st.dat, cred->ticket_st.length);
+ p += cred->ticket_st.length;
+ p += KRB_PUT_INT(0, p, 4, 4);
+ p += KRB_PUT_INT(cred->issue_date, p, 4, 4);
+ memcpy (p, cred->pname, ANAME_SZ);
+ p += ANAME_SZ;
+ memcpy (p, cred->pinst, INST_SZ);
+ p += INST_SZ;
+ return p - buf;
+}
+
+static int
+unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred)
+{
+ unsigned char *p = buf;
+ u_int32_t tmp;
+
+ strncpy (cred->service, p, ANAME_SZ);
+ cred->service[ANAME_SZ - 1] = '\0';
+ p += ANAME_SZ;
+ strncpy (cred->instance, p, INST_SZ);
+ cred->instance[INST_SZ - 1] = '\0';
+ p += INST_SZ;
+ strncpy (cred->realm, p, REALM_SZ);
+ cred->realm[REALM_SZ - 1] = '\0';
+ p += REALM_SZ;
+
+ memcpy(cred->session, p, 8);
+ p += 8;
+ p += krb_get_int(p, &tmp, 4, 0);
+ cred->lifetime = tmp;
+ p += krb_get_int(p, &tmp, 4, 0);
+ cred->kvno = tmp;
+
+ p += krb_get_int(p, &cred->ticket_st.length, 4, 0);
+ memcpy(cred->ticket_st.dat, p, cred->ticket_st.length);
+ p += cred->ticket_st.length;
+ p += krb_get_int(p, &tmp, 4, 0);
+ cred->ticket_st.mbz = 0;
+ p += krb_get_int(p, (u_int32_t *)&cred->issue_date, 4, 0);
+
+ strncpy (cred->pname, p, ANAME_SZ);
+ cred->pname[ANAME_SZ - 1] = '\0';
+ p += ANAME_SZ;
+ strncpy (cred->pinst, p, INST_SZ);
+ cred->pinst[INST_SZ - 1] = '\0';
+ p += INST_SZ;
+ return 0;
+}
+
+
+int
+kerberos4_forward(Authenticator *ap, void *v)
+{
+ des_cblock *key = (des_cblock *)v;
+ CREDENTIALS cred;
+ char *realm;
+ des_key_schedule ks;
+ int len;
+ unsigned char netcred[sizeof(CREDENTIALS)];
+ int ret;
+
+ realm = krb_realmofhost(RemoteHostName);
+ if(realm == NULL)
+ return -1;
+ memset(&cred, 0, sizeof(cred));
+ ret = krb_get_cred(KRB_TICKET_GRANTING_TICKET,
+ realm,
+ realm,
+ &cred);
+ if(ret)
+ return ret;
+ des_set_key(key, ks);
+ len = pack_cred(&cred, netcred);
+ des_pcbc_encrypt((void*)netcred, (void*)netcred, len,
+ ks, key, DES_ENCRYPT);
+ memset(ks, 0, sizeof(ks));
+ Data(ap, KRB_FORWARD, netcred, len);
+ memset(netcred, 0, sizeof(netcred));
+ return 0;
+}
+
+#endif /* KRB4 */
+
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c
new file mode 100644
index 0000000..0b7818f
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c
@@ -0,0 +1,734 @@
+/*-
+ * 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: kerberos5.c,v 1.37 1999/06/24 17:09:10 assar Exp $");
+
+#ifdef KRB5
+
+#include <arpa/telnet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <pwd.h>
+#define Authenticator k5_Authenticator
+#include <krb5.h>
+#undef Authenticator
+#include <roken.h>
+#ifdef SOCKS
+#include <socks.h>
+#endif
+
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
+
+/* These values need to be the same as those defined in telnet/main.c. */
+/* Either define them in both places, or put in some common header file. */
+#define OPTS_FORWARD_CREDS 0x00000002
+#define OPTS_FORWARDABLE_CREDS 0x00000001
+
+void kerberos5_forward (Authenticator *);
+
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_KERBEROS_V5, };
+
+#define KRB_AUTH 0 /* Authentication data follows */
+#define KRB_REJECT 1 /* Rejected (reason might follow) */
+#define KRB_ACCEPT 2 /* Accepted */
+#define KRB_RESPONSE 3 /* Response for mutual auth. */
+
+#define KRB_FORWARD 4 /* Forwarded credentials follow */
+#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */
+#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */
+
+static krb5_data auth;
+static krb5_ticket *ticket;
+
+static krb5_context context;
+static krb5_auth_context auth_context;
+
+static int
+Data(Authenticator *ap, int type, void *d, int c)
+{
+ unsigned char *p = str_data + 4;
+ unsigned char *cd = (unsigned char *)d;
+
+ if (c == -1)
+ c = strlen(cd);
+
+ if (auth_debug_mode) {
+ printf("%s:%d: [%d] (%d)",
+ str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
+ str_data[3],
+ type, c);
+ printd(d, c);
+ printf("\r\n");
+ }
+ *p++ = ap->type;
+ *p++ = ap->way;
+ *p++ = type;
+ while (c-- > 0) {
+ if ((*p++ = *cd++) == IAC)
+ *p++ = IAC;
+ }
+ *p++ = IAC;
+ *p++ = SE;
+ if (str_data[3] == TELQUAL_IS)
+ printsub('>', &str_data[2], p - &str_data[2]);
+ return(telnet_net_write(str_data, p - str_data));
+}
+
+int
+kerberos5_init(Authenticator *ap, int server)
+{
+ if (server)
+ str_data[3] = TELQUAL_REPLY;
+ else
+ str_data[3] = TELQUAL_IS;
+ krb5_init_context(&context);
+ return(1);
+}
+
+static int
+kerberos5_send(char *name, Authenticator *ap)
+{
+ krb5_error_code ret;
+ krb5_ccache ccache;
+ int ap_opts;
+ krb5_data cksum_data;
+ char foo[2];
+ extern int net;
+
+ printf("[ Trying %s ... ]\r\n", name);
+ if (!UserNameRequested) {
+ if (auth_debug_mode) {
+ printf("Kerberos V5: no user name supplied\r\n");
+ }
+ return(0);
+ }
+
+ ret = krb5_cc_default(context, &ccache);
+ if (ret) {
+ if (auth_debug_mode) {
+ printf("Kerberos V5: could not get default ccache: %s\r\n",
+ krb5_get_err_text (context, ret));
+ }
+ return 0;
+ }
+
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+ ap_opts = AP_OPTS_MUTUAL_REQUIRED;
+ else
+ ap_opts = 0;
+
+ ret = krb5_auth_con_init (context, &auth_context);
+ if (ret) {
+ if (auth_debug_mode) {
+ printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ }
+ return(0);
+ }
+
+ ret = krb5_auth_con_setaddrs_from_fd (context,
+ auth_context,
+ &net);
+ if (ret) {
+ if (auth_debug_mode) {
+ printf ("Kerberos V5:"
+ " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ }
+ return(0);
+ }
+
+ krb5_auth_setkeytype (context, auth_context, KEYTYPE_DES);
+
+ foo[0] = ap->type;
+ foo[1] = ap->way;
+
+ cksum_data.length = sizeof(foo);
+ cksum_data.data = foo;
+ ret = krb5_mk_req(context, &auth_context, ap_opts,
+ "host", RemoteHostName,
+ &cksum_data, ccache, &auth);
+
+ if (ret) {
+ if (1 || auth_debug_mode) {
+ printf("Kerberos V5: mk_req failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ }
+ return(0);
+ }
+
+ if (!auth_sendname((unsigned char *)UserNameRequested,
+ strlen(UserNameRequested))) {
+ if (auth_debug_mode)
+ printf("Not enough room for user name\r\n");
+ return(0);
+ }
+ if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
+ if (auth_debug_mode)
+ printf("Not enough room for authentication data\r\n");
+ return(0);
+ }
+ if (auth_debug_mode) {
+ printf("Sent Kerberos V5 credentials to server\r\n");
+ }
+ return(1);
+}
+
+int
+kerberos5_send_mutual(Authenticator *ap)
+{
+ return kerberos5_send("mutual KERBEROS5", ap);
+}
+
+int
+kerberos5_send_oneway(Authenticator *ap)
+{
+ return kerberos5_send("KERBEROS5", ap);
+}
+
+void
+kerberos5_is(Authenticator *ap, unsigned char *data, int cnt)
+{
+ krb5_error_code ret;
+ krb5_data outbuf;
+ krb5_keyblock *key_block;
+ char *name;
+ krb5_principal server;
+ int zero = 0;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB_AUTH:
+ auth.data = (char *)data;
+ auth.length = cnt;
+
+ auth_context = NULL;
+
+ ret = krb5_auth_con_init (context, &auth_context);
+ if (ret) {
+ Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ if (auth_debug_mode)
+ printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ return;
+ }
+
+ ret = krb5_auth_con_setaddrs_from_fd (context,
+ auth_context,
+ &zero);
+ if (ret) {
+ Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ if (auth_debug_mode)
+ printf("Kerberos V5: "
+ "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ return;
+ }
+
+ ret = krb5_sock_to_principal (context,
+ 0,
+ "host",
+ KRB5_NT_SRV_HST,
+ &server);
+ if (ret) {
+ Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ if (auth_debug_mode)
+ printf("Kerberos V5: "
+ "krb5_sock_to_principal failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ return;
+ }
+
+ ret = krb5_rd_req(context,
+ &auth_context,
+ &auth,
+ server,
+ NULL,
+ NULL,
+ &ticket);
+ krb5_free_principal (context, server);
+
+ if (ret) {
+ char *errbuf;
+
+ asprintf(&errbuf,
+ "Read req failed: %s",
+ krb5_get_err_text(context, ret));
+ Data(ap, KRB_REJECT, errbuf, -1);
+ if (auth_debug_mode)
+ printf("%s\r\n", errbuf);
+ free (errbuf);
+ return;
+ }
+
+ {
+ char foo[2];
+
+ foo[0] = ap->type;
+ foo[1] = ap->way;
+
+ ret = krb5_verify_authenticator_checksum(context,
+ auth_context,
+ foo,
+ sizeof(foo));
+
+ if (ret) {
+ char *errbuf;
+ asprintf(&errbuf, "Bad checksum: %s",
+ krb5_get_err_text(context, ret));
+ Data(ap, KRB_REJECT, errbuf, -1);
+ if (auth_debug_mode)
+ printf ("%s\r\n", errbuf);
+ free(errbuf);
+ return;
+ }
+ }
+ ret = krb5_auth_con_getremotesubkey (context,
+ auth_context,
+ &key_block);
+
+ if (ret) {
+ Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ if (auth_debug_mode)
+ printf("Kerberos V5: "
+ "krb5_auth_con_getremotesubkey failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ return;
+ }
+
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ ret = krb5_mk_rep(context, &auth_context, &outbuf);
+ if (ret) {
+ Data(ap, KRB_REJECT,
+ "krb5_mk_rep failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ if (auth_debug_mode)
+ printf("Kerberos V5: "
+ "krb5_mk_rep failed (%s)\r\n",
+ krb5_get_err_text(context, ret));
+ return;
+ }
+ Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
+ }
+ if (krb5_unparse_name(context, ticket->client, &name))
+ name = 0;
+
+ if(UserNameRequested && krb5_kuserok(context,
+ ticket->client,
+ UserNameRequested)) {
+ Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
+ if (auth_debug_mode) {
+ printf("Kerberos5 identifies him as ``%s''\r\n",
+ name ? name : "");
+ }
+
+ if(key_block->keytype == ETYPE_DES_CBC_MD5 ||
+ key_block->keytype == ETYPE_DES_CBC_MD4 ||
+ key_block->keytype == ETYPE_DES_CBC_CRC) {
+ Session_Key skey;
+
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = key_block->keyvalue.data;
+ encrypt_session_key(&skey, 0);
+ }
+
+ } else {
+ char *msg;
+
+ asprintf (&msg, "user `%s' is not authorized to "
+ "login as `%s'",
+ name ? name : "<unknown>",
+ UserNameRequested ? UserNameRequested : "<nobody>");
+ if (msg == NULL)
+ Data(ap, KRB_REJECT, NULL, 0);
+ else {
+ Data(ap, KRB_REJECT, (void *)msg, -1);
+ free(msg);
+ }
+ }
+ auth_finished(ap, AUTH_USER);
+
+ krb5_free_keyblock_contents(context, key_block);
+
+ break;
+ case KRB_FORWARD: {
+ struct passwd *pwd;
+ char ccname[1024]; /* XXX */
+ krb5_data inbuf;
+ krb5_ccache ccache;
+ inbuf.data = (char *)data;
+ inbuf.length = cnt;
+
+ pwd = getpwnam (UserNameRequested);
+ if (pwd == NULL)
+ break;
+
+ snprintf (ccname, sizeof(ccname),
+ "FILE:/tmp/krb5cc_%u", pwd->pw_uid);
+
+ ret = krb5_cc_resolve (context, ccname, &ccache);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("Kerberos V5: could not get ccache: %s\r\n",
+ krb5_get_err_text(context, ret));
+ break;
+ }
+
+ ret = krb5_cc_initialize (context,
+ ccache,
+ ticket->client);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("Kerberos V5: could not init ccache: %s\r\n",
+ krb5_get_err_text(context, ret));
+ break;
+ }
+
+ ret = krb5_rd_cred (context,
+ auth_context,
+ ccache,
+ &inbuf);
+ if(ret) {
+ char *errbuf;
+
+ asprintf (&errbuf,
+ "Read forwarded creds failed: %s",
+ krb5_get_err_text (context, ret));
+ if(errbuf == NULL)
+ Data(ap, KRB_FORWARD_REJECT, NULL, 0);
+ else
+ Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
+ if (auth_debug_mode)
+ printf("Could not read forwarded credentials: %s\r\n",
+ errbuf);
+ free (errbuf);
+ } else
+ Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
+ chown (ccname + 5, pwd->pw_uid, -1);
+ if (auth_debug_mode)
+ printf("Forwarded credentials obtained\r\n");
+ break;
+ }
+ default:
+ if (auth_debug_mode)
+ printf("Unknown Kerberos option %d\r\n", data[-1]);
+ Data(ap, KRB_REJECT, 0, 0);
+ break;
+ }
+}
+
+void
+kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt)
+{
+ static int mutual_complete = 0;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB_REJECT:
+ if (cnt > 0) {
+ printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
+ cnt, data);
+ } else
+ printf("[ Kerberos V5 refuses authentication ]\r\n");
+ auth_send_retry();
+ return;
+ case KRB_ACCEPT: {
+ krb5_error_code ret;
+ Session_Key skey;
+ krb5_keyblock *keyblock;
+
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
+ !mutual_complete) {
+ printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
+ auth_send_retry();
+ return;
+ }
+ if (cnt)
+ printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
+ else
+ printf("[ Kerberos V5 accepts you ]\r\n");
+
+ ret = krb5_auth_con_getlocalsubkey (context,
+ auth_context,
+ &keyblock);
+ if (ret)
+ ret = krb5_auth_con_getkey (context,
+ auth_context,
+ &keyblock);
+ if(ret) {
+ printf("[ krb5_auth_con_getkey: %s ]\r\n",
+ krb5_get_err_text(context, ret));
+ auth_send_retry();
+ return;
+ }
+
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = keyblock->keyvalue.data;
+ encrypt_session_key(&skey, 0);
+ krb5_free_keyblock_contents (context, keyblock);
+ auth_finished(ap, AUTH_USER);
+ if (forward_flags & OPTS_FORWARD_CREDS)
+ kerberos5_forward(ap);
+ break;
+ }
+ case KRB_RESPONSE:
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ /* the rest of the reply should contain a krb_ap_rep */
+ krb5_ap_rep_enc_part *reply;
+ krb5_data inbuf;
+ krb5_error_code ret;
+
+ inbuf.length = cnt;
+ inbuf.data = (char *)data;
+
+ ret = krb5_rd_rep(context, auth_context, &inbuf, &reply);
+ if (ret) {
+ printf("[ Mutual authentication failed: %s ]\r\n",
+ krb5_get_err_text (context, ret));
+ auth_send_retry();
+ return;
+ }
+ krb5_free_ap_rep_enc_part(context, reply);
+ mutual_complete = 1;
+ }
+ return;
+ case KRB_FORWARD_ACCEPT:
+ printf("[ Kerberos V5 accepted forwarded credentials ]\r\n");
+ return;
+ case KRB_FORWARD_REJECT:
+ printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
+ cnt, data);
+ return;
+ default:
+ if (auth_debug_mode)
+ printf("Unknown Kerberos option %d\r\n", data[-1]);
+ return;
+ }
+}
+
+int
+kerberos5_status(Authenticator *ap, char *name, size_t name_sz, int level)
+{
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested &&
+ krb5_kuserok(context,
+ ticket->client,
+ UserNameRequested))
+ {
+ strcpy_truncate(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
+kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
+{
+ int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case KRB_REJECT: /* Rejected (reason might follow) */
+ strcpy_truncate((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB_ACCEPT: /* Accepted (name might follow) */
+ strcpy_truncate((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 */
+ strcpy_truncate((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB_RESPONSE:
+ strcpy_truncate((char *)buf, " RESPONSE", buflen);
+ goto common2;
+
+ case KRB_FORWARD: /* Forwarded credentials follow */
+ strcpy_truncate((char *)buf, " FORWARD", buflen);
+ goto common2;
+
+ case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
+ strcpy_truncate((char *)buf, " FORWARD_ACCEPT", buflen);
+ goto common2;
+
+ case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
+ /* (reason might follow) */
+ strcpy_truncate((char *)buf, " FORWARD_REJECT", buflen);
+ goto common2;
+
+ default:
+ snprintf(buf, buflen, " %d (unknown)", data[3]);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ snprintf(buf, buflen, " %d", data[i]);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+void
+kerberos5_forward(Authenticator *ap)
+{
+ krb5_error_code ret;
+ krb5_ccache ccache;
+ krb5_creds creds;
+ krb5_kdc_flags flags;
+ krb5_data out_data;
+ krb5_principal principal;
+
+ ret = krb5_cc_default (context, &ccache);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("KerberosV5: could not get default ccache: %s\r\n",
+ krb5_get_err_text (context, ret));
+ return;
+ }
+
+ ret = krb5_cc_get_principal (context, ccache, &principal);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("KerberosV5: could not get principal: %s\r\n",
+ krb5_get_err_text (context, ret));
+ return;
+ }
+
+ memset (&creds, 0, sizeof(creds));
+
+ creds.client = principal;
+
+ ret = krb5_build_principal (context,
+ &creds.server,
+ strlen(principal->realm),
+ principal->realm,
+ "krbtgt",
+ principal->realm,
+ NULL);
+
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("KerberosV5: could not get principal: %s\r\n",
+ krb5_get_err_text (context, ret));
+ return;
+ }
+
+ creds.times.endtime = 0;
+
+ flags.i = 0;
+ flags.b.forwarded = 1;
+ if (forward_flags & OPTS_FORWARDABLE_CREDS)
+ flags.b.forwardable = 1;
+
+ ret = krb5_get_forwarded_creds (context,
+ auth_context,
+ ccache,
+ flags.i,
+ RemoteHostName,
+ &creds,
+ &out_data);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("Kerberos V5: error gettting forwarded creds: %s\r\n",
+ krb5_get_err_text (context, ret));
+ return;
+ }
+
+ if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) {
+ if (auth_debug_mode)
+ printf("Not enough room for authentication data\r\n");
+ } else {
+ if (auth_debug_mode)
+ printf("Forwarded local Kerberos V5 credentials to server\r\n");
+ }
+}
+
+#endif /* KRB5 */
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c b/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c
new file mode 100644
index 0000000..ee1eee2
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c
@@ -0,0 +1,437 @@
+/*-
+ * 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: krb4encpwd.c,v 1.17 1998/07/09 23:16:29 assar Exp $");
+
+#ifdef KRB4_ENCPWD
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <sys/types.h>
+#include <arpa/telnet.h>
+#include <pwd.h>
+#include <stdio.h>
+
+#include <des.h>
+#include <krb.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef SOCKS
+#include <socks.h>
+#endif
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+int krb_mk_encpwd_req (KTEXT, char *, char *, char *, char *, char *, char *);
+int krb_rd_encpwd_req (KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *);
+
+extern auth_debug_mode;
+
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_KRB4_ENCPWD, };
+static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
+ TELQUAL_NAME, };
+
+#define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */
+#define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
+#define KRB4_ENCPWD_ACCEPT 2 /* Accepted */
+#define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */
+#define KRB4_ENCPWD_ACK 4 /* Acknowledge */
+
+#define KRB_SERVICE_NAME "rcmd"
+
+static KTEXT_ST auth;
+static char name[ANAME_SZ];
+static char user_passwd[ANAME_SZ];
+static AUTH_DAT adat = { 0 };
+static des_key_schedule sched;
+static char challenge[REALM_SZ];
+
+ static int
+Data(ap, type, d, c)
+ Authenticator *ap;
+ int type;
+ void *d;
+ int c;
+{
+ unsigned char *p = str_data + 4;
+ unsigned char *cd = (unsigned char *)d;
+
+ if (c == -1)
+ c = strlen(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
+krb4encpwd_init(ap, server)
+ Authenticator *ap;
+ int server;
+{
+ char hostname[80], *cp, *realm;
+ des_clock skey;
+
+ if (server) {
+ str_data[3] = TELQUAL_REPLY;
+ } else {
+ str_data[3] = TELQUAL_IS;
+ gethostname(hostname, sizeof(hostname));
+ realm = krb_realmofhost(hostname);
+ cp = strchr(hostname, '.');
+ if (*cp != NULL) *cp = NULL;
+ if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
+ KEYFILE, (char *)skey)) {
+ return(0);
+ }
+ }
+ return(1);
+}
+
+ int
+krb4encpwd_send(ap)
+ Authenticator *ap;
+{
+
+ printf("[ Trying KRB4ENCPWD ... ]\r\n");
+ if (!UserNameRequested) {
+ return(0);
+ }
+ if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+ return(0);
+ }
+
+ if (!Data(ap, KRB4_ENCPWD_ACK, NULL, 0)) {
+ return(0);
+ }
+
+ return(1);
+}
+
+ void
+krb4encpwd_is(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ Session_Key skey;
+ des_cblock datablock;
+ char r_passwd[ANAME_SZ], r_user[ANAME_SZ];
+ char lhostname[ANAME_SZ], *cp;
+ int r;
+ time_t now;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB4_ENCPWD_AUTH:
+ memmove(auth.dat, data, auth.length = cnt);
+
+ gethostname(lhostname, sizeof(lhostname));
+ if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
+
+ if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
+ Data(ap, KRB4_ENCPWD_REJECT, "Auth failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ auth_encrypt_userpwd(r_passwd);
+ if (passwdok(UserNameRequested, UserPassword) == 0) {
+ /*
+ * illegal username and password
+ */
+ Data(ap, KRB4_ENCPWD_REJECT, "Illegal password", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+
+ memmove(session_key, adat.session, sizeof(des_cblock));
+ Data(ap, KRB4_ENCPWD_ACCEPT, 0, 0);
+ auth_finished(ap, AUTH_USER);
+ break;
+
+ case KRB4_ENCPWD_CHALLENGE:
+ /*
+ * Take the received random challenge text and save
+ * for future authentication.
+ */
+ memmove(challenge, data, sizeof(des_cblock));
+ break;
+
+
+ case KRB4_ENCPWD_ACK:
+ /*
+ * Receive ack, if mutual then send random challenge
+ */
+
+ /*
+ * If we are doing mutual authentication, get set up to send
+ * the challenge, and verify it when the response comes back.
+ */
+
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ int i;
+
+ time(&now);
+ snprintf(challenge, sizeof(challenge), "%x", now);
+ Data(ap, KRB4_ENCPWD_CHALLENGE, challenge, strlen(challenge));
+ }
+ break;
+
+ default:
+ Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
+ break;
+ }
+}
+
+
+ void
+krb4encpwd_reply(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ Session_Key skey;
+ KTEXT_ST krb_token;
+ des_cblock enckey;
+ CREDENTIALS cred;
+ int r;
+ char randchal[REALM_SZ], instance[ANAME_SZ], *cp;
+ char hostname[80], *realm;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB4_ENCPWD_REJECT:
+ if (cnt > 0) {
+ printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
+ cnt, data);
+ } else
+ printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
+ auth_send_retry();
+ return;
+ case KRB4_ENCPWD_ACCEPT:
+ printf("[ KRB4_ENCPWD accepts you ]\r\n");
+ auth_finished(ap, AUTH_USER);
+ return;
+ case KRB4_ENCPWD_CHALLENGE:
+ /*
+ * Verify that the response to the challenge is correct.
+ */
+
+ gethostname(hostname, sizeof(hostname));
+ realm = krb_realmofhost(hostname);
+ memmove(challenge, data, cnt);
+ memset(user_passwd, 0, sizeof(user_passwd));
+ des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
+ UserPassword = user_passwd;
+ Challenge = challenge;
+ strcpy_truncate(instance, RemoteHostName, sizeof(instance));
+ if ((cp = strchr(instance, '.')) != 0) *cp = '\0';
+
+ if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
+ krb_token.length = 0;
+ }
+
+ if (!Data(ap, KRB4_ENCPWD_AUTH, krb_token.dat, krb_token.length)) {
+ return;
+ }
+
+ break;
+
+ default:
+ return;
+ }
+}
+
+ int
+krb4encpwd_status(ap, name, name_sz, level)
+ Authenticator *ap;
+ char *name;
+ size_t name_sz;
+ int level;
+{
+
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
+ strcpy_truncate(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
+krb4encpwd_printsub(data, cnt, buf, buflen)
+ unsigned char *data, *buf;
+ int cnt, buflen;
+{
+ int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */
+ strcpy_truncate((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */
+ strcpy_truncate((char *)buf, " ACCEPT ", buflen);
+ common:
+ BUMP(buf, buflen);
+ if (cnt <= 4)
+ break;
+ ADDC(buf, buflen, '"');
+ for (i = 4; i < cnt; i++)
+ ADDC(buf, buflen, data[i]);
+ ADDC(buf, buflen, '"');
+ ADDC(buf, buflen, '\0');
+ break;
+
+ case KRB4_ENCPWD_AUTH: /* Authentication data follows */
+ strcpy_truncate((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB4_ENCPWD_CHALLENGE:
+ strcpy_truncate((char *)buf, " CHALLENGE", buflen);
+ goto common2;
+
+ case KRB4_ENCPWD_ACK:
+ strcpy_truncate((char *)buf, " ACK", 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 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
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/misc-proto.h b/crypto/kerberosIV/appl/telnet/libtelnet/misc-proto.h
new file mode 100644
index 0000000..a31d924
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/misc-proto.h
@@ -0,0 +1,79 @@
+/*-
+ * 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: misc-proto.h,v 1.7 1998/07/09 23:16:30 assar Exp $ */
+
+#ifndef __MISC_PROTO__
+#define __MISC_PROTO__
+
+void auth_encrypt_init (char *, char *, char *, int);
+void auth_encrypt_user(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 (char *);
+char *telnet_gets (char *, char *, int, int);
+void printsub(int direction, unsigned char *pointer, int length);
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/misc.c b/crypto/kerberosIV/appl/telnet/libtelnet/misc.c
new file mode 100644
index 0000000..2d9199f
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/misc.c
@@ -0,0 +1,94 @@
+/*-
+ * 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: misc.c,v 1.13 1998/06/13 00:06:54 assar Exp $");
+
+#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"
+
+
+char *RemoteHostName;
+char *LocalHostName;
+char *UserNameRequested = 0;
+int ConnectedCount = 0;
+
+void
+auth_encrypt_init(char *local, char *remote, 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(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;
+ }
+}
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/misc.h b/crypto/kerberosIV/appl/telnet/libtelnet/misc.h
new file mode 100644
index 0000000..41ffa7f
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/misc.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)misc.h 8.1 (Berkeley) 6/4/93
+ */
+
+extern char *UserNameRequested;
+extern char *LocalHostName;
+extern char *RemoteHostName;
+extern int ConnectedCount;
+extern int ReservedPort;
+
+#include "misc-proto.h"
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/rsaencpwd.c b/crypto/kerberosIV/appl/telnet/libtelnet/rsaencpwd.c
new file mode 100644
index 0000000..267e98e
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/rsaencpwd.c
@@ -0,0 +1,487 @@
+/*-
+ * 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: rsaencpwd.c,v 1.17 1998/07/09 23:16:32 assar Exp $");
+
+#ifdef RSA_ENCPWD
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <sys/types.h>
+#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),
+ "/etc/.%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 {
+ strcpy_truncate(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)) {
+ strcpy_truncate(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(data, cnt, buf, buflen)
+ unsigned char *data, *buf;
+ int cnt, buflen;
+{
+ int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */
+ strcpy_truncate((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */
+ strcpy_truncate((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 */
+ strcpy_truncate((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case RSA_ENCPWD_CHALLENGEKEY:
+ strcpy_truncate((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
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/spx.c b/crypto/kerberosIV/appl/telnet/libtelnet/spx.c
new file mode 100644
index 0000000..6d2eefe
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/spx.c
@@ -0,0 +1,586 @@
+/*-
+ * 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: spx.c,v 1.16 1998/07/09 23:16:33 assar Exp $");
+
+#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", output_name_buffer.value); fflush(stdout);
+
+ major_status = gss_release_buffer(&status, &output_name_buffer);
+
+ input_chan_bindings = (gss_channel_bindings)
+ malloc(sizeof(gss_channel_bindings_desc));
+
+ input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
+ input_chan_bindings->initiator_address.length = 4;
+ address = (char *) malloc(4);
+ input_chan_bindings->initiator_address.value = (char *) address;
+ address[0] = ((from_addr & 0xff000000) >> 24);
+ address[1] = ((from_addr & 0xff0000) >> 16);
+ address[2] = ((from_addr & 0xff00) >> 8);
+ address[3] = (from_addr & 0xff);
+ input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
+ input_chan_bindings->acceptor_address.length = 4;
+ address = (char *) malloc(4);
+ input_chan_bindings->acceptor_address.value = (char *) address;
+ address[0] = ((to_addr & 0xff000000) >> 24);
+ address[1] = ((to_addr & 0xff0000) >> 16);
+ address[2] = ((to_addr & 0xff00) >> 8);
+ address[3] = (to_addr & 0xff);
+ input_chan_bindings->application_data.length = 0;
+
+ req_flags = 0;
+ if (deleg_flag) req_flags = req_flags | 1;
+ if (mutual_flag) req_flags = req_flags | 2;
+ if (replay_flag) req_flags = req_flags | 4;
+ if (seq_flag) req_flags = req_flags | 8;
+
+ major_status = gss_init_sec_context(&status, /* minor status */
+ GSS_C_NO_CREDENTIAL, /* cred handle */
+ &actual_ctxhandle, /* ctx handle */
+ desired_targname, /* target name */
+ GSS_C_NULL_OID, /* mech type */
+ req_flags, /* req flags */
+ 0, /* time req */
+ input_chan_bindings, /* chan binding */
+ GSS_C_NO_BUFFER, /* input token */
+ &actual_mech_type, /* actual mech */
+ &output_token, /* output token */
+ &ret_flags, /* ret flags */
+ &lifetime_rec); /* time rec */
+
+ if ((major_status != GSS_S_COMPLETE) &&
+ (major_status != GSS_S_CONTINUE_NEEDED)) {
+ gss_display_status(&new_status,
+ status,
+ GSS_C_MECH_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx,
+ &status_string);
+ printf("%s\n", status_string.value);
+ return(0);
+ }
+
+ if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+ return(0);
+ }
+
+ if (!Data(ap, SPX_AUTH, 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",
+ 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) {
+ strcpy_truncate(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(data, cnt, buf, buflen)
+ unsigned char *data, *buf;
+ int cnt, buflen;
+{
+ int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case SPX_REJECT: /* Rejected (reason might follow) */
+ strcpy_truncate((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case SPX_ACCEPT: /* Accepted (name might follow) */
+ strcpy_truncate((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 */
+ strcpy_truncate((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
diff --git a/crypto/kerberosIV/appl/telnet/telnet.state b/crypto/kerberosIV/appl/telnet/telnet.state
new file mode 100644
index 0000000..1927a2b
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet.state
@@ -0,0 +1,80 @@
+
+ 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.
diff --git a/crypto/kerberosIV/appl/telnet/telnet/Makefile.am b/crypto/kerberosIV/appl/telnet/telnet/Makefile.am
new file mode 100644
index 0000000..882aa24
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/Makefile.am
@@ -0,0 +1,20 @@
+# $Id: Makefile.am,v 1.12 1999/06/23 12:37:58 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += -I$(srcdir)/.. $(INCLUDE_krb4)
+
+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
+
+LDADD = ../libtelnet/libtelnet.a \
+ $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_tgetent) \
+ $(LIB_roken)
diff --git a/crypto/kerberosIV/appl/telnet/telnet/Makefile.in b/crypto/kerberosIV/appl/telnet/telnet/Makefile.in
new file mode 100644
index 0000000..4da3e05
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/Makefile.in
@@ -0,0 +1,75 @@
+# $Id: Makefile.in,v 1.34 1999/03/11 13:50:09 joda Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SHELL = /bin/sh
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS = @LD_FLAGS@
+LIBS = @LIBS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+
+PROGS = telnet$(EXECSUFFIX)
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+SOURCES=authenc.c commands.c main.c network.c ring.c \
+ sys_bsd.c telnet.c terminal.c \
+ utilities.c
+
+OBJECTS=authenc.o commands.o main.o network.o ring.o sys_bsd.o \
+ telnet.o terminal.o utilities.o
+
+libtop=@libtop@
+
+LIBKRB = -L../../../lib/krb -lkrb
+LIBDES = -L../../../lib/des -ldes
+LIBROKEN = -L../../../lib/roken -lroken
+
+KLIB=$(LIBKRB) $(LIBDES)
+
+
+all: $(PROGS)
+
+.c.o:
+ $(CC) -c $(DEFS) -I../../../include -I.. -I$(srcdir)/.. $(CFLAGS) $(CPPFLAGS) $<
+
+telnet$(EXECSUFFIX): $(OBJECTS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS) -L../libtelnet -ltelnet $(KLIB) $(LIBROKEN) $(LIBS) @LIB_tgetent@ $(LIBROKEN)
+
+install: all
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
+ for x in $(PROGS); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(PROGS); do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+clean cleandir:
+ rm -f *.o *.a telnet$(EXECSUFFIX) \#* *~ core
+
+distclean: clean
+ rm -f Makefile *~
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/telnet/telnet/authenc.c b/crypto/kerberosIV/appl/telnet/telnet/authenc.c
new file mode 100644
index 0000000..08da93d
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/authenc.c
@@ -0,0 +1,91 @@
+/*-
+ * 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: authenc.c,v 1.9 1999/03/19 23:13:51 assar Exp $");
+
+#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)
+{
+ return(-1);
+}
+
+char *
+telnet_getenv(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))) {
+ strcpy_truncate(result, res, length);
+ res = result;
+ }
+ TerminalNewMode(om);
+ return(res);
+}
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/telnet/commands.c b/crypto/kerberosIV/appl/telnet/telnet/commands.c
new file mode 100644
index 0000000..57803fa
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/commands.c
@@ -0,0 +1,2693 @@
+/*
+ * 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: commands.c,v 1.53 1999/07/07 14:56:17 assar Exp $");
+
+#if defined(IPPROTO_IP) && defined(IP_TOS)
+int tos = -1;
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+char *hostname;
+static char _hostname[MaxHostNameLen];
+
+typedef int (*intrtn_t)(int, char**);
+static int call(intrtn_t, ...);
+
+typedef struct {
+ char *name; /* command name */
+ char *help; /* help string (NULL for no help) */
+ int (*handler)(); /* routine which executes command */
+ int needconnect; /* Do we need to be connected to execute? */
+} Command;
+
+static char line[256];
+static char saveline[256];
+static int margc;
+static char *margv[20];
+
+static void
+makeargv()
+{
+ char *cp, *cp2, c;
+ char **argp = margv;
+
+ margc = 0;
+ cp = line;
+ if (*cp == '!') { /* Special case shell escape */
+ /* save for shell command */
+ strcpy_truncate(saveline, line, sizeof(saveline));
+ *argp++ = "!"; /* No room in string to get this */
+ margc++;
+ cp++;
+ }
+ while ((c = *cp)) {
+ int inquote = 0;
+ while (isspace(c))
+ c = *++cp;
+ if (c == '\0')
+ break;
+ *argp++ = cp;
+ margc += 1;
+ for (cp2 = cp; c != '\0'; c = *++cp) {
+ if (inquote) {
+ if (c == inquote) {
+ inquote = 0;
+ continue;
+ }
+ } else {
+ if (c == '\\') {
+ if ((c = *++cp) == '\0')
+ break;
+ } else if (c == '"') {
+ inquote = '"';
+ continue;
+ } else if (c == '\'') {
+ inquote = '\'';
+ continue;
+ } else if (isspace(c))
+ break;
+ }
+ *cp2++ = c;
+ }
+ *cp2 = '\0';
+ if (c == '\0')
+ break;
+ cp++;
+ }
+ *argp++ = 0;
+}
+
+/*
+ * Make a character string into a number.
+ *
+ * Todo: 1. Could take random integers (12, 0x12, 012, 0b1).
+ */
+
+static char
+special(char *s)
+{
+ char c;
+ char b;
+
+ switch (*s) {
+ case '^':
+ b = *++s;
+ if (b == '?') {
+ c = b | 0x40; /* DEL */
+ } else {
+ c = b & 0x1f;
+ }
+ break;
+ default:
+ c = *s;
+ break;
+ }
+ return c;
+}
+
+/*
+ * Construct a control character sequence
+ * for a special character.
+ */
+static char *
+control(cc_t c)
+{
+ static char buf[5];
+ /*
+ * The only way I could get the Sun 3.5 compiler
+ * to shut up about
+ * if ((unsigned int)c >= 0x80)
+ * was to assign "c" to an unsigned int variable...
+ * Arggg....
+ */
+ unsigned int uic = (unsigned int)c;
+
+ if (uic == 0x7f)
+ return ("^?");
+ if (c == (cc_t)_POSIX_VDISABLE) {
+ return "off";
+ }
+ if (uic >= 0x80) {
+ buf[0] = '\\';
+ buf[1] = ((c>>6)&07) + '0';
+ buf[2] = ((c>>3)&07) + '0';
+ buf[3] = (c&07) + '0';
+ buf[4] = 0;
+ } else if (uic >= 0x20) {
+ buf[0] = c;
+ buf[1] = 0;
+ } else {
+ buf[0] = '^';
+ buf[1] = '@'+c;
+ buf[2] = 0;
+ }
+ return (buf);
+}
+
+
+
+/*
+ * The following are data structures and routines for
+ * the "send" command.
+ *
+ */
+
+struct sendlist {
+ char *name; /* How user refers to it (case independent) */
+ char *help; /* Help information (0 ==> no help) */
+ int needconnect; /* Need to be connected */
+ int narg; /* Number of arguments */
+ int (*handler)(); /* Routine to perform (for special ops) */
+ int nbyte; /* Number of bytes to send this command */
+ int what; /* Character to be sent (<0 ==> special) */
+};
+
+
+static int
+ send_esc (void),
+ send_help (void),
+ send_docmd (char *),
+ send_dontcmd (char *),
+ send_willcmd (char *),
+ send_wontcmd (char *);
+
+static struct sendlist Sendlist[] = {
+ { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO },
+ { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT },
+ { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK },
+ { "break", 0, 1, 0, 0, 2, BREAK },
+ { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC },
+ { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL },
+ { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 },
+ { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA },
+ { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP },
+ { "intp", 0, 1, 0, 0, 2, IP },
+ { "interrupt", 0, 1, 0, 0, 2, IP },
+ { "intr", 0, 1, 0, 0, 2, IP },
+ { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP },
+ { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR },
+ { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT },
+ { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP },
+ { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF },
+ { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 },
+ { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 },
+ { "?", "Display send options", 0, 0, send_help, 0, 0 },
+ { "help", 0, 0, 0, send_help, 0, 0 },
+ { "do", 0, 0, 1, send_docmd, 3, 0 },
+ { "dont", 0, 0, 1, send_dontcmd, 3, 0 },
+ { "will", 0, 0, 1, send_willcmd, 3, 0 },
+ { "wont", 0, 0, 1, send_wontcmd, 3, 0 },
+ { 0 }
+};
+
+#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
+ sizeof(struct sendlist)))
+
+static int
+sendcmd(int argc, char **argv)
+{
+ int count; /* how many bytes we are going to need to send */
+ int i;
+ struct sendlist *s; /* pointer to current command */
+ int success = 0;
+ int needconnect = 0;
+
+ if (argc < 2) {
+ printf("need at least one argument for 'send' command\r\n");
+ printf("'send ?' for help\r\n");
+ return 0;
+ }
+ /*
+ * First, validate all the send arguments.
+ * In addition, we see how much space we are going to need, and
+ * whether or not we will be doing a "SYNCH" operation (which
+ * flushes the network queue).
+ */
+ count = 0;
+ for (i = 1; i < argc; i++) {
+ s = GETSEND(argv[i]);
+ if (s == 0) {
+ printf("Unknown send argument '%s'\r\n'send ?' for help.\r\n",
+ argv[i]);
+ return 0;
+ } else if (Ambiguous(s)) {
+ printf("Ambiguous send argument '%s'\r\n'send ?' for help.\r\n",
+ argv[i]);
+ return 0;
+ }
+ if (i + s->narg >= argc) {
+ fprintf(stderr,
+ "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\r\n",
+ s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
+ return 0;
+ }
+ count += s->nbyte;
+ if (s->handler == send_help) {
+ send_help();
+ return 0;
+ }
+
+ i += s->narg;
+ needconnect += s->needconnect;
+ }
+ if (!connected && needconnect) {
+ printf("?Need to be connected first.\r\n");
+ printf("'send ?' for help\r\n");
+ return 0;
+ }
+ /* Now, do we have enough room? */
+ if (NETROOM() < count) {
+ printf("There is not enough room in the buffer TO the network\r\n");
+ printf("to process your request. Nothing will be done.\r\n");
+ printf("('send synch' will throw away most data in the network\r\n");
+ printf("buffer, if this might help.)\r\n");
+ return 0;
+ }
+ /* OK, they are all OK, now go through again and actually send */
+ count = 0;
+ for (i = 1; i < argc; i++) {
+ if ((s = GETSEND(argv[i])) == 0) {
+ fprintf(stderr, "Telnet 'send' error - argument disappeared!\r\n");
+ quit();
+ /*NOTREACHED*/
+ }
+ if (s->handler) {
+ count++;
+ success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
+ (s->narg > 1) ? argv[i+2] : 0);
+ i += s->narg;
+ } else {
+ NET2ADD(IAC, s->what);
+ printoption("SENT", IAC, s->what);
+ }
+ }
+ return (count == success);
+}
+
+static int
+send_tncmd(void (*func)(), char *cmd, char *name);
+
+static int
+send_esc()
+{
+ NETADD(escape);
+ return 1;
+}
+
+static int
+send_docmd(char *name)
+{
+ return(send_tncmd(send_do, "do", name));
+}
+
+static int
+send_dontcmd(char *name)
+{
+ return(send_tncmd(send_dont, "dont", name));
+}
+
+static int
+send_willcmd(char *name)
+{
+ return(send_tncmd(send_will, "will", name));
+}
+
+static int
+send_wontcmd(char *name)
+{
+ return(send_tncmd(send_wont, "wont", name));
+}
+
+static int
+send_tncmd(void (*func)(), char *cmd, char *name)
+{
+ char **cpp;
+ extern char *telopts[];
+ int val = 0;
+
+ if (isprefix(name, "help") || isprefix(name, "?")) {
+ int col, len;
+
+ printf("Usage: send %s <value|option>\r\n", cmd);
+ printf("\"value\" must be from 0 to 255\r\n");
+ printf("Valid options are:\r\n\t");
+
+ col = 8;
+ for (cpp = telopts; *cpp; cpp++) {
+ len = strlen(*cpp) + 3;
+ if (col + len > 65) {
+ printf("\r\n\t");
+ col = 8;
+ }
+ printf(" \"%s\"", *cpp);
+ col += len;
+ }
+ printf("\r\n");
+ return 0;
+ }
+ cpp = genget(name, telopts, sizeof(char *));
+ if (Ambiguous(cpp)) {
+ fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\r\n",
+ name, cmd);
+ return 0;
+ }
+ if (cpp) {
+ val = cpp - telopts;
+ } else {
+ char *cp = name;
+
+ while (*cp >= '0' && *cp <= '9') {
+ val *= 10;
+ val += *cp - '0';
+ cp++;
+ }
+ if (*cp != 0) {
+ fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\r\n",
+ name, cmd);
+ return 0;
+ } else if (val < 0 || val > 255) {
+ fprintf(stderr, "'%s': bad value ('send %s ?' for help).\r\n",
+ name, cmd);
+ return 0;
+ }
+ }
+ if (!connected) {
+ printf("?Need to be connected first.\r\n");
+ return 0;
+ }
+ (*func)(val, 1);
+ return 1;
+}
+
+static int
+send_help()
+{
+ struct sendlist *s; /* pointer to current command */
+ for (s = Sendlist; s->name; s++) {
+ if (s->help)
+ printf("%-15s %s\r\n", s->name, s->help);
+ }
+ return(0);
+}
+
+/*
+ * The following are the routines and data structures referred
+ * to by the arguments to the "toggle" command.
+ */
+
+static int
+lclchars()
+{
+ donelclchars = 1;
+ return 1;
+}
+
+static int
+togdebug()
+{
+#ifndef NOT43
+ if (net > 0 &&
+ (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
+ perror("setsockopt (SO_DEBUG)");
+ }
+#else /* NOT43 */
+ if (debug) {
+ if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+ perror("setsockopt (SO_DEBUG)");
+ } else
+ printf("Cannot turn off socket debugging\r\n");
+#endif /* NOT43 */
+ return 1;
+}
+
+#if defined(KRB4) && defined(HAVE_KRB_DISABLE_DEBUG)
+#include <krb.h>
+
+static int
+togkrbdebug(void)
+{
+ if(krb_debug)
+ krb_enable_debug();
+ else
+ krb_disable_debug();
+ return 1;
+}
+#endif
+
+static int
+togcrlf()
+{
+ if (crlf) {
+ printf("Will send carriage returns as telnet <CR><LF>.\r\n");
+ } else {
+ printf("Will send carriage returns as telnet <CR><NUL>.\r\n");
+ }
+ return 1;
+}
+
+int binmode;
+
+static int
+togbinary(int val)
+{
+ donebinarytoggle = 1;
+
+ if (val >= 0) {
+ binmode = val;
+ } else {
+ if (my_want_state_is_will(TELOPT_BINARY) &&
+ my_want_state_is_do(TELOPT_BINARY)) {
+ binmode = 1;
+ } else if (my_want_state_is_wont(TELOPT_BINARY) &&
+ my_want_state_is_dont(TELOPT_BINARY)) {
+ binmode = 0;
+ }
+ val = binmode ? 0 : 1;
+ }
+
+ if (val == 1) {
+ if (my_want_state_is_will(TELOPT_BINARY) &&
+ my_want_state_is_do(TELOPT_BINARY)) {
+ printf("Already operating in binary mode with remote host.\r\n");
+ } else {
+ printf("Negotiating binary mode with remote host.\r\n");
+ tel_enter_binary(3);
+ }
+ } else {
+ if (my_want_state_is_wont(TELOPT_BINARY) &&
+ my_want_state_is_dont(TELOPT_BINARY)) {
+ printf("Already in network ascii mode with remote host.\r\n");
+ } else {
+ printf("Negotiating network ascii mode with remote host.\r\n");
+ tel_leave_binary(3);
+ }
+ }
+ return 1;
+}
+
+static int
+togrbinary(int val)
+{
+ donebinarytoggle = 1;
+
+ if (val == -1)
+ val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
+
+ if (val == 1) {
+ if (my_want_state_is_do(TELOPT_BINARY)) {
+ printf("Already receiving in binary mode.\r\n");
+ } else {
+ printf("Negotiating binary mode on input.\r\n");
+ tel_enter_binary(1);
+ }
+ } else {
+ if (my_want_state_is_dont(TELOPT_BINARY)) {
+ printf("Already receiving in network ascii mode.\r\n");
+ } else {
+ printf("Negotiating network ascii mode on input.\r\n");
+ tel_leave_binary(1);
+ }
+ }
+ return 1;
+}
+
+static int
+togxbinary(int val)
+{
+ donebinarytoggle = 1;
+
+ if (val == -1)
+ val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
+
+ if (val == 1) {
+ if (my_want_state_is_will(TELOPT_BINARY)) {
+ printf("Already transmitting in binary mode.\r\n");
+ } else {
+ printf("Negotiating binary mode on output.\r\n");
+ tel_enter_binary(2);
+ }
+ } else {
+ if (my_want_state_is_wont(TELOPT_BINARY)) {
+ printf("Already transmitting in network ascii mode.\r\n");
+ } else {
+ printf("Negotiating network ascii mode on output.\r\n");
+ tel_leave_binary(2);
+ }
+ }
+ return 1;
+}
+
+
+static int togglehelp (void);
+#if defined(AUTHENTICATION)
+extern int auth_togdebug (int);
+#endif
+#if defined(ENCRYPTION)
+extern int EncryptAutoEnc (int);
+extern int EncryptAutoDec (int);
+extern int EncryptDebug (int);
+extern int EncryptVerbose (int);
+#endif
+
+struct togglelist {
+ char *name; /* name of toggle */
+ char *help; /* help message */
+ int (*handler)(); /* routine to do actual setting */
+ int *variable;
+ char *actionexplanation;
+};
+
+static struct togglelist Togglelist[] = {
+ { "autoflush",
+ "flushing of output when sending interrupt characters",
+ 0,
+ &autoflush,
+ "flush output when sending interrupt characters" },
+ { "autosynch",
+ "automatic sending of interrupt characters in urgent mode",
+ 0,
+ &autosynch,
+ "send interrupt characters in urgent mode" },
+#if defined(AUTHENTICATION)
+ { "autologin",
+ "automatic sending of login and/or authentication info",
+ 0,
+ &autologin,
+ "send login name and/or authentication information" },
+ { "authdebug",
+ "Toggle authentication debugging",
+ auth_togdebug,
+ 0,
+ "print authentication debugging information" },
+#endif
+#if defined(ENCRYPTION)
+ { "autoencrypt",
+ "automatic encryption of data stream",
+ EncryptAutoEnc,
+ 0,
+ "automatically encrypt output" },
+ { "autodecrypt",
+ "automatic decryption of data stream",
+ EncryptAutoDec,
+ 0,
+ "automatically decrypt input" },
+ { "verbose_encrypt",
+ "Toggle verbose encryption output",
+ EncryptVerbose,
+ 0,
+ "print verbose encryption output" },
+ { "encdebug",
+ "Toggle encryption debugging",
+ EncryptDebug,
+ 0,
+ "print encryption debugging information" },
+#endif
+ { "skiprc",
+ "don't read ~/.telnetrc file",
+ 0,
+ &skiprc,
+ "skip reading of ~/.telnetrc file" },
+ { "binary",
+ "sending and receiving of binary data",
+ togbinary,
+ 0,
+ 0 },
+ { "inbinary",
+ "receiving of binary data",
+ togrbinary,
+ 0,
+ 0 },
+ { "outbinary",
+ "sending of binary data",
+ togxbinary,
+ 0,
+ 0 },
+ { "crlf",
+ "sending carriage returns as telnet <CR><LF>",
+ togcrlf,
+ &crlf,
+ 0 },
+ { "crmod",
+ "mapping of received carriage returns",
+ 0,
+ &crmod,
+ "map carriage return on output" },
+ { "localchars",
+ "local recognition of certain control characters",
+ lclchars,
+ &localchars,
+ "recognize certain control characters" },
+ { " ", "", 0 }, /* empty line */
+ { "debug",
+ "debugging",
+ togdebug,
+ &debug,
+ "turn on socket level debugging" },
+#if defined(KRB4) && defined(HAVE_KRB_DISABLE_DEBUG)
+ { "krb_debug",
+ "kerberos 4 debugging",
+ togkrbdebug,
+ &krb_debug,
+ "turn on kerberos 4 debugging" },
+#endif
+ { "netdata",
+ "printing of hexadecimal network data (debugging)",
+ 0,
+ &netdata,
+ "print hexadecimal representation of network traffic" },
+ { "prettydump",
+ "output of \"netdata\" to user readable format (debugging)",
+ 0,
+ &prettydump,
+ "print user readable output for \"netdata\"" },
+ { "options",
+ "viewing of options processing (debugging)",
+ 0,
+ &showoptions,
+ "show option processing" },
+ { "termdata",
+ "(debugging) toggle printing of hexadecimal terminal data",
+ 0,
+ &termdata,
+ "print hexadecimal representation of terminal traffic" },
+ { "?",
+ 0,
+ togglehelp },
+ { "help",
+ 0,
+ togglehelp },
+ { 0 }
+};
+
+static int
+togglehelp()
+{
+ struct togglelist *c;
+
+ for (c = Togglelist; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s toggle %s\r\n", c->name, c->help);
+ else
+ printf("\r\n");
+ }
+ }
+ printf("\r\n");
+ printf("%-15s %s\r\n", "?", "display help information");
+ return 0;
+}
+
+static void
+settogglehelp(int set)
+{
+ struct togglelist *c;
+
+ for (c = Togglelist; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s %s\r\n", c->name, set ? "enable" : "disable",
+ c->help);
+ else
+ printf("\r\n");
+ }
+ }
+}
+
+#define GETTOGGLE(name) (struct togglelist *) \
+ genget(name, (char **) Togglelist, sizeof(struct togglelist))
+
+static int
+toggle(int argc, char *argv[])
+{
+ int retval = 1;
+ char *name;
+ struct togglelist *c;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'toggle' command. 'toggle ?' for help.\r\n");
+ return 0;
+ }
+ argc--;
+ argv++;
+ while (argc--) {
+ name = *argv++;
+ c = GETTOGGLE(name);
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\r\n",
+ name);
+ return 0;
+ } else if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\r\n",
+ name);
+ return 0;
+ } else {
+ if (c->variable) {
+ *c->variable = !*c->variable; /* invert it */
+ if (c->actionexplanation) {
+ printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
+ c->actionexplanation);
+ }
+ }
+ if (c->handler) {
+ retval &= (*c->handler)(-1);
+ }
+ }
+ }
+ return retval;
+}
+
+/*
+ * The following perform the "set" command.
+ */
+
+struct termios new_tc = { 0 };
+
+struct setlist {
+ char *name; /* name */
+ char *help; /* help information */
+ void (*handler)();
+ cc_t *charp; /* where it is located at */
+};
+
+static struct setlist Setlist[] = {
+#ifdef KLUDGELINEMODE
+ { "echo", "character to toggle local echoing on/off", 0, &echoc },
+#endif
+ { "escape", "character to escape back to telnet command mode", 0, &escape },
+ { "rlogin", "rlogin escape character", 0, &rlogin },
+ { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
+ { " ", "" },
+ { " ", "The following need 'localchars' to be toggled true", 0, 0 },
+ { "flushoutput", "character to cause an Abort Output", 0, &termFlushChar },
+ { "interrupt", "character to cause an Interrupt Process", 0, &termIntChar },
+ { "quit", "character to cause an Abort process", 0, &termQuitChar },
+ { "eof", "character to cause an EOF ", 0, &termEofChar },
+ { " ", "" },
+ { " ", "The following are for local editing in linemode", 0, 0 },
+ { "erase", "character to use to erase a character", 0, &termEraseChar },
+ { "kill", "character to use to erase a line", 0, &termKillChar },
+ { "lnext", "character to use for literal next", 0, &termLiteralNextChar },
+ { "susp", "character to cause a Suspend Process", 0, &termSuspChar },
+ { "reprint", "character to use for line reprint", 0, &termRprntChar },
+ { "worderase", "character to use to erase a word", 0, &termWerasChar },
+ { "start", "character to use for XON", 0, &termStartChar },
+ { "stop", "character to use for XOFF", 0, &termStopChar },
+ { "forw1", "alternate end of line character", 0, &termForw1Char },
+ { "forw2", "alternate end of line character", 0, &termForw2Char },
+ { "ayt", "alternate AYT character", 0, &termAytChar },
+ { 0 }
+};
+
+static struct setlist *
+getset(char *name)
+{
+ return (struct setlist *)
+ genget(name, (char **) Setlist, sizeof(struct setlist));
+}
+
+void
+set_escape_char(char *s)
+{
+ if (rlogin != _POSIX_VDISABLE) {
+ rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
+ printf("Telnet rlogin escape character is '%s'.\r\n",
+ control(rlogin));
+ } else {
+ escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
+ printf("Telnet escape character is '%s'.\r\n", control(escape));
+ }
+}
+
+static int
+setcmd(int argc, char *argv[])
+{
+ int value;
+ struct setlist *ct;
+ struct togglelist *c;
+
+ if (argc < 2 || argc > 3) {
+ printf("Format is 'set Name Value'\r\n'set ?' for help.\r\n");
+ return 0;
+ }
+ if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
+ for (ct = Setlist; ct->name; ct++)
+ printf("%-15s %s\r\n", ct->name, ct->help);
+ printf("\r\n");
+ settogglehelp(1);
+ printf("%-15s %s\r\n", "?", "display help information");
+ return 0;
+ }
+
+ ct = getset(argv[1]);
+ if (ct == 0) {
+ c = GETTOGGLE(argv[1]);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('set ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ } else if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ if (c->variable) {
+ if ((argc == 2) || (strcmp("on", argv[2]) == 0))
+ *c->variable = 1;
+ else if (strcmp("off", argv[2]) == 0)
+ *c->variable = 0;
+ else {
+ printf("Format is 'set togglename [on|off]'\r\n'set ?' for help.\r\n");
+ return 0;
+ }
+ if (c->actionexplanation) {
+ printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
+ c->actionexplanation);
+ }
+ }
+ if (c->handler)
+ (*c->handler)(1);
+ } else if (argc != 3) {
+ printf("Format is 'set Name Value'\r\n'set ?' for help.\r\n");
+ return 0;
+ } else if (Ambiguous(ct)) {
+ fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ } else if (ct->handler) {
+ (*ct->handler)(argv[2]);
+ printf("%s set to \"%s\".\r\n", ct->name, (char *)ct->charp);
+ } else {
+ if (strcmp("off", argv[2])) {
+ value = special(argv[2]);
+ } else {
+ value = _POSIX_VDISABLE;
+ }
+ *(ct->charp) = (cc_t)value;
+ printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp)));
+ }
+ slc_check();
+ return 1;
+}
+
+static int
+unsetcmd(int argc, char *argv[])
+{
+ struct setlist *ct;
+ struct togglelist *c;
+ char *name;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'unset' command. 'unset ?' for help.\r\n");
+ return 0;
+ }
+ if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
+ for (ct = Setlist; ct->name; ct++)
+ printf("%-15s %s\r\n", ct->name, ct->help);
+ printf("\r\n");
+ settogglehelp(0);
+ printf("%-15s %s\r\n", "?", "display help information");
+ return 0;
+ }
+
+ argc--;
+ argv++;
+ while (argc--) {
+ name = *argv++;
+ ct = getset(name);
+ if (ct == 0) {
+ c = GETTOGGLE(name);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\r\n",
+ name);
+ return 0;
+ } else if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\r\n",
+ name);
+ return 0;
+ }
+ if (c->variable) {
+ *c->variable = 0;
+ if (c->actionexplanation) {
+ printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
+ c->actionexplanation);
+ }
+ }
+ if (c->handler)
+ (*c->handler)(0);
+ } else if (Ambiguous(ct)) {
+ fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\r\n",
+ name);
+ return 0;
+ } else if (ct->handler) {
+ (*ct->handler)(0);
+ printf("%s reset to \"%s\".\r\n", ct->name, (char *)ct->charp);
+ } else {
+ *(ct->charp) = _POSIX_VDISABLE;
+ printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp)));
+ }
+ }
+ return 1;
+}
+
+/*
+ * The following are the data structures and routines for the
+ * 'mode' command.
+ */
+#ifdef KLUDGELINEMODE
+extern int kludgelinemode;
+
+static int
+dokludgemode(void)
+{
+ kludgelinemode = 1;
+ send_wont(TELOPT_LINEMODE, 1);
+ send_dont(TELOPT_SGA, 1);
+ send_dont(TELOPT_ECHO, 1);
+ return 1;
+}
+#endif
+
+static int
+dolinemode()
+{
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode)
+ send_dont(TELOPT_SGA, 1);
+#endif
+ send_will(TELOPT_LINEMODE, 1);
+ send_dont(TELOPT_ECHO, 1);
+ return 1;
+}
+
+static int
+docharmode()
+{
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode)
+ send_do(TELOPT_SGA, 1);
+ else
+#endif
+ send_wont(TELOPT_LINEMODE, 1);
+ send_do(TELOPT_ECHO, 1);
+ return 1;
+}
+
+static int
+dolmmode(int bit, int on)
+{
+ unsigned char c;
+ extern int linemode;
+
+ if (my_want_state_is_wont(TELOPT_LINEMODE)) {
+ printf("?Need to have LINEMODE option enabled first.\r\n");
+ printf("'mode ?' for help.\r\n");
+ return 0;
+ }
+
+ if (on)
+ c = (linemode | bit);
+ else
+ c = (linemode & ~bit);
+ lm_mode(&c, 1, 1);
+ return 1;
+}
+
+static int
+tn_setmode(int bit)
+{
+ return dolmmode(bit, 1);
+}
+
+static int
+tn_clearmode(int bit)
+{
+ return dolmmode(bit, 0);
+}
+
+struct modelist {
+ char *name; /* command name */
+ char *help; /* help string */
+ int (*handler)(); /* routine which executes command */
+ int needconnect; /* Do we need to be connected to execute? */
+ int arg1;
+};
+
+static int modehelp(void);
+
+static struct modelist ModeList[] = {
+ { "character", "Disable LINEMODE option", docharmode, 1 },
+#ifdef KLUDGELINEMODE
+ { "", "(or disable obsolete line-by-line mode)", 0 },
+#endif
+ { "line", "Enable LINEMODE option", dolinemode, 1 },
+#ifdef KLUDGELINEMODE
+ { "", "(or enable obsolete line-by-line mode)", 0 },
+#endif
+ { "", "", 0 },
+ { "", "These require the LINEMODE option to be enabled", 0 },
+ { "isig", "Enable signal trapping", tn_setmode, 1, MODE_TRAPSIG },
+ { "+isig", 0, tn_setmode, 1, MODE_TRAPSIG },
+ { "-isig", "Disable signal trapping", tn_clearmode, 1, MODE_TRAPSIG },
+ { "edit", "Enable character editing", tn_setmode, 1, MODE_EDIT },
+ { "+edit", 0, tn_setmode, 1, MODE_EDIT },
+ { "-edit", "Disable character editing", tn_clearmode, 1, MODE_EDIT },
+ { "softtabs", "Enable tab expansion", tn_setmode, 1, MODE_SOFT_TAB },
+ { "+softtabs", 0, tn_setmode, 1, MODE_SOFT_TAB },
+ { "-softtabs", "Disable character editing", tn_clearmode, 1, MODE_SOFT_TAB },
+ { "litecho", "Enable literal character echo", tn_setmode, 1, MODE_LIT_ECHO },
+ { "+litecho", 0, tn_setmode, 1, MODE_LIT_ECHO },
+ { "-litecho", "Disable literal character echo", tn_clearmode, 1, MODE_LIT_ECHO },
+ { "help", 0, modehelp, 0 },
+#ifdef KLUDGELINEMODE
+ { "kludgeline", 0, dokludgemode, 1 },
+#endif
+ { "", "", 0 },
+ { "?", "Print help information", modehelp, 0 },
+ { 0 },
+};
+
+
+static int
+modehelp(void)
+{
+ struct modelist *mt;
+
+ printf("format is: 'mode Mode', where 'Mode' is one of:\r\n\r\n");
+ for (mt = ModeList; mt->name; mt++) {
+ if (mt->help) {
+ if (*mt->help)
+ printf("%-15s %s\r\n", mt->name, mt->help);
+ else
+ printf("\r\n");
+ }
+ }
+ return 0;
+}
+
+#define GETMODECMD(name) (struct modelist *) \
+ genget(name, (char **) ModeList, sizeof(struct modelist))
+
+static int
+modecmd(int argc, char **argv)
+{
+ struct modelist *mt;
+
+ if (argc != 2) {
+ printf("'mode' command requires an argument\r\n");
+ printf("'mode ?' for help.\r\n");
+ } else if ((mt = GETMODECMD(argv[1])) == 0) {
+ fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\r\n", argv[1]);
+ } else if (Ambiguous(mt)) {
+ fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\r\n", argv[1]);
+ } else if (mt->needconnect && !connected) {
+ printf("?Need to be connected first.\r\n");
+ printf("'mode ?' for help.\r\n");
+ } else if (mt->handler) {
+ return (*mt->handler)(mt->arg1);
+ }
+ return 0;
+}
+
+/*
+ * The following data structures and routines implement the
+ * "display" command.
+ */
+
+static int
+display(int argc, char *argv[])
+{
+ struct togglelist *tl;
+ struct setlist *sl;
+
+#define dotog(tl) if (tl->variable && tl->actionexplanation) { \
+ if (*tl->variable) { \
+ printf("will"); \
+ } else { \
+ printf("won't"); \
+ } \
+ printf(" %s.\r\n", tl->actionexplanation); \
+ }
+
+#define doset(sl) if (sl->name && *sl->name != ' ') { \
+ if (sl->handler == 0) \
+ printf("%-15s [%s]\r\n", sl->name, control(*sl->charp)); \
+ else \
+ printf("%-15s \"%s\"\r\n", sl->name, (char *)sl->charp); \
+ }
+
+ if (argc == 1) {
+ for (tl = Togglelist; tl->name; tl++) {
+ dotog(tl);
+ }
+ printf("\r\n");
+ for (sl = Setlist; sl->name; sl++) {
+ doset(sl);
+ }
+ } else {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ sl = getset(argv[i]);
+ tl = GETTOGGLE(argv[i]);
+ if (Ambiguous(sl) || Ambiguous(tl)) {
+ printf("?Ambiguous argument '%s'.\r\n", argv[i]);
+ return 0;
+ } else if (!sl && !tl) {
+ printf("?Unknown argument '%s'.\r\n", argv[i]);
+ return 0;
+ } else {
+ if (tl) {
+ dotog(tl);
+ }
+ if (sl) {
+ doset(sl);
+ }
+ }
+ }
+ }
+/*@*/optionstatus();
+#if defined(ENCRYPTION)
+ EncryptStatus();
+#endif
+ return 1;
+#undef doset
+#undef dotog
+}
+
+/*
+ * The following are the data structures, and many of the routines,
+ * relating to command processing.
+ */
+
+/*
+ * Set the escape character.
+ */
+static int
+setescape(int argc, char *argv[])
+{
+ char *arg;
+ char buf[50];
+
+ printf(
+ "Deprecated usage - please use 'set escape%s%s' in the future.\r\n",
+ (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
+ if (argc > 2)
+ arg = argv[1];
+ else {
+ printf("new escape character: ");
+ fgets(buf, sizeof(buf), stdin);
+ arg = buf;
+ }
+ if (arg[0] != '\0')
+ escape = arg[0];
+ printf("Escape character is '%s'.\r\n", control(escape));
+
+ fflush(stdout);
+ return 1;
+}
+
+static int
+togcrmod()
+{
+ crmod = !crmod;
+ printf("Deprecated usage - please use 'toggle crmod' in the future.\r\n");
+ printf("%s map carriage return on output.\r\n", crmod ? "Will" : "Won't");
+ fflush(stdout);
+ return 1;
+}
+
+static int
+telnetsuspend()
+{
+#ifdef SIGTSTP
+ setcommandmode();
+ {
+ long oldrows, oldcols, newrows, newcols, err;
+
+ err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+ kill(0, SIGTSTP);
+ /*
+ * If we didn't get the window size before the SUSPEND, but we
+ * can get them now (?), then send the NAWS to make sure that
+ * we are set up for the right window size.
+ */
+ if (TerminalWindowSize(&newrows, &newcols) && connected &&
+ (err || ((oldrows != newrows) || (oldcols != newcols)))) {
+ sendnaws();
+ }
+ }
+ /* reget parameters in case they were changed */
+ TerminalSaveState();
+ setconnmode(0);
+#else
+ printf("Suspend is not supported. Try the '!' command instead\r\n");
+#endif
+ return 1;
+}
+
+static int
+shell(int argc, char **argv)
+{
+ long oldrows, oldcols, newrows, newcols, err;
+
+ setcommandmode();
+
+ err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+ switch(fork()) {
+ case -1:
+ perror("Fork failed\r\n");
+ break;
+
+ case 0:
+ {
+ /*
+ * Fire up the shell in the child.
+ */
+ char *shellp, *shellname;
+
+ shellp = getenv("SHELL");
+ if (shellp == NULL)
+ shellp = "/bin/sh";
+ if ((shellname = strrchr(shellp, '/')) == 0)
+ shellname = shellp;
+ else
+ shellname++;
+ if (argc > 1)
+ execl(shellp, shellname, "-c", &saveline[1], 0);
+ else
+ execl(shellp, shellname, 0);
+ perror("Execl");
+ _exit(1);
+ }
+ default:
+ wait((int *)0); /* Wait for the shell to complete */
+
+ if (TerminalWindowSize(&newrows, &newcols) && connected &&
+ (err || ((oldrows != newrows) || (oldcols != newcols)))) {
+ sendnaws();
+ }
+ break;
+ }
+ return 1;
+}
+
+static int
+bye(int argc, char **argv)
+{
+ extern int resettermname;
+
+ if (connected) {
+ shutdown(net, 2);
+ printf("Connection closed.\r\n");
+ NetClose(net);
+ connected = 0;
+ resettermname = 1;
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ auth_encrypt_connect(connected);
+#endif
+ /* reset options */
+ tninit();
+ }
+ if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0))
+ longjmp(toplevel, 1);
+ return 0; /* NOTREACHED */
+}
+
+int
+quit(void)
+{
+ call(bye, "bye", "fromquit", 0);
+ Exit(0);
+ return 0; /*NOTREACHED*/
+}
+
+static int
+logout()
+{
+ send_do(TELOPT_LOGOUT, 1);
+ netflush();
+ return 1;
+}
+
+
+/*
+ * The SLC command.
+ */
+
+struct slclist {
+ char *name;
+ char *help;
+ void (*handler)();
+ int arg;
+};
+
+static void slc_help(void);
+
+struct slclist SlcList[] = {
+ { "export", "Use local special character definitions",
+ slc_mode_export, 0 },
+ { "import", "Use remote special character definitions",
+ slc_mode_import, 1 },
+ { "check", "Verify remote special character definitions",
+ slc_mode_import, 0 },
+ { "help", 0, slc_help, 0 },
+ { "?", "Print help information", slc_help, 0 },
+ { 0 },
+};
+
+static void
+slc_help(void)
+{
+ struct slclist *c;
+
+ for (c = SlcList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\r\n", c->name, c->help);
+ else
+ printf("\r\n");
+ }
+ }
+}
+
+static struct slclist *
+getslc(char *name)
+{
+ return (struct slclist *)
+ genget(name, (char **) SlcList, sizeof(struct slclist));
+}
+
+static int
+slccmd(int argc, char **argv)
+{
+ struct slclist *c;
+
+ if (argc != 2) {
+ fprintf(stderr,
+ "Need an argument to 'slc' command. 'slc ?' for help.\r\n");
+ return 0;
+ }
+ c = getslc(argv[1]);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ (*c->handler)(c->arg);
+ slcstate();
+ return 1;
+}
+
+/*
+ * The ENVIRON command.
+ */
+
+struct envlist {
+ char *name;
+ char *help;
+ void (*handler)();
+ int narg;
+};
+
+static void env_help (void);
+
+struct envlist EnvList[] = {
+ { "define", "Define an environment variable",
+ (void (*)())env_define, 2 },
+ { "undefine", "Undefine an environment variable",
+ env_undefine, 1 },
+ { "export", "Mark an environment variable for automatic export",
+ env_export, 1 },
+ { "unexport", "Don't mark an environment variable for automatic export",
+ env_unexport, 1 },
+ { "send", "Send an environment variable", env_send, 1 },
+ { "list", "List the current environment variables",
+ env_list, 0 },
+ { "help", 0, env_help, 0 },
+ { "?", "Print help information", env_help, 0 },
+ { 0 },
+};
+
+static void
+env_help()
+{
+ struct envlist *c;
+
+ for (c = EnvList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\r\n", c->name, c->help);
+ else
+ printf("\r\n");
+ }
+ }
+}
+
+static struct envlist *
+getenvcmd(char *name)
+{
+ return (struct envlist *)
+ genget(name, (char **) EnvList, sizeof(struct envlist));
+}
+
+static int
+env_cmd(int argc, char **argv)
+{
+ struct envlist *c;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'environ' command. 'environ ?' for help.\r\n");
+ return 0;
+ }
+ c = getenvcmd(argv[1]);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ if (c->narg + 2 != argc) {
+ fprintf(stderr,
+ "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\r\n",
+ c->narg < argc + 2 ? "only " : "",
+ c->narg, c->narg == 1 ? "" : "s", c->name);
+ return 0;
+ }
+ (*c->handler)(argv[2], argv[3]);
+ return 1;
+}
+
+struct env_lst {
+ struct env_lst *next; /* pointer to next structure */
+ struct env_lst *prev; /* pointer to previous structure */
+ unsigned char *var; /* pointer to variable name */
+ unsigned char *value; /* pointer to variable value */
+ int export; /* 1 -> export with default list of variables */
+ int welldefined; /* A well defined variable */
+};
+
+struct env_lst envlisthead;
+
+struct env_lst *
+env_find(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ for (ep = envlisthead.next; ep; ep = ep->next) {
+ if (strcmp((char *)ep->var, (char *)var) == 0)
+ return(ep);
+ }
+ return(NULL);
+}
+
+#if IRIX == 4
+#define environ _environ
+#endif
+
+void
+env_init(void)
+{
+ extern char **environ;
+ char **epp, *cp;
+ struct env_lst *ep;
+
+ for (epp = environ; *epp; epp++) {
+ if ((cp = strchr(*epp, '='))) {
+ *cp = '\0';
+ ep = env_define((unsigned char *)*epp,
+ (unsigned char *)cp+1);
+ ep->export = 0;
+ *cp = '=';
+ }
+ }
+ /*
+ * Special case for DISPLAY variable. If it is ":0.0" or
+ * "unix:0.0", we have to get rid of "unix" and insert our
+ * hostname.
+ */
+ if ((ep = env_find("DISPLAY"))
+ && (*ep->value == ':'
+ || strncmp((char *)ep->value, "unix:", 5) == 0)) {
+ char hbuf[256+1];
+ char *cp2 = strchr((char *)ep->value, ':');
+
+ /* XXX - should be k_gethostname? */
+ gethostname(hbuf, 256);
+ hbuf[256] = '\0';
+
+ /* If this is not the full name, try to get it via DNS */
+ if (strchr(hbuf, '.') == 0) {
+ struct hostent *he = roken_gethostbyname(hbuf);
+ if (he != NULL)
+ strcpy_truncate(hbuf, he->h_name, 256);
+ }
+
+ asprintf (&cp, "%s%s", hbuf, cp2);
+ free (ep->value);
+ ep->value = (unsigned char *)cp;
+ }
+ /*
+ * If USER is not defined, but LOGNAME is, then add
+ * USER with the value from LOGNAME. By default, we
+ * don't export the USER variable.
+ */
+ if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
+ env_define((unsigned char *)"USER", ep->value);
+ env_unexport((unsigned char *)"USER");
+ }
+ env_export((unsigned char *)"DISPLAY");
+ env_export((unsigned char *)"PRINTER");
+ env_export((unsigned char *)"XAUTHORITY");
+}
+
+struct env_lst *
+env_define(unsigned char *var, unsigned char *value)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var))) {
+ if (ep->var)
+ free(ep->var);
+ if (ep->value)
+ free(ep->value);
+ } else {
+ ep = (struct env_lst *)malloc(sizeof(struct env_lst));
+ ep->next = envlisthead.next;
+ envlisthead.next = ep;
+ ep->prev = &envlisthead;
+ if (ep->next)
+ ep->next->prev = ep;
+ }
+ ep->welldefined = opt_welldefined((char *)var);
+ ep->export = 1;
+ ep->var = (unsigned char *)strdup((char *)var);
+ ep->value = (unsigned char *)strdup((char *)value);
+ return(ep);
+}
+
+void
+env_undefine(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var))) {
+ ep->prev->next = ep->next;
+ if (ep->next)
+ ep->next->prev = ep->prev;
+ if (ep->var)
+ free(ep->var);
+ if (ep->value)
+ free(ep->value);
+ free(ep);
+ }
+}
+
+void
+env_export(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)))
+ ep->export = 1;
+}
+
+void
+env_unexport(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)))
+ ep->export = 0;
+}
+
+void
+env_send(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ if (my_state_is_wont(TELOPT_NEW_ENVIRON)
+#ifdef OLD_ENVIRON
+ && my_state_is_wont(TELOPT_OLD_ENVIRON)
+#endif
+ ) {
+ fprintf(stderr,
+ "Cannot send '%s': Telnet ENVIRON option not enabled\r\n",
+ var);
+ return;
+ }
+ ep = env_find(var);
+ if (ep == 0) {
+ fprintf(stderr, "Cannot send '%s': variable not defined\r\n",
+ var);
+ return;
+ }
+ env_opt_start_info();
+ env_opt_add(ep->var);
+ env_opt_end(0);
+}
+
+void
+env_list(void)
+{
+ struct env_lst *ep;
+
+ for (ep = envlisthead.next; ep; ep = ep->next) {
+ printf("%c %-20s %s\r\n", ep->export ? '*' : ' ',
+ ep->var, ep->value);
+ }
+}
+
+unsigned char *
+env_default(int init, int welldefined)
+{
+ static struct env_lst *nep = NULL;
+
+ if (init) {
+ nep = &envlisthead;
+ return NULL;
+ }
+ if (nep) {
+ while ((nep = nep->next)) {
+ if (nep->export && (nep->welldefined == welldefined))
+ return(nep->var);
+ }
+ }
+ return(NULL);
+}
+
+unsigned char *
+env_getvalue(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)))
+ return(ep->value);
+ return(NULL);
+}
+
+
+#if defined(AUTHENTICATION)
+/*
+ * The AUTHENTICATE command.
+ */
+
+struct authlist {
+ char *name;
+ char *help;
+ int (*handler)();
+ int narg;
+};
+
+static int
+ auth_help (void);
+
+struct authlist AuthList[] = {
+ { "status", "Display current status of authentication information",
+ auth_status, 0 },
+ { "disable", "Disable an authentication type ('auth disable ?' for more)",
+ auth_disable, 1 },
+ { "enable", "Enable an authentication type ('auth enable ?' for more)",
+ auth_enable, 1 },
+ { "help", 0, auth_help, 0 },
+ { "?", "Print help information", auth_help, 0 },
+ { 0 },
+};
+
+static int
+auth_help()
+{
+ struct authlist *c;
+
+ for (c = AuthList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\r\n", c->name, c->help);
+ else
+ printf("\r\n");
+ }
+ }
+ return 0;
+}
+
+static int
+auth_cmd(int argc, char **argv)
+{
+ struct authlist *c;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'auth' command. 'auth ?' for help.\r\n");
+ return 0;
+ }
+
+ c = (struct authlist *)
+ genget(argv[1], (char **) AuthList, sizeof(struct authlist));
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ if (c->narg + 2 != argc) {
+ fprintf(stderr,
+ "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\r\n",
+ c->narg < argc + 2 ? "only " : "",
+ c->narg, c->narg == 1 ? "" : "s", c->name);
+ return 0;
+ }
+ return((*c->handler)(argv[2], argv[3]));
+}
+#endif
+
+
+#if defined(ENCRYPTION)
+/*
+ * The ENCRYPT command.
+ */
+
+struct encryptlist {
+ char *name;
+ char *help;
+ int (*handler)();
+ int needconnect;
+ int minarg;
+ int maxarg;
+};
+
+static int
+ EncryptHelp (void);
+
+struct encryptlist EncryptList[] = {
+ { "enable", "Enable encryption. ('encrypt enable ?' for more)",
+ EncryptEnable, 1, 1, 2 },
+ { "disable", "Disable encryption. ('encrypt enable ?' for more)",
+ EncryptDisable, 0, 1, 2 },
+ { "type", "Set encryptiong type. ('encrypt type ?' for more)",
+ EncryptType, 0, 1, 1 },
+ { "start", "Start encryption. ('encrypt start ?' for more)",
+ EncryptStart, 1, 0, 1 },
+ { "stop", "Stop encryption. ('encrypt stop ?' for more)",
+ EncryptStop, 1, 0, 1 },
+ { "input", "Start encrypting the input stream",
+ EncryptStartInput, 1, 0, 0 },
+ { "-input", "Stop encrypting the input stream",
+ EncryptStopInput, 1, 0, 0 },
+ { "output", "Start encrypting the output stream",
+ EncryptStartOutput, 1, 0, 0 },
+ { "-output", "Stop encrypting the output stream",
+ EncryptStopOutput, 1, 0, 0 },
+
+ { "status", "Display current status of authentication information",
+ EncryptStatus, 0, 0, 0 },
+ { "help", 0, EncryptHelp, 0, 0, 0 },
+ { "?", "Print help information", EncryptHelp, 0, 0, 0 },
+ { 0 },
+};
+
+static int
+EncryptHelp()
+{
+ struct encryptlist *c;
+
+ for (c = EncryptList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\r\n", c->name, c->help);
+ else
+ printf("\r\n");
+ }
+ }
+ return 0;
+}
+
+static int
+encrypt_cmd(int argc, char **argv)
+{
+ struct encryptlist *c;
+
+ c = (struct encryptlist *)
+ genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\r\n",
+ argv[1]);
+ return 0;
+ }
+ argc -= 2;
+ if (argc < c->minarg || argc > c->maxarg) {
+ if (c->minarg == c->maxarg) {
+ fprintf(stderr, "Need %s%d argument%s ",
+ c->minarg < argc ? "only " : "", c->minarg,
+ c->minarg == 1 ? "" : "s");
+ } else {
+ fprintf(stderr, "Need %s%d-%d arguments ",
+ c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
+ }
+ fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\r\n",
+ c->name);
+ return 0;
+ }
+ if (c->needconnect && !connected) {
+ if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
+ printf("?Need to be connected first.\r\n");
+ return 0;
+ }
+ }
+ return ((*c->handler)(argc > 0 ? argv[2] : 0,
+ argc > 1 ? argv[3] : 0,
+ argc > 2 ? argv[4] : 0));
+}
+#endif
+
+
+/*
+ * Print status about the connection.
+ */
+
+static int
+status(int argc, char **argv)
+{
+ if (connected) {
+ printf("Connected to %s.\r\n", hostname);
+ if ((argc < 2) || strcmp(argv[1], "notmuch")) {
+ int mode = getconnmode();
+
+ if (my_want_state_is_will(TELOPT_LINEMODE)) {
+ printf("Operating with LINEMODE option\r\n");
+ printf("%s line editing\r\n", (mode&MODE_EDIT) ? "Local" : "No");
+ printf("%s catching of signals\r\n",
+ (mode&MODE_TRAPSIG) ? "Local" : "No");
+ slcstate();
+#ifdef KLUDGELINEMODE
+ } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
+ printf("Operating in obsolete linemode\r\n");
+#endif
+ } else {
+ printf("Operating in single character mode\r\n");
+ if (localchars)
+ printf("Catching signals locally\r\n");
+ }
+ printf("%s character echo\r\n", (mode&MODE_ECHO) ? "Local" : "Remote");
+ if (my_want_state_is_will(TELOPT_LFLOW))
+ printf("%s flow control\r\n", (mode&MODE_FLOW) ? "Local" : "No");
+#if defined(ENCRYPTION)
+ encrypt_display();
+#endif
+ }
+ } else {
+ printf("No connection.\r\n");
+ }
+ printf("Escape character is '%s'.\r\n", control(escape));
+ fflush(stdout);
+ return 1;
+}
+
+#ifdef SIGINFO
+/*
+ * Function that gets called when SIGINFO is received.
+ */
+void
+ayt_status(int ignore)
+{
+ call(status, "status", "notmuch", 0);
+}
+#endif
+
+static Command *getcmd(char *name);
+
+static void
+cmdrc(char *m1, char *m2)
+{
+ static char rcname[128];
+ Command *c;
+ FILE *rcfile;
+ int gotmachine = 0;
+ int l1 = strlen(m1);
+ int l2 = strlen(m2);
+ char m1save[64];
+
+ if (skiprc)
+ return;
+
+ strcpy_truncate(m1save, m1, sizeof(m1save));
+ m1 = m1save;
+
+ if (rcname[0] == 0) {
+ char *home = getenv("HOME");
+
+ snprintf (rcname, sizeof(rcname), "%s/.telnetrc",
+ home ? home : "");
+ }
+
+ if ((rcfile = fopen(rcname, "r")) == 0) {
+ return;
+ }
+
+ for (;;) {
+ if (fgets(line, sizeof(line), rcfile) == NULL)
+ break;
+ if (line[0] == 0)
+ break;
+ if (line[0] == '#')
+ continue;
+ if (gotmachine) {
+ if (!isspace(line[0]))
+ gotmachine = 0;
+ }
+ if (gotmachine == 0) {
+ if (isspace(line[0]))
+ continue;
+ if (strncasecmp(line, m1, l1) == 0)
+ strncpy(line, &line[l1], sizeof(line) - l1);
+ else if (strncasecmp(line, m2, l2) == 0)
+ strncpy(line, &line[l2], sizeof(line) - l2);
+ else if (strncasecmp(line, "DEFAULT", 7) == 0)
+ strncpy(line, &line[7], sizeof(line) - 7);
+ else
+ continue;
+ if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
+ continue;
+ gotmachine = 1;
+ }
+ makeargv();
+ if (margv[0] == 0)
+ continue;
+ c = getcmd(margv[0]);
+ if (Ambiguous(c)) {
+ printf("?Ambiguous command: %s\r\n", margv[0]);
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command: %s\r\n", margv[0]);
+ continue;
+ }
+ /*
+ * This should never happen...
+ */
+ if (c->needconnect && !connected) {
+ printf("?Need to be connected first for %s.\r\n", margv[0]);
+ continue;
+ }
+ (*c->handler)(margc, margv);
+ }
+ fclose(rcfile);
+}
+
+int
+tn(int argc, char **argv)
+{
+ struct hostent *host = 0;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 sin6;
+#endif
+ struct sockaddr_in sin;
+ struct sockaddr *sa = NULL;
+ int sa_size = 0;
+ struct servent *sp = 0;
+ unsigned long temp;
+ extern char *inet_ntoa();
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ char *srp = 0;
+ int srlen;
+#endif
+ char *cmd, *hostp = 0, *portp = 0;
+ char *user = 0;
+ int family, port = 0;
+ char **addr_list;
+
+ /* clear the socket address prior to use */
+
+ if (connected) {
+ printf("?Already connected to %s\r\n", hostname);
+ setuid(getuid());
+ return 0;
+ }
+ if (argc < 2) {
+ strcpy_truncate(line, "open ", sizeof(line));
+ printf("(to) ");
+ fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ cmd = *argv;
+ --argc; ++argv;
+ while (argc) {
+ if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
+ goto usage;
+ if (strcmp(*argv, "-l") == 0) {
+ --argc; ++argv;
+ if (argc == 0)
+ goto usage;
+ user = strdup(*argv++);
+ --argc;
+ continue;
+ }
+ if (strcmp(*argv, "-a") == 0) {
+ --argc; ++argv;
+ autologin = 1;
+ continue;
+ }
+ if (hostp == 0) {
+ hostp = *argv++;
+ --argc;
+ continue;
+ }
+ if (portp == 0) {
+ portp = *argv++;
+ --argc;
+ continue;
+ }
+ usage:
+ printf("usage: %s [-l user] [-a] host-name [port]\r\n", cmd);
+ setuid(getuid());
+ return 0;
+ }
+ if (hostp == 0)
+ goto usage;
+
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ if (hostp[0] == '@' || hostp[0] == '!') {
+ if ((hostname = strrchr(hostp, ':')) == NULL)
+ hostname = strrchr(hostp, '@');
+ hostname++;
+ srp = 0;
+ temp = sourceroute(hostp, &srp, &srlen);
+ if (temp == 0) {
+ fprintf (stderr, "%s: %s\r\n", srp ? srp : "", hstrerror(h_errno));
+ setuid(getuid());
+ return 0;
+ } else if (temp == -1) {
+ printf("Bad source route option: %s\r\n", hostp);
+ setuid(getuid());
+ return 0;
+ } else {
+ abort();
+ }
+ } else {
+#endif
+ memset (&sin, 0, sizeof(sin));
+#ifdef HAVE_IPV6
+ memset (&sin6, 0, sizeof(sin6));
+
+ if(inet_pton(AF_INET6, hostp, &sin6.sin6_addr)) {
+ sin6.sin6_family = family = AF_INET6;
+ sa = (struct sockaddr *)&sin6;
+ sa_size = sizeof(sin6);
+ strcpy_truncate(_hostname, hostp, sizeof(_hostname));
+ hostname =_hostname;
+ } else
+#endif
+ if(inet_aton(hostp, &sin.sin_addr)){
+ sin.sin_family = family = AF_INET;
+ sa = (struct sockaddr *)&sin;
+ sa_size = sizeof(sin);
+ strcpy_truncate(_hostname, hostp, sizeof(_hostname));
+ hostname = _hostname;
+ } else {
+#ifdef HAVE_GETHOSTBYNAME2
+#ifdef HAVE_IPV6
+ host = gethostbyname2(hostp, AF_INET6);
+ if(host == NULL)
+#endif
+ host = gethostbyname2(hostp, AF_INET);
+#else
+ host = roken_gethostbyname(hostp);
+#endif
+ if (host) {
+ strcpy_truncate(_hostname, host->h_name, sizeof(_hostname));
+ family = host->h_addrtype;
+ addr_list = host->h_addr_list;
+
+ switch(family) {
+ case AF_INET:
+ memset(&sin, 0, sizeof(sin));
+ sa_size = sizeof(sin);
+ sa = (struct sockaddr *)&sin;
+ sin.sin_family = family;
+ sin.sin_addr = *((struct in_addr *)(*addr_list));
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ memset(&sin6, 0, sizeof(sin6));
+ sa_size = sizeof(sin6);
+ sa = (struct sockaddr *)&sin6;
+ sin6.sin6_family = family;
+ sin6.sin6_addr = *((struct in6_addr *)(*addr_list));
+ break;
+#endif
+ default:
+ fprintf(stderr, "Bad address family: %d\n", family);
+ return 0;
+ }
+
+ _hostname[sizeof(_hostname)-1] = '\0';
+ hostname = _hostname;
+ } else {
+ fprintf (stderr, "%s: %s\r\n", hostp ? hostp : "",
+ hstrerror(h_errno));
+ setuid(getuid());
+ return 0;
+ }
+ }
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ }
+#endif
+ if (portp) {
+ if (*portp == '-') {
+ portp++;
+ telnetport = 1;
+ } else
+ telnetport = 0;
+ port = atoi(portp);
+ if (port == 0) {
+ sp = roken_getservbyname(portp, "tcp");
+ if (sp)
+ port = sp->s_port;
+ else {
+ printf("%s: bad port number\r\n", portp);
+ setuid(getuid());
+ return 0;
+ }
+ } else {
+ port = htons(port);
+ }
+ } else {
+ if (sp == 0) {
+ sp = roken_getservbyname("telnet", "tcp");
+ if (sp == 0) {
+ fprintf(stderr, "telnet: tcp/telnet: unknown service\r\n");
+ setuid(getuid());
+ return 0;
+ }
+ port = sp->s_port;
+ }
+ telnetport = 1;
+ }
+ do {
+ switch(family) {
+ case AF_INET:
+ sin.sin_port = port;
+ printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr));
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+ char buf[INET6_ADDRSTRLEN];
+
+ sin6.sin6_port = port;
+#ifdef HAVE_INET_NTOP
+ printf("Trying %s...\r\n", inet_ntop(AF_INET6,
+ &sin6.sin6_addr,
+ buf,
+ sizeof(buf)));
+#endif
+ break;
+ }
+#endif
+ default:
+ abort();
+ }
+
+
+ net = socket(family, SOCK_STREAM, 0);
+ setuid(getuid());
+ if (net < 0) {
+ perror("telnet: socket");
+ return 0;
+ }
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP) && defined(HAVE_SETSOCKOPT)
+ if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (void *)srp,
+ srlen) < 0)
+ perror("setsockopt (IP_OPTIONS)");
+#endif
+#if defined(IPPROTO_IP) && defined(IP_TOS)
+ {
+# if defined(HAVE_GETTOSBYNAME)
+ struct tosent *tp;
+ if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+ tos = tp->t_tos;
+# endif
+ if (tos < 0)
+ tos = 020; /* Low Delay bit */
+ if (tos
+ && (setsockopt(net, IPPROTO_IP, IP_TOS,
+ (void *)&tos, sizeof(int)) < 0)
+ && (errno != ENOPROTOOPT))
+ perror("telnet: setsockopt (IP_TOS) (ignored)");
+ }
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+ if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
+ perror("setsockopt (SO_DEBUG)");
+ }
+
+ if (connect(net, sa, sa_size) < 0) {
+ if (host && addr_list[1]) {
+ int oerrno = errno;
+
+ switch(family) {
+ case AF_INET :
+ fprintf(stderr, "telnet: connect to address %s: ",
+ inet_ntoa(sin.sin_addr));
+ sin.sin_addr = *((struct in_addr *)(*++addr_list));
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ char buf[INET6_ADDRSTRLEN];
+
+ fprintf(stderr, "telnet: connect to address %s: ",
+ inet_ntop(AF_INET6, &sin6.sin6_addr, buf,
+ sizeof(buf)));
+ sin6.sin6_addr = *((struct in6_addr *)(*++addr_list));
+ break;
+ }
+#endif
+ default:
+ abort();
+ }
+
+ errno = oerrno;
+ perror(NULL);
+ NetClose(net);
+ continue;
+ }
+ perror("telnet: Unable to connect to remote host");
+ return 0;
+ }
+ connected++;
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ auth_encrypt_connect(connected);
+#endif
+ } while (connected == 0);
+ cmdrc(hostp, hostname);
+ if (autologin && user == NULL)
+ user = (char *)get_default_username ();
+ if (user) {
+ env_define((unsigned char *)"USER", (unsigned char *)user);
+ env_export((unsigned char *)"USER");
+ }
+ call(status, "status", "notmuch", 0);
+ if (setjmp(peerdied) == 0)
+ my_telnet((char *)user);
+ NetClose(net);
+ ExitString("Connection closed by foreign host.\r\n",1);
+ /*NOTREACHED*/
+ return 0;
+}
+
+#define HELPINDENT ((int)sizeof ("connect"))
+
+static char
+ openhelp[] = "connect to a site",
+ closehelp[] = "close current connection",
+ logouthelp[] = "forcibly logout remote user and close the connection",
+ quithelp[] = "exit telnet",
+ statushelp[] = "print status information",
+ helphelp[] = "print help information",
+ sendhelp[] = "transmit special characters ('send ?' for more)",
+ sethelp[] = "set operating parameters ('set ?' for more)",
+ unsethelp[] = "unset operating parameters ('unset ?' for more)",
+ togglestring[] ="toggle operating parameters ('toggle ?' for more)",
+ slchelp[] = "change state of special charaters ('slc ?' for more)",
+ displayhelp[] = "display operating parameters",
+#if defined(AUTHENTICATION)
+ authhelp[] = "turn on (off) authentication ('auth ?' for more)",
+#endif
+#if defined(ENCRYPTION)
+ encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)",
+#endif
+ zhelp[] = "suspend telnet",
+ shellhelp[] = "invoke a subshell",
+ envhelp[] = "change environment variables ('environ ?' for more)",
+ modestring[] = "try to enter line or character mode ('mode ?' for more)";
+
+static int help(int argc, char **argv);
+
+static Command cmdtab[] = {
+ { "close", closehelp, bye, 1 },
+ { "logout", logouthelp, logout, 1 },
+ { "display", displayhelp, display, 0 },
+ { "mode", modestring, modecmd, 0 },
+ { "open", openhelp, tn, 0 },
+ { "quit", quithelp, quit, 0 },
+ { "send", sendhelp, sendcmd, 0 },
+ { "set", sethelp, setcmd, 0 },
+ { "unset", unsethelp, unsetcmd, 0 },
+ { "status", statushelp, status, 0 },
+ { "toggle", togglestring, toggle, 0 },
+ { "slc", slchelp, slccmd, 0 },
+#if defined(AUTHENTICATION)
+ { "auth", authhelp, auth_cmd, 0 },
+#endif
+#if defined(ENCRYPTION)
+ { "encrypt", encrypthelp, encrypt_cmd, 0 },
+#endif
+ { "z", zhelp, telnetsuspend, 0 },
+ { "!", shellhelp, shell, 0 },
+ { "environ", envhelp, env_cmd, 0 },
+ { "?", helphelp, help, 0 },
+ { 0, 0, 0, 0 }
+};
+
+static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead";
+static char escapehelp[] = "deprecated command -- use 'set escape' instead";
+
+static Command cmdtab2[] = {
+ { "help", 0, help, 0 },
+ { "escape", escapehelp, setescape, 0 },
+ { "crmod", crmodhelp, togcrmod, 0 },
+ { 0, 0, 0, 0 }
+};
+
+
+/*
+ * Call routine with argc, argv set from args (terminated by 0).
+ */
+
+static int
+call(intrtn_t routine, ...)
+{
+ va_list ap;
+ char *args[100];
+ int argno = 0;
+
+ va_start(ap, routine);
+ while ((args[argno++] = va_arg(ap, char *)) != 0);
+ va_end(ap);
+ return (*routine)(argno-1, args);
+}
+
+
+static Command
+*getcmd(char *name)
+{
+ Command *cm;
+
+ if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command))))
+ return cm;
+ return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
+}
+
+void
+command(int top, char *tbuf, int cnt)
+{
+ Command *c;
+
+ setcommandmode();
+ if (!top) {
+ putchar('\n');
+ } else {
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ }
+ for (;;) {
+ if (rlogin == _POSIX_VDISABLE)
+ printf("%s> ", prompt);
+ if (tbuf) {
+ char *cp;
+ cp = line;
+ while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
+ cnt--;
+ tbuf = 0;
+ if (cp == line || *--cp != '\n' || cp == line)
+ goto getline;
+ *cp = '\0';
+ if (rlogin == _POSIX_VDISABLE)
+ printf("%s\r\n", line);
+ } else {
+ getline:
+ if (rlogin != _POSIX_VDISABLE)
+ printf("%s> ", prompt);
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ if (feof(stdin) || ferror(stdin)) {
+ quit();
+ /*NOTREACHED*/
+ }
+ break;
+ }
+ }
+ if (line[0] == 0)
+ break;
+ makeargv();
+ if (margv[0] == 0) {
+ break;
+ }
+ c = getcmd(margv[0]);
+ if (Ambiguous(c)) {
+ printf("?Ambiguous command\r\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\r\n");
+ continue;
+ }
+ if (c->needconnect && !connected) {
+ printf("?Need to be connected first.\r\n");
+ continue;
+ }
+ if ((*c->handler)(margc, margv)) {
+ break;
+ }
+ }
+ if (!top) {
+ if (!connected) {
+ longjmp(toplevel, 1);
+ /*NOTREACHED*/
+ }
+ setconnmode(0);
+ }
+}
+
+/*
+ * Help command.
+ */
+static int
+help(int argc, char **argv)
+{
+ Command *c;
+
+ if (argc == 1) {
+ printf("Commands may be abbreviated. Commands are:\r\n\r\n");
+ for (c = cmdtab; c->name; c++)
+ if (c->help) {
+ printf("%-*s\t%s\r\n", HELPINDENT, c->name,
+ c->help);
+ }
+ return 0;
+ }
+ while (--argc > 0) {
+ char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (Ambiguous(c))
+ printf("?Ambiguous help command %s\r\n", arg);
+ else if (c == (Command *)0)
+ printf("?Invalid help command %s\r\n", arg);
+ else
+ printf("%s\r\n", c->help);
+ }
+ return 0;
+}
+
+
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+
+/*
+ * Source route is handed in as
+ * [!]@hop1@hop2...[@|:]dst
+ * If the leading ! is present, it is a
+ * strict source route, otherwise it is
+ * assmed to be a loose source route.
+ *
+ * We fill in the source route option as
+ * hop1,hop2,hop3...dest
+ * and return a pointer to hop1, which will
+ * be the address to connect() to.
+ *
+ * Arguments:
+ * arg: pointer to route list to decipher
+ *
+ * cpp: If *cpp is not equal to NULL, this is a
+ * pointer to a pointer to a character array
+ * that should be filled in with the option.
+ *
+ * lenp: pointer to an integer that contains the
+ * length of *cpp if *cpp != NULL.
+ *
+ * Return values:
+ *
+ * Returns the address of the host to connect to. If the
+ * return value is -1, there was a syntax error in the
+ * option, either unknown characters, or too many hosts.
+ * If the return value is 0, one of the hostnames in the
+ * path is unknown, and *cpp is set to point to the bad
+ * hostname.
+ *
+ * *cpp: If *cpp was equal to NULL, it will be filled
+ * in with a pointer to our static area that has
+ * the option filled in. This will be 32bit aligned.
+ *
+ * *lenp: This will be filled in with how long the option
+ * pointed to by *cpp is.
+ *
+ */
+unsigned long
+sourceroute(char *arg, char **cpp, int *lenp)
+{
+ static char lsr[44];
+ char *cp, *cp2, *lsrp, *lsrep;
+ int tmp;
+ struct in_addr sin_addr;
+ struct hostent *host = 0;
+ char c;
+
+ /*
+ * Verify the arguments, and make sure we have
+ * at least 7 bytes for the option.
+ */
+ if (cpp == NULL || lenp == NULL)
+ return((unsigned long)-1);
+ if (*cpp != NULL && *lenp < 7)
+ return((unsigned long)-1);
+ /*
+ * Decide whether we have a buffer passed to us,
+ * or if we need to use our own static buffer.
+ */
+ if (*cpp) {
+ lsrp = *cpp;
+ lsrep = lsrp + *lenp;
+ } else {
+ *cpp = lsrp = lsr;
+ lsrep = lsrp + 44;
+ }
+
+ cp = arg;
+
+ /*
+ * Next, decide whether we have a loose source
+ * route or a strict source route, and fill in
+ * the begining of the option.
+ */
+ if (*cp == '!') {
+ cp++;
+ *lsrp++ = IPOPT_SSRR;
+ } else
+ *lsrp++ = IPOPT_LSRR;
+
+ if (*cp != '@')
+ return((unsigned long)-1);
+
+ lsrp++; /* skip over length, we'll fill it in later */
+ *lsrp++ = 4;
+
+ cp++;
+
+ sin_addr.s_addr = 0;
+
+ for (c = 0;;) {
+ if (c == ':')
+ cp2 = 0;
+ else for (cp2 = cp; (c = *cp2); cp2++) {
+ if (c == ',') {
+ *cp2++ = '\0';
+ if (*cp2 == '@')
+ cp2++;
+ } else if (c == '@') {
+ *cp2++ = '\0';
+ } else if (c == ':') {
+ *cp2++ = '\0';
+ } else
+ continue;
+ break;
+ }
+ if (!c)
+ cp2 = 0;
+
+ if ((tmp = inet_addr(cp)) != -1) {
+ sin_addr.s_addr = tmp;
+ } else if ((host = roken_gethostbyname(cp))) {
+ memmove(&sin_addr,
+ host->h_addr_list[0],
+ sizeof(sin_addr));
+ } else {
+ *cpp = cp;
+ return(0);
+ }
+ memmove(lsrp, &sin_addr, 4);
+ lsrp += 4;
+ if (cp2)
+ cp = cp2;
+ else
+ break;
+ /*
+ * Check to make sure there is space for next address
+ */
+ if (lsrp + 4 > lsrep)
+ return((unsigned long)-1);
+ }
+ if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
+ *cpp = 0;
+ *lenp = 0;
+ return((unsigned long)-1);
+ }
+ *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
+ *lenp = lsrp - *cpp;
+ return(sin_addr.s_addr);
+}
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/telnet/defines.h b/crypto/kerberosIV/appl/telnet/telnet/defines.h
new file mode 100644
index 0000000..5c1ac2b
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/defines.h
@@ -0,0 +1,60 @@
+/*
+ * 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 */
diff --git a/crypto/kerberosIV/appl/telnet/telnet/externs.h b/crypto/kerberosIV/appl/telnet/telnet/externs.h
new file mode 100644
index 0000000..f8b1668
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/externs.h
@@ -0,0 +1,429 @@
+/*
+ * 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: externs.h,v 1.18 1998/07/09 23:16:36 assar Exp $ */
+
+#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,
+ 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 cc_t escape; /* Escape to command mode */
+extern cc_t rlogin; /* Rlogin mode escape character */
+#ifdef KLUDGELINEMODE
+extern cc_t echoc; /* Toggle local echoing */
+#endif
+
+extern char
+ *prompt; /* Prompt for command. */
+
+extern char
+ doopt[],
+ dont[],
+ will[],
+ wont[],
+ options[], /* All the little options */
+ *hostname; /* Who are we connected to? */
+#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 symetrical
+ */
+
+#define HIS_STATE_WILL MY_STATE_DO
+#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO
+#define HIS_STATE_DO MY_STATE_WILL
+#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL
+
+#define his_state_is_do my_state_is_will
+#define his_state_is_will my_state_is_do
+#define his_want_state_is_do my_want_state_is_will
+#define his_want_state_is_will my_want_state_is_do
+
+#define his_state_is_dont my_state_is_wont
+#define his_state_is_wont my_state_is_dont
+#define his_want_state_is_dont my_want_state_is_wont
+#define his_want_state_is_wont my_want_state_is_dont
+
+#define set_his_state_do set_my_state_will
+#define set_his_state_will set_my_state_do
+#define set_his_want_state_do set_my_want_state_will
+#define set_his_want_state_will set_my_want_state_do
+
+#define set_his_state_dont set_my_state_wont
+#define set_his_state_wont set_my_state_dont
+#define set_his_want_state_dont set_my_want_state_wont
+#define set_his_want_state_wont set_my_want_state_dont
+
+
+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. */
+
+/* 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(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);
+unsigned long sourceroute(char *arg, char **cpp, int *lenp);
+
+#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
+void ayt_status(int);
+#endif
+int tn(int argc, char **argv);
+void command(int top, char *tbuf, int cnt);
+
+/* main.c */
+
+void tninit(void);
+void usage(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 printsub (int, unsigned char *, 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 tninit (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, int 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;
+
diff --git a/crypto/kerberosIV/appl/telnet/telnet/main.c b/crypto/kerberosIV/appl/telnet/telnet/main.c
new file mode 100644
index 0000000..2c896eb
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/main.c
@@ -0,0 +1,321 @@
+/*
+ * 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: main.c,v 1.27 1999/03/11 13:49:23 joda Exp $");
+
+/* These values need to be the same as defined in libtelnet/kerberos5.c */
+/* Either define them in both places, or put in some common header file. */
+#define OPTS_FORWARD_CREDS 0x00000002
+#define OPTS_FORWARDABLE_CREDS 0x00000001
+
+#if KRB5
+#define FORWARD
+#endif
+
+/*
+ * Initialize variables.
+ */
+void
+tninit(void)
+{
+ init_terminal();
+
+ init_network();
+
+ init_telnet();
+
+ init_sys();
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "Usage: %s %s%s%s%s\n", prompt,
+#ifdef AUTHENTICATION
+ "[-8] [-E] [-K] [-L] [-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(1);
+}
+
+/*
+ * main. Parse arguments, invoke the protocol or command parser.
+ */
+
+
+#ifdef KRB5
+/* XXX ugly hack to setup dns-proxy stuff */
+#define Authenticator asn1_Authenticator
+#include <krb5.h>
+static void
+krb5_init(void)
+{
+ krb5_context context;
+ krb5_init_context(&context);
+ krb5_free_context(context);
+
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ char *user;
+#ifdef FORWARD
+ extern int forward_flags;
+#endif /* FORWARD */
+
+#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;
+
+ while((ch = getopt(argc, argv, "78DEKLS:X:abcde:fFk:l:n:rx")) != EOF) {
+ 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("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':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+ if (forward_flags & OPTS_FORWARD_CREDS) {
+ fprintf(stderr,
+ "%s: Only one of -f and -F allowed.\n",
+ prompt);
+ usage();
+ }
+ forward_flags |= OPTS_FORWARD_CREDS;
+#else
+ fprintf(stderr,
+ "%s: Warning: -f ignored, no Kerberos V5 support.\n",
+ prompt);
+#endif
+ break;
+ case 'F':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+ if (forward_flags & OPTS_FORWARD_CREDS) {
+ fprintf(stderr,
+ "%s: Only one of -f and -F allowed.\n",
+ prompt);
+ usage();
+ }
+ forward_flags |= OPTS_FORWARD_CREDS;
+ forward_flags |= OPTS_FORWARDABLE_CREDS;
+#else
+ fprintf(stderr,
+ "%s: Warning: -F ignored, no Kerberos V5 support.\n",
+ prompt);
+#endif
+ break;
+ case 'k':
+#if defined(AUTHENTICATION) && defined(KRB4)
+ {
+ extern char *dest_realm, dst_realm_buf[];
+ extern int dst_realm_sz;
+ dest_realm = dst_realm_buf;
+ strcpy_truncate(dest_realm, optarg, dst_realm_sz);
+ }
+#else
+ fprintf(stderr,
+ "%s: Warning: -k ignored, no Kerberos V4 support.\n",
+ prompt);
+#endif
+ 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);
+ EncryptVerbose(1);
+#else
+ fprintf(stderr,
+ "%s: Warning: -x ignored, no ENCRYPT support.\n",
+ prompt);
+#endif
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (autologin == -1) { /* esc@magic.fi; force */
+#if defined(AUTHENTICATION)
+ autologin = 1;
+#endif
+#if defined(ENCRYPTION)
+ encrypt_auto(1);
+ decrypt_auto(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();
+ *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);
+ }
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnet/network.c b/crypto/kerberosIV/appl/telnet/telnet/network.c
new file mode 100644
index 0000000..faacc30
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/network.c
@@ -0,0 +1,163 @@
+/*
+ * 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: network.c,v 1.10 1997/05/04 04:01:08 assar Exp $");
+
+Ring netoring, netiring;
+unsigned char netobuf[2*BUFSIZ], netibuf[BUFSIZ];
+
+/*
+ * Initialize internal network data structures.
+ */
+
+void
+init_network(void)
+{
+ if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
+ exit(1);
+ }
+ if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
+ exit(1);
+ }
+ NetTrace = stdout;
+}
+
+
+/*
+ * Check to see if any out-of-band data exists on a socket (for
+ * Telnet "synch" processing).
+ */
+
+int
+stilloob(void)
+{
+ static struct timeval timeout = { 0 };
+ fd_set excepts;
+ int value;
+
+ do {
+ FD_ZERO(&excepts);
+ 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;
+ }
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnet/ring.c b/crypto/kerberosIV/appl/telnet/telnet/ring.c
new file mode 100644
index 0000000..d791476
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/ring.c
@@ -0,0 +1,321 @@
+/*
+ * 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.c,v 1.10 1997/05/04 04:01:08 assar Exp $");
+
+/*
+ * 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 *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
+
diff --git a/crypto/kerberosIV/appl/telnet/telnet/ring.h b/crypto/kerberosIV/appl/telnet/telnet/ring.h
new file mode 100644
index 0000000..fa7ad18
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/ring.h
@@ -0,0 +1,99 @@
+/*
+ * 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: ring.h,v 1.3 1997/05/04 04:01:09 assar Exp $ */
+
+/*
+ * 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)()),
+ ring_clearto (Ring *ring);
+#endif
+
+extern int ring_at_mark(Ring *ring);
+
+extern void
+ ring_clear_mark(Ring *ring),
+ ring_mark(Ring *ring);
diff --git a/crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c b/crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c
new file mode 100644
index 0000000..334ef04
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c
@@ -0,0 +1,972 @@
+/*
+ * 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: sys_bsd.c,v 1.23 1998/06/09 19:24:46 joda Exp $");
+
+/*
+ * 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 */
+}
+
+#ifdef KLUDGELINEMODE
+extern int kludgelinemode;
+#endif
+/*
+ * TerminalSpecialChars()
+ *
+ * Look at an input character to see if it is a special character
+ * and decide what to do.
+ *
+ * Output:
+ *
+ * 0 Don't add this character.
+ * 1 Do add this character
+ */
+
+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();
+#endif /* SIGTSTP */
+#ifdef SIGINFO
+static RETSIGTYPE ayt();
+#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
+ RETSIGTYPE ayt_status();
+
+ 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)
+{
+ struct winsize ws;
+
+ if (get_window_size (STDIN_FILENO, &ws) == 0) {
+ *rows = ws.ws_row;
+ *cols = ws.ws_col;
+ 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);
+}
+
+ /* ARGSUSED */
+static RETSIGTYPE
+intr(int sig)
+{
+ 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");
+ }
+#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 (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(16, &ibits, &obits, &xbits,
+ (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
+ if (c == -1) {
+ /*
+ * we can get EINTR if we are in line mode,
+ * and the user does an escape (TSTP), or
+ * some other signal generator.
+ */
+ if (errno == EINTR) {
+ return 0;
+ }
+ /* 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;
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnet/telnet.c b/crypto/kerberosIV/appl/telnet/telnet/telnet.c
new file mode 100644
index 0000000..1df4d6e
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/telnet.c
@@ -0,0 +1,2313 @@
+/*
+ * 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"
+#ifdef HAVE_TERMCAP_H
+#include <termcap.h>
+#endif
+
+RCSID("$Id: telnet.c,v 1.25 1999/03/11 13:49:34 joda Exp $");
+
+#define strip(x) (eight ? (x) : ((x) & 0x7f))
+
+static unsigned char subbuffer[SUBBUFSIZE],
+ *subpointer, *subend; /* buffer for sub-options */
+#define SB_CLEAR() subpointer = subbuffer;
+#define SB_TERM() { subend = subpointer; SB_CLEAR(); }
+#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
+ *subpointer++ = (c); \
+ }
+
+#define SB_GET() ((*subpointer++)&0xff)
+#define SB_PEEK() ((*subpointer)&0xff)
+#define SB_EOF() (subpointer >= subend)
+#define SB_LEN() (subend - subpointer)
+
+char options[256]; /* The combined options */
+char do_dont_resp[256];
+char will_wont_resp[256];
+
+int
+ eight = 3,
+ binary = 0,
+ autologin = 0, /* Autologin anyone? */
+ skiprc = 0,
+ connected,
+ showoptions,
+ ISend, /* trying to send network data in */
+ debug = 0,
+ crmod,
+ netdata, /* Print out network data flow */
+ crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
+ telnetport,
+ SYNCHing, /* we are in TELNET SYNCH mode */
+ flushout, /* flush output */
+ autoflush = 0, /* flush output when interrupting? */
+ autosynch, /* send interrupt characters with SYNCH? */
+ localflow, /* we handle flow control locally */
+ restartany, /* if flow control enabled, restart on any character */
+ localchars, /* we recognize interrupt/quit */
+ donelclchars, /* the user has set "localchars" */
+ donebinarytoggle, /* the user has put us in binary */
+ dontlecho, /* do we suppress local echoing right now? */
+ globalmode;
+
+char *prompt = 0;
+
+cc_t escape;
+cc_t rlogin;
+#ifdef KLUDGELINEMODE
+cc_t echoc;
+#endif
+
+/*
+ * Telnet receiver states for fsm
+ */
+#define TS_DATA 0
+#define TS_IAC 1
+#define TS_WILL 2
+#define TS_WONT 3
+#define TS_DO 4
+#define TS_DONT 5
+#define TS_CR 6
+#define TS_SB 7 /* sub-option collection */
+#define TS_SE 8 /* looking for sub-option end */
+
+static int telrcv_state;
+#ifdef OLD_ENVIRON
+unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
+#else
+# define telopt_environ TELOPT_NEW_ENVIRON
+#endif
+
+jmp_buf toplevel;
+jmp_buf peerdied;
+
+int flushline;
+int linemode;
+
+#ifdef KLUDGELINEMODE
+int kludgelinemode = 1;
+#endif
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+Clocks clocks;
+
+static int is_unique(char *name, char **as, char **ae);
+
+
+/*
+ * Initialize telnet environment.
+ */
+
+void
+init_telnet(void)
+{
+ env_init();
+
+ SB_CLEAR();
+ memset(options, 0, sizeof options);
+
+ connected = ISend = localflow = donebinarytoggle = 0;
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+ restartany = -1;
+
+ SYNCHing = 0;
+
+ /* Don't change NetTrace */
+
+ escape = CONTROL(']');
+ rlogin = _POSIX_VDISABLE;
+#ifdef KLUDGELINEMODE
+ echoc = CONTROL('E');
+#endif
+
+ flushline = 1;
+ telrcv_state = TS_DATA;
+}
+
+
+/*
+ * These routines are in charge of sending option negotiations
+ * to the other side.
+ *
+ * The basic idea is that we send the negotiation if either side
+ * is in disagreement as to what the current state should be.
+ */
+
+void
+send_do(int c, int init)
+{
+ if (init) {
+ if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
+ my_want_state_is_do(c))
+ return;
+ set_my_want_state_do(c);
+ do_dont_resp[c]++;
+ }
+ NET2ADD(IAC, DO);
+ NETADD(c);
+ printoption("SENT", DO, c);
+}
+
+void
+send_dont(int c, int init)
+{
+ if (init) {
+ if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
+ my_want_state_is_dont(c))
+ return;
+ set_my_want_state_dont(c);
+ do_dont_resp[c]++;
+ }
+ NET2ADD(IAC, DONT);
+ NETADD(c);
+ printoption("SENT", DONT, c);
+}
+
+void
+send_will(int c, int init)
+{
+ if (init) {
+ if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
+ my_want_state_is_will(c))
+ return;
+ set_my_want_state_will(c);
+ will_wont_resp[c]++;
+ }
+ NET2ADD(IAC, WILL);
+ NETADD(c);
+ printoption("SENT", WILL, c);
+}
+
+void
+send_wont(int c, int init)
+{
+ if (init) {
+ if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
+ my_want_state_is_wont(c))
+ return;
+ set_my_want_state_wont(c);
+ will_wont_resp[c]++;
+ }
+ NET2ADD(IAC, WONT);
+ NETADD(c);
+ printoption("SENT", WONT, c);
+}
+
+
+void
+willoption(int option)
+{
+ int new_state_ok = 0;
+
+ if (do_dont_resp[option]) {
+ --do_dont_resp[option];
+ if (do_dont_resp[option] && my_state_is_do(option))
+ --do_dont_resp[option];
+ }
+
+ if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
+
+ switch (option) {
+
+ case TELOPT_ECHO:
+ case TELOPT_BINARY:
+ case TELOPT_SGA:
+ settimer(modenegotiated);
+ /* FALL THROUGH */
+ case TELOPT_STATUS:
+#if defined(AUTHENTICATION)
+ case TELOPT_AUTHENTICATION:
+#endif
+#if defined(ENCRYPTION)
+ case TELOPT_ENCRYPT:
+#endif
+ new_state_ok = 1;
+ break;
+
+ case TELOPT_TM:
+ if (flushout)
+ flushout = 0;
+ /*
+ * Special case for TM. If we get back a WILL,
+ * pretend we got back a WONT.
+ */
+ set_my_want_state_dont(option);
+ set_my_state_dont(option);
+ return; /* Never reply to TM will's/wont's */
+
+ case TELOPT_LINEMODE:
+ default:
+ break;
+ }
+
+ if (new_state_ok) {
+ set_my_want_state_do(option);
+ send_do(option, 0);
+ setconnmode(0); /* possibly set new tty mode */
+ } else {
+ do_dont_resp[option]++;
+ send_dont(option, 0);
+ }
+ }
+ set_my_state_do(option);
+#if defined(ENCRYPTION)
+ if (option == TELOPT_ENCRYPT)
+ encrypt_send_support();
+#endif
+}
+
+void
+wontoption(int option)
+{
+ if (do_dont_resp[option]) {
+ --do_dont_resp[option];
+ if (do_dont_resp[option] && my_state_is_dont(option))
+ --do_dont_resp[option];
+ }
+
+ if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
+
+ switch (option) {
+
+#ifdef KLUDGELINEMODE
+ case TELOPT_SGA:
+ if (!kludgelinemode)
+ break;
+ /* FALL THROUGH */
+#endif
+ case TELOPT_ECHO:
+ settimer(modenegotiated);
+ break;
+
+ case TELOPT_TM:
+ if (flushout)
+ flushout = 0;
+ set_my_want_state_dont(option);
+ set_my_state_dont(option);
+ return; /* Never reply to TM will's/wont's */
+
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ encrypt_not();
+ break;
+#endif
+ default:
+ break;
+ }
+ set_my_want_state_dont(option);
+ if (my_state_is_do(option))
+ send_dont(option, 0);
+ setconnmode(0); /* Set new tty mode */
+ } else if (option == TELOPT_TM) {
+ /*
+ * Special case for TM.
+ */
+ if (flushout)
+ flushout = 0;
+ set_my_want_state_dont(option);
+ }
+ set_my_state_dont(option);
+}
+
+static void
+dooption(int option)
+{
+ int new_state_ok = 0;
+
+ if (will_wont_resp[option]) {
+ --will_wont_resp[option];
+ if (will_wont_resp[option] && my_state_is_will(option))
+ --will_wont_resp[option];
+ }
+
+ if (will_wont_resp[option] == 0) {
+ if (my_want_state_is_wont(option)) {
+
+ switch (option) {
+
+ case TELOPT_TM:
+ /*
+ * Special case for TM. We send a WILL, but pretend
+ * we sent WONT.
+ */
+ send_will(option, 0);
+ set_my_want_state_wont(TELOPT_TM);
+ set_my_state_wont(TELOPT_TM);
+ return;
+
+ case TELOPT_BINARY: /* binary mode */
+ case TELOPT_NAWS: /* window size */
+ case TELOPT_TSPEED: /* terminal speed */
+ case TELOPT_LFLOW: /* local flow control */
+ case TELOPT_TTYPE: /* terminal type option */
+ case TELOPT_SGA: /* no big deal */
+#if defined(ENCRYPTION)
+ case TELOPT_ENCRYPT: /* encryption variable option */
+#endif
+ new_state_ok = 1;
+ break;
+
+ case TELOPT_NEW_ENVIRON: /* New environment variable option */
+#ifdef OLD_ENVIRON
+ if (my_state_is_will(TELOPT_OLD_ENVIRON))
+ send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
+ goto env_common;
+ case TELOPT_OLD_ENVIRON: /* Old environment variable option */
+ if (my_state_is_will(TELOPT_NEW_ENVIRON))
+ break; /* Don't enable if new one is in use! */
+ env_common:
+ telopt_environ = option;
+#endif
+ new_state_ok = 1;
+ break;
+
+#if defined(AUTHENTICATION)
+ case TELOPT_AUTHENTICATION:
+ if (autologin)
+ new_state_ok = 1;
+ break;
+#endif
+
+ case TELOPT_XDISPLOC: /* X Display location */
+ if (env_getvalue((unsigned char *)"DISPLAY"))
+ new_state_ok = 1;
+ break;
+
+ case TELOPT_LINEMODE:
+#ifdef KLUDGELINEMODE
+ kludgelinemode = 0;
+ send_do(TELOPT_SGA, 1);
+#endif
+ set_my_want_state_will(TELOPT_LINEMODE);
+ send_will(option, 0);
+ set_my_state_will(TELOPT_LINEMODE);
+ slc_init();
+ return;
+
+ case TELOPT_ECHO: /* We're never going to echo... */
+ default:
+ break;
+ }
+
+ if (new_state_ok) {
+ set_my_want_state_will(option);
+ send_will(option, 0);
+ setconnmode(0); /* Set new tty mode */
+ } else {
+ will_wont_resp[option]++;
+ send_wont(option, 0);
+ }
+ } else {
+ /*
+ * Handle options that need more things done after the
+ * other side has acknowledged the option.
+ */
+ switch (option) {
+ case TELOPT_LINEMODE:
+#ifdef KLUDGELINEMODE
+ kludgelinemode = 0;
+ send_do(TELOPT_SGA, 1);
+#endif
+ set_my_state_will(option);
+ slc_init();
+ send_do(TELOPT_SGA, 0);
+ return;
+ }
+ }
+ }
+ set_my_state_will(option);
+}
+
+static void
+dontoption(int option)
+{
+
+ if (will_wont_resp[option]) {
+ --will_wont_resp[option];
+ if (will_wont_resp[option] && my_state_is_wont(option))
+ --will_wont_resp[option];
+ }
+
+ if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
+ switch (option) {
+ case TELOPT_LINEMODE:
+ linemode = 0; /* put us back to the default state */
+ break;
+#ifdef OLD_ENVIRON
+ case TELOPT_NEW_ENVIRON:
+ /*
+ * The new environ option wasn't recognized, try
+ * the old one.
+ */
+ send_will(TELOPT_OLD_ENVIRON, 1);
+ telopt_environ = TELOPT_OLD_ENVIRON;
+ break;
+#endif
+#if 0
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ encrypt_not();
+ break;
+#endif
+#endif
+ }
+ /* we always accept a DONT */
+ set_my_want_state_wont(option);
+ if (my_state_is_will(option))
+ send_wont(option, 0);
+ setconnmode(0); /* Set new tty mode */
+ }
+ set_my_state_wont(option);
+}
+
+/*
+ * Given a buffer returned by tgetent(), this routine will turn
+ * the pipe seperated list of names in the buffer into an array
+ * of pointers to null terminated names. We toss out any bad,
+ * duplicate, or verbose names (names with spaces).
+ */
+
+static char *name_unknown = "UNKNOWN";
+static char *unknown[] = { 0, 0 };
+
+static char **
+mklist(char *buf, char *name)
+{
+ int n;
+ char c, *cp, **argvp, *cp2, **argv, **avt;
+
+ if (name) {
+ if ((int)strlen(name) > 40) {
+ name = 0;
+ unknown[0] = name_unknown;
+ } else {
+ unknown[0] = name;
+ strupr(name);
+ }
+ } else
+ unknown[0] = name_unknown;
+ /*
+ * Count up the number of names.
+ */
+ for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
+ if (*cp == '|')
+ n++;
+ }
+ /*
+ * Allocate an array to put the name pointers into
+ */
+ argv = (char **)malloc((n+3)*sizeof(char *));
+ if (argv == 0)
+ return(unknown);
+
+ /*
+ * Fill up the array of pointers to names.
+ */
+ *argv = 0;
+ argvp = argv+1;
+ n = 0;
+ for (cp = cp2 = buf; (c = *cp); cp++) {
+ if (c == '|' || c == ':') {
+ *cp++ = '\0';
+ /*
+ * Skip entries that have spaces or are over 40
+ * characters long. If this is our environment
+ * name, then put it up front. Otherwise, as
+ * long as this is not a duplicate name (case
+ * insensitive) add it to the list.
+ */
+ if (n || (cp - cp2 > 41))
+ ;
+ else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
+ *argv = cp2;
+ else if (is_unique(cp2, argv+1, argvp))
+ *argvp++ = cp2;
+ if (c == ':')
+ break;
+ /*
+ * Skip multiple delimiters. Reset cp2 to
+ * the beginning of the next name. Reset n,
+ * the flag for names with spaces.
+ */
+ while ((c = *cp) == '|')
+ cp++;
+ cp2 = cp;
+ n = 0;
+ }
+ /*
+ * Skip entries with spaces or non-ascii values.
+ * Convert lower case letters to upper case.
+ */
+#define ISASCII(c) (!((c)&0x80))
+ if ((c == ' ') || !ISASCII(c))
+ n = 1;
+ else if (islower(c))
+ *cp = toupper(c);
+ }
+
+ /*
+ * Check for an old V6 2 character name. If the second
+ * name points to the beginning of the buffer, and is
+ * only 2 characters long, move it to the end of the array.
+ */
+ if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
+ --argvp;
+ for (avt = &argv[1]; avt < argvp; avt++)
+ *avt = *(avt+1);
+ *argvp++ = buf;
+ }
+
+ /*
+ * Duplicate last name, for TTYPE option, and null
+ * terminate the array. If we didn't find a match on
+ * our terminal name, put that name at the beginning.
+ */
+ cp = *(argvp-1);
+ *argvp++ = cp;
+ *argvp = 0;
+
+ if (*argv == 0) {
+ if (name)
+ *argv = name;
+ else {
+ --argvp;
+ for (avt = argv; avt < argvp; avt++)
+ *avt = *(avt+1);
+ }
+ }
+ if (*argv)
+ return(argv);
+ else
+ return(unknown);
+}
+
+static int
+is_unique(char *name, char **as, char **ae)
+{
+ char **ap;
+ int n;
+
+ n = strlen(name) + 1;
+ for (ap = as; ap < ae; ap++)
+ if (strncasecmp(*ap, name, n) == 0)
+ return(0);
+ return (1);
+}
+
+static char termbuf[1024];
+
+static int
+telnet_setupterm(const char *tname, int fd, int *errp)
+{
+ if (tgetent(termbuf, tname) == 1) {
+ termbuf[1023] = '\0';
+ if (errp)
+ *errp = 1;
+ return(0);
+ }
+ if (errp)
+ *errp = 0;
+ return(-1);
+}
+
+int resettermname = 1;
+
+static char *
+gettermname()
+{
+ char *tname;
+ static char **tnamep = 0;
+ static char **next;
+ int err;
+
+ if (resettermname) {
+ resettermname = 0;
+ if (tnamep && tnamep != unknown)
+ free(tnamep);
+ if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
+ telnet_setupterm(tname, 1, &err) == 0) {
+ tnamep = mklist(termbuf, tname);
+ } else {
+ if (tname && ((int)strlen(tname) <= 40)) {
+ unknown[0] = tname;
+ strupr(tname);
+ } else
+ unknown[0] = name_unknown;
+ tnamep = unknown;
+ }
+ next = tnamep;
+ }
+ if (*next == 0)
+ next = tnamep;
+ return(*next++);
+}
+/*
+ * suboption()
+ *
+ * Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ *
+ * Currently we recognize:
+ *
+ * Terminal type, send request.
+ * Terminal speed (send request).
+ * Local flow control (is request).
+ * Linemode
+ */
+
+static void
+suboption()
+{
+ unsigned char subchar;
+
+ printsub('<', subbuffer, SB_LEN()+2);
+ switch (subchar = SB_GET()) {
+ case TELOPT_TTYPE:
+ if (my_want_state_is_wont(TELOPT_TTYPE))
+ return;
+ if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
+ return;
+ } else {
+ char *name;
+ unsigned char temp[50];
+ int len;
+
+ name = gettermname();
+ len = strlen(name) + 4 + 2;
+ if (len < NETROOM()) {
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
+ TELQUAL_IS, name, IAC, SE);
+ ring_supply_data(&netoring, temp, len);
+ printsub('>', &temp[2], len-2);
+ } else {
+ ExitString("No room in buffer for terminal type.\n", 1);
+ /*NOTREACHED*/
+ }
+ }
+ break;
+ case TELOPT_TSPEED:
+ if (my_want_state_is_wont(TELOPT_TSPEED))
+ return;
+ if (SB_EOF())
+ return;
+ if (SB_GET() == TELQUAL_SEND) {
+ long output_speed, input_speed;
+ unsigned char temp[50];
+ int len;
+
+ TerminalSpeeds(&input_speed, &output_speed);
+
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%u,%u%c%c", IAC, SB, TELOPT_TSPEED,
+ TELQUAL_IS,
+ (unsigned)output_speed,
+ (unsigned)input_speed, IAC, SE);
+ len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
+
+ if (len < NETROOM()) {
+ ring_supply_data(&netoring, temp, len);
+ printsub('>', temp+2, len - 2);
+ }
+/*@*/ else printf("lm_will: not enough room in buffer\n");
+ }
+ break;
+ case TELOPT_LFLOW:
+ if (my_want_state_is_wont(TELOPT_LFLOW))
+ return;
+ if (SB_EOF())
+ return;
+ switch(SB_GET()) {
+ case LFLOW_RESTART_ANY:
+ restartany = 1;
+ break;
+ case LFLOW_RESTART_XON:
+ restartany = 0;
+ break;
+ case LFLOW_ON:
+ localflow = 1;
+ break;
+ case LFLOW_OFF:
+ localflow = 0;
+ break;
+ default:
+ return;
+ }
+ setcommandmode();
+ setconnmode(0);
+ break;
+
+ case TELOPT_LINEMODE:
+ if (my_want_state_is_wont(TELOPT_LINEMODE))
+ return;
+ if (SB_EOF())
+ return;
+ switch (SB_GET()) {
+ case WILL:
+ lm_will(subpointer, SB_LEN());
+ break;
+ case WONT:
+ lm_wont(subpointer, SB_LEN());
+ break;
+ case DO:
+ lm_do(subpointer, SB_LEN());
+ break;
+ case DONT:
+ lm_dont(subpointer, SB_LEN());
+ break;
+ case LM_SLC:
+ slc(subpointer, SB_LEN());
+ break;
+ case LM_MODE:
+ lm_mode(subpointer, SB_LEN(), 0);
+ break;
+ default:
+ break;
+ }
+ break;
+
+#ifdef OLD_ENVIRON
+ case TELOPT_OLD_ENVIRON:
+#endif
+ case TELOPT_NEW_ENVIRON:
+ if (SB_EOF())
+ return;
+ switch(SB_PEEK()) {
+ case TELQUAL_IS:
+ case TELQUAL_INFO:
+ if (my_want_state_is_dont(subchar))
+ return;
+ break;
+ case TELQUAL_SEND:
+ if (my_want_state_is_wont(subchar)) {
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+ env_opt(subpointer, SB_LEN());
+ break;
+
+ case TELOPT_XDISPLOC:
+ if (my_want_state_is_wont(TELOPT_XDISPLOC))
+ return;
+ if (SB_EOF())
+ return;
+ if (SB_GET() == TELQUAL_SEND) {
+ unsigned char temp[50], *dp;
+ int len;
+
+ if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
+ /*
+ * Something happened, we no longer have a DISPLAY
+ * variable. So, turn off the option.
+ */
+ send_wont(TELOPT_XDISPLOC, 1);
+ break;
+ }
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
+ TELQUAL_IS, dp, IAC, SE);
+ len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
+
+ if (len < NETROOM()) {
+ ring_supply_data(&netoring, temp, len);
+ printsub('>', temp+2, len - 2);
+ }
+/*@*/ else printf("lm_will: not enough room in buffer\n");
+ }
+ break;
+
+#if defined(AUTHENTICATION)
+ case TELOPT_AUTHENTICATION: {
+ if (!autologin)
+ break;
+ if (SB_EOF())
+ return;
+ switch(SB_GET()) {
+ case TELQUAL_IS:
+ if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+ return;
+ auth_is(subpointer, SB_LEN());
+ break;
+ case TELQUAL_SEND:
+ if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+ return;
+ auth_send(subpointer, SB_LEN());
+ break;
+ case TELQUAL_REPLY:
+ if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+ return;
+ auth_reply(subpointer, SB_LEN());
+ break;
+ case TELQUAL_NAME:
+ if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+ return;
+ auth_name(subpointer, SB_LEN());
+ break;
+ }
+ }
+ break;
+#endif
+#if defined(ENCRYPTION)
+ case TELOPT_ENCRYPT:
+ if (SB_EOF())
+ return;
+ switch(SB_GET()) {
+ case ENCRYPT_START:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_start(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_END:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_end();
+ break;
+ case ENCRYPT_SUPPORT:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_support(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REQSTART:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_request_start(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REQEND:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ /*
+ * We can always send an REQEND so that we cannot
+ * get stuck encrypting. We should only get this
+ * if we have been able to get in the correct mode
+ * anyhow.
+ */
+ encrypt_request_end();
+ break;
+ case ENCRYPT_IS:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_is(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REPLY:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_reply(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_ENC_KEYID:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_enc_keyid(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_DEC_KEYID:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_dec_keyid(subpointer, SB_LEN());
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
+
+void
+lm_will(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK: /* We shouldn't ever get this... */
+ default:
+ str_lm[3] = DONT;
+ str_lm[4] = cmd[0];
+ if (NETROOM() > sizeof(str_lm)) {
+ ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+ printsub('>', &str_lm[2], sizeof(str_lm)-2);
+ }
+/*@*/ else printf("lm_will: not enough room in buffer\n");
+ break;
+ }
+}
+
+void
+lm_wont(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK: /* We shouldn't ever get this... */
+ default:
+ /* We are always DONT, so don't respond */
+ return;
+ }
+}
+
+void
+lm_do(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK:
+ default:
+ str_lm[3] = WONT;
+ str_lm[4] = cmd[0];
+ if (NETROOM() > sizeof(str_lm)) {
+ ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+ printsub('>', &str_lm[2], sizeof(str_lm)-2);
+ }
+/*@*/ else printf("lm_do: not enough room in buffer\n");
+ break;
+ }
+}
+
+void
+lm_dont(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK:
+ default:
+ /* we are always WONT, so don't respond */
+ break;
+ }
+}
+
+static unsigned char str_lm_mode[] = {
+ IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
+};
+
+void
+lm_mode(unsigned char *cmd, int len, int init)
+{
+ if (len != 1)
+ return;
+ if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
+ return;
+ if (*cmd&MODE_ACK)
+ return;
+ linemode = *cmd&(MODE_MASK&~MODE_ACK);
+ str_lm_mode[4] = linemode;
+ if (!init)
+ str_lm_mode[4] |= MODE_ACK;
+ if (NETROOM() > sizeof(str_lm_mode)) {
+ ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
+ printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
+ }
+/*@*/ else printf("lm_mode: not enough room in buffer\n");
+ setconnmode(0); /* set changed mode */
+}
+
+
+
+/*
+ * slc()
+ * Handle special character suboption of LINEMODE.
+ */
+
+struct spc {
+ cc_t val;
+ cc_t *valp;
+ char flags; /* Current flags & level */
+ char mylevel; /* Maximum level & flags */
+} spc_data[NSLC+1];
+
+#define SLC_IMPORT 0
+#define SLC_EXPORT 1
+#define SLC_RVALUE 2
+static int slc_mode = SLC_EXPORT;
+
+void
+slc_init()
+{
+ struct spc *spcp;
+
+ localchars = 1;
+ for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
+ spcp->val = 0;
+ spcp->valp = 0;
+ spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
+ }
+
+#define initfunc(func, flags) { \
+ spcp = &spc_data[func]; \
+ if ((spcp->valp = tcval(func))) { \
+ spcp->val = *spcp->valp; \
+ spcp->mylevel = SLC_VARIABLE|flags; \
+ } else { \
+ spcp->val = 0; \
+ spcp->mylevel = SLC_DEFAULT; \
+ } \
+ }
+
+ initfunc(SLC_SYNCH, 0);
+ /* No BRK */
+ initfunc(SLC_AO, 0);
+ initfunc(SLC_AYT, 0);
+ /* No EOR */
+ initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
+ initfunc(SLC_EOF, 0);
+ initfunc(SLC_SUSP, SLC_FLUSHIN);
+ initfunc(SLC_EC, 0);
+ initfunc(SLC_EL, 0);
+ initfunc(SLC_EW, 0);
+ initfunc(SLC_RP, 0);
+ initfunc(SLC_LNEXT, 0);
+ initfunc(SLC_XON, 0);
+ initfunc(SLC_XOFF, 0);
+ initfunc(SLC_FORW1, 0);
+ initfunc(SLC_FORW2, 0);
+ /* No FORW2 */
+
+ initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
+#undef initfunc
+
+ if (slc_mode == SLC_EXPORT)
+ slc_export();
+ else
+ slc_import(1);
+
+}
+
+void
+slcstate()
+{
+ printf("Special characters are %s values\n",
+ slc_mode == SLC_IMPORT ? "remote default" :
+ slc_mode == SLC_EXPORT ? "local" :
+ "remote");
+}
+
+void
+slc_mode_export()
+{
+ slc_mode = SLC_EXPORT;
+ if (my_state_is_will(TELOPT_LINEMODE))
+ slc_export();
+}
+
+void
+slc_mode_import(int def)
+{
+ slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
+ if (my_state_is_will(TELOPT_LINEMODE))
+ slc_import(def);
+}
+
+unsigned char slc_import_val[] = {
+ IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
+};
+unsigned char slc_import_def[] = {
+ IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
+};
+
+void
+slc_import(int def)
+{
+ if (NETROOM() > sizeof(slc_import_val)) {
+ if (def) {
+ ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
+ printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
+ } else {
+ ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
+ printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
+ }
+ }
+/*@*/ else printf("slc_import: not enough room\n");
+}
+
+void
+slc_export()
+{
+ struct spc *spcp;
+
+ TerminalDefaultChars();
+
+ slc_start_reply();
+ for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+ if (spcp->mylevel != SLC_NOSUPPORT) {
+ if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+ spcp->flags = SLC_NOSUPPORT;
+ else
+ spcp->flags = spcp->mylevel;
+ if (spcp->valp)
+ spcp->val = *spcp->valp;
+ slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+ }
+ }
+ slc_end_reply();
+ slc_update();
+ setconnmode(1); /* Make sure the character values are set */
+}
+
+void
+slc(unsigned char *cp, int len)
+{
+ struct spc *spcp;
+ int func,level;
+
+ slc_start_reply();
+
+ for (; len >= 3; len -=3, cp +=3) {
+
+ func = cp[SLC_FUNC];
+
+ if (func == 0) {
+ /*
+ * Client side: always ignore 0 function.
+ */
+ continue;
+ }
+ if (func > NSLC) {
+ if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
+ slc_add_reply(func, SLC_NOSUPPORT, 0);
+ continue;
+ }
+
+ spcp = &spc_data[func];
+
+ level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
+
+ if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
+ ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
+ continue;
+ }
+
+ if (level == (SLC_DEFAULT|SLC_ACK)) {
+ /*
+ * This is an error condition, the SLC_ACK
+ * bit should never be set for the SLC_DEFAULT
+ * level. Our best guess to recover is to
+ * ignore the SLC_ACK bit.
+ */
+ cp[SLC_FLAGS] &= ~SLC_ACK;
+ }
+
+ if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
+ spcp->val = (cc_t)cp[SLC_VALUE];
+ spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
+ continue;
+ }
+
+ level &= ~SLC_ACK;
+
+ if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
+ spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
+ spcp->val = (cc_t)cp[SLC_VALUE];
+ }
+ if (level == SLC_DEFAULT) {
+ if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
+ spcp->flags = spcp->mylevel;
+ else
+ spcp->flags = SLC_NOSUPPORT;
+ }
+ slc_add_reply(func, spcp->flags, spcp->val);
+ }
+ slc_end_reply();
+ if (slc_update())
+ setconnmode(1); /* set the new character values */
+}
+
+void
+slc_check()
+{
+ struct spc *spcp;
+
+ slc_start_reply();
+ for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+ if (spcp->valp && spcp->val != *spcp->valp) {
+ spcp->val = *spcp->valp;
+ if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+ spcp->flags = SLC_NOSUPPORT;
+ else
+ spcp->flags = spcp->mylevel;
+ slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+ }
+ }
+ slc_end_reply();
+ setconnmode(1);
+}
+
+
+unsigned char slc_reply[128];
+unsigned char *slc_replyp;
+
+void
+slc_start_reply()
+{
+ slc_replyp = slc_reply;
+ *slc_replyp++ = IAC;
+ *slc_replyp++ = SB;
+ *slc_replyp++ = TELOPT_LINEMODE;
+ *slc_replyp++ = LM_SLC;
+}
+
+void
+slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
+{
+ if ((*slc_replyp++ = func) == IAC)
+ *slc_replyp++ = IAC;
+ if ((*slc_replyp++ = flags) == IAC)
+ *slc_replyp++ = IAC;
+ if ((*slc_replyp++ = (unsigned char)value) == IAC)
+ *slc_replyp++ = IAC;
+}
+
+void
+slc_end_reply()
+{
+ int len;
+
+ *slc_replyp++ = IAC;
+ *slc_replyp++ = SE;
+ len = slc_replyp - slc_reply;
+ if (len <= 6)
+ return;
+ if (NETROOM() > len) {
+ ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
+ printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
+ }
+/*@*/else printf("slc_end_reply: not enough room\n");
+}
+
+int
+slc_update()
+{
+ struct spc *spcp;
+ int need_update = 0;
+
+ for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+ if (!(spcp->flags&SLC_ACK))
+ continue;
+ spcp->flags &= ~SLC_ACK;
+ if (spcp->valp && (*spcp->valp != spcp->val)) {
+ *spcp->valp = spcp->val;
+ need_update = 1;
+ }
+ }
+ return(need_update);
+}
+
+#ifdef OLD_ENVIRON
+# define old_env_var OLD_ENV_VAR
+# define old_env_value OLD_ENV_VALUE
+#endif
+
+void
+env_opt(unsigned char *buf, int len)
+{
+ unsigned char *ep = 0, *epc = 0;
+ int i;
+
+ switch(buf[0]&0xff) {
+ case TELQUAL_SEND:
+ env_opt_start();
+ if (len == 1) {
+ env_opt_add(NULL);
+ } else for (i = 1; i < len; i++) {
+ switch (buf[i]&0xff) {
+#ifdef OLD_ENVIRON
+ case OLD_ENV_VAR:
+ case OLD_ENV_VALUE:
+ /*
+ * Although OLD_ENV_VALUE is not legal, we will
+ * still recognize it, just in case it is an
+ * old server that has VAR & VALUE mixed up...
+ */
+ /* FALL THROUGH */
+#else
+ case NEW_ENV_VAR:
+#endif
+ case ENV_USERVAR:
+ if (ep) {
+ *epc = 0;
+ env_opt_add(ep);
+ }
+ ep = epc = &buf[i+1];
+ break;
+ case ENV_ESC:
+ i++;
+ /*FALL THROUGH*/
+ default:
+ if (epc)
+ *epc++ = buf[i];
+ break;
+ }
+ }
+ if (ep) {
+ *epc = 0;
+ env_opt_add(ep);
+ }
+ env_opt_end(1);
+ break;
+
+ case TELQUAL_IS:
+ case TELQUAL_INFO:
+ /* Ignore for now. We shouldn't get it anyway. */
+ break;
+
+ default:
+ break;
+ }
+}
+
+#define OPT_REPLY_SIZE 256
+unsigned char *opt_reply;
+unsigned char *opt_replyp;
+unsigned char *opt_replyend;
+
+void
+env_opt_start()
+{
+ if (opt_reply)
+ opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
+ else
+ opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE);
+ if (opt_reply == NULL) {
+/*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
+ opt_reply = opt_replyp = opt_replyend = NULL;
+ return;
+ }
+ opt_replyp = opt_reply;
+ opt_replyend = opt_reply + OPT_REPLY_SIZE;
+ *opt_replyp++ = IAC;
+ *opt_replyp++ = SB;
+ *opt_replyp++ = telopt_environ;
+ *opt_replyp++ = TELQUAL_IS;
+}
+
+void
+env_opt_start_info()
+{
+ env_opt_start();
+ if (opt_replyp)
+ opt_replyp[-1] = TELQUAL_INFO;
+}
+
+void
+env_opt_add(unsigned char *ep)
+{
+ unsigned char *vp, c;
+
+ if (opt_reply == NULL) /*XXX*/
+ return; /*XXX*/
+
+ if (ep == NULL || *ep == '\0') {
+ /* Send user defined variables first. */
+ env_default(1, 0);
+ while ((ep = env_default(0, 0)))
+ env_opt_add(ep);
+
+ /* Now add the list of well know variables. */
+ env_default(1, 1);
+ while ((ep = env_default(0, 1)))
+ env_opt_add(ep);
+ return;
+ }
+ vp = env_getvalue(ep);
+ if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
+ strlen((char *)ep) + 6 > opt_replyend)
+ {
+ int len;
+ opt_replyend += OPT_REPLY_SIZE;
+ len = opt_replyend - opt_reply;
+ opt_reply = (unsigned char *)realloc(opt_reply, len);
+ if (opt_reply == NULL) {
+/*@*/ printf("env_opt_add: realloc() failed!!!\n");
+ opt_reply = opt_replyp = opt_replyend = NULL;
+ return;
+ }
+ opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
+ opt_replyend = opt_reply + len;
+ }
+ if (opt_welldefined((char *)ep)) {
+#ifdef OLD_ENVIRON
+ if (telopt_environ == TELOPT_OLD_ENVIRON)
+ *opt_replyp++ = old_env_var;
+ else
+#endif
+ *opt_replyp++ = NEW_ENV_VAR;
+ } else
+ *opt_replyp++ = ENV_USERVAR;
+ for (;;) {
+ while ((c = *ep++)) {
+ switch(c&0xff) {
+ case IAC:
+ *opt_replyp++ = IAC;
+ break;
+ case NEW_ENV_VAR:
+ case NEW_ENV_VALUE:
+ case ENV_ESC:
+ case ENV_USERVAR:
+ *opt_replyp++ = ENV_ESC;
+ break;
+ }
+ *opt_replyp++ = c;
+ }
+ if ((ep = vp)) {
+#ifdef OLD_ENVIRON
+ if (telopt_environ == TELOPT_OLD_ENVIRON)
+ *opt_replyp++ = old_env_value;
+ else
+#endif
+ *opt_replyp++ = NEW_ENV_VALUE;
+ vp = NULL;
+ } else
+ break;
+ }
+}
+
+int
+opt_welldefined(char *ep)
+{
+ if ((strcmp(ep, "USER") == 0) ||
+ (strcmp(ep, "DISPLAY") == 0) ||
+ (strcmp(ep, "PRINTER") == 0) ||
+ (strcmp(ep, "SYSTEMTYPE") == 0) ||
+ (strcmp(ep, "JOB") == 0) ||
+ (strcmp(ep, "ACCT") == 0))
+ return(1);
+ return(0);
+}
+
+void
+env_opt_end(int emptyok)
+{
+ int len;
+
+ len = opt_replyp - opt_reply + 2;
+ if (emptyok || len > 6) {
+ *opt_replyp++ = IAC;
+ *opt_replyp++ = SE;
+ if (NETROOM() > len) {
+ ring_supply_data(&netoring, opt_reply, len);
+ printsub('>', &opt_reply[2], len - 2);
+ }
+/*@*/ else printf("slc_end_reply: not enough room\n");
+ }
+ if (opt_reply) {
+ free(opt_reply);
+ opt_reply = opt_replyp = opt_replyend = NULL;
+ }
+}
+
+
+
+int
+telrcv(void)
+{
+ int c;
+ int scc;
+ unsigned char *sbp = NULL;
+ int count;
+ int returnValue = 0;
+
+ scc = 0;
+ count = 0;
+ while (TTYROOM() > 2) {
+ if (scc == 0) {
+ if (count) {
+ ring_consumed(&netiring, count);
+ returnValue = 1;
+ count = 0;
+ }
+ sbp = netiring.consume;
+ scc = ring_full_consecutive(&netiring);
+ if (scc == 0) {
+ /* No more data coming in */
+ break;
+ }
+ }
+
+ c = *sbp++ & 0xff, scc--; count++;
+#if defined(ENCRYPTION)
+ if (decrypt_input)
+ c = (*decrypt_input)(c);
+#endif
+
+ switch (telrcv_state) {
+
+ case TS_CR:
+ telrcv_state = TS_DATA;
+ if (c == '\0') {
+ break; /* Ignore \0 after CR */
+ }
+ else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
+ TTYADD(c);
+ break;
+ }
+ /* Else, fall through */
+
+ case TS_DATA:
+ if (c == IAC) {
+ telrcv_state = TS_IAC;
+ break;
+ }
+ /*
+ * The 'crmod' hack (see following) is needed
+ * since we can't set CRMOD on output only.
+ * Machines like MULTICS like to send \r without
+ * \n; since we must turn off CRMOD to get proper
+ * input, the mapping is done here (sigh).
+ */
+ if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
+ if (scc > 0) {
+ c = *sbp&0xff;
+#if defined(ENCRYPTION)
+ if (decrypt_input)
+ c = (*decrypt_input)(c);
+#endif
+ if (c == 0) {
+ sbp++, scc--; count++;
+ /* a "true" CR */
+ TTYADD('\r');
+ } else if (my_want_state_is_dont(TELOPT_ECHO) &&
+ (c == '\n')) {
+ sbp++, scc--; count++;
+ TTYADD('\n');
+ } else {
+#if defined(ENCRYPTION)
+ if (decrypt_input)
+ (*decrypt_input)(-1);
+#endif
+
+ TTYADD('\r');
+ if (crmod) {
+ TTYADD('\n');
+ }
+ }
+ } else {
+ telrcv_state = TS_CR;
+ TTYADD('\r');
+ if (crmod) {
+ TTYADD('\n');
+ }
+ }
+ } else {
+ TTYADD(c);
+ }
+ continue;
+
+ case TS_IAC:
+process_iac:
+ switch (c) {
+
+ case WILL:
+ telrcv_state = TS_WILL;
+ continue;
+
+ case WONT:
+ telrcv_state = TS_WONT;
+ continue;
+
+ case DO:
+ telrcv_state = TS_DO;
+ continue;
+
+ case DONT:
+ telrcv_state = TS_DONT;
+ continue;
+
+ case DM:
+ /*
+ * We may have missed an urgent notification,
+ * so make sure we flush whatever is in the
+ * buffer currently.
+ */
+ printoption("RCVD", IAC, DM);
+ SYNCHing = 1;
+ ttyflush(1);
+ SYNCHing = stilloob();
+ settimer(gotDM);
+ break;
+
+ case SB:
+ SB_CLEAR();
+ telrcv_state = TS_SB;
+ continue;
+
+
+ case IAC:
+ TTYADD(IAC);
+ break;
+
+ case NOP:
+ case GA:
+ default:
+ printoption("RCVD", IAC, c);
+ break;
+ }
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_WILL:
+ printoption("RCVD", WILL, c);
+ willoption(c);
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_WONT:
+ printoption("RCVD", WONT, c);
+ wontoption(c);
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_DO:
+ printoption("RCVD", DO, c);
+ dooption(c);
+ if (c == TELOPT_NAWS) {
+ sendnaws();
+ } else if (c == TELOPT_LFLOW) {
+ localflow = 1;
+ setcommandmode();
+ setconnmode(0);
+ }
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_DONT:
+ printoption("RCVD", DONT, c);
+ dontoption(c);
+ flushline = 1;
+ setconnmode(0); /* set new tty mode (maybe) */
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_SB:
+ if (c == IAC) {
+ telrcv_state = TS_SE;
+ } else {
+ SB_ACCUM(c);
+ }
+ continue;
+
+ case TS_SE:
+ if (c != SE) {
+ if (c != IAC) {
+ /*
+ * This is an error. We only expect to get
+ * "IAC IAC" or "IAC SE". Several things may
+ * have happend. An IAC was not doubled, the
+ * IAC SE was left off, or another option got
+ * inserted into the suboption are all possibilities.
+ * If we assume that the IAC was not doubled,
+ * and really the IAC SE was left off, we could
+ * get into an infinate loop here. So, instead,
+ * we terminate the suboption, and process the
+ * partial suboption if we can.
+ */
+ SB_ACCUM(IAC);
+ SB_ACCUM(c);
+ subpointer -= 2;
+ SB_TERM();
+
+ printoption("In SUBOPTION processing, RCVD", IAC, c);
+ suboption(); /* handle sub-option */
+ telrcv_state = TS_IAC;
+ goto process_iac;
+ }
+ SB_ACCUM(c);
+ telrcv_state = TS_SB;
+ } else {
+ SB_ACCUM(IAC);
+ SB_ACCUM(SE);
+ subpointer -= 2;
+ SB_TERM();
+ suboption(); /* handle sub-option */
+ telrcv_state = TS_DATA;
+ }
+ }
+ }
+ if (count)
+ ring_consumed(&netiring, count);
+ return returnValue||count;
+}
+
+static int bol = 1, local = 0;
+
+int
+rlogin_susp(void)
+{
+ if (local) {
+ local = 0;
+ bol = 1;
+ command(0, "z\n", 2);
+ return(1);
+ }
+ return(0);
+}
+
+static int
+telsnd()
+{
+ int tcc;
+ int count;
+ int returnValue = 0;
+ unsigned char *tbp = NULL;
+
+ tcc = 0;
+ count = 0;
+ while (NETROOM() > 2) {
+ int sc;
+ int c;
+
+ if (tcc == 0) {
+ if (count) {
+ ring_consumed(&ttyiring, count);
+ returnValue = 1;
+ count = 0;
+ }
+ tbp = ttyiring.consume;
+ tcc = ring_full_consecutive(&ttyiring);
+ if (tcc == 0) {
+ break;
+ }
+ }
+ c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
+ if (rlogin != _POSIX_VDISABLE) {
+ if (bol) {
+ bol = 0;
+ if (sc == rlogin) {
+ local = 1;
+ continue;
+ }
+ } else if (local) {
+ local = 0;
+ if (sc == '.' || c == termEofChar) {
+ bol = 1;
+ command(0, "close\n", 6);
+ continue;
+ }
+ if (sc == termSuspChar) {
+ bol = 1;
+ command(0, "z\n", 2);
+ continue;
+ }
+ if (sc == escape) {
+ command(0, (char *)tbp, tcc);
+ bol = 1;
+ count += tcc;
+ tcc = 0;
+ flushline = 1;
+ break;
+ }
+ if (sc != rlogin) {
+ ++tcc;
+ --tbp;
+ --count;
+ c = sc = rlogin;
+ }
+ }
+ if ((sc == '\n') || (sc == '\r'))
+ bol = 1;
+ } else if (sc == escape) {
+ /*
+ * Double escape is a pass through of a single escape character.
+ */
+ if (tcc && strip(*tbp) == escape) {
+ tbp++;
+ tcc--;
+ count++;
+ bol = 0;
+ } else {
+ command(0, (char *)tbp, tcc);
+ bol = 1;
+ count += tcc;
+ tcc = 0;
+ flushline = 1;
+ break;
+ }
+ } else
+ bol = 0;
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
+ if (tcc > 0 && strip(*tbp) == echoc) {
+ tcc--; tbp++; count++;
+ } else {
+ dontlecho = !dontlecho;
+ settimer(echotoggle);
+ setconnmode(0);
+ flushline = 1;
+ break;
+ }
+ }
+#endif
+ if (MODE_LOCAL_CHARS(globalmode)) {
+ if (TerminalSpecialChars(sc) == 0) {
+ bol = 1;
+ break;
+ }
+ }
+ if (my_want_state_is_wont(TELOPT_BINARY)) {
+ switch (c) {
+ case '\n':
+ /*
+ * If we are in CRMOD mode (\r ==> \n)
+ * on our local machine, then probably
+ * a newline (unix) is CRLF (TELNET).
+ */
+ if (MODE_LOCAL_CHARS(globalmode)) {
+ NETADD('\r');
+ }
+ NETADD('\n');
+ bol = flushline = 1;
+ break;
+ case '\r':
+ if (!crlf) {
+ NET2ADD('\r', '\0');
+ } else {
+ NET2ADD('\r', '\n');
+ }
+ bol = flushline = 1;
+ break;
+ case IAC:
+ NET2ADD(IAC, IAC);
+ break;
+ default:
+ NETADD(c);
+ break;
+ }
+ } else if (c == IAC) {
+ NET2ADD(IAC, IAC);
+ } else {
+ NETADD(c);
+ }
+ }
+ if (count)
+ ring_consumed(&ttyiring, count);
+ return returnValue||count; /* Non-zero if we did anything */
+}
+
+/*
+ * Scheduler()
+ *
+ * Try to do something.
+ *
+ * If we do something useful, return 1; else return 0.
+ *
+ */
+
+
+static int
+Scheduler(int block) /* should we block in the select ? */
+{
+ /* One wants to be a bit careful about setting returnValue
+ * to one, since a one implies we did some useful work,
+ * and therefore probably won't be called to block next
+ * time (TN3270 mode only).
+ */
+ int returnValue;
+ int netin, netout, netex, ttyin, ttyout;
+
+ /* Decide which rings should be processed */
+
+ netout = ring_full_count(&netoring) &&
+ (flushline ||
+ (my_want_state_is_wont(TELOPT_LINEMODE)
+#ifdef KLUDGELINEMODE
+ && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
+#endif
+ ) ||
+ my_want_state_is_will(TELOPT_BINARY));
+ ttyout = ring_full_count(&ttyoring);
+
+ ttyin = ring_empty_count(&ttyiring);
+
+ netin = !ISend && ring_empty_count(&netiring);
+
+ netex = !SYNCHing;
+
+ /* If we have seen a signal recently, reset things */
+
+ /* Call to system code to process rings */
+
+ returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
+
+ /* Now, look at the input rings, looking for work to do. */
+
+ if (ring_full_count(&ttyiring)) {
+ returnValue |= telsnd();
+ }
+
+ if (ring_full_count(&netiring)) {
+ returnValue |= telrcv();
+ }
+ return returnValue;
+}
+
+/*
+ * Select from tty and network...
+ */
+void
+my_telnet(char *user)
+{
+ sys_telnet_init();
+
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ {
+ static char local_host[256] = { 0 };
+
+ if (!local_host[0]) {
+ /* XXX - should be k_gethostname? */
+ gethostname(local_host, sizeof(local_host));
+ local_host[sizeof(local_host)-1] = 0;
+ }
+ auth_encrypt_init(local_host, hostname, "TELNET", 0);
+ auth_encrypt_user(user);
+ }
+#endif
+ if (telnetport) {
+#if defined(AUTHENTICATION)
+ if (autologin)
+ send_will(TELOPT_AUTHENTICATION, 1);
+#endif
+#if defined(ENCRYPTION)
+ send_do(TELOPT_ENCRYPT, 1);
+ send_will(TELOPT_ENCRYPT, 1);
+#endif
+ send_do(TELOPT_SGA, 1);
+ send_will(TELOPT_TTYPE, 1);
+ send_will(TELOPT_NAWS, 1);
+ send_will(TELOPT_TSPEED, 1);
+ send_will(TELOPT_LFLOW, 1);
+ send_will(TELOPT_LINEMODE, 1);
+ send_will(TELOPT_NEW_ENVIRON, 1);
+ send_do(TELOPT_STATUS, 1);
+ if (env_getvalue((unsigned char *)"DISPLAY"))
+ send_will(TELOPT_XDISPLOC, 1);
+ if (binary)
+ tel_enter_binary(binary);
+ }
+
+ for (;;) {
+ int schedValue;
+
+ while ((schedValue = Scheduler(0)) != 0) {
+ if (schedValue == -1) {
+ setcommandmode();
+ return;
+ }
+ }
+
+ if (Scheduler(1) == -1) {
+ setcommandmode();
+ return;
+ }
+ }
+}
+
+/*
+ * netclear()
+ *
+ * We are about to do a TELNET SYNCH operation. Clear
+ * the path to the network.
+ *
+ * Things are a bit tricky since we may have sent the first
+ * byte or so of a previous TELNET command into the network.
+ * So, we have to scan the network buffer from the beginning
+ * until we are up to where we want to be.
+ *
+ * A side effect of what we do, just to keep things
+ * simple, is to clear the urgent data pointer. The principal
+ * caller should be setting the urgent data pointer AFTER calling
+ * us in any case.
+ */
+
+static void
+netclear()
+{
+#if 0 /* XXX */
+ char *thisitem, *next;
+ char *good;
+#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
+ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+
+ thisitem = netobuf;
+
+ while ((next = nextitem(thisitem)) <= netobuf.send) {
+ thisitem = next;
+ }
+
+ /* Now, thisitem is first before/at boundary. */
+
+ good = netobuf; /* where the good bytes go */
+
+ while (netoring.add > thisitem) {
+ if (wewant(thisitem)) {
+ int length;
+
+ next = thisitem;
+ do {
+ next = nextitem(next);
+ } while (wewant(next) && (nfrontp > next));
+ length = next-thisitem;
+ memmove(good, thisitem, length);
+ good += length;
+ thisitem = next;
+ } else {
+ thisitem = nextitem(thisitem);
+ }
+ }
+
+#endif /* 0 */
+}
+
+/*
+ * These routines add various telnet commands to the data stream.
+ */
+
+static void
+doflush()
+{
+ NET2ADD(IAC, DO);
+ NETADD(TELOPT_TM);
+ flushline = 1;
+ flushout = 1;
+ ttyflush(1); /* Flush/drop output */
+ /* do printoption AFTER flush, otherwise the output gets tossed... */
+ printoption("SENT", DO, TELOPT_TM);
+}
+
+void
+xmitAO(void)
+{
+ NET2ADD(IAC, AO);
+ printoption("SENT", IAC, AO);
+ if (autoflush) {
+ doflush();
+ }
+}
+
+
+void
+xmitEL(void)
+{
+ NET2ADD(IAC, EL);
+ printoption("SENT", IAC, EL);
+}
+
+void
+xmitEC(void)
+{
+ NET2ADD(IAC, EC);
+ printoption("SENT", IAC, EC);
+}
+
+
+int
+dosynch()
+{
+ netclear(); /* clear the path to the network */
+ NETADD(IAC);
+ setneturg();
+ NETADD(DM);
+ printoption("SENT", IAC, DM);
+ return 1;
+}
+
+int want_status_response = 0;
+
+int
+get_status()
+{
+ unsigned char tmp[16];
+ unsigned char *cp;
+
+ if (my_want_state_is_dont(TELOPT_STATUS)) {
+ printf("Remote side does not support STATUS option\n");
+ return 0;
+ }
+ cp = tmp;
+
+ *cp++ = IAC;
+ *cp++ = SB;
+ *cp++ = TELOPT_STATUS;
+ *cp++ = TELQUAL_SEND;
+ *cp++ = IAC;
+ *cp++ = SE;
+ if (NETROOM() >= cp - tmp) {
+ ring_supply_data(&netoring, tmp, cp-tmp);
+ printsub('>', tmp+2, cp - tmp - 2);
+ }
+ ++want_status_response;
+ return 1;
+}
+
+void
+intp(void)
+{
+ NET2ADD(IAC, IP);
+ printoption("SENT", IAC, IP);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch();
+ }
+}
+
+void
+sendbrk(void)
+{
+ NET2ADD(IAC, BREAK);
+ printoption("SENT", IAC, BREAK);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch();
+ }
+}
+
+void
+sendabort(void)
+{
+ NET2ADD(IAC, ABORT);
+ printoption("SENT", IAC, ABORT);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch();
+ }
+}
+
+void
+sendsusp(void)
+{
+ NET2ADD(IAC, SUSP);
+ printoption("SENT", IAC, SUSP);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch();
+ }
+}
+
+void
+sendeof(void)
+{
+ NET2ADD(IAC, xEOF);
+ printoption("SENT", IAC, xEOF);
+}
+
+void
+sendayt(void)
+{
+ NET2ADD(IAC, AYT);
+ printoption("SENT", IAC, AYT);
+}
+
+/*
+ * Send a window size update to the remote system.
+ */
+
+void
+sendnaws()
+{
+ long rows, cols;
+ unsigned char tmp[16];
+ unsigned char *cp;
+
+ if (my_state_is_wont(TELOPT_NAWS))
+ return;
+
+#define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
+ if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
+
+ if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
+ return;
+ }
+
+ cp = tmp;
+
+ *cp++ = IAC;
+ *cp++ = SB;
+ *cp++ = TELOPT_NAWS;
+ PUTSHORT(cp, cols);
+ PUTSHORT(cp, rows);
+ *cp++ = IAC;
+ *cp++ = SE;
+ if (NETROOM() >= cp - tmp) {
+ ring_supply_data(&netoring, tmp, cp-tmp);
+ printsub('>', tmp+2, cp - tmp - 2);
+ }
+}
+
+void
+tel_enter_binary(int rw)
+{
+ if (rw&1)
+ send_do(TELOPT_BINARY, 1);
+ if (rw&2)
+ send_will(TELOPT_BINARY, 1);
+}
+
+void
+tel_leave_binary(int rw)
+{
+ if (rw&1)
+ send_dont(TELOPT_BINARY, 1);
+ if (rw&2)
+ send_wont(TELOPT_BINARY, 1);
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h b/crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h
new file mode 100644
index 0000000..b4a3782
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h
@@ -0,0 +1,176 @@
+/*
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. 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: telnet_locl.h,v 1.16.8.1 1999/07/22 03:22:52 assar Exp $ */
+
+#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 */
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#if defined(SOCKS) && defined(HAVE_CURSES_H)
+#include <curses.h>
+#endif
+
+#if defined(HAVE_SYS_TERMIO_H) && !defined(HAVE_TERMIOS_H)
+#include <sys/termio.h>
+#endif
+
+#if defined(HAVE_TERMCAP_H)
+#include <termcap.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
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+
+#ifdef SOCKS
+#include <socks.h>
+#endif
+
+#include <roken.h>
+/* krb.h? */
+
+#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
+#define KLUDGELINEMODE
+
+#include "ring.h"
+#include "externs.h"
+#include "defines.h"
+#include "types.h"
+
+/* prototypes */
+
diff --git a/crypto/kerberosIV/appl/telnet/telnet/terminal.c b/crypto/kerberosIV/appl/telnet/telnet/terminal.c
new file mode 100644
index 0000000..4404384
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/terminal.c
@@ -0,0 +1,225 @@
+/*
+ * 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: terminal.c,v 1.10 1997/12/15 19:53:06 joda Exp $");
+
+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)
+{
+ extern int linemode;
+ int mode = 0;
+#ifdef KLUDGELINEMODE
+ extern int kludgelinemode;
+#endif
+
+ 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);
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnet/types.h b/crypto/kerberosIV/appl/telnet/telnet/types.h
new file mode 100644
index 0000000..191d311
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/types.h
@@ -0,0 +1,52 @@
+/*
+ * 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;
diff --git a/crypto/kerberosIV/appl/telnet/telnet/utilities.c b/crypto/kerberosIV/appl/telnet/telnet/utilities.c
new file mode 100644
index 0000000..5d677cf
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/utilities.c
@@ -0,0 +1,863 @@
+/*
+ * 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: utilities.c,v 1.21 1998/06/09 19:24:47 joda Exp $");
+
+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) {
+ strcpy_truncate(NetTraceFile, file, sizeof(NetTraceFile));
+ return;
+ }
+ fprintf(stderr, "Cannot open %s.\n", file);
+ }
+ NetTrace = stdout;
+ strcpy_truncate(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;
+ extern char will_wont_resp[], do_dont_resp[];
+
+ 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);
+ }
+ }
+ }
+
+}
+
+void
+printsub(int direction, unsigned char *pointer, int length)
+{
+ int i;
+ unsigned char buf[512];
+ extern int want_status_response;
+
+ if (showoptions || direction == 0 ||
+ (want_status_response && (pointer[0] == TELOPT_STATUS))) {
+ if (direction) {
+ fprintf(NetTrace, "%s IAC SB ",
+ (direction == '<')? "RCVD":"SENT");
+ if (length >= 3) {
+ int j;
+
+ i = pointer[length-2];
+ j = pointer[length-1];
+
+ if (i != IAC || j != SE) {
+ fprintf(NetTrace, "(terminated by ");
+ if (TELOPT_OK(i))
+ fprintf(NetTrace, "%s ", TELOPT(i));
+ else if (TELCMD_OK(i))
+ fprintf(NetTrace, "%s ", TELCMD(i));
+ else
+ fprintf(NetTrace, "%d ", i);
+ if (TELOPT_OK(j))
+ fprintf(NetTrace, "%s", TELOPT(j));
+ else if (TELCMD_OK(j))
+ fprintf(NetTrace, "%s", TELCMD(j));
+ else
+ fprintf(NetTrace, "%d", j);
+ fprintf(NetTrace, ", not IAC SE!) ");
+ }
+ }
+ length -= 2;
+ }
+ if (length < 1) {
+ fprintf(NetTrace, "(Empty suboption??\?)");
+ if (NetTrace == stdout)
+ fflush(NetTrace);
+ return;
+ }
+ switch (pointer[0]) {
+ case TELOPT_TTYPE:
+ fprintf(NetTrace, "TERMINAL-TYPE ");
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+ break;
+ case TELQUAL_SEND:
+ fprintf(NetTrace, "SEND");
+ break;
+ default:
+ fprintf(NetTrace,
+ "- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
+ }
+ break;
+ case TELOPT_TSPEED:
+ fprintf(NetTrace, "TERMINAL-SPEED");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ fprintf(NetTrace, " IS ");
+ fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
+ break;
+ default:
+ if (pointer[1] == 1)
+ fprintf(NetTrace, " SEND");
+ else
+ fprintf(NetTrace, " %d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+ }
+ break;
+
+ case TELOPT_LFLOW:
+ fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case LFLOW_OFF:
+ fprintf(NetTrace, " OFF"); break;
+ case LFLOW_ON:
+ fprintf(NetTrace, " ON"); break;
+ case LFLOW_RESTART_ANY:
+ fprintf(NetTrace, " RESTART-ANY"); break;
+ case LFLOW_RESTART_XON:
+ fprintf(NetTrace, " RESTART-XON"); break;
+ default:
+ fprintf(NetTrace, " %d (unknown)", pointer[1]);
+ }
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+
+ case TELOPT_NAWS:
+ fprintf(NetTrace, "NAWS");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ if (length == 2) {
+ fprintf(NetTrace, " ?%d?", pointer[1]);
+ break;
+ }
+ fprintf(NetTrace, " %d %d (%d)",
+ pointer[1], pointer[2],
+ (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
+ if (length == 4) {
+ fprintf(NetTrace, " ?%d?", pointer[3]);
+ break;
+ }
+ fprintf(NetTrace, " %d %d (%d)",
+ pointer[3], pointer[4],
+ (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
+ for (i = 5; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+
+#if defined(AUTHENTICATION)
+ 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\"", 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 noquote = 2;
+ for (i = 2; i < length; i++ ) {
+ switch (pointer[i]) {
+ case NEW_ENV_VALUE:
+#ifdef OLD_ENVIRON
+ /* case NEW_ENV_OVAR: */
+ if (pointer[0] == TELOPT_OLD_ENVIRON) {
+ fprintf(NetTrace, "\" VAR " + noquote);
+ } else
+#endif /* OLD_ENVIRON */
+ fprintf(NetTrace, "\" VALUE " + noquote);
+ noquote = 2;
+ break;
+
+ case NEW_ENV_VAR:
+#ifdef OLD_ENVIRON
+ /* case OLD_ENV_VALUE: */
+ if (pointer[0] == TELOPT_OLD_ENVIRON) {
+ fprintf(NetTrace, "\" VALUE " + noquote);
+ } else
+#endif /* OLD_ENVIRON */
+ fprintf(NetTrace, "\" VAR " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_ESC:
+ fprintf(NetTrace, "\" ESC " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_USERVAR:
+ fprintf(NetTrace, "\" USERVAR " + noquote);
+ noquote = 2;
+ break;
+
+ default:
+ if (isprint(pointer[i]) && pointer[i] != '"') {
+ if (noquote) {
+ putc('"', NetTrace);
+ noquote = 0;
+ }
+ putc(pointer[i], NetTrace);
+ } else {
+ fprintf(NetTrace, "\" %03o " + noquote,
+ pointer[i]);
+ noquote = 2;
+ }
+ break;
+ }
+ }
+ if (!noquote)
+ putc('"', NetTrace);
+ break;
+ }
+ }
+ break;
+
+ default:
+ if (TELOPT_OK(pointer[0]))
+ fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
+ else
+ fprintf(NetTrace, "%d (unknown)", pointer[0]);
+ for (i = 1; i < length; i++)
+ fprintf(NetTrace, " %d", pointer[i]);
+ break;
+ }
+ if (direction) {
+ if (NetTrace == stdout)
+ fprintf(NetTrace, "\r\n");
+ else
+ fprintf(NetTrace, "\n");
+ }
+ if (NetTrace == stdout)
+ fflush(NetTrace);
+ }
+}
+
+/* EmptyTerminal - called to make sure that the terminal buffer is empty.
+ * Note that we consider the buffer to run all the
+ * way to the kernel (thus the select).
+ */
+
+void
+EmptyTerminal(void)
+{
+ fd_set outs;
+
+ FD_ZERO(&outs);
+
+ 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);
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/Makefile.am b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.am
new file mode 100644
index 0000000..c228518
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.am
@@ -0,0 +1,21 @@
+# $Id: Makefile.am,v 1.12 1999/04/09 18:24:38 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += -I$(srcdir)/.. $(INCLUDE_krb4)
+
+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
+
+LDADD = \
+ ../libtelnet/libtelnet.a \
+ $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_tgetent) \
+ $(LIB_logwtmp) \
+ $(LIB_roken)
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/Makefile.in b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.in
new file mode 100644
index 0000000..ed42d1d
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.in
@@ -0,0 +1,79 @@
+# $Id: Makefile.in,v 1.38 1999/03/11 13:50:16 joda Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+top_builddir = ../../..
+
+SHELL = /bin/sh
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@ -DBINDIR='"$(bindir)"'
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS = @LD_FLAGS@
+LIBS = @LIBS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+libexecdir = @libexecdir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+PROGS = telnetd$(EXECSUFFIX)
+
+SOURCES=telnetd.c state.c termstat.c slc.c sys_term.c \
+ utility.c global.c authenc.c
+
+OBJECTS=telnetd.o state.o termstat.o slc.o sys_term.o \
+ utility.o global.o authenc.o
+
+libtop = @libtop@
+
+LIBKRB = -L../../../lib/krb -lkrb
+LIBDES = -L../../../lib/des -ldes
+LIBKAFS = @KRB_KAFS_LIB@
+LIBROKEN = -L../../../lib/roken -lroken
+
+KLIB=$(LIBKAFS) $(LIBKRB) $(LIBDES)
+
+
+all: $(PROGS)
+
+.c.o:
+ $(CC) -c $(DEFS) -I../../../include -I.. -I$(srcdir)/.. -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $<
+
+telnetd$(EXECSUFFIX): $(OBJECTS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS) -L../libtelnet -ltelnet $(KLIB) $(LIBROKEN) $(LIBS) @LIB_tgetent@ $(LIBROKEN)
+
+install: all
+ $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir)
+ for x in $(PROGS); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(PROGS); do \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+clean cleandir:
+ rm -f *.o *.a telnetd$(EXECSUFFIX) \#* *~ core
+
+distclean: clean
+ rm -f Makefile *~
+
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/authenc.c b/crypto/kerberosIV/appl/telnet/telnetd/authenc.c
new file mode 100644
index 0000000..2a95127
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/authenc.c
@@ -0,0 +1,82 @@
+/*-
+ * 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: authenc.c,v 1.8 1998/07/09 23:16:37 assar Exp $");
+
+#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)
+{
+ ttloop();
+ return(0);
+}
+
+char *
+telnet_getenv(char *val)
+{
+ extern char *getenv(const char *);
+ return(getenv(val));
+}
+
+char *
+telnet_gets(char *prompt, char *result, int length, int echo)
+{
+ return NULL;
+}
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/defs.h b/crypto/kerberosIV/appl/telnet/telnetd/defs.h
new file mode 100644
index 0000000..dc3f842
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/defs.h
@@ -0,0 +1,190 @@
+/*
+ * 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 symetrical
+ */
+
+#define HIS_STATE_WILL MY_STATE_DO
+#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO
+#define HIS_STATE_DO MY_STATE_WILL
+#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL
+
+#define his_state_is_do my_state_is_will
+#define his_state_is_will my_state_is_do
+#define his_want_state_is_do my_want_state_is_will
+#define his_want_state_is_will my_want_state_is_do
+
+#define his_state_is_dont my_state_is_wont
+#define his_state_is_wont my_state_is_dont
+#define his_want_state_is_dont my_want_state_is_wont
+#define his_want_state_is_wont my_want_state_is_dont
+
+#define set_his_state_do set_my_state_will
+#define set_his_state_will set_my_state_do
+#define set_his_want_state_do set_my_want_state_will
+#define set_his_want_state_will set_my_want_state_do
+
+#define set_his_state_dont set_my_state_wont
+#define set_his_state_wont set_my_state_dont
+#define set_his_want_state_dont set_my_want_state_wont
+#define set_his_want_state_wont set_my_want_state_dont
+
+#define his_will_wont_is_changing my_do_dont_is_changing
+#define his_do_dont_is_changing my_will_wont_is_changing
+
+#endif /* __DEFS_H__ */
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/ext.h b/crypto/kerberosIV/appl/telnet/telnetd/ext.h
new file mode 100644
index 0000000..83b7166
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/ext.h
@@ -0,0 +1,204 @@
+/*
+ * 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: ext.h,v 1.17 1998/07/09 23:16:38 assar Exp $ */
+
+#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;
+
+/*
+ * 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 (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 *line);
+void startslave (char *host, int autologin, char *autoname);
+void init_env (void);
+void start_login (char *host, int autologin, char *name);
+void cleanup (int sig);
+int main (int argc, char **argv);
+void usage (void);
+int getterminaltype (char *name, size_t);
+void _gettermname (void);
+int terminaltypeok (char *s);
+void doit (struct sockaddr_in *who);
+void my_telnet (int f, int p, 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);
+void ttloop (void);
+int stilloob (int s);
+void ptyflush (void);
+char *nextitem (char *current);
+void netclear (void);
+void netflush (void);
+void writenet (unsigned char *ptr, int len);
+void fatal (int f, char *msg);
+void fatalperror (int f, const char *msg);
+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, int length);
+void printdata (char *tag, char *ptr, int 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;
+
+#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__ */
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/global.c b/crypto/kerberosIV/appl/telnet/telnetd/global.c
new file mode 100644
index 0000000..275cb45
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/global.c
@@ -0,0 +1,107 @@
+/*
+ * 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: global.c,v 1.12 1997/05/11 06:29:59 assar Exp $");
+
+/*
+ * 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;
+
+/*
+ * 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;
+ size_t remaining, ret;
+
+ va_start(args, format);
+ remaining = BUFSIZ - (nfrontp - netobuf);
+ ret = vsnprintf (nfrontp,
+ remaining,
+ format,
+ args);
+ nfrontp += ret;
+ va_end(args);
+ return ret;
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/slc.c b/crypto/kerberosIV/appl/telnet/telnetd/slc.c
new file mode 100644
index 0000000..799d2d8
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/slc.c
@@ -0,0 +1,57 @@
+/*
+ * 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: slc.c,v 1.10 1997/05/11 06:30:00 assar Exp $");
+
+/*
+ * 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;
+ }
+
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/state.c b/crypto/kerberosIV/appl/telnet/telnetd/state.c
new file mode 100644
index 0000000..80b90ea
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/state.c
@@ -0,0 +1,1356 @@
+/*
+ * 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: state.c,v 1.13 1999/05/13 23:12:50 assar Exp $");
+
+unsigned char doopt[] = { IAC, DO, '%', 'c', 0 };
+unsigned char dont[] = { IAC, DONT, '%', 'c', 0 };
+unsigned char will[] = { IAC, WILL, '%', 'c', 0 };
+unsigned char wont[] = { IAC, WONT, '%', 'c', 0 };
+int not42 = 1;
+
+/*
+ * Buffer for sub-options, and macros
+ * for suboptions buffer manipulations
+ */
+unsigned char subbuffer[2048], *subpointer= subbuffer, *subend= subbuffer;
+
+#define SB_CLEAR() subpointer = subbuffer
+#define SB_TERM() { subend = subpointer; SB_CLEAR(); }
+#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
+ *subpointer++ = (c); \
+ }
+#define SB_GET() ((*subpointer++)&0xff)
+#define SB_EOF() (subpointer >= subend)
+#define SB_LEN() (subend - subpointer)
+
+#ifdef ENV_HACK
+unsigned char *subsave;
+#define SB_SAVE() subsave = subpointer;
+#define SB_RESTORE() subpointer = subsave;
+#endif
+
+
+/*
+ * State for recv fsm
+ */
+#define TS_DATA 0 /* base state */
+#define TS_IAC 1 /* look for double IAC's */
+#define TS_CR 2 /* CR-LF ->'s CR */
+#define TS_SB 3 /* throw away begin's... */
+#define TS_SE 4 /* ...end's (suboption negotiation) */
+#define TS_WILL 5 /* will option negotiation */
+#define TS_WONT 6 /* wont -''- */
+#define TS_DO 7 /* do -''- */
+#define TS_DONT 8 /* dont -''- */
+
+void
+telrcv(void)
+{
+ int c;
+ static int state = TS_DATA;
+
+ while (ncc > 0) {
+ if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
+ break;
+ c = *netip++ & 0377, ncc--;
+#ifdef ENCRYPTION
+ if (decrypt_input)
+ c = (*decrypt_input)(c);
+#endif
+ switch (state) {
+
+ case TS_CR:
+ state = TS_DATA;
+ /* Strip off \n or \0 after a \r */
+ if ((c == 0) || (c == '\n')) {
+ break;
+ }
+ /* FALL THROUGH */
+
+ case TS_DATA:
+ if (c == IAC) {
+ state = TS_IAC;
+ break;
+ }
+ /*
+ * We now map \r\n ==> \r for pragmatic reasons.
+ * Many client implementations send \r\n when
+ * the user hits the CarriageReturn key.
+ *
+ * We USED to map \r\n ==> \n, since \r\n says
+ * that we want to be in column 1 of the next
+ * printable line, and \n is the standard
+ * unix way of saying that (\r is only good
+ * if CRMOD is set, which it normally is).
+ */
+ if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
+ int nc = *netip;
+#ifdef ENCRYPTION
+ if (decrypt_input)
+ nc = (*decrypt_input)(nc & 0xff);
+#endif
+ {
+#ifdef ENCRYPTION
+ if (decrypt_input)
+ (void)(*decrypt_input)(-1);
+#endif
+ state = TS_CR;
+ }
+ }
+ *pfrontp++ = c;
+ break;
+
+ case TS_IAC:
+ gotiac: switch (c) {
+
+ /*
+ * Send the process on the pty side an
+ * interrupt. Do this with a NULL or
+ * interrupt char; depending on the tty mode.
+ */
+ case IP:
+ DIAG(TD_OPTIONS,
+ printoption("td: recv IAC", c));
+ interrupt();
+ break;
+
+ case BREAK:
+ DIAG(TD_OPTIONS,
+ printoption("td: recv IAC", c));
+ sendbrk();
+ break;
+
+ /*
+ * Are You There?
+ */
+ case AYT:
+ DIAG(TD_OPTIONS,
+ printoption("td: recv IAC", c));
+ recv_ayt();
+ break;
+
+ /*
+ * Abort Output
+ */
+ case AO:
+ {
+ DIAG(TD_OPTIONS,
+ printoption("td: recv IAC", c));
+ ptyflush(); /* half-hearted */
+ init_termbuf();
+
+ if (slctab[SLC_AO].sptr &&
+ *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
+ *pfrontp++ =
+ (unsigned char)*slctab[SLC_AO].sptr;
+ }
+
+ netclear(); /* clear buffer back */
+ output_data ("%c%c", IAC, DM);
+ neturg = nfrontp-1; /* off by one XXX */
+ DIAG(TD_OPTIONS,
+ printoption("td: send IAC", DM));
+ break;
+ }
+
+ /*
+ * Erase Character and
+ * Erase Line
+ */
+ case EC:
+ case EL:
+ {
+ cc_t ch;
+
+ DIAG(TD_OPTIONS,
+ printoption("td: recv IAC", c));
+ ptyflush(); /* half-hearted */
+ init_termbuf();
+ if (c == EC)
+ ch = *slctab[SLC_EC].sptr;
+ else
+ ch = *slctab[SLC_EL].sptr;
+ if (ch != (cc_t)(_POSIX_VDISABLE))
+ *pfrontp++ = (unsigned char)ch;
+ break;
+ }
+
+ /*
+ * Check for urgent data...
+ */
+ case DM:
+ DIAG(TD_OPTIONS,
+ printoption("td: recv IAC", c));
+ SYNCHing = stilloob(net);
+ settimer(gotDM);
+ break;
+
+
+ /*
+ * Begin option subnegotiation...
+ */
+ case SB:
+ state = TS_SB;
+ SB_CLEAR();
+ continue;
+
+ case WILL:
+ state = TS_WILL;
+ continue;
+
+ case WONT:
+ state = TS_WONT;
+ continue;
+
+ case DO:
+ state = TS_DO;
+ continue;
+
+ case DONT:
+ state = TS_DONT;
+ continue;
+ case EOR:
+ if (his_state_is_will(TELOPT_EOR))
+ doeof();
+ break;
+
+ /*
+ * Handle RFC 10xx Telnet linemode option additions
+ * to command stream (EOF, SUSP, ABORT).
+ */
+ case xEOF:
+ doeof();
+ break;
+
+ case SUSP:
+ sendsusp();
+ break;
+
+ case ABORT:
+ sendbrk();
+ break;
+
+ case IAC:
+ *pfrontp++ = c;
+ break;
+ }
+ state = TS_DATA;
+ break;
+
+ case TS_SB:
+ if (c == IAC) {
+ state = TS_SE;
+ } else {
+ SB_ACCUM(c);
+ }
+ break;
+
+ case TS_SE:
+ if (c != SE) {
+ if (c != IAC) {
+ /*
+ * bad form of suboption negotiation.
+ * handle it in such a way as to avoid
+ * damage to local state. Parse
+ * suboption buffer found so far,
+ * then treat remaining stream as
+ * another command sequence.
+ */
+
+ /* for DIAGNOSTICS */
+ SB_ACCUM(IAC);
+ SB_ACCUM(c);
+ subpointer -= 2;
+
+ SB_TERM();
+ suboption();
+ state = TS_IAC;
+ goto gotiac;
+ }
+ SB_ACCUM(c);
+ state = TS_SB;
+ } else {
+ /* for DIAGNOSTICS */
+ SB_ACCUM(IAC);
+ SB_ACCUM(SE);
+ subpointer -= 2;
+
+ SB_TERM();
+ suboption(); /* handle sub-option */
+ state = TS_DATA;
+ }
+ break;
+
+ case TS_WILL:
+ willoption(c);
+ state = TS_DATA;
+ continue;
+
+ case TS_WONT:
+ wontoption(c);
+ if (c==TELOPT_ENCRYPT && his_do_dont_is_changing(TELOPT_ENCRYPT) )
+ dontoption(c);
+ state = TS_DATA;
+ continue;
+
+ case TS_DO:
+ dooption(c);
+ state = TS_DATA;
+ continue;
+
+ case TS_DONT:
+ dontoption(c);
+ state = TS_DATA;
+ continue;
+
+ default:
+ syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
+ printf("telnetd: panic state=%d\n", state);
+ exit(1);
+ }
+ }
+} /* end of telrcv */
+
+/*
+ * The will/wont/do/dont state machines are based on Dave Borman's
+ * Telnet option processing state machine.
+ *
+ * These correspond to the following states:
+ * my_state = the last negotiated state
+ * want_state = what I want the state to go to
+ * want_resp = how many requests I have sent
+ * All state defaults are negative, and resp defaults to 0.
+ *
+ * When initiating a request to change state to new_state:
+ *
+ * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
+ * do nothing;
+ * } else {
+ * want_state = new_state;
+ * send new_state;
+ * want_resp++;
+ * }
+ *
+ * When receiving new_state:
+ *
+ * if (want_resp) {
+ * want_resp--;
+ * if (want_resp && (new_state == my_state))
+ * want_resp--;
+ * }
+ * if ((want_resp == 0) && (new_state != want_state)) {
+ * if (ok_to_switch_to new_state)
+ * want_state = new_state;
+ * else
+ * want_resp++;
+ * send want_state;
+ * }
+ * my_state = new_state;
+ *
+ * Note that new_state is implied in these functions by the function itself.
+ * will and do imply positive new_state, wont and dont imply negative.
+ *
+ * Finally, there is one catch. If we send a negative response to a
+ * positive request, my_state will be the positive while want_state will
+ * remain negative. my_state will revert to negative when the negative
+ * acknowlegment arrives from the peer. Thus, my_state generally tells
+ * us not only the last negotiated state, but also tells us what the peer
+ * wants to be doing as well. It is important to understand this difference
+ * as we may wish to be processing data streams based on our desired state
+ * (want_state) or based on what the peer thinks the state is (my_state).
+ *
+ * This all works fine because if the peer sends a positive request, the data
+ * that we receive prior to negative acknowlegment will probably be affected
+ * by the positive state, and we can process it as such (if we can; if we
+ * can't then it really doesn't matter). If it is that important, then the
+ * peer probably should be buffering until this option state negotiation
+ * is complete.
+ *
+ */
+void
+send_do(int option, int init)
+{
+ if (init) {
+ if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
+ his_want_state_is_will(option))
+ return;
+ /*
+ * Special case for TELOPT_TM: We send a DO, but pretend
+ * that we sent a DONT, so that we can send more DOs if
+ * we want to.
+ */
+ if (option == TELOPT_TM)
+ set_his_want_state_wont(option);
+ else
+ set_his_want_state_will(option);
+ do_dont_resp[option]++;
+ }
+ output_data((const char *)doopt, option);
+
+ DIAG(TD_OPTIONS, printoption("td: send do", option));
+}
+
+#ifdef AUTHENTICATION
+extern void auth_request(void);
+#endif
+#ifdef ENCRYPTION
+extern void encrypt_send_support();
+#endif
+
+void
+willoption(int option)
+{
+ int changeok = 0;
+ void (*func)() = 0;
+
+ /*
+ * process input from peer.
+ */
+
+ DIAG(TD_OPTIONS, printoption("td: recv will", option));
+
+ if (do_dont_resp[option]) {
+ do_dont_resp[option]--;
+ if (do_dont_resp[option] && his_state_is_will(option))
+ do_dont_resp[option]--;
+ }
+ if (do_dont_resp[option] == 0) {
+ if (his_want_state_is_wont(option)) {
+ switch (option) {
+
+ case TELOPT_BINARY:
+ init_termbuf();
+ tty_binaryin(1);
+ set_termbuf();
+ changeok++;
+ break;
+
+ case TELOPT_ECHO:
+ /*
+ * See comments below for more info.
+ */
+ not42 = 0; /* looks like a 4.2 system */
+ break;
+
+ case TELOPT_TM:
+ /*
+ * We never respond to a WILL TM, and
+ * we leave the state WONT.
+ */
+ return;
+
+ case TELOPT_LFLOW:
+ /*
+ * If we are going to support flow control
+ * option, then don't worry peer that we can't
+ * change the flow control characters.
+ */
+ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
+ slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
+ slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
+ slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
+ case TELOPT_TTYPE:
+ case TELOPT_SGA:
+ case TELOPT_NAWS:
+ case TELOPT_TSPEED:
+ case TELOPT_XDISPLOC:
+ case TELOPT_NEW_ENVIRON:
+ case TELOPT_OLD_ENVIRON:
+ changeok++;
+ break;
+
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ func = auth_request;
+ changeok++;
+ break;
+#endif
+
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ func = encrypt_send_support;
+ changeok++;
+ break;
+#endif
+
+ default:
+ break;
+ }
+ if (changeok) {
+ set_his_want_state_will(option);
+ send_do(option, 0);
+ } else {
+ do_dont_resp[option]++;
+ send_dont(option, 0);
+ }
+ } else {
+ /*
+ * Option processing that should happen when
+ * we receive conformation of a change in
+ * state that we had requested.
+ */
+ switch (option) {
+ case TELOPT_ECHO:
+ not42 = 0; /* looks like a 4.2 system */
+ /*
+ * Egads, he responded "WILL ECHO". Turn
+ * it off right now!
+ */
+ send_dont(option, 1);
+ /*
+ * "WILL ECHO". Kludge upon kludge!
+ * A 4.2 client is now echoing user input at
+ * the tty. This is probably undesireable and
+ * it should be stopped. The client will
+ * respond WONT TM to the DO TM that we send to
+ * check for kludge linemode. When the WONT TM
+ * arrives, linemode will be turned off and a
+ * change propogated to the pty. This change
+ * will cause us to process the new pty state
+ * in localstat(), which will notice that
+ * linemode is off and send a WILL ECHO
+ * so that we are properly in character mode and
+ * all is well.
+ */
+ break;
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ func = auth_request;
+ break;
+#endif
+
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ func = encrypt_send_support;
+ break;
+#endif
+
+ case TELOPT_LFLOW:
+ func = flowstat;
+ break;
+ }
+ }
+ }
+ set_his_state_will(option);
+ if (func)
+ (*func)();
+} /* end of willoption */
+
+void
+send_dont(int option, int init)
+{
+ if (init) {
+ if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) ||
+ his_want_state_is_wont(option))
+ return;
+ set_his_want_state_wont(option);
+ do_dont_resp[option]++;
+ }
+ output_data((const char *)dont, option);
+
+ DIAG(TD_OPTIONS, printoption("td: send dont", option));
+}
+
+void
+wontoption(int option)
+{
+ /*
+ * Process client input.
+ */
+
+ DIAG(TD_OPTIONS, printoption("td: recv wont", option));
+
+ if (do_dont_resp[option]) {
+ do_dont_resp[option]--;
+ if (do_dont_resp[option] && his_state_is_wont(option))
+ do_dont_resp[option]--;
+ }
+ if (do_dont_resp[option] == 0) {
+ if (his_want_state_is_will(option)) {
+ /* it is always ok to change to negative state */
+ switch (option) {
+ case TELOPT_ECHO:
+ not42 = 1; /* doesn't seem to be a 4.2 system */
+ break;
+
+ case TELOPT_BINARY:
+ init_termbuf();
+ tty_binaryin(0);
+ set_termbuf();
+ break;
+
+ case TELOPT_TM:
+ /*
+ * If we get a WONT TM, and had sent a DO TM,
+ * don't respond with a DONT TM, just leave it
+ * as is. Short circut the state machine to
+ * achive this.
+ */
+ set_his_want_state_wont(TELOPT_TM);
+ return;
+
+ case TELOPT_LFLOW:
+ /*
+ * If we are not going to support flow control
+ * option, then let peer know that we can't
+ * change the flow control characters.
+ */
+ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
+ slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
+ slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
+ slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
+ break;
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ auth_finished(0, AUTH_REJECT);
+ break;
+#endif
+
+ /*
+ * For options that we might spin waiting for
+ * sub-negotiation, if the client turns off the
+ * option rather than responding to the request,
+ * we have to treat it here as if we got a response
+ * to the sub-negotiation, (by updating the timers)
+ * so that we'll break out of the loop.
+ */
+ case TELOPT_TTYPE:
+ settimer(ttypesubopt);
+ break;
+
+ case TELOPT_TSPEED:
+ settimer(tspeedsubopt);
+ break;
+
+ case TELOPT_XDISPLOC:
+ settimer(xdisplocsubopt);
+ break;
+
+ case TELOPT_OLD_ENVIRON:
+ settimer(oenvironsubopt);
+ break;
+
+ case TELOPT_NEW_ENVIRON:
+ settimer(environsubopt);
+ break;
+
+ default:
+ break;
+ }
+ set_his_want_state_wont(option);
+ if (his_state_is_will(option))
+ send_dont(option, 0);
+ } else {
+ switch (option) {
+ case TELOPT_TM:
+ break;
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ auth_finished(0, AUTH_REJECT);
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+ }
+ set_his_state_wont(option);
+
+} /* end of wontoption */
+
+void
+send_will(int option, int init)
+{
+ if (init) {
+ if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
+ my_want_state_is_will(option))
+ return;
+ set_my_want_state_will(option);
+ will_wont_resp[option]++;
+ }
+ output_data ((const char *)will, option);
+
+ DIAG(TD_OPTIONS, printoption("td: send will", option));
+}
+
+/*
+ * When we get a DONT SGA, we will try once to turn it
+ * back on. If the other side responds DONT SGA, we
+ * leave it at that. This is so that when we talk to
+ * clients that understand KLUDGELINEMODE but not LINEMODE,
+ * we'll keep them in char-at-a-time mode.
+ */
+int turn_on_sga = 0;
+
+void
+dooption(int option)
+{
+ int changeok = 0;
+
+ /*
+ * Process client input.
+ */
+
+ DIAG(TD_OPTIONS, printoption("td: recv do", option));
+
+ if (will_wont_resp[option]) {
+ will_wont_resp[option]--;
+ if (will_wont_resp[option] && my_state_is_will(option))
+ will_wont_resp[option]--;
+ }
+ if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
+ switch (option) {
+ case TELOPT_ECHO:
+ {
+ init_termbuf();
+ tty_setecho(1);
+ set_termbuf();
+ }
+ changeok++;
+ break;
+
+ case TELOPT_BINARY:
+ init_termbuf();
+ tty_binaryout(1);
+ set_termbuf();
+ changeok++;
+ break;
+
+ case TELOPT_SGA:
+ turn_on_sga = 0;
+ changeok++;
+ break;
+
+ case TELOPT_STATUS:
+ changeok++;
+ break;
+
+ case TELOPT_TM:
+ /*
+ * Special case for TM. We send a WILL, but
+ * pretend we sent a WONT.
+ */
+ send_will(option, 0);
+ set_my_want_state_wont(option);
+ set_my_state_wont(option);
+ return;
+
+ case TELOPT_LOGOUT:
+ /*
+ * When we get a LOGOUT option, respond
+ * with a WILL LOGOUT, make sure that
+ * it gets written out to the network,
+ * and then just go away...
+ */
+ set_my_want_state_will(TELOPT_LOGOUT);
+ send_will(TELOPT_LOGOUT, 0);
+ set_my_state_will(TELOPT_LOGOUT);
+ netflush();
+ cleanup(0);
+ /* NOT REACHED */
+ break;
+
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ changeok++;
+ break;
+#endif
+ case TELOPT_LINEMODE:
+ case TELOPT_TTYPE:
+ case TELOPT_NAWS:
+ case TELOPT_TSPEED:
+ case TELOPT_LFLOW:
+ case TELOPT_XDISPLOC:
+#ifdef TELOPT_ENVIRON
+ case TELOPT_NEW_ENVIRON:
+#endif
+ case TELOPT_OLD_ENVIRON:
+ default:
+ break;
+ }
+ if (changeok) {
+ set_my_want_state_will(option);
+ send_will(option, 0);
+ } else {
+ will_wont_resp[option]++;
+ send_wont(option, 0);
+ }
+ }
+ set_my_state_will(option);
+
+} /* end of dooption */
+
+void
+send_wont(int option, int init)
+{
+ if (init) {
+ if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
+ my_want_state_is_wont(option))
+ return;
+ set_my_want_state_wont(option);
+ will_wont_resp[option]++;
+ }
+ output_data ((const char *)wont, option);
+
+ DIAG(TD_OPTIONS, printoption("td: send wont", option));
+}
+
+void
+dontoption(int option)
+{
+ /*
+ * Process client input.
+ */
+
+
+ DIAG(TD_OPTIONS, printoption("td: recv dont", option));
+
+ if (will_wont_resp[option]) {
+ will_wont_resp[option]--;
+ if (will_wont_resp[option] && my_state_is_wont(option))
+ will_wont_resp[option]--;
+ }
+ if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
+ switch (option) {
+ case TELOPT_BINARY:
+ init_termbuf();
+ tty_binaryout(0);
+ set_termbuf();
+ break;
+
+ case TELOPT_ECHO: /* we should stop echoing */
+ {
+ init_termbuf();
+ tty_setecho(0);
+ set_termbuf();
+ }
+ break;
+
+ case TELOPT_SGA:
+ set_my_want_state_wont(option);
+ if (my_state_is_will(option))
+ send_wont(option, 0);
+ set_my_state_wont(option);
+ if (turn_on_sga ^= 1)
+ send_will(option, 1);
+ return;
+
+ default:
+ break;
+ }
+
+ set_my_want_state_wont(option);
+ if (my_state_is_will(option))
+ send_wont(option, 0);
+ }
+ set_my_state_wont(option);
+
+} /* end of dontoption */
+
+#ifdef ENV_HACK
+int env_ovar = -1;
+int env_ovalue = -1;
+#else /* ENV_HACK */
+# define env_ovar OLD_ENV_VAR
+# define env_ovalue OLD_ENV_VALUE
+#endif /* ENV_HACK */
+
+/*
+ * suboption()
+ *
+ * Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ *
+ * Currently we recognize:
+ *
+ * Terminal type is
+ * Linemode
+ * Window size
+ * Terminal speed
+ */
+void
+suboption(void)
+{
+ int subchar;
+
+ DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
+
+ subchar = SB_GET();
+ switch (subchar) {
+ case TELOPT_TSPEED: {
+ int xspeed, rspeed;
+
+ if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */
+ break;
+
+ settimer(tspeedsubopt);
+
+ if (SB_EOF() || SB_GET() != TELQUAL_IS)
+ return;
+
+ xspeed = atoi((char *)subpointer);
+
+ while (SB_GET() != ',' && !SB_EOF());
+ if (SB_EOF())
+ return;
+
+ rspeed = atoi((char *)subpointer);
+ clientstat(TELOPT_TSPEED, xspeed, rspeed);
+
+ break;
+
+ } /* end of case TELOPT_TSPEED */
+
+ case TELOPT_TTYPE: { /* Yaaaay! */
+ static char terminalname[41];
+
+ if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */
+ break;
+ settimer(ttypesubopt);
+
+ if (SB_EOF() || SB_GET() != TELQUAL_IS) {
+ return; /* ??? XXX but, this is the most robust */
+ }
+
+ terminaltype = terminalname;
+
+ while ((terminaltype < (terminalname + sizeof terminalname-1)) &&
+ !SB_EOF()) {
+ int c;
+
+ c = SB_GET();
+ if (isupper(c)) {
+ c = tolower(c);
+ }
+ *terminaltype++ = c; /* accumulate name */
+ }
+ *terminaltype = 0;
+ terminaltype = terminalname;
+ break;
+ } /* end of case TELOPT_TTYPE */
+
+ case TELOPT_NAWS: {
+ int xwinsize, ywinsize;
+
+ if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */
+ break;
+
+ if (SB_EOF())
+ return;
+ xwinsize = SB_GET() << 8;
+ if (SB_EOF())
+ return;
+ xwinsize |= SB_GET();
+ if (SB_EOF())
+ return;
+ ywinsize = SB_GET() << 8;
+ if (SB_EOF())
+ return;
+ ywinsize |= SB_GET();
+ clientstat(TELOPT_NAWS, xwinsize, ywinsize);
+
+ break;
+
+ } /* end of case TELOPT_NAWS */
+
+ case TELOPT_STATUS: {
+ int mode;
+
+ if (SB_EOF())
+ break;
+ mode = SB_GET();
+ switch (mode) {
+ case TELQUAL_SEND:
+ if (my_state_is_will(TELOPT_STATUS))
+ send_status();
+ break;
+
+ case TELQUAL_IS:
+ break;
+
+ default:
+ break;
+ }
+ break;
+ } /* end of case TELOPT_STATUS */
+
+ case TELOPT_XDISPLOC: {
+ if (SB_EOF() || SB_GET() != TELQUAL_IS)
+ return;
+ settimer(xdisplocsubopt);
+ subpointer[SB_LEN()] = '\0';
+ setenv("DISPLAY", (char *)subpointer, 1);
+ break;
+ } /* end of case TELOPT_XDISPLOC */
+
+#ifdef TELOPT_NEW_ENVIRON
+ case TELOPT_NEW_ENVIRON:
+#endif
+ case TELOPT_OLD_ENVIRON: {
+ int c;
+ char *cp, *varp, *valp;
+
+ if (SB_EOF())
+ return;
+ c = SB_GET();
+ if (c == TELQUAL_IS) {
+ if (subchar == TELOPT_OLD_ENVIRON)
+ settimer(oenvironsubopt);
+ else
+ settimer(environsubopt);
+ } else if (c != TELQUAL_INFO) {
+ return;
+ }
+
+#ifdef TELOPT_NEW_ENVIRON
+ if (subchar == TELOPT_NEW_ENVIRON) {
+ while (!SB_EOF()) {
+ c = SB_GET();
+ if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
+ break;
+ }
+ } else
+#endif
+ {
+#ifdef ENV_HACK
+ /*
+ * We only want to do this if we haven't already decided
+ * whether or not the other side has its VALUE and VAR
+ * reversed.
+ */
+ if (env_ovar < 0) {
+ int last = -1; /* invalid value */
+ int empty = 0;
+ int got_var = 0, got_value = 0, got_uservar = 0;
+
+ /*
+ * The other side might have its VALUE and VAR values
+ * reversed. To be interoperable, we need to determine
+ * which way it is. If the first recognized character
+ * is a VAR or VALUE, then that will tell us what
+ * type of client it is. If the fist recognized
+ * character is a USERVAR, then we continue scanning
+ * the suboption looking for two consecutive
+ * VAR or VALUE fields. We should not get two
+ * consecutive VALUE fields, so finding two
+ * consecutive VALUE or VAR fields will tell us
+ * what the client is.
+ */
+ SB_SAVE();
+ while (!SB_EOF()) {
+ c = SB_GET();
+ switch(c) {
+ case OLD_ENV_VAR:
+ if (last < 0 || last == OLD_ENV_VAR
+ || (empty && (last == OLD_ENV_VALUE)))
+ goto env_ovar_ok;
+ got_var++;
+ last = OLD_ENV_VAR;
+ break;
+ case OLD_ENV_VALUE:
+ if (last < 0 || last == OLD_ENV_VALUE
+ || (empty && (last == OLD_ENV_VAR)))
+ goto env_ovar_wrong;
+ got_value++;
+ last = OLD_ENV_VALUE;
+ break;
+ case ENV_USERVAR:
+ /* count strings of USERVAR as one */
+ if (last != ENV_USERVAR)
+ got_uservar++;
+ if (empty) {
+ if (last == OLD_ENV_VALUE)
+ goto env_ovar_ok;
+ if (last == OLD_ENV_VAR)
+ goto env_ovar_wrong;
+ }
+ last = ENV_USERVAR;
+ break;
+ case ENV_ESC:
+ if (!SB_EOF())
+ c = SB_GET();
+ /* FALL THROUGH */
+ default:
+ empty = 0;
+ continue;
+ }
+ empty = 1;
+ }
+ if (empty) {
+ if (last == OLD_ENV_VALUE)
+ goto env_ovar_ok;
+ if (last == OLD_ENV_VAR)
+ goto env_ovar_wrong;
+ }
+ /*
+ * Ok, the first thing was a USERVAR, and there
+ * are not two consecutive VAR or VALUE commands,
+ * and none of the VAR or VALUE commands are empty.
+ * If the client has sent us a well-formed option,
+ * then the number of VALUEs received should always
+ * be less than or equal to the number of VARs and
+ * USERVARs received.
+ *
+ * If we got exactly as many VALUEs as VARs and
+ * USERVARs, the client has the same definitions.
+ *
+ * If we got exactly as many VARs as VALUEs and
+ * USERVARS, the client has reversed definitions.
+ */
+ if (got_uservar + got_var == got_value) {
+ env_ovar_ok:
+ env_ovar = OLD_ENV_VAR;
+ env_ovalue = OLD_ENV_VALUE;
+ } else if (got_uservar + got_value == got_var) {
+ env_ovar_wrong:
+ env_ovar = OLD_ENV_VALUE;
+ env_ovalue = OLD_ENV_VAR;
+ DIAG(TD_OPTIONS, {
+ output_data("ENVIRON VALUE and VAR are reversed!\r\n");
+ });
+
+ }
+ }
+ SB_RESTORE();
+#endif
+
+ while (!SB_EOF()) {
+ c = SB_GET();
+ if ((c == env_ovar) || (c == ENV_USERVAR))
+ break;
+ }
+ }
+
+ if (SB_EOF())
+ return;
+
+ cp = varp = (char *)subpointer;
+ valp = 0;
+
+ while (!SB_EOF()) {
+ c = SB_GET();
+ if (subchar == TELOPT_OLD_ENVIRON) {
+ if (c == env_ovar)
+ c = NEW_ENV_VAR;
+ else if (c == env_ovalue)
+ c = NEW_ENV_VALUE;
+ }
+ switch (c) {
+
+ case NEW_ENV_VALUE:
+ *cp = '\0';
+ cp = valp = (char *)subpointer;
+ break;
+
+ case NEW_ENV_VAR:
+ case ENV_USERVAR:
+ *cp = '\0';
+ if (valp)
+ setenv(varp, valp, 1);
+ else
+ unsetenv(varp);
+ cp = varp = (char *)subpointer;
+ valp = 0;
+ break;
+
+ case ENV_ESC:
+ if (SB_EOF())
+ break;
+ c = SB_GET();
+ /* FALL THROUGH */
+ default:
+ *cp++ = c;
+ break;
+ }
+ }
+ *cp = '\0';
+ if (valp)
+ setenv(varp, valp, 1);
+ else
+ unsetenv(varp);
+ break;
+ } /* end of case TELOPT_NEW_ENVIRON */
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ if (SB_EOF())
+ break;
+ switch(SB_GET()) {
+ case TELQUAL_SEND:
+ case TELQUAL_REPLY:
+ /*
+ * These are sent by us and cannot be sent by
+ * the client.
+ */
+ break;
+ case TELQUAL_IS:
+ auth_is(subpointer, SB_LEN());
+ break;
+ case TELQUAL_NAME:
+ auth_name(subpointer, SB_LEN());
+ break;
+ }
+ break;
+#endif
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ if (SB_EOF())
+ break;
+ switch(SB_GET()) {
+ case ENCRYPT_SUPPORT:
+ encrypt_support(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_IS:
+ encrypt_is(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REPLY:
+ encrypt_reply(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_START:
+ encrypt_start(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_END:
+ encrypt_end();
+ break;
+ case ENCRYPT_REQSTART:
+ encrypt_request_start(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REQEND:
+ /*
+ * We can always send an REQEND so that we cannot
+ * get stuck encrypting. We should only get this
+ * if we have been able to get in the correct mode
+ * anyhow.
+ */
+ encrypt_request_end();
+ break;
+ case ENCRYPT_ENC_KEYID:
+ encrypt_enc_keyid(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_DEC_KEYID:
+ encrypt_dec_keyid(subpointer, SB_LEN());
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+
+ default:
+ break;
+ } /* end of switch */
+
+} /* end of suboption */
+
+void
+doclientstat(void)
+{
+ clientstat(TELOPT_LINEMODE, WILL, 0);
+}
+
+#define ADD(c) *ncp++ = c
+#define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; }
+
+void
+send_status(void)
+{
+ unsigned char statusbuf[256];
+ unsigned char *ncp;
+ unsigned char i;
+
+ ncp = statusbuf;
+
+ netflush(); /* get rid of anything waiting to go out */
+
+ ADD(IAC);
+ ADD(SB);
+ ADD(TELOPT_STATUS);
+ ADD(TELQUAL_IS);
+
+ /*
+ * We check the want_state rather than the current state,
+ * because if we received a DO/WILL for an option that we
+ * don't support, and the other side didn't send a DONT/WONT
+ * in response to our WONT/DONT, then the "state" will be
+ * WILL/DO, and the "want_state" will be WONT/DONT. We
+ * need to go by the latter.
+ */
+ for (i = 0; i < (unsigned char)NTELOPTS; i++) {
+ if (my_want_state_is_will(i)) {
+ ADD(WILL);
+ ADD_DATA(i);
+ }
+ if (his_want_state_is_will(i)) {
+ ADD(DO);
+ ADD_DATA(i);
+ }
+ }
+
+ if (his_want_state_is_will(TELOPT_LFLOW)) {
+ ADD(SB);
+ ADD(TELOPT_LFLOW);
+ if (flowmode) {
+ ADD(LFLOW_ON);
+ } else {
+ ADD(LFLOW_OFF);
+ }
+ ADD(SE);
+
+ if (restartany >= 0) {
+ ADD(SB);
+ ADD(TELOPT_LFLOW);
+ if (restartany) {
+ ADD(LFLOW_RESTART_ANY);
+ } else {
+ ADD(LFLOW_RESTART_XON);
+ }
+ ADD(SE);
+ }
+ }
+
+
+ ADD(IAC);
+ ADD(SE);
+
+ writenet(statusbuf, ncp - statusbuf);
+ netflush(); /* Send it on its way */
+
+ DIAG(TD_OPTIONS,
+ {printsub('>', statusbuf, ncp - statusbuf); netflush();});
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/sys_term.c b/crypto/kerberosIV/appl/telnet/telnetd/sys_term.c
new file mode 100644
index 0000000..09753c0
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/sys_term.c
@@ -0,0 +1,1863 @@
+/*
+ * 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: sys_term.c,v 1.85.2.1 1999/07/22 03:23:19 assar Exp $");
+
+#if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H))
+# define PARENT_DOES_UTMP
+#endif
+
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+
+#ifdef HAVE_UTMPX_H
+struct utmpx wtmp;
+#elif defined(HAVE_UTMP_H)
+struct utmp wtmp;
+#endif /* HAVE_UTMPX_H */
+
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+int utmp_len = sizeof(wtmp.ut_host);
+#else
+int utmp_len = MaxHostNameLen;
+#endif
+
+#ifndef UTMP_FILE
+#ifdef _PATH_UTMP
+#define UTMP_FILE _PATH_UTMP
+#else
+#define UTMP_FILE "/etc/utmp"
+#endif
+#endif
+
+#if !defined(WTMP_FILE) && defined(_PATH_WTMP)
+#define WTMP_FILE _PATH_WTMP
+#endif
+
+#ifndef PARENT_DOES_UTMP
+#ifdef WTMP_FILE
+char wtmpf[] = WTMP_FILE;
+#else
+char wtmpf[] = "/usr/adm/wtmp";
+#endif
+char utmpf[] = UTMP_FILE;
+#else /* PARENT_DOES_UTMP */
+#ifdef WTMP_FILE
+char wtmpf[] = WTMP_FILE;
+#else
+char wtmpf[] = "/etc/wtmp";
+#endif
+#endif /* PARENT_DOES_UTMP */
+
+#ifdef HAVE_TMPDIR_H
+#include <tmpdir.h>
+#endif /* CRAY */
+
+#ifdef STREAMSPTY
+
+#ifdef HAVE_SAC_H
+#include <sac.h>
+#endif
+
+#ifdef HAVE_SYS_STROPTS_H
+#include <sys/stropts.h>
+#endif
+
+#endif /* STREAMSPTY */
+
+#ifdef HAVE_SYS_STREAM_H
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef __hpux
+#undef SE
+#endif
+#include <sys/stream.h>
+#endif
+#if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY)
+#include <sys/tty.h>
+#endif
+#ifdef t_erase
+#undef t_erase
+#undef t_kill
+#undef t_intrc
+#undef t_quitc
+#undef t_startc
+#undef t_stopc
+#undef t_eofc
+#undef t_brkc
+#undef t_suspc
+#undef t_dsuspc
+#undef t_rprntc
+#undef t_flushc
+#undef t_werasc
+#undef t_lnextc
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#else
+#ifdef HAVE_TERMIO_H
+#include <termio.h>
+#endif
+#endif
+
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+# ifndef TCSANOW
+# ifdef TCSETS
+# define TCSANOW TCSETS
+# define TCSADRAIN TCSETSW
+# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
+# else
+# ifdef TCSETA
+# define TCSANOW TCSETA
+# define TCSADRAIN TCSETAW
+# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
+# else
+# define TCSANOW TIOCSETA
+# define TCSADRAIN TIOCSETAW
+# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
+# endif
+# endif
+# define tcsetattr(f, a, t) ioctl(f, a, t)
+# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
+(tp)->c_cflag |= (val)
+# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
+# ifdef CIBAUD
+# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
+ (tp)->c_cflag |= ((val)<<IBSHIFT)
+# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
+# else
+# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
+ (tp)->c_cflag |= (val)
+# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
+# endif
+# endif /* TCSANOW */
+ struct termios termbuf, termbuf2; /* pty control structure */
+# ifdef STREAMSPTY
+ static int ttyfd = -1;
+ int really_stream = 0;
+# endif
+
+ const char *new_login = _PATH_LOGIN;
+
+/*
+ * init_termbuf()
+ * copy_termbuf(cp)
+ * set_termbuf()
+ *
+ * These three routines are used to get and set the "termbuf" structure
+ * to and from the kernel. init_termbuf() gets the current settings.
+ * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
+ * set_termbuf() writes the structure into the kernel.
+ */
+
+ void
+ init_termbuf(void)
+{
+# ifdef STREAMSPTY
+ if (really_stream)
+ tcgetattr(ttyfd, &termbuf);
+ else
+# endif
+ tcgetattr(ourpty, &termbuf);
+ termbuf2 = termbuf;
+}
+
+void
+set_termbuf(void)
+{
+ /*
+ * Only make the necessary changes.
+ */
+ if (memcmp(&termbuf, &termbuf2, sizeof(termbuf)))
+# ifdef STREAMSPTY
+ if (really_stream)
+ tcsetattr(ttyfd, TCSANOW, &termbuf);
+ else
+# endif
+ tcsetattr(ourpty, TCSANOW, &termbuf);
+}
+
+
+/*
+ * spcset(func, valp, valpp)
+ *
+ * This function takes various special characters (func), and
+ * sets *valp to the current value of that character, and
+ * *valpp to point to where in the "termbuf" structure that
+ * value is kept.
+ *
+ * It returns the SLC_ level of support for this function.
+ */
+
+
+int
+spcset(int func, cc_t *valp, cc_t **valpp)
+{
+
+#define setval(a, b) *valp = termbuf.c_cc[a]; \
+ *valpp = &termbuf.c_cc[a]; \
+ return(b);
+#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
+
+ switch(func) {
+ case SLC_EOF:
+ setval(VEOF, SLC_VARIABLE);
+ case SLC_EC:
+ setval(VERASE, SLC_VARIABLE);
+ case SLC_EL:
+ setval(VKILL, SLC_VARIABLE);
+ case SLC_IP:
+ setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+ case SLC_ABORT:
+ setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
+ case SLC_XON:
+#ifdef VSTART
+ setval(VSTART, SLC_VARIABLE);
+#else
+ defval(0x13);
+#endif
+ case SLC_XOFF:
+#ifdef VSTOP
+ setval(VSTOP, SLC_VARIABLE);
+#else
+ defval(0x11);
+#endif
+ case SLC_EW:
+#ifdef VWERASE
+ setval(VWERASE, SLC_VARIABLE);
+#else
+ defval(0);
+#endif
+ case SLC_RP:
+#ifdef VREPRINT
+ setval(VREPRINT, SLC_VARIABLE);
+#else
+ defval(0);
+#endif
+ case SLC_LNEXT:
+#ifdef VLNEXT
+ setval(VLNEXT, SLC_VARIABLE);
+#else
+ defval(0);
+#endif
+ case SLC_AO:
+#if !defined(VDISCARD) && defined(VFLUSHO)
+# define VDISCARD VFLUSHO
+#endif
+#ifdef VDISCARD
+ setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
+#else
+ defval(0);
+#endif
+ case SLC_SUSP:
+#ifdef VSUSP
+ setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
+#else
+ defval(0);
+#endif
+#ifdef VEOL
+ case SLC_FORW1:
+ setval(VEOL, SLC_VARIABLE);
+#endif
+#ifdef VEOL2
+ case SLC_FORW2:
+ setval(VEOL2, SLC_VARIABLE);
+#endif
+ case SLC_AYT:
+#ifdef VSTATUS
+ setval(VSTATUS, SLC_VARIABLE);
+#else
+ defval(0);
+#endif
+
+ case SLC_BRK:
+ case SLC_SYNCH:
+ case SLC_EOR:
+ defval(0);
+
+ default:
+ *valp = 0;
+ *valpp = 0;
+ return(SLC_NOSUPPORT);
+ }
+}
+
+#ifdef _CRAY
+/*
+ * getnpty()
+ *
+ * Return the number of pty's configured into the system.
+ */
+int
+getnpty()
+{
+#ifdef _SC_CRAY_NPTY
+ int numptys;
+
+ if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
+ return numptys;
+ else
+#endif /* _SC_CRAY_NPTY */
+ return 128;
+}
+#endif /* CRAY */
+
+/*
+ * getpty()
+ *
+ * Allocate a pty. As a side effect, the external character
+ * array "line" contains the name of the slave side.
+ *
+ * Returns the file descriptor of the opened pty.
+ */
+
+static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+char *line = Xline;
+
+#ifdef _CRAY
+char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+#endif /* CRAY */
+
+#if !defined(HAVE_PTSNAME) && defined(STREAMSPTY)
+static char *ptsname(int fd)
+{
+#ifdef HAVE_TTYNAME
+ return ttyname(fd);
+#else
+ return NULL;
+#endif
+}
+#endif
+
+int getpty(int *ptynum)
+{
+#ifdef __osf__ /* XXX */
+ int master;
+ int slave;
+ if(openpty(&master, &slave, line, 0, 0) == 0){
+ close(slave);
+ return master;
+ }
+ return -1;
+#else
+#ifdef HAVE__GETPTY
+ int master, slave;
+ char *p;
+ p = _getpty(&master, O_RDWR, 0600, 1);
+ if(p == NULL)
+ return -1;
+ strcpy_truncate(line, p, sizeof(Xline));
+ return master;
+#else
+
+ int p;
+ char *cp, *p1, *p2;
+ int i;
+#if SunOS == 40
+ int dummy;
+#endif
+#if 0 /* && defined(HAVE_OPENPTY) */
+ int master;
+ int slave;
+ if(openpty(&master, &slave, line, 0, 0) == 0){
+ close(slave);
+ return master;
+ }
+#else
+#ifdef STREAMSPTY
+ char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm",
+ "/dev/ptym/clone", 0 };
+
+ char **q;
+ for(q=clone; *q; q++){
+ p=open(*q, O_RDWR);
+ if(p >= 0){
+#ifdef HAVE_GRANTPT
+ grantpt(p);
+#endif
+#ifdef HAVE_UNLOCKPT
+ unlockpt(p);
+#endif
+ strcpy_truncate(line, ptsname(p), sizeof(Xline));
+ really_stream = 1;
+ return p;
+ }
+ }
+#endif /* STREAMSPTY */
+#ifndef _CRAY
+
+#ifndef __hpux
+ snprintf(line, sizeof(Xline), "/dev/ptyXX");
+ p1 = &line[8];
+ p2 = &line[9];
+#else
+ snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX");
+ p1 = &line[13];
+ p2 = &line[14];
+#endif
+
+
+ for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
+ struct stat stb;
+
+ *p1 = *cp;
+ *p2 = '0';
+ /*
+ * This stat() check is just to keep us from
+ * looping through all 256 combinations if there
+ * aren't that many ptys available.
+ */
+ if (stat(line, &stb) < 0)
+ break;
+ for (i = 0; i < 16; i++) {
+ *p2 = "0123456789abcdef"[i];
+ p = open(line, O_RDWR);
+ if (p > 0) {
+#ifndef __hpux
+ line[5] = 't';
+#else
+ for (p1 = &line[8]; *p1; p1++)
+ *p1 = *(p1+1);
+ line[9] = 't';
+#endif
+ chown(line, 0, 0);
+ chmod(line, 0600);
+#if SunOS == 40
+ if (ioctl(p, TIOCGPGRP, &dummy) == 0
+ || errno != EIO) {
+ chmod(line, 0666);
+ close(p);
+ line[5] = 'p';
+ } else
+#endif /* SunOS == 40 */
+ return(p);
+ }
+ }
+ }
+#else /* CRAY */
+ extern lowpty, highpty;
+ struct stat sb;
+
+ for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
+ snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum);
+ p = open(myline, 2);
+ if (p < 0)
+ continue;
+ snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum);
+ /*
+ * Here are some shenanigans to make sure that there
+ * are no listeners lurking on the line.
+ */
+ if(stat(line, &sb) < 0) {
+ close(p);
+ continue;
+ }
+ if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
+ chown(line, 0, 0);
+ chmod(line, 0600);
+ close(p);
+ p = open(myline, 2);
+ if (p < 0)
+ continue;
+ }
+ /*
+ * Now it should be safe...check for accessability.
+ */
+ if (access(line, 6) == 0)
+ return(p);
+ else {
+ /* no tty side to pty so skip it */
+ close(p);
+ }
+ }
+#endif /* CRAY */
+#endif /* STREAMSPTY */
+#endif /* OPENPTY */
+ return(-1);
+#endif
+}
+
+
+int
+tty_isecho(void)
+{
+ return (termbuf.c_lflag & ECHO);
+}
+
+int
+tty_flowmode(void)
+{
+ return((termbuf.c_iflag & IXON) ? 1 : 0);
+}
+
+int
+tty_restartany(void)
+{
+ return((termbuf.c_iflag & IXANY) ? 1 : 0);
+}
+
+void
+tty_setecho(int on)
+{
+ if (on)
+ termbuf.c_lflag |= ECHO;
+ else
+ termbuf.c_lflag &= ~ECHO;
+}
+
+int
+tty_israw(void)
+{
+ return(!(termbuf.c_lflag & ICANON));
+}
+
+void
+tty_binaryin(int on)
+{
+ if (on) {
+ termbuf.c_iflag &= ~ISTRIP;
+ } else {
+ termbuf.c_iflag |= ISTRIP;
+ }
+}
+
+void
+tty_binaryout(int on)
+{
+ if (on) {
+ termbuf.c_cflag &= ~(CSIZE|PARENB);
+ termbuf.c_cflag |= CS8;
+ termbuf.c_oflag &= ~OPOST;
+ } else {
+ termbuf.c_cflag &= ~CSIZE;
+ termbuf.c_cflag |= CS7|PARENB;
+ termbuf.c_oflag |= OPOST;
+ }
+}
+
+int
+tty_isbinaryin(void)
+{
+ return(!(termbuf.c_iflag & ISTRIP));
+}
+
+int
+tty_isbinaryout(void)
+{
+ return(!(termbuf.c_oflag&OPOST));
+}
+
+
+int
+tty_issofttab(void)
+{
+# ifdef OXTABS
+ return (termbuf.c_oflag & OXTABS);
+# endif
+# ifdef TABDLY
+ return ((termbuf.c_oflag & TABDLY) == TAB3);
+# endif
+}
+
+void
+tty_setsofttab(int on)
+{
+ if (on) {
+# ifdef OXTABS
+ termbuf.c_oflag |= OXTABS;
+# endif
+# ifdef TABDLY
+ termbuf.c_oflag &= ~TABDLY;
+ termbuf.c_oflag |= TAB3;
+# endif
+ } else {
+# ifdef OXTABS
+ termbuf.c_oflag &= ~OXTABS;
+# endif
+# ifdef TABDLY
+ termbuf.c_oflag &= ~TABDLY;
+ termbuf.c_oflag |= TAB0;
+# endif
+ }
+}
+
+int
+tty_islitecho(void)
+{
+# ifdef ECHOCTL
+ return (!(termbuf.c_lflag & ECHOCTL));
+# endif
+# ifdef TCTLECH
+ return (!(termbuf.c_lflag & TCTLECH));
+# endif
+# if !defined(ECHOCTL) && !defined(TCTLECH)
+ return (0); /* assumes ctl chars are echoed '^x' */
+# endif
+}
+
+void
+tty_setlitecho(int on)
+{
+# ifdef ECHOCTL
+ if (on)
+ termbuf.c_lflag &= ~ECHOCTL;
+ else
+ termbuf.c_lflag |= ECHOCTL;
+# endif
+# ifdef TCTLECH
+ if (on)
+ termbuf.c_lflag &= ~TCTLECH;
+ else
+ termbuf.c_lflag |= TCTLECH;
+# endif
+}
+
+int
+tty_iscrnl(void)
+{
+ return (termbuf.c_iflag & ICRNL);
+}
+
+/*
+ * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
+ */
+#if B4800 != 4800
+#define DECODE_BAUD
+#endif
+
+#ifdef DECODE_BAUD
+
+/*
+ * A table of available terminal speeds
+ */
+struct termspeeds {
+ int speed;
+ int value;
+} termspeeds[] = {
+ { 0, B0 }, { 50, B50 }, { 75, B75 },
+ { 110, B110 }, { 134, B134 }, { 150, B150 },
+ { 200, B200 }, { 300, B300 }, { 600, B600 },
+ { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
+ { 4800, B4800 },
+#ifdef B7200
+ { 7200, B7200 },
+#endif
+ { 9600, B9600 },
+#ifdef B14400
+ { 14400, B14400 },
+#endif
+#ifdef B19200
+ { 19200, B19200 },
+#endif
+#ifdef B28800
+ { 28800, B28800 },
+#endif
+#ifdef B38400
+ { 38400, B38400 },
+#endif
+#ifdef B57600
+ { 57600, B57600 },
+#endif
+#ifdef B115200
+ { 115200, B115200 },
+#endif
+#ifdef B230400
+ { 230400, B230400 },
+#endif
+ { -1, 0 }
+};
+#endif /* DECODE_BUAD */
+
+void
+tty_tspeed(int val)
+{
+#ifdef DECODE_BAUD
+ struct termspeeds *tp;
+
+ for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
+ ;
+ if (tp->speed == -1) /* back up to last valid value */
+ --tp;
+ cfsetospeed(&termbuf, tp->value);
+#else /* DECODE_BUAD */
+ cfsetospeed(&termbuf, val);
+#endif /* DECODE_BUAD */
+}
+
+void
+tty_rspeed(int val)
+{
+#ifdef DECODE_BAUD
+ struct termspeeds *tp;
+
+ for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
+ ;
+ if (tp->speed == -1) /* back up to last valid value */
+ --tp;
+ cfsetispeed(&termbuf, tp->value);
+#else /* DECODE_BAUD */
+ cfsetispeed(&termbuf, val);
+#endif /* DECODE_BAUD */
+}
+
+#ifdef PARENT_DOES_UTMP
+extern struct utmp wtmp;
+extern char wtmpf[];
+
+extern void utmp_sig_init (void);
+extern void utmp_sig_reset (void);
+extern void utmp_sig_wait (void);
+extern void utmp_sig_notify (int);
+# endif /* PARENT_DOES_UTMP */
+
+#ifdef STREAMSPTY
+
+/* I_FIND seems to live a life of its own */
+static int my_find(int fd, char *module)
+{
+#if defined(I_FIND) && defined(I_LIST)
+ static int flag;
+ static struct str_list sl;
+ int n;
+ int i;
+
+ if(!flag){
+ n = ioctl(fd, I_LIST, 0);
+ if(n < 0){
+ perror("ioctl(fd, I_LIST, 0)");
+ return -1;
+ }
+ sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist));
+ sl.sl_nmods = n;
+ n = ioctl(fd, I_LIST, &sl);
+ if(n < 0){
+ perror("ioctl(fd, I_LIST, n)");
+ return -1;
+ }
+ flag = 1;
+ }
+
+ for(i=0; i<sl.sl_nmods; i++)
+ if(!strcmp(sl.sl_modlist[i].l_name, module))
+ return 1;
+#endif
+ return 0;
+}
+
+static void maybe_push_modules(int fd, char **modules)
+{
+ char **p;
+ int err;
+
+ for(p=modules; *p; p++){
+ err = my_find(fd, *p);
+ if(err == 1)
+ break;
+ if(err < 0 && errno != EINVAL)
+ fatalperror(net, "my_find()");
+ /* module not pushed or does not exist */
+ }
+ /* p points to null or to an already pushed module, now push all
+ modules before this one */
+
+ for(p--; p >= modules; p--){
+ err = ioctl(fd, I_PUSH, *p);
+ if(err < 0 && errno != EINVAL)
+ fatalperror(net, "I_PUSH");
+ }
+}
+#endif
+
+/*
+ * getptyslave()
+ *
+ * Open the slave side of the pty, and do any initialization
+ * that is necessary. The return value is a file descriptor
+ * for the slave side.
+ */
+void getptyslave(void)
+{
+ int t = -1;
+
+ struct winsize ws;
+ extern int def_row, def_col;
+ extern int def_tspeed, def_rspeed;
+ /*
+ * Opening the slave side may cause initilization of the
+ * kernel tty structure. We need remember the state of
+ * if linemode was turned on
+ * terminal window size
+ * terminal speed
+ * so that we can re-set them if we need to.
+ */
+
+
+ /*
+ * Make sure that we don't have a controlling tty, and
+ * that we are the session (process group) leader.
+ */
+
+#ifdef HAVE_SETSID
+ if(setsid()<0)
+ fatalperror(net, "setsid()");
+#else
+# ifdef TIOCNOTTY
+ t = open(_PATH_TTY, O_RDWR);
+ if (t >= 0) {
+ ioctl(t, TIOCNOTTY, (char *)0);
+ close(t);
+ }
+# endif
+#endif
+
+# ifdef PARENT_DOES_UTMP
+ /*
+ * Wait for our parent to get the utmp stuff to get done.
+ */
+ utmp_sig_wait();
+# endif
+
+ t = cleanopen(line);
+ if (t < 0)
+ fatalperror(net, line);
+
+#ifdef STREAMSPTY
+ ttyfd = t;
+
+
+ /*
+ * Not all systems have (or need) modules ttcompat and pckt so
+ * don't flag it as a fatal error if they don't exist.
+ */
+
+ if (really_stream)
+ {
+ /* these are the streams modules that we want pushed. note
+ that they are in reverse order, ptem will be pushed
+ first. maybe_push_modules() will try to push all modules
+ before the first one that isn't already pushed. i.e if
+ ldterm is pushed, only ttcompat will be attempted.
+
+ all this is because we don't know which modules are
+ available, and we don't know which modules are already
+ pushed (via autopush, for instance).
+
+ */
+
+ char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL };
+ char *ptymodules[] = { "pckt", NULL };
+
+ maybe_push_modules(t, ttymodules);
+ maybe_push_modules(ourpty, ptymodules);
+ }
+#endif
+ /*
+ * set up the tty modes as we like them to be.
+ */
+ init_termbuf();
+# ifdef TIOCSWINSZ
+ if (def_row || def_col) {
+ memset(&ws, 0, sizeof(ws));
+ ws.ws_col = def_col;
+ ws.ws_row = def_row;
+ ioctl(t, TIOCSWINSZ, (char *)&ws);
+ }
+# endif
+
+ /*
+ * Settings for sgtty based systems
+ */
+
+ /*
+ * Settings for UNICOS (and HPUX)
+ */
+# if defined(_CRAY) || defined(__hpux)
+ termbuf.c_oflag = OPOST|ONLCR|TAB3;
+ termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
+ termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
+ termbuf.c_cflag = EXTB|HUPCL|CS8;
+# endif
+
+ /*
+ * Settings for all other termios/termio based
+ * systems, other than 4.4BSD. In 4.4BSD the
+ * kernel does the initial terminal setup.
+ */
+# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)
+# ifndef OXTABS
+# define OXTABS 0
+# endif
+ termbuf.c_lflag |= ECHO;
+ termbuf.c_oflag |= ONLCR|OXTABS;
+ termbuf.c_iflag |= ICRNL;
+ termbuf.c_iflag &= ~IXOFF;
+# endif
+ tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
+ tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
+
+ /*
+ * Set the tty modes, and make this our controlling tty.
+ */
+ set_termbuf();
+ if (login_tty(t) == -1)
+ fatalperror(net, "login_tty");
+ if (net > 2)
+ close(net);
+ if (ourpty > 2) {
+ close(ourpty);
+ ourpty = -1;
+ }
+}
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+/*
+ * Open the specified slave side of the pty,
+ * making sure that we have a clean tty.
+ */
+
+int cleanopen(char *line)
+{
+ int t;
+
+#ifdef STREAMSPTY
+ if (!really_stream)
+#endif
+ {
+ /*
+ * Make sure that other people can't open the
+ * slave side of the connection.
+ */
+ chown(line, 0, 0);
+ chmod(line, 0600);
+ }
+
+#ifdef HAVE_REVOKE
+ revoke(line);
+#endif
+
+ t = open(line, O_RDWR|O_NOCTTY);
+
+ if (t < 0)
+ return(-1);
+
+ /*
+ * Hangup anybody else using this ttyp, then reopen it for
+ * ourselves.
+ */
+# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
+ signal(SIGHUP, SIG_IGN);
+#ifdef HAVE_VHANGUP
+ vhangup();
+#else
+#endif
+ signal(SIGHUP, SIG_DFL);
+ t = open(line, O_RDWR|O_NOCTTY);
+ if (t < 0)
+ return(-1);
+# endif
+# if defined(_CRAY) && defined(TCVHUP)
+ {
+ int i;
+ signal(SIGHUP, SIG_IGN);
+ ioctl(t, TCVHUP, (char *)0);
+ signal(SIGHUP, SIG_DFL);
+
+ i = open(line, O_RDWR);
+
+ if (i < 0)
+ return(-1);
+ close(t);
+ t = i;
+ }
+# endif /* defined(CRAY) && defined(TCVHUP) */
+ return(t);
+}
+
+#if !defined(BSD4_4)
+
+int login_tty(int t)
+{
+# if defined(TIOCSCTTY) && !defined(__hpux)
+ if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
+ fatalperror(net, "ioctl(sctty)");
+# ifdef _CRAY
+ /*
+ * Close the hard fd to /dev/ttypXXX, and re-open through
+ * the indirect /dev/tty interface.
+ */
+ close(t);
+ if ((t = open("/dev/tty", O_RDWR)) < 0)
+ fatalperror(net, "open(/dev/tty)");
+# endif
+# else
+ /*
+ * We get our controlling tty assigned as a side-effect
+ * of opening up a tty device. But on BSD based systems,
+ * this only happens if our process group is zero. The
+ * setsid() call above may have set our pgrp, so clear
+ * it out before opening the tty...
+ */
+#ifdef HAVE_SETPGID
+ setpgid(0, 0);
+#else
+ setpgrp(0, 0); /* if setpgid isn't available, setpgrp
+ probably takes arguments */
+#endif
+ close(open(line, O_RDWR));
+# endif
+ if (t != 0)
+ dup2(t, 0);
+ if (t != 1)
+ dup2(t, 1);
+ if (t != 2)
+ dup2(t, 2);
+ if (t > 2)
+ close(t);
+ return(0);
+}
+#endif /* BSD <= 43 */
+
+/*
+ * This comes from ../../bsd/tty.c and should not really be here.
+ */
+
+/*
+ * Clean the tty name. Return a pointer to the cleaned version.
+ */
+
+static char *
+clean_ttyname (char *tty)
+{
+ char *res = tty;
+
+ if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0)
+ res += strlen(_PATH_DEV);
+ if (strncmp (res, "pty/", 4) == 0)
+ res += 4;
+ if (strncmp (res, "ptym/", 5) == 0)
+ res += 5;
+ return res;
+}
+
+/*
+ * Generate a name usable as an `ut_id', typically without `tty'.
+ */
+
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+static char *
+make_id (char *tty)
+{
+ char *res = tty;
+
+ if (strncmp (res, "pts/", 4) == 0)
+ res += 4;
+ if (strncmp (res, "tty", 3) == 0)
+ res += 3;
+ return res;
+}
+#endif
+
+/*
+ * startslave(host)
+ *
+ * Given a hostname, do whatever
+ * is necessary to startup the login process on the slave side of the pty.
+ */
+
+/* ARGSUSED */
+void
+startslave(char *host, int autologin, char *autoname)
+{
+ int i;
+
+#ifdef AUTHENTICATION
+ if (!autoname || !autoname[0])
+ autologin = 0;
+
+ if (autologin < auth_level) {
+ fatal(net, "Authorization failed");
+ exit(1);
+ }
+#endif
+
+ {
+ char *tbuf =
+ "\r\n*** Connection not encrypted! "
+ "Communication may be eavesdropped. ***\r\n";
+#ifdef ENCRYPTION
+ if (!no_warn && (encrypt_output == 0 || decrypt_input == 0))
+#endif
+ writenet((unsigned char*)tbuf, strlen(tbuf));
+ }
+# ifdef PARENT_DOES_UTMP
+ utmp_sig_init();
+# endif /* PARENT_DOES_UTMP */
+
+ if ((i = fork()) < 0)
+ fatalperror(net, "fork");
+ if (i) {
+# ifdef PARENT_DOES_UTMP
+ /*
+ * Cray parent will create utmp entry for child and send
+ * signal to child to tell when done. Child waits for signal
+ * before doing anything important.
+ */
+ int pid = i;
+ void sigjob (int);
+
+ setpgrp();
+ utmp_sig_reset(); /* reset handler to default */
+ /*
+ * Create utmp entry for child
+ */
+ time(&wtmp.ut_time);
+ wtmp.ut_type = LOGIN_PROCESS;
+ wtmp.ut_pid = pid;
+ strncpy(wtmp.ut_user, "LOGIN", sizeof(wtmp.ut_user));
+ strncpy(wtmp.ut_host, host, sizeof(wtmp.ut_host));
+ strncpy(wtmp.ut_line, clean_ttyname(line), sizeof(wtmp.ut_line));
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+ strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id));
+#endif
+
+ pututline(&wtmp);
+ endutent();
+ if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
+ write(i, &wtmp, sizeof(struct utmp));
+ close(i);
+ }
+#ifdef _CRAY
+ signal(WJSIGNAL, sigjob);
+#endif
+ utmp_sig_notify(pid);
+# endif /* PARENT_DOES_UTMP */
+ } else {
+ getptyslave();
+ start_login(host, autologin, autoname);
+ /*NOTREACHED*/
+ }
+}
+
+char *envinit[3];
+extern char **environ;
+
+void
+init_env(void)
+{
+ extern char *getenv(const char *);
+ char **envp;
+
+ envp = envinit;
+ if ((*envp = getenv("TZ")))
+ *envp++ -= 3;
+#if defined(_CRAY) || defined(__hpux)
+ else
+ *envp++ = "TZ=GMT0";
+#endif
+ *envp = 0;
+ environ = envinit;
+}
+
+/*
+ * scrub_env()
+ *
+ * Remove variables from the environment that might cause login to
+ * behave in a bad manner. To avoid this, login should be staticly
+ * linked.
+ */
+
+static void scrub_env(void)
+{
+ static char *remove[] = { "LD_", "_RLD_", "LIBPATH=", "IFS=", NULL };
+
+ char **cpp, **cpp2;
+ char **p;
+
+ for (cpp2 = cpp = environ; *cpp; cpp++) {
+ for(p = remove; *p; p++)
+ if(strncmp(*cpp, *p, strlen(*p)) == 0)
+ break;
+ if(*p == NULL)
+ *cpp2++ = *cpp;
+ }
+ *cpp2 = 0;
+}
+
+
+struct arg_val {
+ int size;
+ int argc;
+ char **argv;
+};
+
+static int addarg(struct arg_val*, char*);
+
+/*
+ * start_login(host)
+ *
+ * Assuming that we are now running as a child processes, this
+ * function will turn us into the login process.
+ */
+
+void
+start_login(char *host, int autologin, char *name)
+{
+ struct arg_val argv;
+ char *user;
+
+#ifdef HAVE_UTMPX_H
+ int pid = getpid();
+ struct utmpx utmpx;
+ char *clean_tty;
+
+ /*
+ * Create utmp entry for child
+ */
+
+ clean_tty = clean_ttyname(line);
+ memset(&utmpx, 0, sizeof(utmpx));
+ strncpy(utmpx.ut_user, ".telnet", sizeof(utmpx.ut_user));
+ strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+ strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id));
+#endif
+ utmpx.ut_pid = pid;
+
+ utmpx.ut_type = LOGIN_PROCESS;
+
+ gettimeofday (&utmpx.ut_tv, NULL);
+ if (pututxline(&utmpx) == NULL)
+ fatal(net, "pututxline failed");
+#endif
+
+ scrub_env();
+
+ /*
+ * -h : pass on name of host.
+ * WARNING: -h is accepted by login if and only if
+ * getuid() == 0.
+ * -p : don't clobber the environment (so terminal type stays set).
+ *
+ * -f : force this login, he has already been authenticated
+ */
+
+ /* init argv structure */
+ argv.size=0;
+ argv.argc=0;
+ argv.argv=(char**)malloc(0); /*so we can call realloc later */
+ addarg(&argv, "login");
+ addarg(&argv, "-h");
+ addarg(&argv, host);
+ addarg(&argv, "-p");
+ if(name[0])
+ user = name;
+ else
+ user = getenv("USER");
+#ifdef AUTHENTICATION
+ if (auth_level < 0 || autologin != AUTH_VALID) {
+ if(!no_warn) {
+ printf("User not authenticated. ");
+ if (require_otp)
+ printf("Using one-time password\r\n");
+ else
+ printf("Using plaintext username and password\r\n");
+ }
+ if (require_otp) {
+ addarg(&argv, "-a");
+ addarg(&argv, "otp");
+ }
+ if(log_unauth)
+ syslog(LOG_INFO, "unauthenticated access from %s (%s)",
+ host, user ? user : "unknown user");
+ }
+ if (auth_level >= 0 && autologin == AUTH_VALID)
+ addarg(&argv, "-f");
+#endif
+ if(user){
+ addarg(&argv, "--");
+ addarg(&argv, strdup(user));
+ }
+ if (getenv("USER")) {
+ /*
+ * Assume that login will set the USER variable
+ * correctly. For SysV systems, this means that
+ * USER will no longer be set, just LOGNAME by
+ * login. (The problem is that if the auto-login
+ * fails, and the user then specifies a different
+ * account name, he can get logged in with both
+ * LOGNAME and USER in his environment, but the
+ * USER value will be wrong.
+ */
+ unsetenv("USER");
+ }
+ closelog();
+ /*
+ * This sleep(1) is in here so that telnetd can
+ * finish up with the tty. There's a race condition
+ * the login banner message gets lost...
+ */
+ sleep(1);
+
+ execv(new_login, argv.argv);
+
+ syslog(LOG_ERR, "%s: %m\n", new_login);
+ fatalperror(net, new_login);
+ /*NOTREACHED*/
+}
+
+
+
+static int addarg(struct arg_val *argv, char *val)
+{
+ if(argv->size <= argv->argc+1){
+ argv->argv = (char**)realloc(argv->argv, sizeof(char*) * (argv->size + 10));
+ if(argv->argv == NULL)
+ return 1; /* this should probably be handled better */
+ argv->size+=10;
+ }
+ argv->argv[argv->argc++]=val;
+ argv->argv[argv->argc]=NULL;
+ return 0;
+}
+
+
+/*
+ * rmut()
+ *
+ * This is the function called by cleanup() to
+ * remove the utmp entry for this person.
+ */
+
+#ifdef HAVE_UTMPX_H
+static void
+rmut(void)
+{
+ struct utmpx *utxp, utmpx;
+ char *clean_tty = clean_ttyname(line);
+
+ /*
+ * This updates the utmpx and utmp entries and make a wtmp/x entry
+ */
+
+ setutxent();
+ memset(&utmpx, 0, sizeof(utmpx));
+ strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));
+ utmpx.ut_type = LOGIN_PROCESS;
+ utxp = getutxline(&utmpx);
+ if (utxp) {
+ utxp->ut_user[0] = '\0';
+ utxp->ut_type = DEAD_PROCESS;
+#ifdef HAVE_STRUCT_UTMPX_UT_EXIT
+#ifdef _STRUCT___EXIT_STATUS
+ utxp->ut_exit.__e_termination = 0;
+ utxp->ut_exit.__e_exit = 0;
+#elif defined(__osf__) /* XXX */
+ utxp->ut_exit.ut_termination = 0;
+ utxp->ut_exit.ut_exit = 0;
+#else
+ utxp->ut_exit.e_termination = 0;
+ utxp->ut_exit.e_exit = 0;
+#endif
+#endif
+ gettimeofday(&utxp->ut_tv, NULL);
+ pututxline(utxp);
+#ifdef WTMPX_FILE
+ updwtmpx(WTMPX_FILE, utxp);
+#elif defined(WTMP_FILE)
+ /* This is a strange system with a utmpx and a wtmp! */
+ {
+ int f = open(wtmpf, O_WRONLY|O_APPEND);
+ struct utmp wtmp;
+ if (f >= 0) {
+ strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line));
+ strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name));
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host));
+#endif
+ time(&wtmp.ut_time);
+ write(f, &wtmp, sizeof(wtmp));
+ close(f);
+ }
+ }
+#else
+
+#endif
+ }
+ endutxent();
+} /* end of rmut */
+#endif
+
+#if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43
+static void
+rmut(void)
+{
+ int f;
+ int found = 0;
+ struct utmp *u, *utmp;
+ int nutmp;
+ struct stat statbf;
+ char *clean_tty = clean_ttyname(line);
+
+ f = open(utmpf, O_RDWR);
+ if (f >= 0) {
+ fstat(f, &statbf);
+ utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
+ if (!utmp)
+ syslog(LOG_ERR, "utmp malloc failed");
+ if (statbf.st_size && utmp) {
+ nutmp = read(f, utmp, (int)statbf.st_size);
+ nutmp /= sizeof(struct utmp);
+
+ for (u = utmp ; u < &utmp[nutmp] ; u++) {
+ if (strncmp(u->ut_line,
+ clean_tty,
+ sizeof(u->ut_line)) ||
+ u->ut_name[0]==0)
+ continue;
+ lseek(f, ((long)u)-((long)utmp), L_SET);
+ strncpy(u->ut_name, "", sizeof(u->ut_name));
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(u->ut_host, "", sizeof(u->ut_host));
+#endif
+ time(&u->ut_time);
+ write(f, u, sizeof(wtmp));
+ found++;
+ }
+ }
+ close(f);
+ }
+ if (found) {
+ f = open(wtmpf, O_WRONLY|O_APPEND);
+ if (f >= 0) {
+ strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line));
+ strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name));
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host));
+#endif
+ time(&wtmp.ut_time);
+ write(f, &wtmp, sizeof(wtmp));
+ close(f);
+ }
+ }
+ chmod(line, 0666);
+ chown(line, 0, 0);
+ line[strlen("/dev/")] = 'p';
+ chmod(line, 0666);
+ chown(line, 0, 0);
+} /* end of rmut */
+#endif /* CRAY */
+
+#if defined(__hpux) && !defined(HAVE_UTMPX_H)
+static void
+rmut (char *line)
+{
+ struct utmp utmp;
+ struct utmp *utptr;
+ int fd; /* for /etc/wtmp */
+
+ utmp.ut_type = USER_PROCESS;
+ strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line));
+ setutent();
+ utptr = getutline(&utmp);
+ /* write it out only if it exists */
+ if (utptr) {
+ utptr->ut_type = DEAD_PROCESS;
+ utptr->ut_time = time(NULL);
+ pututline(utptr);
+ /* set wtmp entry if wtmp file exists */
+ if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
+ write(fd, utptr, sizeof(utmp));
+ close(fd);
+ }
+ }
+ endutent();
+
+ chmod(line, 0666);
+ chown(line, 0, 0);
+ line[14] = line[13];
+ line[13] = line[12];
+ line[8] = 'm';
+ line[9] = '/';
+ line[10] = 'p';
+ line[11] = 't';
+ line[12] = 'y';
+ chmod(line, 0666);
+ chown(line, 0, 0);
+}
+#endif
+
+/*
+ * cleanup()
+ *
+ * This is the routine to call when we are all through, to
+ * clean up anything that needs to be cleaned up.
+ */
+
+#ifdef PARENT_DOES_UTMP
+
+void
+cleanup(int sig)
+{
+#ifdef _CRAY
+ static int incleanup = 0;
+ int t;
+ int child_status; /* status of child process as returned by waitpid */
+ int flags = WNOHANG|WUNTRACED;
+
+ /*
+ * 1: Pick up the zombie, if we are being called
+ * as the signal handler.
+ * 2: If we are a nested cleanup(), return.
+ * 3: Try to clean up TMPDIR.
+ * 4: Fill in utmp with shutdown of process.
+ * 5: Close down the network and pty connections.
+ * 6: Finish up the TMPDIR cleanup, if needed.
+ */
+ if (sig == SIGCHLD) {
+ while (waitpid(-1, &child_status, flags) > 0)
+ ; /* VOID */
+ /* Check if the child process was stopped
+ * rather than exited. We want cleanup only if
+ * the child has died.
+ */
+ if (WIFSTOPPED(child_status)) {
+ return;
+ }
+ }
+ t = sigblock(sigmask(SIGCHLD));
+ if (incleanup) {
+ sigsetmask(t);
+ return;
+ }
+ incleanup = 1;
+ sigsetmask(t);
+
+ t = cleantmp(&wtmp);
+ setutent(); /* just to make sure */
+#endif /* CRAY */
+ rmut(line);
+ close(ourpty);
+ shutdown(net, 2);
+#ifdef _CRAY
+ if (t == 0)
+ cleantmp(&wtmp);
+#endif /* CRAY */
+ exit(1);
+}
+
+#else /* PARENT_DOES_UTMP */
+
+void
+cleanup(int sig)
+{
+#if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP)
+ rmut();
+#ifdef HAVE_VHANGUP
+#ifndef __sgi
+ vhangup(); /* XXX */
+#endif
+#endif
+#else
+ char *p;
+
+ p = line + sizeof("/dev/") - 1;
+ if (logout(p))
+ logwtmp(p, "", "");
+ chmod(line, 0666);
+ chown(line, 0, 0);
+ *p = 'p';
+ chmod(line, 0666);
+ chown(line, 0, 0);
+#endif
+ shutdown(net, 2);
+ exit(1);
+}
+
+#endif /* PARENT_DOES_UTMP */
+
+#ifdef PARENT_DOES_UTMP
+/*
+ * _utmp_sig_rcv
+ * utmp_sig_init
+ * utmp_sig_wait
+ * These three functions are used to coordinate the handling of
+ * the utmp file between the server and the soon-to-be-login shell.
+ * The server actually creates the utmp structure, the child calls
+ * utmp_sig_wait(), until the server calls utmp_sig_notify() and
+ * signals the future-login shell to proceed.
+ */
+static int caught=0; /* NZ when signal intercepted */
+static void (*func)(); /* address of previous handler */
+
+void
+_utmp_sig_rcv(sig)
+ int sig;
+{
+ caught = 1;
+ signal(SIGUSR1, func);
+}
+
+void
+utmp_sig_init()
+{
+ /*
+ * register signal handler for UTMP creation
+ */
+ if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
+ fatalperror(net, "telnetd/signal");
+}
+
+void
+utmp_sig_reset()
+{
+ signal(SIGUSR1, func); /* reset handler to default */
+}
+
+# ifdef __hpux
+# define sigoff() /* do nothing */
+# define sigon() /* do nothing */
+# endif
+
+void
+utmp_sig_wait()
+{
+ /*
+ * Wait for parent to write our utmp entry.
+ */
+ sigoff();
+ while (caught == 0) {
+ pause(); /* wait until we get a signal (sigon) */
+ sigoff(); /* turn off signals while we check caught */
+ }
+ sigon(); /* turn on signals again */
+}
+
+void
+utmp_sig_notify(pid)
+{
+ kill(pid, SIGUSR1);
+}
+
+#ifdef _CRAY
+static int gotsigjob = 0;
+
+ /*ARGSUSED*/
+void
+sigjob(sig)
+ int sig;
+{
+ int jid;
+ struct jobtemp *jp;
+
+ while ((jid = waitjob(NULL)) != -1) {
+ if (jid == 0) {
+ return;
+ }
+ gotsigjob++;
+ jobend(jid, NULL, NULL);
+ }
+}
+
+/*
+ * jid_getutid:
+ * called by jobend() before calling cleantmp()
+ * to find the correct $TMPDIR to cleanup.
+ */
+
+struct utmp *
+jid_getutid(jid)
+ int jid;
+{
+ struct utmp *cur = NULL;
+
+ setutent(); /* just to make sure */
+ while (cur = getutent()) {
+ if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
+ return(cur);
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * Clean up the TMPDIR that login created.
+ * The first time this is called we pick up the info
+ * from the utmp. If the job has already gone away,
+ * then we'll clean up and be done. If not, then
+ * when this is called the second time it will wait
+ * for the signal that the job is done.
+ */
+int
+cleantmp(wtp)
+ struct utmp *wtp;
+{
+ struct utmp *utp;
+ static int first = 1;
+ int mask, omask, ret;
+ extern struct utmp *getutid (const struct utmp *_Id);
+
+
+ mask = sigmask(WJSIGNAL);
+
+ if (first == 0) {
+ omask = sigblock(mask);
+ while (gotsigjob == 0)
+ sigpause(omask);
+ return(1);
+ }
+ first = 0;
+ setutent(); /* just to make sure */
+
+ utp = getutid(wtp);
+ if (utp == 0) {
+ syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
+ return(-1);
+ }
+ /*
+ * Nothing to clean up if the user shell was never started.
+ */
+ if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
+ return(1);
+
+ /*
+ * Block the WJSIGNAL while we are in jobend().
+ */
+ omask = sigblock(mask);
+ ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
+ sigsetmask(omask);
+ return(ret);
+}
+
+int
+jobend(jid, path, user)
+ int jid;
+ char *path;
+ char *user;
+{
+ static int saved_jid = 0;
+ static int pty_saved_jid = 0;
+ static char saved_path[sizeof(wtmp.ut_tpath)+1];
+ static char saved_user[sizeof(wtmp.ut_user)+1];
+
+ /*
+ * this little piece of code comes into play
+ * only when ptyreconnect is used to reconnect
+ * to an previous session.
+ *
+ * this is the only time when the
+ * "saved_jid != jid" code is executed.
+ */
+
+ if ( saved_jid && saved_jid != jid ) {
+ if (!path) { /* called from signal handler */
+ pty_saved_jid = jid;
+ } else {
+ pty_saved_jid = saved_jid;
+ }
+ }
+
+ if (path) {
+ strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
+ strncpy(saved_user, user, sizeof(wtmp.ut_user));
+ saved_path[sizeof(saved_path)] = '\0';
+ saved_user[sizeof(saved_user)] = '\0';
+ }
+ if (saved_jid == 0) {
+ saved_jid = jid;
+ return(0);
+ }
+
+ /* if the jid has changed, get the correct entry from the utmp file */
+
+ if ( saved_jid != jid ) {
+ struct utmp *utp = NULL;
+ struct utmp *jid_getutid();
+
+ utp = jid_getutid(pty_saved_jid);
+
+ if (utp == 0) {
+ syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
+ return(-1);
+ }
+
+ cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
+ return(1);
+ }
+
+ cleantmpdir(jid, saved_path, saved_user);
+ return(1);
+}
+
+/*
+ * Fork a child process to clean up the TMPDIR
+ */
+cleantmpdir(jid, tpath, user)
+ int jid;
+ char *tpath;
+ char *user;
+{
+ switch(fork()) {
+ case -1:
+ syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
+ tpath);
+ break;
+ case 0:
+ execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
+ syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
+ tpath, CLEANTMPCMD);
+ exit(1);
+ default:
+ /*
+ * Forget about child. We will exit, and
+ * /etc/init will pick it up.
+ */
+ break;
+ }
+}
+#endif /* CRAY */
+#endif /* defined(PARENT_DOES_UTMP) */
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/telnetd.c b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.c
new file mode 100644
index 0000000..73008a3
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.c
@@ -0,0 +1,1357 @@
+/*
+ * 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: telnetd.c,v 1.53 1999/03/15 16:40:52 joda Exp $");
+
+#ifdef _SC_CRAY_SECURE_SYS
+#include <sys/sysv.h>
+#include <sys/secdev.h>
+#include <sys/secparm.h>
+#include <sys/usrv.h>
+int secflag;
+char tty_dev[16];
+struct secdev dv;
+struct sysv sysv;
+struct socksec ss;
+#endif /* _SC_CRAY_SECURE_SYS */
+
+#ifdef AUTHENTICATION
+int auth_level = 0;
+#endif
+
+extern int utmp_len;
+int registerd_host_only = 0;
+
+#ifdef STREAMSPTY
+# include <stropts.h>
+# include <termios.h>
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif /* HAVE_SYS_UIO_H */
+#ifdef HAVE_SYS_STREAM_H
+#include <sys/stream.h>
+#endif
+#ifdef _AIX
+#include <sys/termio.h>
+#endif
+# ifdef HAVE_SYS_STRTTY_H
+# include <sys/strtty.h>
+# endif
+# ifdef HAVE_SYS_STR_TTY_H
+# include <sys/str_tty.h>
+# endif
+/* make sure we don't get the bsd version */
+/* what is this here for? solaris? /joda */
+# ifdef HAVE_SYS_TTY_H
+# include "/usr/include/sys/tty.h"
+# endif
+# ifdef HAVE_SYS_PTYVAR_H
+# include <sys/ptyvar.h>
+# endif
+
+/*
+ * Because of the way ptyibuf is used with streams messages, we need
+ * ptyibuf+1 to be on a full-word boundary. The following wierdness
+ * is simply to make that happen.
+ */
+long ptyibufbuf[BUFSIZ/sizeof(long)+1];
+char *ptyibuf = ((char *)&ptyibufbuf[1])-1;
+char *ptyip = ((char *)&ptyibufbuf[1])-1;
+char ptyibuf2[BUFSIZ];
+unsigned char ctlbuf[BUFSIZ];
+struct strbuf strbufc, strbufd;
+
+int readstream(int, char*, int);
+
+#else /* ! STREAMPTY */
+
+/*
+ * I/O data buffers,
+ * pointers, and counters.
+ */
+char ptyibuf[BUFSIZ], *ptyip = ptyibuf;
+char ptyibuf2[BUFSIZ];
+
+#endif /* ! STREAMPTY */
+
+int hostinfo = 1; /* do we print login banner? */
+
+#ifdef _CRAY
+extern int newmap; /* nonzero if \n maps to ^M^J */
+int lowpty = 0, highpty; /* low, high pty numbers */
+#endif /* CRAY */
+
+int debug = 0;
+int keepalive = 1;
+char *progname;
+
+extern void usage (void);
+
+/*
+ * The string to pass to getopt(). We do it this way so
+ * that only the actual options that we support will be
+ * passed off to getopt().
+ */
+char valid_opts[] = "Bd:hklnS:u:UL:y"
+#ifdef AUTHENTICATION
+ "a:X:z"
+#endif
+#ifdef DIAGNOSTICS
+ "D:"
+#endif
+#ifdef _CRAY
+ "r:"
+#endif
+ ;
+
+void doit(struct sockaddr_in*);
+
+int main(int argc, char **argv)
+{
+ struct sockaddr_in from;
+ int on = 1, fromlen;
+ int ch;
+#if defined(IPPROTO_IP) && defined(IP_TOS)
+ int tos = -1;
+#endif
+#ifdef ENCRYPTION
+ extern int des_check_key;
+ des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */
+#endif
+ pfrontp = pbackp = ptyobuf;
+ netip = netibuf;
+ nfrontp = nbackp = netobuf;
+
+ progname = *argv;
+#ifdef ENCRYPTION
+ nclearto = 0;
+#endif
+
+#ifdef _CRAY
+ /*
+ * Get number of pty's before trying to process options,
+ * which may include changing pty range.
+ */
+ highpty = getnpty();
+#endif /* CRAY */
+
+ while ((ch = getopt(argc, argv, valid_opts)) != EOF) {
+ switch(ch) {
+
+#ifdef AUTHENTICATION
+ case 'a':
+ /*
+ * Check for required authentication level
+ */
+ if (strcmp(optarg, "debug") == 0) {
+ auth_debug_mode = 1;
+ } else if (strcasecmp(optarg, "none") == 0) {
+ auth_level = 0;
+ } else if (strcasecmp(optarg, "otp") == 0) {
+ auth_level = 0;
+ require_otp = 1;
+ } else if (strcasecmp(optarg, "other") == 0) {
+ auth_level = AUTH_OTHER;
+ } else if (strcasecmp(optarg, "user") == 0) {
+ auth_level = AUTH_USER;
+ } else if (strcasecmp(optarg, "valid") == 0) {
+ auth_level = AUTH_VALID;
+ } else if (strcasecmp(optarg, "off") == 0) {
+ /*
+ * This hack turns off authentication
+ */
+ auth_level = -1;
+ } else {
+ fprintf(stderr,
+ "telnetd: unknown authorization level for -a\n");
+ }
+ break;
+#endif /* AUTHENTICATION */
+
+ case 'B': /* BFTP mode is not supported any more */
+ break;
+ case 'd':
+ if (strcmp(optarg, "ebug") == 0) {
+ debug++;
+ break;
+ }
+ usage();
+ /* NOTREACHED */
+ break;
+
+#ifdef DIAGNOSTICS
+ case 'D':
+ /*
+ * Check for desired diagnostics capabilities.
+ */
+ if (!strcmp(optarg, "report")) {
+ diagnostic |= TD_REPORT|TD_OPTIONS;
+ } else if (!strcmp(optarg, "exercise")) {
+ diagnostic |= TD_EXERCISE;
+ } else if (!strcmp(optarg, "netdata")) {
+ diagnostic |= TD_NETDATA;
+ } else if (!strcmp(optarg, "ptydata")) {
+ diagnostic |= TD_PTYDATA;
+ } else if (!strcmp(optarg, "options")) {
+ diagnostic |= TD_OPTIONS;
+ } else {
+ usage();
+ /* NOT REACHED */
+ }
+ break;
+#endif /* DIAGNOSTICS */
+
+
+ case 'h':
+ hostinfo = 0;
+ break;
+
+ case 'k': /* Linemode is not supported any more */
+ case 'l':
+ break;
+
+ case 'n':
+ keepalive = 0;
+ break;
+
+#ifdef _CRAY
+ case 'r':
+ {
+ char *strchr();
+ char *c;
+
+ /*
+ * Allow the specification of alterations
+ * to the pty search range. It is legal to
+ * specify only one, and not change the
+ * other from its default.
+ */
+ c = strchr(optarg, '-');
+ if (c) {
+ *c++ = '\0';
+ highpty = atoi(c);
+ }
+ if (*optarg != '\0')
+ lowpty = atoi(optarg);
+ if ((lowpty > highpty) || (lowpty < 0) ||
+ (highpty > 32767)) {
+ usage();
+ /* NOT REACHED */
+ }
+ break;
+ }
+#endif /* CRAY */
+
+ case 'S':
+#ifdef HAVE_PARSETOS
+ if ((tos = parsetos(optarg, "tcp")) < 0)
+ fprintf(stderr, "%s%s%s\n",
+ "telnetd: Bad TOS argument '", optarg,
+ "'; will try to use default TOS");
+#else
+ fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
+ "-S flag not supported\n");
+#endif
+ break;
+
+ case 'u':
+ utmp_len = atoi(optarg);
+ break;
+
+ case 'U':
+ registerd_host_only = 1;
+ break;
+
+#ifdef AUTHENTICATION
+ case 'X':
+ /*
+ * Check for invalid authentication types
+ */
+ auth_disable_name(optarg);
+ break;
+#endif
+ case 'y':
+ no_warn = 1;
+ break;
+#ifdef AUTHENTICATION
+ case 'z':
+ log_unauth = 1;
+ break;
+
+#endif /* AUTHENTICATION */
+
+ case 'L':
+ new_login = optarg;
+ break;
+
+ default:
+ fprintf(stderr, "telnetd: %c: unknown option\n", ch);
+ /* FALLTHROUGH */
+ case '?':
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (debug) {
+ int port = 0;
+ struct servent *sp;
+
+ if (argc > 1) {
+ usage ();
+ } else if (argc == 1) {
+ sp = roken_getservbyname (*argv, "tcp");
+ if (sp)
+ port = sp->s_port;
+ else
+ port = htons(atoi(*argv));
+ } else {
+#ifdef KRB5
+ port = krb5_getportbyname (NULL, "telnet", "tcp", 23);
+#else
+ port = k_getportbyname("telnet", "tcp", htons(23));
+#endif
+ }
+ mini_inetd (port);
+ } else if (argc > 0) {
+ usage();
+ /* NOT REACHED */
+ }
+
+#ifdef _SC_CRAY_SECURE_SYS
+ secflag = sysconf(_SC_CRAY_SECURE_SYS);
+
+ /*
+ * Get socket's security label
+ */
+ if (secflag) {
+ int szss = sizeof(ss);
+ int sock_multi;
+ int szi = sizeof(int);
+
+ memset(&dv, 0, sizeof(dv));
+
+ if (getsysv(&sysv, sizeof(struct sysv)) != 0)
+ fatalperror(net, "getsysv");
+
+ /*
+ * Get socket security label and set device values
+ * {security label to be set on ttyp device}
+ */
+#ifdef SO_SEC_MULTI /* 8.0 code */
+ if ((getsockopt(0, SOL_SOCKET, SO_SECURITY,
+ (void *)&ss, &szss) < 0) ||
+ (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI,
+ (void *)&sock_multi, &szi) < 0))
+ fatalperror(net, "getsockopt");
+ else {
+ dv.dv_actlvl = ss.ss_actlabel.lt_level;
+ dv.dv_actcmp = ss.ss_actlabel.lt_compart;
+ if (!sock_multi) {
+ dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl;
+ dv.dv_valcmp = dv.dv_actcmp;
+ } else {
+ dv.dv_minlvl = ss.ss_minlabel.lt_level;
+ dv.dv_maxlvl = ss.ss_maxlabel.lt_level;
+ dv.dv_valcmp = ss.ss_maxlabel.lt_compart;
+ }
+ dv.dv_devflg = 0;
+ }
+#else /* SO_SEC_MULTI */ /* 7.0 code */
+ if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
+ (void *)&ss, &szss) >= 0) {
+ dv.dv_actlvl = ss.ss_slevel;
+ dv.dv_actcmp = ss.ss_compart;
+ dv.dv_minlvl = ss.ss_minlvl;
+ dv.dv_maxlvl = ss.ss_maxlvl;
+ dv.dv_valcmp = ss.ss_maxcmp;
+ }
+#endif /* SO_SEC_MULTI */
+ }
+#endif /* _SC_CRAY_SECURE_SYS */
+
+ roken_openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+ fromlen = sizeof (from);
+ if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
+ fprintf(stderr, "%s: ", progname);
+ perror("getpeername");
+ _exit(1);
+ }
+ if (keepalive &&
+ setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
+ (void *)&on, sizeof (on)) < 0) {
+ syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+ }
+
+#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ {
+# ifdef HAVE_GETTOSBYNAME
+ struct tosent *tp;
+ if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+ tos = tp->t_tos;
+# endif
+ if (tos < 0)
+ tos = 020; /* Low Delay bit */
+ if (tos
+ && (setsockopt(0, IPPROTO_IP, IP_TOS,
+ (void *)&tos, sizeof(tos)) < 0)
+ && (errno != ENOPROTOOPT) )
+ syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+ }
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+ net = 0;
+ doit(&from);
+ /* NOTREACHED */
+ return 0;
+} /* end of main */
+
+void
+usage()
+{
+ fprintf(stderr, "Usage: telnetd");
+#ifdef AUTHENTICATION
+ fprintf(stderr, " [-a (debug|other|otp|user|valid|off|none)]\n\t");
+#endif
+ fprintf(stderr, " [-debug]");
+#ifdef DIAGNOSTICS
+ fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
+#endif
+#ifdef AUTHENTICATION
+ fprintf(stderr, " [-edebug]");
+#endif
+ fprintf(stderr, " [-h]");
+ fprintf(stderr, " [-L login]");
+ fprintf(stderr, " [-n]");
+#ifdef _CRAY
+ fprintf(stderr, " [-r[lowpty]-[highpty]]");
+#endif
+ fprintf(stderr, "\n\t");
+#ifdef HAVE_GETTOSBYNAME
+ fprintf(stderr, " [-S tos]");
+#endif
+#ifdef AUTHENTICATION
+ fprintf(stderr, " [-X auth-type] [-y] [-z]");
+#endif
+ fprintf(stderr, " [-u utmp_hostname_length] [-U]");
+ fprintf(stderr, " [port]\n");
+ exit(1);
+}
+
+/*
+ * getterminaltype
+ *
+ * Ask the other end to send along its terminal type and speed.
+ * Output is the variable terminaltype filled in.
+ */
+static unsigned char ttytype_sbbuf[] = {
+ IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
+};
+
+int
+getterminaltype(char *name, size_t name_sz)
+{
+ int retval = -1;
+ void _gettermname();
+
+ settimer(baseline);
+#ifdef AUTHENTICATION
+ /*
+ * Handle the Authentication option before we do anything else.
+ */
+ send_do(TELOPT_AUTHENTICATION, 1);
+ while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
+ ttloop();
+ if (his_state_is_will(TELOPT_AUTHENTICATION)) {
+ retval = auth_wait(name, name_sz);
+ }
+#endif
+
+#ifdef ENCRYPTION
+ send_will(TELOPT_ENCRYPT, 1);
+ send_do(TELOPT_ENCRYPT, 1); /* esc@magic.fi */
+#endif
+ send_do(TELOPT_TTYPE, 1);
+ send_do(TELOPT_TSPEED, 1);
+ send_do(TELOPT_XDISPLOC, 1);
+ send_do(TELOPT_NEW_ENVIRON, 1);
+ send_do(TELOPT_OLD_ENVIRON, 1);
+ while (
+#ifdef ENCRYPTION
+ his_do_dont_is_changing(TELOPT_ENCRYPT) ||
+#endif
+ his_will_wont_is_changing(TELOPT_TTYPE) ||
+ his_will_wont_is_changing(TELOPT_TSPEED) ||
+ his_will_wont_is_changing(TELOPT_XDISPLOC) ||
+ his_will_wont_is_changing(TELOPT_NEW_ENVIRON) ||
+ his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) {
+ ttloop();
+ }
+#ifdef ENCRYPTION
+ /*
+ * Wait for the negotiation of what type of encryption we can
+ * send with. If autoencrypt is not set, this will just return.
+ */
+ if (his_state_is_will(TELOPT_ENCRYPT)) {
+ encrypt_wait();
+ }
+#endif
+ if (his_state_is_will(TELOPT_TSPEED)) {
+ static unsigned char sb[] =
+ { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
+
+ telnet_net_write (sb, sizeof sb);
+ DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+ }
+ if (his_state_is_will(TELOPT_XDISPLOC)) {
+ static unsigned char sb[] =
+ { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
+
+ telnet_net_write (sb, sizeof sb);
+ DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+ }
+ if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
+ static unsigned char sb[] =
+ { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
+
+ telnet_net_write (sb, sizeof sb);
+ DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+ }
+ else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
+ static unsigned char sb[] =
+ { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
+
+ telnet_net_write (sb, sizeof sb);
+ DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
+ }
+ if (his_state_is_will(TELOPT_TTYPE)) {
+
+ telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);
+ DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
+ sizeof ttytype_sbbuf - 2););
+ }
+ if (his_state_is_will(TELOPT_TSPEED)) {
+ while (sequenceIs(tspeedsubopt, baseline))
+ ttloop();
+ }
+ if (his_state_is_will(TELOPT_XDISPLOC)) {
+ while (sequenceIs(xdisplocsubopt, baseline))
+ ttloop();
+ }
+ if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
+ while (sequenceIs(environsubopt, baseline))
+ ttloop();
+ }
+ if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
+ while (sequenceIs(oenvironsubopt, baseline))
+ ttloop();
+ }
+ if (his_state_is_will(TELOPT_TTYPE)) {
+ char first[256], last[256];
+
+ while (sequenceIs(ttypesubopt, baseline))
+ ttloop();
+
+ /*
+ * If the other side has already disabled the option, then
+ * we have to just go with what we (might) have already gotten.
+ */
+ if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
+ strcpy_truncate(first, terminaltype, sizeof(first));
+ for(;;) {
+ /*
+ * Save the unknown name, and request the next name.
+ */
+ strcpy_truncate(last, terminaltype, sizeof(last));
+ _gettermname();
+ if (terminaltypeok(terminaltype))
+ break;
+ if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
+ his_state_is_wont(TELOPT_TTYPE)) {
+ /*
+ * We've hit the end. If this is the same as
+ * the first name, just go with it.
+ */
+ if (strncmp(first, terminaltype, sizeof(first)) == 0)
+ break;
+ /*
+ * Get the terminal name one more time, so that
+ * RFC1091 compliant telnets will cycle back to
+ * the start of the list.
+ */
+ _gettermname();
+ if (strncmp(first, terminaltype, sizeof(first)) != 0)
+ strcpy(terminaltype, first);
+ break;
+ }
+ }
+ }
+ }
+ return(retval);
+} /* end of getterminaltype */
+
+void
+_gettermname()
+{
+ /*
+ * If the client turned off the option,
+ * we can't send another request, so we
+ * just return.
+ */
+ if (his_state_is_wont(TELOPT_TTYPE))
+ return;
+ settimer(baseline);
+ telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);
+ DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
+ sizeof ttytype_sbbuf - 2););
+ while (sequenceIs(ttypesubopt, baseline))
+ ttloop();
+}
+
+int
+terminaltypeok(char *s)
+{
+ return 1;
+}
+
+
+char *hostname;
+char host_name[MaxHostNameLen];
+char remote_host_name[MaxHostNameLen];
+
+/*
+ * Get a pty, scan input lines.
+ */
+void
+doit(struct sockaddr_in *who)
+{
+ char *host = NULL;
+ struct hostent *hp;
+ int level;
+ int ptynum;
+ char user_name[256];
+
+ /*
+ * Find an available pty to use.
+ */
+ ourpty = getpty(&ptynum);
+ if (ourpty < 0)
+ fatal(net, "All network ports in use");
+
+#ifdef _SC_CRAY_SECURE_SYS
+ /*
+ * set ttyp line security label
+ */
+ if (secflag) {
+ char slave_dev[16];
+
+ snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum);
+ if (setdevs(tty_dev, &dv) < 0)
+ fatal(net, "cannot set pty security");
+ snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum);
+ if (setdevs(slave_dev, &dv) < 0)
+ fatal(net, "cannot set tty security");
+ }
+#endif /* _SC_CRAY_SECURE_SYS */
+
+ /* get name of connected client */
+ hp = roken_gethostbyaddr((const char *)&who->sin_addr,
+ sizeof (struct in_addr),
+ who->sin_family);
+
+ if (hp == NULL && registerd_host_only) {
+ fatal(net, "Couldn't resolve your address into a host name.\r\n\
+Please contact your net administrator");
+ } else if (hp) {
+ host = hp->h_name;
+ } else {
+ host = inet_ntoa(who->sin_addr);
+ }
+ /*
+ * We must make a copy because Kerberos is probably going
+ * to also do a gethost* and overwrite the static data...
+ */
+ strcpy_truncate(remote_host_name, host, sizeof(remote_host_name));
+ host = remote_host_name;
+
+ /* XXX - should be k_gethostname? */
+ gethostname(host_name, sizeof (host_name));
+ hostname = host_name;
+
+ /* Only trim if too long (and possible) */
+ if (strlen(remote_host_name) > abs(utmp_len)) {
+ char *domain = strchr(host_name, '.');
+ char *p = strchr(remote_host_name, '.');
+ if (domain && p && (strcmp(p, domain) == 0))
+ *p = 0; /* remove domain part */
+ }
+
+
+ /*
+ * If hostname still doesn't fit utmp, use ipaddr.
+ */
+ if (strlen(remote_host_name) > abs(utmp_len))
+ strcpy_truncate(remote_host_name,
+ inet_ntoa(who->sin_addr),
+ sizeof(remote_host_name));
+
+#ifdef AUTHENTICATION
+ auth_encrypt_init(hostname, host, "TELNETD", 1);
+#endif
+
+ init_env();
+ /*
+ * get terminal type.
+ */
+ *user_name = 0;
+ level = getterminaltype(user_name, sizeof(user_name));
+ setenv("TERM", terminaltype ? terminaltype : "network", 1);
+
+#ifdef _SC_CRAY_SECURE_SYS
+ if (secflag) {
+ if (setulvl(dv.dv_actlvl) < 0)
+ fatal(net,"cannot setulvl()");
+ if (setucmp(dv.dv_actcmp) < 0)
+ fatal(net, "cannot setucmp()");
+ }
+#endif /* _SC_CRAY_SECURE_SYS */
+
+ /* begin server processing */
+ my_telnet(net, ourpty, host, level, user_name);
+ /*NOTREACHED*/
+} /* end of doit */
+
+/* output contents of /etc/issue.net, or /etc/issue */
+static void
+show_issue(void)
+{
+ FILE *f;
+ char buf[128];
+ f = fopen("/etc/issue.net", "r");
+ if(f == NULL)
+ f = fopen("/etc/issue", "r");
+ if(f){
+ while(fgets(buf, sizeof(buf)-2, f)){
+ strcpy(buf + strcspn(buf, "\r\n"), "\r\n");
+ writenet((unsigned char*)buf, strlen(buf));
+ }
+ fclose(f);
+ }
+}
+
+/*
+ * Main loop. Select from pty and network, and
+ * hand data to telnet receiver finite state machine.
+ */
+void
+my_telnet(int f, int p, char *host, int level, char *autoname)
+{
+ int on = 1;
+ char *he;
+ char *IM;
+ int nfd;
+ int startslave_called = 0;
+ time_t timeout;
+
+ /*
+ * Initialize the slc mapping table.
+ */
+ get_slc_defaults();
+
+ /*
+ * Do some tests where it is desireable to wait for a response.
+ * Rather than doing them slowly, one at a time, do them all
+ * at once.
+ */
+ if (my_state_is_wont(TELOPT_SGA))
+ send_will(TELOPT_SGA, 1);
+ /*
+ * Is the client side a 4.2 (NOT 4.3) system? We need to know this
+ * because 4.2 clients are unable to deal with TCP urgent data.
+ *
+ * To find out, we send out a "DO ECHO". If the remote system
+ * answers "WILL ECHO" it is probably a 4.2 client, and we note
+ * that fact ("WILL ECHO" ==> that the client will echo what
+ * WE, the server, sends it; it does NOT mean that the client will
+ * echo the terminal input).
+ */
+ send_do(TELOPT_ECHO, 1);
+
+ /*
+ * Send along a couple of other options that we wish to negotiate.
+ */
+ send_do(TELOPT_NAWS, 1);
+ send_will(TELOPT_STATUS, 1);
+ flowmode = 1; /* default flow control state */
+ restartany = -1; /* uninitialized... */
+ send_do(TELOPT_LFLOW, 1);
+
+ /*
+ * Spin, waiting for a response from the DO ECHO. However,
+ * some REALLY DUMB telnets out there might not respond
+ * to the DO ECHO. So, we spin looking for NAWS, (most dumb
+ * telnets so far seem to respond with WONT for a DO that
+ * they don't understand...) because by the time we get the
+ * response, it will already have processed the DO ECHO.
+ * Kludge upon kludge.
+ */
+ while (his_will_wont_is_changing(TELOPT_NAWS))
+ ttloop();
+
+ /*
+ * But...
+ * The client might have sent a WILL NAWS as part of its
+ * startup code; if so, we'll be here before we get the
+ * response to the DO ECHO. We'll make the assumption
+ * that any implementation that understands about NAWS
+ * is a modern enough implementation that it will respond
+ * to our DO ECHO request; hence we'll do another spin
+ * waiting for the ECHO option to settle down, which is
+ * what we wanted to do in the first place...
+ */
+ if (his_want_state_is_will(TELOPT_ECHO) &&
+ his_state_is_will(TELOPT_NAWS)) {
+ while (his_will_wont_is_changing(TELOPT_ECHO))
+ ttloop();
+ }
+ /*
+ * On the off chance that the telnet client is broken and does not
+ * respond to the DO ECHO we sent, (after all, we did send the
+ * DO NAWS negotiation after the DO ECHO, and we won't get here
+ * until a response to the DO NAWS comes back) simulate the
+ * receipt of a will echo. This will also send a WONT ECHO
+ * to the client, since we assume that the client failed to
+ * respond because it believes that it is already in DO ECHO
+ * mode, which we do not want.
+ */
+ if (his_want_state_is_will(TELOPT_ECHO)) {
+ DIAG(TD_OPTIONS,
+ {output_data("td: simulating recv\r\n");
+ });
+ willoption(TELOPT_ECHO);
+ }
+
+ /*
+ * Finally, to clean things up, we turn on our echo. This
+ * will break stupid 4.2 telnets out of local terminal echo.
+ */
+
+ if (my_state_is_wont(TELOPT_ECHO))
+ send_will(TELOPT_ECHO, 1);
+
+#ifdef TIOCPKT
+#ifdef STREAMSPTY
+ if (!really_stream)
+#endif
+ /*
+ * Turn on packet mode
+ */
+ ioctl(p, TIOCPKT, (char *)&on);
+#endif
+
+
+ /*
+ * Call telrcv() once to pick up anything received during
+ * terminal type negotiation, 4.2/4.3 determination, and
+ * linemode negotiation.
+ */
+ telrcv();
+
+ ioctl(f, FIONBIO, (char *)&on);
+ ioctl(p, FIONBIO, (char *)&on);
+
+#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
+ setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
+ (void *)&on, sizeof on);
+#endif /* defined(SO_OOBINLINE) */
+
+#ifdef SIGTSTP
+ signal(SIGTSTP, SIG_IGN);
+#endif
+#ifdef SIGTTOU
+ /*
+ * Ignoring SIGTTOU keeps the kernel from blocking us
+ * in ttioct() in /sys/tty.c.
+ */
+ signal(SIGTTOU, SIG_IGN);
+#endif
+
+ signal(SIGCHLD, cleanup);
+
+#ifdef TIOCNOTTY
+ {
+ int t;
+ t = open(_PATH_TTY, O_RDWR);
+ if (t >= 0) {
+ ioctl(t, TIOCNOTTY, (char *)0);
+ close(t);
+ }
+ }
+#endif
+
+ show_issue();
+ /*
+ * Show banner that getty never gave.
+ *
+ * We put the banner in the pty input buffer. This way, it
+ * gets carriage return null processing, etc., just like all
+ * other pty --> client data.
+ */
+
+ if (getenv("USER"))
+ hostinfo = 0;
+
+ IM = DEFAULT_IM;
+ he = 0;
+ edithost(he, host_name);
+ if (hostinfo && *IM)
+ putf(IM, ptyibuf2);
+
+ if (pcc)
+ strncat(ptyibuf2, ptyip, pcc+1);
+ ptyip = ptyibuf2;
+ pcc = strlen(ptyip);
+
+ DIAG(TD_REPORT, {
+ output_data("td: Entering processing loop\r\n");
+ });
+
+
+ nfd = ((f > p) ? f : p) + 1;
+ timeout = time(NULL) + 5;
+ for (;;) {
+ fd_set ibits, obits, xbits;
+ int c;
+
+ /* wait for encryption to be turned on, but don't wait
+ indefinitely */
+ if(!startslave_called && (!encrypt_delay() || timeout > time(NULL))){
+ startslave_called = 1;
+ startslave(host, level, autoname);
+ }
+
+ if (ncc < 0 && pcc < 0)
+ break;
+
+ FD_ZERO(&ibits);
+ FD_ZERO(&obits);
+ FD_ZERO(&xbits);
+ /*
+ * Never look for input if there's still
+ * stuff in the corresponding output buffer
+ */
+ if (nfrontp - nbackp || pcc > 0) {
+ FD_SET(f, &obits);
+ } else {
+ FD_SET(p, &ibits);
+ }
+ if (pfrontp - pbackp || ncc > 0) {
+ FD_SET(p, &obits);
+ } else {
+ FD_SET(f, &ibits);
+ }
+ if (!SYNCHing) {
+ FD_SET(f, &xbits);
+ }
+ if ((c = select(nfd, &ibits, &obits, &xbits,
+ (struct timeval *)0)) < 1) {
+ if (c == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ }
+ sleep(5);
+ continue;
+ }
+
+ /*
+ * Any urgent data?
+ */
+ if (FD_ISSET(net, &xbits)) {
+ SYNCHing = 1;
+ }
+
+ /*
+ * Something to read from the network...
+ */
+ if (FD_ISSET(net, &ibits)) {
+#ifndef SO_OOBINLINE
+ /*
+ * In 4.2 (and 4.3 beta) systems, the
+ * OOB indication and data handling in the kernel
+ * is such that if two separate TCP Urgent requests
+ * come in, one byte of TCP data will be overlaid.
+ * This is fatal for Telnet, but we try to live
+ * with it.
+ *
+ * In addition, in 4.2 (and...), a special protocol
+ * is needed to pick up the TCP Urgent data in
+ * the correct sequence.
+ *
+ * What we do is: if we think we are in urgent
+ * mode, we look to see if we are "at the mark".
+ * If we are, we do an OOB receive. If we run
+ * this twice, we will do the OOB receive twice,
+ * but the second will fail, since the second
+ * time we were "at the mark", but there wasn't
+ * any data there (the kernel doesn't reset
+ * "at the mark" until we do a normal read).
+ * Once we've read the OOB data, we go ahead
+ * and do normal reads.
+ *
+ * There is also another problem, which is that
+ * since the OOB byte we read doesn't put us
+ * out of OOB state, and since that byte is most
+ * likely the TELNET DM (data mark), we would
+ * stay in the TELNET SYNCH (SYNCHing) state.
+ * So, clocks to the rescue. If we've "just"
+ * received a DM, then we test for the
+ * presence of OOB data when the receive OOB
+ * fails (and AFTER we did the normal mode read
+ * to clear "at the mark").
+ */
+ if (SYNCHing) {
+ int atmark;
+
+ ioctl(net, SIOCATMARK, (char *)&atmark);
+ if (atmark) {
+ ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
+ if ((ncc == -1) && (errno == EINVAL)) {
+ ncc = read(net, netibuf, sizeof (netibuf));
+ if (sequenceIs(didnetreceive, gotDM)) {
+ SYNCHing = stilloob(net);
+ }
+ }
+ } else {
+ ncc = read(net, netibuf, sizeof (netibuf));
+ }
+ } else {
+ ncc = read(net, netibuf, sizeof (netibuf));
+ }
+ settimer(didnetreceive);
+#else /* !defined(SO_OOBINLINE)) */
+ ncc = read(net, netibuf, sizeof (netibuf));
+#endif /* !defined(SO_OOBINLINE)) */
+ if (ncc < 0 && errno == EWOULDBLOCK)
+ ncc = 0;
+ else {
+ if (ncc <= 0) {
+ break;
+ }
+ netip = netibuf;
+ }
+ DIAG((TD_REPORT | TD_NETDATA), {
+ output_data("td: netread %d chars\r\n", ncc);
+ });
+ DIAG(TD_NETDATA, printdata("nd", netip, ncc));
+ }
+
+ /*
+ * Something to read from the pty...
+ */
+ if (FD_ISSET(p, &ibits)) {
+#ifdef STREAMSPTY
+ if (really_stream)
+ pcc = readstream(p, ptyibuf, BUFSIZ);
+ else
+#endif
+ pcc = read(p, ptyibuf, BUFSIZ);
+
+ /*
+ * On some systems, if we try to read something
+ * off the master side before the slave side is
+ * opened, we get EIO.
+ */
+ if (pcc < 0 && (errno == EWOULDBLOCK ||
+#ifdef EAGAIN
+ errno == EAGAIN ||
+#endif
+ errno == EIO)) {
+ pcc = 0;
+ } else {
+ if (pcc <= 0)
+ break;
+ if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
+ netclear(); /* clear buffer back */
+#ifndef NO_URGENT
+ /*
+ * There are client telnets on some
+ * operating systems get screwed up
+ * royally if we send them urgent
+ * mode data.
+ */
+ output_data ("%c%c", IAC, DM);
+
+ neturg = nfrontp-1; /* off by one XXX */
+ DIAG(TD_OPTIONS,
+ printoption("td: send IAC", DM));
+
+#endif
+ }
+ if (his_state_is_will(TELOPT_LFLOW) &&
+ (ptyibuf[0] &
+ (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
+ int newflow =
+ ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
+ if (newflow != flowmode) {
+ flowmode = newflow;
+ output_data("%c%c%c%c%c%c",
+ IAC, SB, TELOPT_LFLOW,
+ flowmode ? LFLOW_ON
+ : LFLOW_OFF,
+ IAC, SE);
+ DIAG(TD_OPTIONS, printsub('>',
+ (unsigned char *)nfrontp-4,
+ 4););
+ }
+ }
+ pcc--;
+ ptyip = ptyibuf+1;
+ }
+ }
+
+ while (pcc > 0) {
+ if ((&netobuf[BUFSIZ] - nfrontp) < 3)
+ break;
+ c = *ptyip++ & 0377, pcc--;
+ if (c == IAC)
+ *nfrontp++ = c;
+ *nfrontp++ = c;
+ if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
+ if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
+ *nfrontp++ = *ptyip++ & 0377;
+ pcc--;
+ } else
+ *nfrontp++ = '\0';
+ }
+ }
+
+ if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
+ netflush();
+ if (ncc > 0)
+ telrcv();
+ if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
+ ptyflush();
+ }
+ cleanup(0);
+}
+
+#ifndef TCSIG
+# ifdef TIOCSIG
+# define TCSIG TIOCSIG
+# endif
+#endif
+
+#ifdef STREAMSPTY
+
+ int flowison = -1; /* current state of flow: -1 is unknown */
+
+int
+readstream(int p, char *ibuf, int bufsize)
+{
+ int flags = 0;
+ int ret = 0;
+ struct termios *tsp;
+#if 0
+ struct termio *tp;
+#endif
+ struct iocblk *ip;
+ char vstop, vstart;
+ int ixon;
+ int newflow;
+
+ strbufc.maxlen = BUFSIZ;
+ strbufc.buf = (char *)ctlbuf;
+ strbufd.maxlen = bufsize-1;
+ strbufd.len = 0;
+ strbufd.buf = ibuf+1;
+ ibuf[0] = 0;
+
+ ret = getmsg(p, &strbufc, &strbufd, &flags);
+ if (ret < 0) /* error of some sort -- probably EAGAIN */
+ return(-1);
+
+ if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
+ /* data message */
+ if (strbufd.len > 0) { /* real data */
+ return(strbufd.len + 1); /* count header char */
+ } else {
+ /* nothing there */
+ errno = EAGAIN;
+ return(-1);
+ }
+ }
+
+ /*
+ * It's a control message. Return 1, to look at the flag we set
+ */
+
+ switch (ctlbuf[0]) {
+ case M_FLUSH:
+ if (ibuf[1] & FLUSHW)
+ ibuf[0] = TIOCPKT_FLUSHWRITE;
+ return(1);
+
+ case M_IOCTL:
+ ip = (struct iocblk *) (ibuf+1);
+
+ switch (ip->ioc_cmd) {
+#ifdef TCSETS
+ case TCSETS:
+ case TCSETSW:
+ case TCSETSF:
+ tsp = (struct termios *)
+ (ibuf+1 + sizeof(struct iocblk));
+ vstop = tsp->c_cc[VSTOP];
+ vstart = tsp->c_cc[VSTART];
+ ixon = tsp->c_iflag & IXON;
+ break;
+#endif
+#if 0
+ case TCSETA:
+ case TCSETAW:
+ case TCSETAF:
+ tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));
+ vstop = tp->c_cc[VSTOP];
+ vstart = tp->c_cc[VSTART];
+ ixon = tp->c_iflag & IXON;
+ break;
+#endif
+ default:
+ errno = EAGAIN;
+ return(-1);
+ }
+
+ newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
+ if (newflow != flowison) { /* it's a change */
+ flowison = newflow;
+ ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
+ return(1);
+ }
+ }
+
+ /* nothing worth doing anything about */
+ errno = EAGAIN;
+ return(-1);
+}
+#endif /* STREAMSPTY */
+
+/*
+ * Send interrupt to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write intr char.
+ */
+void
+interrupt()
+{
+ ptyflush(); /* half-hearted */
+
+#if defined(STREAMSPTY) && defined(TIOCSIGNAL)
+ /* Streams PTY style ioctl to post a signal */
+ if (really_stream)
+ {
+ int sig = SIGINT;
+ ioctl(ourpty, TIOCSIGNAL, &sig);
+ ioctl(ourpty, I_FLUSH, FLUSHR);
+ }
+#else
+#ifdef TCSIG
+ ioctl(ourpty, TCSIG, (char *)SIGINT);
+#else /* TCSIG */
+ init_termbuf();
+ *pfrontp++ = slctab[SLC_IP].sptr ?
+ (unsigned char)*slctab[SLC_IP].sptr : '\177';
+#endif /* TCSIG */
+#endif
+}
+
+/*
+ * Send quit to process on other side of pty.
+ * If it is in raw mode, just write NULL;
+ * otherwise, write quit char.
+ */
+void
+sendbrk()
+{
+ ptyflush(); /* half-hearted */
+#ifdef TCSIG
+ ioctl(ourpty, TCSIG, (char *)SIGQUIT);
+#else /* TCSIG */
+ init_termbuf();
+ *pfrontp++ = slctab[SLC_ABORT].sptr ?
+ (unsigned char)*slctab[SLC_ABORT].sptr : '\034';
+#endif /* TCSIG */
+}
+
+void
+sendsusp()
+{
+#ifdef SIGTSTP
+ ptyflush(); /* half-hearted */
+# ifdef TCSIG
+ ioctl(ourpty, TCSIG, (char *)SIGTSTP);
+# else /* TCSIG */
+ *pfrontp++ = slctab[SLC_SUSP].sptr ?
+ (unsigned char)*slctab[SLC_SUSP].sptr : '\032';
+# endif /* TCSIG */
+#endif /* SIGTSTP */
+}
+
+/*
+ * When we get an AYT, if ^T is enabled, use that. Otherwise,
+ * just send back "[Yes]".
+ */
+void
+recv_ayt()
+{
+#if defined(SIGINFO) && defined(TCSIG)
+ if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
+ ioctl(ourpty, TCSIG, (char *)SIGINFO);
+ return;
+ }
+#endif
+ output_data("\r\n[Yes]\r\n");
+}
+
+void
+doeof()
+{
+ init_termbuf();
+
+ *pfrontp++ = slctab[SLC_EOF].sptr ?
+ (unsigned char)*slctab[SLC_EOF].sptr : '\004';
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/telnetd.h b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.h
new file mode 100644
index 0000000..5ad5bd8
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)telnetd.h 8.1 (Berkeley) 6/4/93
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.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 /* HAVE_SYS_RESOURCE_H */
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+/* including both <sys/ioctl.h> and <termios.h> in SunOS 4 generates a
+ lot of warnings */
+
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.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
+
+#include <signal.h>
+#include <errno.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#include <ctype.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <termios.h>
+
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+
+#include "defs.h"
+
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+
+#ifndef _POSIX_VDISABLE
+# ifdef VDISABLE
+# define _POSIX_VDISABLE VDISABLE
+# else
+# define _POSIX_VDISABLE ((unsigned char)'\377')
+# endif
+#endif
+
+
+#ifdef HAVE_SYS_PTY_H
+#include <sys/pty.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_SYS_PTYIO_H
+#include <sys/ptyio.h>
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
+#include "ext.h"
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifdef SOCKS
+#include <socks.h>
+/* This doesn't belong here. */
+struct tm *localtime(const time_t *);
+struct hostent *gethostbyname(const char *);
+#endif
+
+#ifdef KRB4
+#include <des.h>
+#include <krb.h>
+#endif
+
+#ifdef AUTHENTICATION
+#include <libtelnet/auth.h>
+#include <libtelnet/misc.h>
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+#endif
+
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+
+#include <roken.h>
+
+/* Don't use the system login, use our version instead */
+
+/* BINDIR should be defined somewhere else... */
+
+#ifndef BINDIR
+#define BINDIR "/usr/athena/bin"
+#endif
+
+#undef _PATH_LOGIN
+#define _PATH_LOGIN BINDIR "/login"
+
+/* fallbacks */
+
+#ifndef _PATH_DEV
+#define _PATH_DEV "/dev/"
+#endif
+
+#ifndef _PATH_TTY
+#define _PATH_TTY "/dev/tty"
+#endif /* _PATH_TTY */
+
+#ifdef DIAGNOSTICS
+#define DIAG(a,b) if (diagnostic & (a)) b
+#else
+#define DIAG(a,b)
+#endif
+
+/* other external variables */
+extern char **environ;
+
+/* prototypes */
+
+/* appends data to nfrontp and advances */
+int output_data (const char *format, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/termstat.c b/crypto/kerberosIV/appl/telnet/telnetd/termstat.c
new file mode 100644
index 0000000..80ee145
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/termstat.c
@@ -0,0 +1,140 @@
+/*
+ * 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: termstat.c,v 1.11 1997/05/11 06:30:04 assar Exp $");
+
+/*
+ * local variables
+ */
+int def_tspeed = -1, def_rspeed = -1;
+#ifdef TIOCSWINSZ
+int def_row = 0, def_col = 0;
+#endif
+
+/*
+ * flowstat
+ *
+ * Check for changes to flow control
+ */
+void
+flowstat()
+{
+ if (his_state_is_will(TELOPT_LFLOW)) {
+ if (tty_flowmode() != flowmode) {
+ flowmode = tty_flowmode();
+ output_data("%c%c%c%c%c%c",
+ IAC, SB, TELOPT_LFLOW,
+ flowmode ? LFLOW_ON : LFLOW_OFF,
+ IAC, SE);
+ }
+ if (tty_restartany() != restartany) {
+ restartany = tty_restartany();
+ output_data("%c%c%c%c%c%c",
+ IAC, SB, TELOPT_LFLOW,
+ restartany ? LFLOW_RESTART_ANY
+ : LFLOW_RESTART_XON,
+ IAC, SE);
+ }
+ }
+}
+
+/*
+ * clientstat
+ *
+ * Process linemode related requests from the client.
+ * Client can request a change to only one of linemode, editmode or slc's
+ * at a time, and if using kludge linemode, then only linemode may be
+ * affected.
+ */
+void
+clientstat(int code, int parm1, int parm2)
+{
+ void netflush();
+
+ /*
+ * Get a copy of terminal characteristics.
+ */
+ init_termbuf();
+
+ /*
+ * Process request from client. code tells what it is.
+ */
+ switch (code) {
+ case TELOPT_NAWS:
+#ifdef TIOCSWINSZ
+ {
+ struct winsize ws;
+
+ def_col = parm1;
+ def_row = parm2;
+
+ /*
+ * Change window size as requested by client.
+ */
+
+ ws.ws_col = parm1;
+ ws.ws_row = parm2;
+ ioctl(ourpty, TIOCSWINSZ, (char *)&ws);
+ }
+#endif /* TIOCSWINSZ */
+
+ break;
+
+ case TELOPT_TSPEED:
+ {
+ def_tspeed = parm1;
+ def_rspeed = parm2;
+ /*
+ * Change terminal speed as requested by client.
+ * We set the receive speed first, so that if we can't
+ * store seperate receive and transmit speeds, the transmit
+ * speed will take precedence.
+ */
+ tty_rspeed(parm2);
+ tty_tspeed(parm1);
+ set_termbuf();
+
+ break;
+
+ } /* end of case TELOPT_TSPEED */
+
+ default:
+ /* What? */
+ break;
+ } /* end of switch */
+
+ netflush();
+
+}
diff --git a/crypto/kerberosIV/appl/telnet/telnetd/utility.c b/crypto/kerberosIV/appl/telnet/telnetd/utility.c
new file mode 100644
index 0000000..cfca89a
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/utility.c
@@ -0,0 +1,1157 @@
+/*
+ * 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.
+ */
+
+#define PRINTOPTIONS
+#include "telnetd.h"
+
+RCSID("$Id: utility.c,v 1.20 1998/06/13 00:06:56 assar Exp $");
+
+/*
+ * utility functions performing io related tasks
+ */
+
+/*
+ * ttloop
+ *
+ * A small subroutine to flush the network output buffer, get some
+ * data from the network, and pass it through the telnet state
+ * machine. We also flush the pty input buffer (by dropping its data)
+ * if it becomes too full.
+ */
+
+void
+ttloop(void)
+{
+ void netflush(void);
+
+ DIAG(TD_REPORT, {
+ output_data("td: ttloop\r\n");
+ });
+ if (nfrontp-nbackp)
+ netflush();
+ ncc = read(net, netibuf, sizeof netibuf);
+ if (ncc < 0) {
+ syslog(LOG_INFO, "ttloop: read: %m\n");
+ exit(1);
+ } else if (ncc == 0) {
+ syslog(LOG_INFO, "ttloop: peer died: %m\n");
+ exit(1);
+ }
+ DIAG(TD_REPORT, {
+ output_data("td: ttloop read %d chars\r\n", ncc);
+ });
+ netip = netibuf;
+ telrcv(); /* state machine */
+ if (ncc > 0) {
+ pfrontp = pbackp = ptyobuf;
+ telrcv();
+ }
+} /* end of ttloop */
+
+/*
+ * Check a descriptor to see if out of band data exists on it.
+ */
+int
+stilloob(int s)
+{
+ static struct timeval timeout = { 0 };
+ fd_set excepts;
+ int value;
+
+ do {
+ FD_ZERO(&excepts);
+ FD_SET(s, &excepts);
+ value = select(s+1, 0, 0, &excepts, &timeout);
+ } while ((value == -1) && (errno == EINTR));
+
+ if (value < 0) {
+ fatalperror(ourpty, "select");
+ }
+ if (FD_ISSET(s, &excepts)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void
+ptyflush(void)
+{
+ int n;
+
+ if ((n = pfrontp - pbackp) > 0) {
+ DIAG((TD_REPORT | TD_PTYDATA), {
+ output_data("td: ptyflush %d chars\r\n", n);
+ });
+ DIAG(TD_PTYDATA, printdata("pd", pbackp, n));
+ n = write(ourpty, pbackp, n);
+ }
+ if (n < 0) {
+ if (errno == EWOULDBLOCK || errno == EINTR)
+ return;
+ cleanup(0);
+ }
+ pbackp += n;
+ if (pbackp == pfrontp)
+ pbackp = pfrontp = ptyobuf;
+}
+
+/*
+ * nextitem()
+ *
+ * Return the address of the next "item" in the TELNET data
+ * stream. This will be the address of the next character if
+ * the current address is a user data character, or it will
+ * be the address of the character following the TELNET command
+ * if the current address is a TELNET IAC ("I Am a Command")
+ * character.
+ */
+char *
+nextitem(char *current)
+{
+ if ((*current&0xff) != IAC) {
+ return current+1;
+ }
+ switch (*(current+1)&0xff) {
+ case DO:
+ case DONT:
+ case WILL:
+ case WONT:
+ return current+3;
+ case SB:{
+ /* loop forever looking for the SE */
+ char *look = current+2;
+
+ for (;;) {
+ if ((*look++&0xff) == IAC) {
+ if ((*look++&0xff) == SE) {
+ return look;
+ }
+ }
+ }
+ }
+ default:
+ return current+2;
+ }
+}
+
+
+/*
+ * netclear()
+ *
+ * We are about to do a TELNET SYNCH operation. Clear
+ * the path to the network.
+ *
+ * Things are a bit tricky since we may have sent the first
+ * byte or so of a previous TELNET command into the network.
+ * So, we have to scan the network buffer from the beginning
+ * until we are up to where we want to be.
+ *
+ * A side effect of what we do, just to keep things
+ * simple, is to clear the urgent data pointer. The principal
+ * caller should be setting the urgent data pointer AFTER calling
+ * us in any case.
+ */
+void
+netclear(void)
+{
+ char *thisitem, *next;
+ char *good;
+#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
+ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+
+#ifdef ENCRYPTION
+ thisitem = nclearto > netobuf ? nclearto : netobuf;
+#else
+ thisitem = netobuf;
+#endif
+
+ while ((next = nextitem(thisitem)) <= nbackp) {
+ thisitem = next;
+ }
+
+ /* Now, thisitem is first before/at boundary. */
+
+#ifdef ENCRYPTION
+ good = nclearto > netobuf ? nclearto : netobuf;
+#else
+ good = netobuf; /* where the good bytes go */
+#endif
+
+ while (nfrontp > thisitem) {
+ if (wewant(thisitem)) {
+ int length;
+
+ next = thisitem;
+ do {
+ next = nextitem(next);
+ } while (wewant(next) && (nfrontp > next));
+ length = next-thisitem;
+ memmove(good, thisitem, length);
+ good += length;
+ thisitem = next;
+ } else {
+ thisitem = nextitem(thisitem);
+ }
+ }
+
+ nbackp = netobuf;
+ nfrontp = good; /* next byte to be sent */
+ neturg = 0;
+} /* end of netclear */
+
+/*
+ * netflush
+ * Send as much data as possible to the network,
+ * handling requests for urgent data.
+ */
+void
+netflush(void)
+{
+ int n;
+ extern int not42;
+
+ if ((n = nfrontp - nbackp) > 0) {
+ DIAG(TD_REPORT,
+ { n += output_data("td: netflush %d chars\r\n", n);
+ });
+#ifdef ENCRYPTION
+ if (encrypt_output) {
+ char *s = nclearto ? nclearto : nbackp;
+ if (nfrontp - s > 0) {
+ (*encrypt_output)((unsigned char *)s, nfrontp-s);
+ nclearto = nfrontp;
+ }
+ }
+#endif
+ /*
+ * if no urgent data, or if the other side appears to be an
+ * old 4.2 client (and thus unable to survive TCP urgent data),
+ * write the entire buffer in non-OOB mode.
+ */
+#if 1 /* remove this to make it work between solaris 2.6 and linux */
+ if ((neturg == 0) || (not42 == 0)) {
+#endif
+ n = write(net, nbackp, n); /* normal write */
+#if 1 /* remove this to make it work between solaris 2.6 and linux */
+ } else {
+ n = neturg - nbackp;
+ /*
+ * In 4.2 (and 4.3) systems, there is some question about
+ * what byte in a sendOOB operation is the "OOB" data.
+ * To make ourselves compatible, we only send ONE byte
+ * out of band, the one WE THINK should be OOB (though
+ * we really have more the TCP philosophy of urgent data
+ * rather than the Unix philosophy of OOB data).
+ */
+ if (n > 1) {
+ n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */
+ } else {
+ n = send(net, nbackp, n, MSG_OOB); /* URGENT data */
+ }
+ }
+#endif
+ }
+ if (n < 0) {
+ if (errno == EWOULDBLOCK || errno == EINTR)
+ return;
+ cleanup(0);
+ }
+ nbackp += n;
+#ifdef ENCRYPTION
+ if (nbackp > nclearto)
+ nclearto = 0;
+#endif
+ if (nbackp >= neturg) {
+ neturg = 0;
+ }
+ if (nbackp == nfrontp) {
+ nbackp = nfrontp = netobuf;
+#ifdef ENCRYPTION
+ nclearto = 0;
+#endif
+ }
+ return;
+}
+
+
+/*
+ * writenet
+ *
+ * Just a handy little function to write a bit of raw data to the net.
+ * It will force a transmit of the buffer if necessary
+ *
+ * arguments
+ * ptr - A pointer to a character string to write
+ * len - How many bytes to write
+ */
+void
+writenet(unsigned char *ptr, int len)
+{
+ /* flush buffer if no room for new data) */
+ while ((&netobuf[BUFSIZ] - nfrontp) < len) {
+ /* if this fails, don't worry, buffer is a little big */
+ netflush();
+ }
+
+ memmove(nfrontp, ptr, len);
+ nfrontp += len;
+}
+
+
+/*
+ * miscellaneous functions doing a variety of little jobs follow ...
+ */
+
+
+void fatal(int f, char *msg)
+{
+ char buf[BUFSIZ];
+
+ snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg);
+#ifdef ENCRYPTION
+ if (encrypt_output) {
+ /*
+ * Better turn off encryption first....
+ * Hope it flushes...
+ */
+ encrypt_send_end();
+ netflush();
+ }
+#endif
+ write(f, buf, (int)strlen(buf));
+ sleep(1); /*XXX*/
+ exit(1);
+}
+
+void
+fatalperror(int f, const char *msg)
+{
+ char buf[BUFSIZ];
+
+ snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno));
+ fatal(f, buf);
+}
+
+char editedhost[32];
+
+void edithost(char *pat, char *host)
+{
+ char *res = editedhost;
+
+ if (!pat)
+ pat = "";
+ while (*pat) {
+ switch (*pat) {
+
+ case '#':
+ if (*host)
+ host++;
+ break;
+
+ case '@':
+ if (*host)
+ *res++ = *host++;
+ break;
+
+ default:
+ *res++ = *pat;
+ break;
+ }
+ if (res == &editedhost[sizeof editedhost - 1]) {
+ *res = '\0';
+ return;
+ }
+ pat++;
+ }
+ if (*host)
+ strcpy_truncate (res, host,
+ sizeof editedhost - (res - editedhost));
+ else
+ *res = '\0';
+ editedhost[sizeof editedhost - 1] = '\0';
+}
+
+static char *putlocation;
+
+void
+putstr(char *s)
+{
+
+ while (*s)
+ putchr(*s++);
+}
+
+void
+putchr(int cc)
+{
+ *putlocation++ = cc;
+}
+
+/*
+ * This is split on two lines so that SCCS will not see the M
+ * between two % signs and expand it...
+ */
+static char fmtstr[] = { "%l:%M" "%P on %A, %d %B %Y" };
+
+void putf(char *cp, char *where)
+{
+#ifdef HAVE_UNAME
+ struct utsname name;
+#endif
+ char *slash;
+ time_t t;
+ char db[100];
+
+ /* if we don't have uname, set these to sensible values */
+ char *sysname = "Unix",
+ *machine = "",
+ *release = "",
+ *version = "";
+
+#ifdef HAVE_UNAME
+ uname(&name);
+ sysname=name.sysname;
+ machine=name.machine;
+ release=name.release;
+ version=name.version;
+#endif
+
+ putlocation = where;
+
+ while (*cp) {
+ if (*cp != '%') {
+ putchr(*cp++);
+ continue;
+ }
+ switch (*++cp) {
+
+ case 't':
+#ifdef STREAMSPTY
+ /* names are like /dev/pts/2 -- we want pts/2 */
+ slash = strchr(line+1, '/');
+#else
+ slash = strrchr(line, '/');
+#endif
+ if (slash == (char *) 0)
+ putstr(line);
+ else
+ putstr(&slash[1]);
+ break;
+
+ case 'h':
+ putstr(editedhost);
+ break;
+
+ case 's':
+ putstr(sysname);
+ break;
+
+ case 'm':
+ putstr(machine);
+ break;
+
+ case 'r':
+ putstr(release);
+ break;
+
+ case 'v':
+ putstr(version);
+ break;
+
+ case 'd':
+ time(&t);
+ strftime(db, sizeof(db), fmtstr, localtime(&t));
+ putstr(db);
+ break;
+
+ case '%':
+ putchr('%');
+ break;
+ }
+ cp++;
+ }
+}
+
+#ifdef DIAGNOSTICS
+/*
+ * Print telnet options and commands in plain text, if possible.
+ */
+void
+printoption(char *fmt, int option)
+{
+ if (TELOPT_OK(option))
+ output_data("%s %s\r\n",
+ fmt,
+ TELOPT(option));
+ else if (TELCMD_OK(option))
+ output_data("%s %s\r\n",
+ fmt,
+ TELCMD(option));
+ else
+ output_data("%s %d\r\n",
+ fmt,
+ option);
+ return;
+}
+
+void
+printsub(int direction, unsigned char *pointer, int length)
+ /* '<' or '>' */
+ /* where suboption data sits */
+ /* length of suboption data */
+{
+ int i = 0;
+ unsigned char buf[512];
+
+ if (!(diagnostic & TD_OPTIONS))
+ return;
+
+ if (direction) {
+ output_data("td: %s suboption ",
+ direction == '<' ? "recv" : "send");
+ if (length >= 3) {
+ int j;
+
+ i = pointer[length-2];
+ j = pointer[length-1];
+
+ if (i != IAC || j != SE) {
+ output_data("(terminated by ");
+ if (TELOPT_OK(i))
+ output_data("%s ",
+ TELOPT(i));
+ else if (TELCMD_OK(i))
+ output_data("%s ",
+ TELCMD(i));
+ else
+ output_data("%d ",
+ i);
+ if (TELOPT_OK(j))
+ output_data("%s",
+ TELOPT(j));
+ else if (TELCMD_OK(j))
+ output_data("%s",
+ TELCMD(j));
+ else
+ output_data("%d",
+ j);
+ output_data(", not IAC SE!) ");
+ }
+ }
+ length -= 2;
+ }
+ if (length < 1) {
+ output_data("(Empty suboption??\?)");
+ return;
+ }
+ switch (pointer[0]) {
+ case TELOPT_TTYPE:
+ output_data("TERMINAL-TYPE ");
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ output_data("IS \"%.*s\"",
+ length-2,
+ (char *)pointer+2);
+ break;
+ case TELQUAL_SEND:
+ output_data("SEND");
+ break;
+ default:
+ output_data("- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
+ }
+ break;
+ case TELOPT_TSPEED:
+ output_data("TERMINAL-SPEED");
+ if (length < 2) {
+ output_data(" (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ output_data(" IS %.*s", length-2, (char *)pointer+2);
+ break;
+ default:
+ if (pointer[1] == 1)
+ output_data(" SEND");
+ else
+ output_data(" %d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++) {
+ output_data(" ?%d?", pointer[i]);
+ }
+ break;
+ }
+ break;
+
+ case TELOPT_LFLOW:
+ output_data("TOGGLE-FLOW-CONTROL");
+ if (length < 2) {
+ output_data(" (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case LFLOW_OFF:
+ output_data(" OFF");
+ break;
+ case LFLOW_ON:
+ output_data(" ON");
+ break;
+ case LFLOW_RESTART_ANY:
+ output_data(" RESTART-ANY");
+ break;
+ case LFLOW_RESTART_XON:
+ output_data(" RESTART-XON");
+ break;
+ default:
+ output_data(" %d (unknown)",
+ pointer[1]);
+ }
+ for (i = 2; i < length; i++) {
+ output_data(" ?%d?",
+ pointer[i]);
+ }
+ break;
+
+ case TELOPT_NAWS:
+ output_data("NAWS");
+ if (length < 2) {
+ output_data(" (empty suboption??\?)");
+ break;
+ }
+ if (length == 2) {
+ output_data(" ?%d?",
+ pointer[1]);
+ break;
+ }
+ output_data(" %u %u(%u)",
+ pointer[1],
+ pointer[2],
+ (((unsigned int)pointer[1])<<8) + pointer[2]);
+ if (length == 4) {
+ output_data(" ?%d?",
+ pointer[3]);
+ break;
+ }
+ output_data(" %u %u(%u)",
+ pointer[3],
+ pointer[4],
+ (((unsigned int)pointer[3])<<8) + pointer[4]);
+ for (i = 5; i < length; i++) {
+ output_data(" ?%d?",
+ pointer[i]);
+ }
+ break;
+
+ case TELOPT_LINEMODE:
+ output_data("LINEMODE ");
+ if (length < 2) {
+ output_data(" (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case WILL:
+ output_data("WILL ");
+ goto common;
+ case WONT:
+ output_data("WONT ");
+ goto common;
+ case DO:
+ output_data("DO ");
+ goto common;
+ case DONT:
+ output_data("DONT ");
+ common:
+ if (length < 3) {
+ output_data("(no option??\?)");
+ break;
+ }
+ switch (pointer[2]) {
+ case LM_FORWARDMASK:
+ output_data("Forward Mask");
+ for (i = 3; i < length; i++) {
+ output_data(" %x", pointer[i]);
+ }
+ break;
+ default:
+ output_data("%d (unknown)",
+ pointer[2]);
+ for (i = 3; i < length; i++) {
+ output_data(" %d",
+ pointer[i]);
+ }
+ break;
+ }
+ break;
+
+ case LM_SLC:
+ output_data("SLC");
+ for (i = 2; i < length - 2; i += 3) {
+ if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
+ output_data(" %s",
+ SLC_NAME(pointer[i+SLC_FUNC]));
+ else
+ output_data(" %d",
+ pointer[i+SLC_FUNC]);
+ switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
+ case SLC_NOSUPPORT:
+ output_data(" NOSUPPORT");
+ break;
+ case SLC_CANTCHANGE:
+ output_data(" CANTCHANGE");
+ break;
+ case SLC_VARIABLE:
+ output_data(" VARIABLE");
+ break;
+ case SLC_DEFAULT:
+ output_data(" DEFAULT");
+ break;
+ }
+ output_data("%s%s%s",
+ pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
+ pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
+ pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
+ if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
+ SLC_FLUSHOUT| SLC_LEVELBITS)) {
+ output_data("(0x%x)",
+ pointer[i+SLC_FLAGS]);
+ }
+ output_data(" %d;",
+ pointer[i+SLC_VALUE]);
+ if ((pointer[i+SLC_VALUE] == IAC) &&
+ (pointer[i+SLC_VALUE+1] == IAC))
+ i++;
+ }
+ for (; i < length; i++) {
+ output_data(" ?%d?",
+ pointer[i]);
+ }
+ break;
+
+ case LM_MODE:
+ output_data("MODE ");
+ if (length < 3) {
+ output_data("(no mode??\?)");
+ break;
+ }
+ {
+ char tbuf[32];
+ 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" : "");
+ output_data("%s",
+ tbuf[1] ? &tbuf[1] : "0");
+ }
+ if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) {
+ output_data(" (0x%x)",
+ pointer[2]);
+ }
+ for (i = 3; i < length; i++) {
+ output_data(" ?0x%x?",
+ pointer[i]);
+ }
+ break;
+ default:
+ output_data("%d (unknown)",
+ pointer[1]);
+ for (i = 2; i < length; i++) {
+ output_data(" %d", pointer[i]);
+ }
+ }
+ break;
+
+ case TELOPT_STATUS: {
+ char *cp;
+ int j, k;
+
+ output_data("STATUS");
+
+ switch (pointer[1]) {
+ default:
+ if (pointer[1] == TELQUAL_SEND)
+ output_data(" SEND");
+ else
+ output_data(" %d (unknown)",
+ pointer[1]);
+ for (i = 2; i < length; i++) {
+ output_data(" ?%d?",
+ pointer[i]);
+ }
+ break;
+ case TELQUAL_IS:
+ output_data(" IS\r\n");
+
+ for (i = 2; i < length; i++) {
+ switch(pointer[i]) {
+ case DO: cp = "DO"; goto common2;
+ case DONT: cp = "DONT"; goto common2;
+ case WILL: cp = "WILL"; goto common2;
+ case WONT: cp = "WONT"; goto common2;
+ common2:
+ i++;
+ if (TELOPT_OK(pointer[i]))
+ output_data(" %s %s",
+ cp,
+ TELOPT(pointer[i]));
+ else
+ output_data(" %s %d",
+ cp,
+ pointer[i]);
+
+ output_data("\r\n");
+ break;
+
+ case SB:
+ output_data(" SB ");
+ i++;
+ j = k = i;
+ while (j < length) {
+ if (pointer[j] == SE) {
+ if (j+1 == length)
+ break;
+ if (pointer[j+1] == SE)
+ j++;
+ else
+ break;
+ }
+ pointer[k++] = pointer[j++];
+ }
+ printsub(0, &pointer[i], k - i);
+ if (i < length) {
+ output_data(" SE");
+ i = j;
+ } else
+ i = j - 1;
+
+ output_data("\r\n");
+
+ break;
+
+ default:
+ output_data(" %d",
+ pointer[i]);
+ break;
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ case TELOPT_XDISPLOC:
+ output_data("X-DISPLAY-LOCATION ");
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ output_data("IS \"%.*s\"",
+ length-2,
+ (char *)pointer+2);
+ break;
+ case TELQUAL_SEND:
+ output_data("SEND");
+ break;
+ default:
+ output_data("- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
+ }
+ break;
+
+ case TELOPT_NEW_ENVIRON:
+ output_data("NEW-ENVIRON ");
+ goto env_common1;
+ case TELOPT_OLD_ENVIRON:
+ output_data("OLD-ENVIRON");
+ env_common1:
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ output_data("IS ");
+ goto env_common;
+ case TELQUAL_SEND:
+ output_data("SEND ");
+ goto env_common;
+ case TELQUAL_INFO:
+ output_data("INFO ");
+ env_common:
+ {
+ int noquote = 2;
+ for (i = 2; i < length; i++ ) {
+ switch (pointer[i]) {
+ case NEW_ENV_VAR:
+ output_data("\" VAR " + noquote);
+ noquote = 2;
+ break;
+
+ case NEW_ENV_VALUE:
+ output_data("\" VALUE " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_ESC:
+ output_data("\" ESC " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_USERVAR:
+ output_data("\" USERVAR " + noquote);
+ noquote = 2;
+ break;
+
+ default:
+ if (isprint(pointer[i]) && pointer[i] != '"') {
+ if (noquote) {
+ output_data ("\"");
+ noquote = 0;
+ }
+ output_data ("%c", pointer[i]);
+ } else {
+ output_data("\" %03o " + noquote,
+ pointer[i]);
+ noquote = 2;
+ }
+ break;
+ }
+ }
+ if (!noquote)
+ output_data ("\"");
+ break;
+ }
+ }
+ break;
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ output_data("AUTHENTICATION");
+
+ if (length < 2) {
+ output_data(" (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case TELQUAL_REPLY:
+ case TELQUAL_IS:
+ output_data(" %s ",
+ (pointer[1] == TELQUAL_IS) ?
+ "IS" : "REPLY");
+ if (AUTHTYPE_NAME_OK(pointer[2]))
+ output_data("%s ",
+ AUTHTYPE_NAME(pointer[2]));
+ else
+ output_data("%d ",
+ pointer[2]);
+ if (length < 3) {
+ output_data("(partial suboption??\?)");
+ break;
+ }
+ output_data("%s|%s",
+ ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+ "CLIENT" : "SERVER",
+ ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+ "MUTUAL" : "ONE-WAY");
+
+ auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+ output_data("%s",
+ buf);
+ break;
+
+ case TELQUAL_SEND:
+ i = 2;
+ output_data(" SEND ");
+ while (i < length) {
+ if (AUTHTYPE_NAME_OK(pointer[i]))
+ output_data("%s ",
+ AUTHTYPE_NAME(pointer[i]));
+ else
+ output_data("%d ",
+ pointer[i]);
+ if (++i >= length) {
+ output_data("(partial suboption??\?)");
+ break;
+ }
+ output_data("%s|%s ",
+ ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+ "CLIENT" : "SERVER",
+ ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+ "MUTUAL" : "ONE-WAY");
+ ++i;
+ }
+ break;
+
+ case TELQUAL_NAME:
+ i = 2;
+ output_data(" NAME \"%.*s\"",
+ length - 2,
+ pointer);
+ break;
+
+ default:
+ for (i = 2; i < length; i++) {
+ output_data(" ?%d?",
+ pointer[i]);
+ }
+ break;
+ }
+ break;
+#endif
+
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ output_data("ENCRYPT");
+ if (length < 2) {
+ output_data(" (empty suboption?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case ENCRYPT_START:
+ output_data(" START");
+ break;
+
+ case ENCRYPT_END:
+ output_data(" END");
+ break;
+
+ case ENCRYPT_REQSTART:
+ output_data(" REQUEST-START");
+ break;
+
+ case ENCRYPT_REQEND:
+ output_data(" REQUEST-END");
+ break;
+
+ case ENCRYPT_IS:
+ case ENCRYPT_REPLY:
+ output_data(" %s ",
+ (pointer[1] == ENCRYPT_IS) ?
+ "IS" : "REPLY");
+ if (length < 3) {
+ output_data(" (partial suboption?)");
+ break;
+ }
+ if (ENCTYPE_NAME_OK(pointer[2]))
+ output_data("%s ",
+ ENCTYPE_NAME(pointer[2]));
+ else
+ output_data(" %d (unknown)",
+ pointer[2]);
+
+ encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+ output_data("%s",
+ buf);
+ break;
+
+ case ENCRYPT_SUPPORT:
+ i = 2;
+ output_data(" SUPPORT ");
+ while (i < length) {
+ if (ENCTYPE_NAME_OK(pointer[i]))
+ output_data("%s ",
+ ENCTYPE_NAME(pointer[i]));
+ else
+ output_data("%d ",
+ pointer[i]);
+ i++;
+ }
+ break;
+
+ case ENCRYPT_ENC_KEYID:
+ output_data(" ENC_KEYID %d", pointer[1]);
+ goto encommon;
+
+ case ENCRYPT_DEC_KEYID:
+ output_data(" DEC_KEYID %d", pointer[1]);
+ goto encommon;
+
+ default:
+ output_data(" %d (unknown)", pointer[1]);
+ encommon:
+ for (i = 2; i < length; i++) {
+ output_data(" %d", pointer[i]);
+ }
+ break;
+ }
+ break;
+#endif
+
+ default:
+ if (TELOPT_OK(pointer[0]))
+ output_data("%s (unknown)",
+ TELOPT(pointer[0]));
+ else
+ output_data("%d (unknown)",
+ pointer[i]);
+ for (i = 1; i < length; i++) {
+ output_data(" %d", pointer[i]);
+ }
+ break;
+ }
+ output_data("\r\n");
+}
+
+/*
+ * Dump a data buffer in hex and ascii to the output data stream.
+ */
+void
+printdata(char *tag, char *ptr, int cnt)
+{
+ int i;
+ char xbuf[30];
+
+ while (cnt) {
+ /* flush net output buffer if no room for new data) */
+ if ((&netobuf[BUFSIZ] - nfrontp) < 80) {
+ netflush();
+ }
+
+ /* add a line of output */
+ output_data("%s: ", tag);
+ for (i = 0; i < 20 && cnt; i++) {
+ output_data("%02x", *ptr);
+ if (isprint(*ptr)) {
+ xbuf[i] = *ptr;
+ } else {
+ xbuf[i] = '.';
+ }
+ if (i % 2) {
+ output_data(" ");
+ }
+ cnt--;
+ ptr++;
+ }
+ xbuf[i] = '\0';
+ output_data(" %s\r\n", xbuf);
+ }
+}
+#endif /* DIAGNOSTICS */
OpenPOWER on IntegriCloud