summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/appl
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/appl')
-rw-r--r--crypto/kerberosIV/appl/Makefile.in43
-rw-r--r--crypto/kerberosIV/appl/afsutil/Makefile.in89
-rw-r--r--crypto/kerberosIV/appl/afsutil/aklog.c250
-rw-r--r--crypto/kerberosIV/appl/afsutil/kstring2key.c138
-rw-r--r--crypto/kerberosIV/appl/afsutil/pagsh.c136
-rw-r--r--crypto/kerberosIV/appl/bsd/Makefile.in136
-rw-r--r--crypto/kerberosIV/appl/bsd/README.login20
-rw-r--r--crypto/kerberosIV/appl/bsd/bsd_locl.h400
-rw-r--r--crypto/kerberosIV/appl/bsd/encrypt.c305
-rw-r--r--crypto/kerberosIV/appl/bsd/forkpty.c477
-rw-r--r--crypto/kerberosIV/appl/bsd/kcmd.c280
-rw-r--r--crypto/kerberosIV/appl/bsd/klogin.c229
-rw-r--r--crypto/kerberosIV/appl/bsd/krcmd.c117
-rw-r--r--crypto/kerberosIV/appl/bsd/login.c1118
-rw-r--r--crypto/kerberosIV/appl/bsd/login_access.c264
-rw-r--r--crypto/kerberosIV/appl/bsd/login_fbtab.c154
-rw-r--r--crypto/kerberosIV/appl/bsd/osfc2.c79
-rw-r--r--crypto/kerberosIV/appl/bsd/pathnames.h_201
-rw-r--r--crypto/kerberosIV/appl/bsd/rcmd_util.c263
-rw-r--r--crypto/kerberosIV/appl/bsd/rcp.c1047
-rw-r--r--crypto/kerberosIV/appl/bsd/rcp_util.c99
-rw-r--r--crypto/kerberosIV/appl/bsd/rlogin.c711
-rw-r--r--crypto/kerberosIV/appl/bsd/rlogind.c970
-rw-r--r--crypto/kerberosIV/appl/bsd/rsh.c384
-rw-r--r--crypto/kerberosIV/appl/bsd/rshd.c652
-rw-r--r--crypto/kerberosIV/appl/bsd/stty_default.c100
-rw-r--r--crypto/kerberosIV/appl/bsd/su.c504
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_default.c95
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_default.h18
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_environ.c193
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_shadow.c45
-rw-r--r--crypto/kerberosIV/appl/bsd/sysv_shadow.h5
-rw-r--r--crypto/kerberosIV/appl/bsd/tty.c70
-rw-r--r--crypto/kerberosIV/appl/bsd/utmp_login.c118
-rw-r--r--crypto/kerberosIV/appl/bsd/utmpx_login.c88
-rw-r--r--crypto/kerberosIV/appl/ftp/ChangeLog384
-rw-r--r--crypto/kerberosIV/appl/ftp/Makefile.am5
-rw-r--r--crypto/kerberosIV/appl/ftp/Makefile.in44
-rw-r--r--crypto/kerberosIV/appl/ftp/common/Makefile.am12
-rw-r--r--crypto/kerberosIV/appl/ftp/common/Makefile.in55
-rw-r--r--crypto/kerberosIV/appl/ftp/common/base64.c149
-rw-r--r--crypto/kerberosIV/appl/ftp/common/base64.h47
-rw-r--r--crypto/kerberosIV/appl/ftp/common/buffer.c69
-rw-r--r--crypto/kerberosIV/appl/ftp/common/common.h60
-rw-r--r--crypto/kerberosIV/appl/ftp/common/glob.c835
-rw-r--r--crypto/kerberosIV/appl/ftp/common/glob.h84
-rw-r--r--crypto/kerberosIV/appl/ftp/common/sockbuf.c56
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/Makefile.am44
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/Makefile.in102
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/cmds.c2117
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/cmdtab.c202
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/domacro.c138
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/extern.h173
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/ftp.c1752
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h140
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/ftp_var.h127
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/globals.c76
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/gssapi.c379
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/kauth.c198
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/krb4.c334
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/krb4.h81
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/main.c551
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/pathnames.h44
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/ruserpass.c312
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/security.c785
-rw-r--r--crypto/kerberosIV/appl/ftp/ftp/security.h131
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/Makefile.am54
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/Makefile.in102
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/auth.c249
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/auth.h109
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/extern.h160
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y1457
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpd.c2250
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h170
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c69
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/kauth.c365
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/krb4.c372
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/krb4.h61
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c137
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ls.c573
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/pathnames.h58
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/popen.c224
-rw-r--r--crypto/kerberosIV/appl/kauth/ChangeLog41
-rw-r--r--crypto/kerberosIV/appl/kauth/Makefile.am42
-rw-r--r--crypto/kerberosIV/appl/kauth/Makefile.in115
-rw-r--r--crypto/kerberosIV/appl/kauth/encdata.c96
-rw-r--r--crypto/kerberosIV/appl/kauth/kauth.c384
-rw-r--r--crypto/kerberosIV/appl/kauth/kauth.h116
-rw-r--r--crypto/kerberosIV/appl/kauth/kauthd.c202
-rw-r--r--crypto/kerberosIV/appl/kauth/ksrvtgt.in15
-rw-r--r--crypto/kerberosIV/appl/kauth/marshall.c126
-rw-r--r--crypto/kerberosIV/appl/kauth/rkinit.c226
-rw-r--r--crypto/kerberosIV/appl/kauth/zrefresh12
-rw-r--r--crypto/kerberosIV/appl/kip/Makefile.in110
-rw-r--r--crypto/kerberosIV/appl/kip/common.c302
-rw-r--r--crypto/kerberosIV/appl/kip/kip-join-network.in53
-rw-r--r--crypto/kerberosIV/appl/kip/kip.c261
-rw-r--r--crypto/kerberosIV/appl/kip/kip.h122
-rw-r--r--crypto/kerberosIV/appl/kip/kipd-control.in54
-rw-r--r--crypto/kerberosIV/appl/kip/kipd.c204
-rw-r--r--crypto/kerberosIV/appl/push/ChangeLog135
-rw-r--r--crypto/kerberosIV/appl/push/Makefile.am27
-rw-r--r--crypto/kerberosIV/appl/push/Makefile.in95
-rw-r--r--crypto/kerberosIV/appl/push/pfrom.in6
-rw-r--r--crypto/kerberosIV/appl/push/push.8139
-rw-r--r--crypto/kerberosIV/appl/push/push.c795
-rw-r--r--crypto/kerberosIV/appl/push/push.cat877
-rw-r--r--crypto/kerberosIV/appl/push/push_locl.h98
-rw-r--r--crypto/kerberosIV/appl/sample/Makefile.in83
-rw-r--r--crypto/kerberosIV/appl/sample/sample.h76
-rw-r--r--crypto/kerberosIV/appl/sample/sample_client.c168
-rw-r--r--crypto/kerberosIV/appl/sample/sample_server.c155
-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/ChangeLog286
-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.c672
-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.c718
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c734
-rw-r--r--crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c438
-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.c358
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/network.c165
-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.c977
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/telnet.c2313
-rw-r--r--crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h171
-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.c866
-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.c81
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/defs.h190
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/ext.h202
-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.c1893
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/telnetd.c1399
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/telnetd.h225
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/termstat.c140
-rw-r--r--crypto/kerberosIV/appl/telnet/telnetd/utility.c1165
168 files changed, 53816 insertions, 0 deletions
diff --git a/crypto/kerberosIV/appl/Makefile.in b/crypto/kerberosIV/appl/Makefile.in
new file mode 100644
index 0000000..74a3b9a
--- /dev/null
+++ b/crypto/kerberosIV/appl/Makefile.in
@@ -0,0 +1,43 @@
+# $Id: Makefile.in,v 1.31.6.1 2000/06/23 04:30:11 assar Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+SHELL = /bin/sh
+
+@SET_MAKE@
+
+SUBDIRS = sample kauth bsd movemail push afsutil \
+ popper xnlock kx kip @OTP_dir@ ftp telnet
+
+all:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) all); done
+
+Wall:
+ make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__"
+
+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:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) clean); done
+
+mostlyclean: clean
+
+distclean:
+ for i in $(SUBDIRS);\
+ do (cd $$i && $(MAKE) $(MFLAGS) distclean); done
+ rm -f Makefile *~
+
+realclean:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) realclean); done
+
+.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..b3370da
--- /dev/null
+++ b/crypto/kerberosIV/appl/afsutil/aklog.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#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.24.2.1 2000/06/23 02:31:15 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_1 (const char *cell, const char *filename)
+{
+ FILE *f;
+ static char buf[128];
+ char *p;
+
+ f = fopen(filename, "r");
+ if(f == NULL)
+ return NULL;
+ 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 NULL;
+}
+
+static const char *
+expand_cell_name(const char *cell)
+{
+ char *ret;
+
+ ret = expand_1(cell, _PATH_CELLSERVDB);
+ if (ret != NULL)
+ return ret;
+ ret = expand_1(cell, _PATH_ARLA_CELLSERVDB);
+ if (ret != NULL)
+ return ret;
+ return cell;
+}
+
+static int
+createuser (const 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)
+ f = fopen (_PATH_ARLA_THISCELL, "r");
+ if (f == NULL)
+ err (1, "open(%s, %s)", _PATH_THISCELL, _PATH_ARLA_THISCELL);
+ if (fgets (cellbuf, sizeof(cellbuf), f) == NULL)
+ err (1, "read cellname from %s %s", _PATH_THISCELL, _PATH_ARLA_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;
+ const 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..70246f9
--- /dev/null
+++ b/crypto/kerberosIV/appl/afsutil/kstring2key.c
@@ -0,0 +1,138 @@
+/*
+ * 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. 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.
+ */
+/* $FreeBSD$ */
+
+#include "config.h"
+
+RCSID("$Id: kstring2key.c,v 1.16 1999/12/02 16:58:28 joda Exp $");
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <err.h>
+
+#include <roken.h>
+
+#include <openssl/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:
+ strlcpy(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..c6704be
--- /dev/null
+++ b/crypto/kerberosIV/appl/afsutil/pagsh.c
@@ -0,0 +1,136 @@
+/*
+ * 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. 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.22 1999/12/02 16:58:28 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
new file mode 100644
index 0000000..fdda8c1
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/Makefile.in
@@ -0,0 +1,136 @@
+# $Id: Makefile.in,v 1.68 1999/03/27 17:05:34 joda Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+top_builddir = ../..
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@ -DBINDIR='"$(bindir)"'
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS = @LD_FLAGS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LIBS = @LIBS@
+LIB_DBM = @LIB_DBM@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+libexecdir = @libexecdir@
+bindir = @bindir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+# Beware, these are all setuid root programs
+PROG_SUIDBIN = rsh$(EXECSUFFIX) \
+ rcp$(EXECSUFFIX) \
+ rlogin$(EXECSUFFIX) \
+ su$(EXECSUFFIX)
+PROG_BIN = login$(EXECSUFFIX)
+PROG_LIBEXEC = rshd$(EXECSUFFIX) \
+ rlogind$(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 \
+ 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 \
+ 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 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 osfc2.o
+su_OBJS = su.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)
+
+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)$(libexecdir)
+ for x in $(PROG_LIBEXEC); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ done
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
+ for x in $(PROG_BIN); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+ -for x in $(PROG_SUIDBIN); do \
+ $(INSTALL_PROGRAM) -o root -m 04555 $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(PROG_LIBEXEC); do \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ done
+ for x in $(PROG_BIN); do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+ for x in $(PROG_SUIDBIN); 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
+
+KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
+KLIB_AFS=@KRB_KAFS_LIB@ $(KLIB)
+OTPLIB=@LIB_otp@
+LIBROKEN=-L../../lib/roken -lroken
+
+LIB_security=@LIB_security@
+
+rcp$(EXECSUFFIX): $(rcp_OBJS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rcp_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) $(LIB_security)
+
+rsh$(EXECSUFFIX): $(rsh_OBJS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rsh_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+rshd$(EXECSUFFIX): $(rshd_OBJS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rshd_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) $(LIB_security)
+
+rlogin$(EXECSUFFIX): $(rlogin_OBJS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogin_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+rlogind$(EXECSUFFIX): $(rlogind_OBJS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogind_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+login$(EXECSUFFIX): $(login_OBJS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(login_OBJS) $(OTPLIB) $(KLIB_AFS) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN) $(LIB_security)
+
+su$(EXECSUFFIX): $(su_OBJS)
+ $(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/README.login b/crypto/kerberosIV/appl/bsd/README.login
new file mode 100644
index 0000000..c072969
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/README.login
@@ -0,0 +1,20 @@
+This login has additional functionalities. They are all based on (part of)
+Wietse Venema's logdaemon package.
+
+
+The following defines can be used:
+1) LOGIN_ACCESS to allow access control on a per tty/user combination
+2) LOGALL to log all logins
+
+-Guido
+
+This login has some of Berkeley's paranoid/broken (depending on your point
+of view) Kerberos code conditionalized out, so that by default it works like
+klogin does at MIT-LCS. You can define KLOGIN_PARANOID to re-enable this code.
+This define also controls whether a warning message is printed when logging
+into a system with no krb.conf file, which usually means that Kerberos is
+not configured.
+
+-GAWollman
+
+(removed S/Key, /assar)
diff --git a/crypto/kerberosIV/appl/bsd/bsd_locl.h b/crypto/kerberosIV/appl/bsd/bsd_locl.h
new file mode 100644
index 0000000..565eb96
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/bsd_locl.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: bsd_locl.h,v 1.111 1999/12/02 16:58:28 joda Exp $ */
+/* $FreeBSD$ */
+
+#define LOGALL
+#ifndef KERBEROS
+#define KERBEROS
+#endif
+#define KLOGIN_PARANOID
+#define LOGIN_ACCESS
+#define PASSWD_FALLBACK
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Any better way to test NO_MOTD? */
+#if (SunOS >= 50) || defined(__hpux)
+#define NO_MOTD
+#endif
+
+#ifdef HAVE_SHADOW_H
+#define SYSV_SHADOW
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#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
+#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_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifndef S_ISTXT
+#ifdef S_ISVTX
+#define S_ISTXT S_ISVTX
+#else
+#define S_ISTXT 0
+#endif
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <signal.h>
+#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_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifndef NCARGS
+#define NCARGS 0x100000 /* (absolute) max # characters in exec arglist */
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_UTIME_H
+#include <utime.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_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.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_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#ifdef HAVE_SYS_STREAM_H
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif /* HAVE_SYS_UIO_H */
+#include <sys/stream.h>
+#endif /* HAVE_SYS_STREAM_H */
+
+#ifdef HAVE_SYS_PTYVAR_H
+#ifdef HAVE_SYS_PROC_H
+#include <sys/proc.h>
+#endif
+#ifdef HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif
+#ifdef HAVE_SYS_PTYIO_H
+#include <sys/ptyio.h>
+#endif
+#include <sys/ptyvar.h>
+#endif /* HAVE_SYS_PTYVAR_H */
+
+/* Cray stuff */
+#ifdef HAVE_UDB_H
+#include <udb.h>
+#endif
+#ifdef HAVE_SYS_CATEGORY_H
+#include <sys/category.h>
+#endif
+
+/* Strange ioctls that are not always defined */
+
+#ifndef TIOCPKT_FLUSHWRITE
+#define TIOCPKT_FLUSHWRITE 0x02
+#endif
+
+#ifndef TIOCPKT_NOSTOP
+#define TIOCPKT_NOSTOP 0x10
+#endif
+
+#ifndef TIOCPKT_DOSTOP
+#define TIOCPKT_DOSTOP 0x20
+#endif
+
+#ifndef TIOCPKT
+#define TIOCPKT _IOW('t', 112, int) /* pty: set/clear packet mode */
+#endif
+
+#ifdef HAVE_LASTLOG_H
+#include <lastlog.h>
+#endif
+
+#ifdef HAVE_LOGIN_H
+#include <login.h>
+#endif
+
+#ifdef HAVE_TTYENT_H
+#include <ttyent.h>
+#endif
+
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#ifndef UT_NAMESIZE
+#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name)
+#endif
+#endif
+
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+
+#ifdef HAVE_USERPW_H
+#include <userpw.h>
+#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
+
+#include <err.h>
+
+#include <roken.h>
+
+#ifdef SOCKS
+#include <socks.h>
+/* This doesn't belong here. */
+struct tm *localtime(const time_t *);
+struct hostent *gethostbyname(const char *);
+#endif
+
+#include <openssl/des.h>
+#include <krb.h>
+#include <kafs.h>
+
+int kcmd(int *sock, char **ahost, u_int16_t rport, char *locuser,
+ char *remuser, char *cmd, int *fd2p, KTEXT ticket,
+ char *service, char *realm, CREDENTIALS *cred,
+ Key_schedule schedule, MSG_DAT *msg_data,
+ struct sockaddr_in *laddr, struct sockaddr_in *faddr,
+ int32_t authopts);
+
+int krcmd(char **ahost, u_int16_t rport, char *remuser, char *cmd,
+ int *fd2p, char *realm);
+
+int krcmd_mutual(char **ahost, u_int16_t rport, char *remuser,
+ char *cmd,int *fd2p, char *realm,
+ CREDENTIALS *cred, Key_schedule sched);
+
+int klogin(struct passwd *pw, char *instance, char *localhost, char *password);
+
+#if 0
+typedef struct {
+ int cnt;
+ char *buf;
+} BUF;
+#endif
+
+char *colon(char *cp);
+int okname(char *cp0);
+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
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_MAILLOCK_H
+#include <maillock.h>
+#endif
+#include "pathnames.h"
+
+void stty_default (void);
+
+int utmpx_login(char *line, char *user, char *host);
+
+extern char **environ;
+
+void sysv_newenv(int argc, char **argv, struct passwd *pwd,
+ char *term, int pflag);
+
+int login_access(struct passwd *user, char *from);
+void fatal(int f, const char *msg, int syserr);
+
+extern int LEFT_JUSTIFIED;
+
+/* 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);
+
+#ifndef HAVE_SETPRIORITY
+#define setpriority(which, who, niceval) 0
+#endif
+
+#ifndef HAVE_GETPRIORITY
+#define getpriority(which, who) 0
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#ifndef _POSIX_VDISABLE
+#define _POSIX_VDISABLE 0
+#endif /* _POSIX_VDISABLE */
+#if SunOS == 40
+#include <sys/ttold.h>
+#endif
+
+#if defined(HAVE_SYS_TERMIO_H) && !defined(HAVE_TERMIOS_H)
+#include <sys/termio.h>
+#endif
+
+#ifndef CEOF
+#define CEOF 04
+#endif
+
+/* concession to Sun */
+#ifndef SIGUSR1
+#define SIGUSR1 30
+#endif
+
+#ifndef TIOCPKT_WINDOW
+#define TIOCPKT_WINDOW 0x80
+#endif
+
+int get_shell_port(int kerberos, int encryption);
+int get_login_port(int kerberos, int encryption);
+int speed_t2int (speed_t);
+speed_t int2speed_t (int);
+void ip_options_and_die (int sock, struct sockaddr_in *);
+void warning(const char *fmt, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+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);
+
+void paranoid_setuid (uid_t uid);
diff --git a/crypto/kerberosIV/appl/bsd/encrypt.c b/crypto/kerberosIV/appl/bsd/encrypt.c
new file mode 100644
index 0000000..9f835c6
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/encrypt.c
@@ -0,0 +1,305 @@
+/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)
+ * All rights reserved.
+ *
+ * This file is part of an SSL implementation written
+ * by Eric Young (eay@mincom.oz.au).
+ * The implementation was written so as to conform with Netscapes SSL
+ * specification. This library and applications are
+ * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
+ * as long as the following conditions are aheared to.
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed. If this code is used in a product,
+ * Eric Young should be given attribution as the author of the parts used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 Eric Young (eay@mincom.oz.au)
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "bsd_locl.h"
+
+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. */
+#define HDRSIZE 4
+
+#define n2l(c,l) (l =((u_int32_t)(*((c)++)))<<24, \
+ l|=((u_int32_t)(*((c)++)))<<16, \
+ l|=((u_int32_t)(*((c)++)))<< 8, \
+ l|=((u_int32_t)(*((c)++))))
+
+#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+/* This has some uglies in it but it works - even over sockets. */
+extern int errno;
+int des_rw_mode=DES_PCBC_MODE;
+int LEFT_JUSTIFIED = 0;
+
+int
+des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock *iv)
+{
+ /* data to be unencrypted */
+ int net_num=0;
+ 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[DES_RW_BSIZE];
+ static int unnet_start=0;
+ static int unnet_left=0;
+ int i;
+ long num=0,rnum;
+ unsigned char *p;
+
+ /* left over data from last decrypt */
+ if (unnet_left != 0)
+ {
+ if (unnet_left < len)
+ {
+ /* we still still need more data but will return
+ * with the number of bytes we have - should always
+ * check the return value */
+ memcpy(buf,&(unnet[unnet_start]),unnet_left);
+ /* eay 26/08/92 I had the next 2 lines
+ * reversed :-( */
+ i=unnet_left;
+ unnet_start=unnet_left=0;
+ }
+ else
+ {
+ memcpy(buf,&(unnet[unnet_start]),len);
+ unnet_start+=len;
+ unnet_left-=len;
+ i=len;
+ }
+ return(i);
+ }
+
+ /* We need to get more data. */
+ if (len > DES_RW_MAXWRITE) len=DES_RW_MAXWRITE;
+
+ /* first - get the length */
+ net_num=0;
+ while (net_num < HDRSIZE)
+ {
+ i=read(fd,&(net[net_num]),(unsigned int)HDRSIZE-net_num);
+ if ((i == -1) && (errno == EINTR)) continue;
+ if (i <= 0) return(0);
+ net_num+=i;
+ }
+
+ /* we now have at net_num bytes in net */
+ p=net;
+ num=0;
+ n2l(p,num);
+ /* 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 > DES_RW_MAXWRITE) || (num < 0)) /* error */
+ return(-1);
+ rnum=(num < 8)?8:((num+7)/8*8);
+
+ net_num=0;
+ while (net_num < rnum)
+ {
+ i=read(fd,&(net[net_num]),(unsigned int)rnum-net_num);
+ if ((i == -1) && (errno == EINTR)) continue;
+ if (i <= 0) return(0);
+ net_num+=i;
+ }
+
+ /* Check if there will be data left over. */
+ if (len < num)
+ {
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
+ num,sched,iv,DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
+ num,sched,iv,DES_DECRYPT);
+ memcpy(buf,unnet,len);
+ unnet_start=len;
+ unnet_left=num-len;
+
+ /* The following line is done because we return num
+ * as the number of bytes read. */
+ num=len;
+ }
+ else
+ {
+ /* >output is a multiple of 8 byes, if len < rnum
+ * >we must be careful. The user must be aware that this
+ * >routine will write more bytes than he asked for.
+ * >The length of the buffer must be correct.
+ * FIXED - Should be ok now 18-9-90 - eay */
+ if (len < rnum)
+ {
+ char tmpbuf[DES_RW_BSIZE];
+
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,
+ (des_cblock *)tmpbuf,
+ num,sched,iv,DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,
+ (des_cblock *)tmpbuf,
+ num,sched,iv,DES_DECRYPT);
+
+ /* eay 26/08/92 fix a bug that returned more
+ * bytes than you asked for (returned len bytes :-( */
+ if (LEFT_JUSTIFIED || (len >= 8))
+ memcpy(buf,tmpbuf,num);
+ else
+ memcpy(buf,tmpbuf+(8-num),num); /* Right justified */
+ }
+ else if (num >= 8)
+ {
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,num,sched,iv,
+ DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,num,sched,iv,
+ DES_DECRYPT);
+ }
+ else
+ {
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,8,sched,iv,
+ DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,8,sched,iv,
+ DES_DECRYPT);
+ if (!LEFT_JUSTIFIED)
+ memcpy(buf, buf+(8-num), num); /* Right justified */
+ }
+ }
+ return(num);
+}
+
+int
+des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock *iv)
+{
+ long rnum;
+ int i,j,k,outnum;
+ char outbuf[DES_RW_BSIZE+HDRSIZE];
+ char shortbuf[8];
+ char *p;
+ static int start=1;
+
+ /* If we are sending less than 8 bytes, the same char will look
+ * the same if we don't pad it out with random bytes */
+ if (start)
+ {
+ start=0;
+ srand(time(NULL));
+ }
+
+ /* lets recurse if we want to send the data in small chunks */
+ if (len > DES_RW_MAXWRITE)
+ {
+ j=0;
+ for (i=0; i<len; i+=k)
+ {
+ k=des_enc_write(fd,&(buf[i]),
+ ((len-i) > DES_RW_MAXWRITE)?DES_RW_MAXWRITE:(len-i),sched,iv);
+ if (k < 0)
+ return(k);
+ else
+ j+=k;
+ }
+ return(j);
+ }
+
+ /* write length first */
+ p=outbuf;
+ l2n(len,p);
+
+ /* pad short strings */
+ if (len < 8)
+ {
+ if (LEFT_JUSTIFIED)
+ {
+ p=shortbuf;
+ memcpy(shortbuf,buf,(unsigned int)len);
+ for (i=len; i<8; i++)
+ shortbuf[i]=rand();
+ rnum=8;
+ }
+ else
+ {
+ p=shortbuf;
+ for (i=0; i<8-len; i++)
+ shortbuf[i]=rand();
+ memcpy(shortbuf + 8 - len, buf, len);
+ rnum=8;
+ }
+ }
+ else
+ {
+ p=buf;
+ rnum=((len+7)/8*8); /* round up to nearest eight */
+ }
+
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]),
+ (long)((len<8)?8:len),sched,iv,DES_ENCRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]),
+ (long)((len<8)?8:len),sched,iv,DES_ENCRYPT);
+
+ /* output */
+ outnum=rnum+HDRSIZE;
+
+ for (j=0; j<outnum; j+=i)
+ {
+ /* eay 26/08/92 I was not doing writing from where we
+ * got upto. */
+ i=write(fd,&(outbuf[j]),(unsigned int)(outnum-j));
+ if (i == -1)
+ {
+ if (errno == EINTR)
+ i=0;
+ else /* This is really a bad error - very bad
+ * It will stuff-up both ends. */
+ return(-1);
+ }
+ }
+
+ return(len);
+}
diff --git a/crypto/kerberosIV/appl/bsd/forkpty.c b/crypto/kerberosIV/appl/bsd/forkpty.c
new file mode 100644
index 0000000..891fb91
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/forkpty.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "bsd_locl.h"
+
+#ifndef HAVE_FORKPTY
+
+RCSID("$Id: forkpty.c,v 1.57 1999/12/02 16:58:28 joda Exp $");
+
+/* Only CRAY is known to have problems with forkpty(). */
+#if defined(CRAY)
+static int forkpty_ok = 0;
+#else
+static int forkpty_ok = 1;
+#endif
+
+#ifndef HAVE_PTSNAME
+static char *ptsname(int fd)
+{
+#ifdef HAVE_TTYNAME
+ return ttyname(fd);
+#else
+ return NULL;
+#endif
+}
+#endif
+
+#ifndef HAVE_GRANTPT
+#define grantpt(fdm) (0)
+#endif
+
+#ifndef HAVE_UNLOCKPT
+#define unlockpt(fdm) (0)
+#endif
+
+#ifndef HAVE_VHANGUP
+#define vhangup() (0)
+#endif
+
+#ifndef HAVE_REVOKE
+static
+void
+revoke(char *line)
+{
+ int slave;
+ RETSIGTYPE (*ofun)();
+
+ if ( (slave = open(line, O_RDWR)) < 0)
+ return;
+
+ ofun = signal(SIGHUP, SIG_IGN);
+ vhangup();
+ signal(SIGHUP, ofun);
+ /*
+ * Some systems (atleast SunOS4) want to have the slave end open
+ * at all times to prevent a race in the child. Login will close
+ * it so it should really not be a problem. However for the
+ * paranoid we use the close on exec flag so it will only be open
+ * in the parent. Additionally since this will be the controlling
+ * tty of rlogind the final vhangup() in rlogind should hangup all
+ * processes. A working revoke would of course have been prefered
+ * though (sigh).
+ */
+ fcntl(slave, F_SETFD, 1);
+ /* close(slave); */
+}
+#endif
+
+
+static int pty_major, pty_minor;
+
+static void
+pty_scan_start(void)
+{
+ pty_major = -1;
+ pty_minor = 0;
+}
+
+static char *bsd_1 = "0123456789abcdefghijklmnopqrstuv";
+/* there are many more */
+static char *bsd_2 = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+static int
+pty_scan_next(char *buf, size_t sz)
+{
+#ifdef CRAY
+ if(++pty_major >= sysconf(_SC_CRAY_NPTY))
+ return -1;
+ snprintf(buf, sz, "/dev/pty/%03d", pty_major);
+#else
+ if(++pty_major == strlen(bsd_1)){
+ pty_major = 0;
+ if(++pty_minor == strlen(bsd_2))
+ return -1;
+ }
+#ifdef __hpux
+ snprintf(buf, sz, "/dev/ptym/pty%c%c", bsd_2[pty_major], bsd_1[pty_minor]);
+#else
+ snprintf(buf, sz, "/dev/pty%c%c", bsd_2[pty_major], bsd_1[pty_minor]);
+#endif /* __hpux */
+#endif /* CRAY */
+ return 0;
+}
+
+static void
+pty_scan_tty(char *buf, size_t sz)
+{
+#ifdef CRAY
+ snprintf(buf, sz, "/dev/ttyp%03d", pty_major);
+#elif defined(__hpux)
+ snprintf(buf, sz, "/dev/pty/tty%c%c", bsd_2[pty_major], bsd_1[pty_minor]);
+#else
+ snprintf(buf, sz, "/dev/tty%c%c", bsd_2[pty_major], bsd_1[pty_minor]);
+#endif
+}
+
+static int
+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",
+ "/dev/ptm", "/dev/ptym/clone", 0 };
+ int fdm;
+ const char *const *q;
+
+ for (q = clone; *q; q++) {
+ fdm = open(*q, O_RDWR);
+ if (fdm >= 0)
+ break;
+ }
+ if (fdm >= 0) {
+ char *ptr1;
+ if ((ptr1 = ptsname(fdm)) != NULL) /* Get slave's name */
+ /* Return name of slave */
+ strlcpy(pts_name, ptr1, pts_name_sz);
+ else {
+ close(fdm);
+ return(-4);
+ }
+ if (grantpt(fdm) < 0) { /* Grant access to slave */
+ close(fdm);
+ return(-2);
+ }
+ if (unlockpt(fdm) < 0) { /* Clear slave's lock flag */
+ close(fdm);
+ return(-3);
+ }
+ return(fdm); /* return fd of master */
+ }
+ return -1;
+}
+
+static int
+ptym_open_bsd_flavor(char *pts_name, size_t pts_name_sz, int *streams_pty)
+{
+ int fdm;
+ char ptm[MaxPathLen];
+
+ pty_scan_start();
+
+ while (pty_scan_next(ptm, sizeof(ptm)) != -1) {
+ fdm = open(ptm, O_RDWR);
+ if (fdm < 0)
+ continue;
+#if SunOS == 40
+ /* Avoid a bug in SunOS4 ttydriver */
+ if (fdm > 0) {
+ int pgrp;
+ if ((ioctl(fdm, TIOCGPGRP, &pgrp) == -1)
+ && (errno == EIO))
+ /* All fine */;
+ else {
+ close(fdm);
+ continue;
+ }
+ }
+#endif
+ pty_scan_tty(pts_name, sizeof(ptm));
+#if CRAY
+ /* this is some magic from the telnet code */
+ {
+ struct stat sb;
+ if(stat(pts_name, &sb) < 0) {
+ close(fdm);
+ continue;
+ }
+ if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
+ chown(pts_name, 0, 0);
+ chmod(pts_name, 0600);
+ close(fdm);
+ fdm = open(ptm, 2);
+ if (fdm < 0)
+ continue;
+ }
+ }
+ /*
+ * Now it should be safe...check for accessability.
+ */
+ if (access(pts_name, 6) != 0){
+ /* no tty side to pty so skip it */
+ close(fdm);
+ continue;
+ }
+#endif
+ return fdm; /* All done! */
+ }
+
+ /* We failed to find BSD style pty */
+ errno = ENOENT;
+ return -1;
+}
+
+/*
+ *
+ * Open a master pty either using the STREAM flavor or the BSD flavor.
+ * Depending on if there are any free ptys in the different classes we
+ * need to try both. Normally try STREAMS first and then BSD.
+ *
+ * Kludge alert: Under HP-UX 10 and perhaps other systems STREAM ptys
+ * doesn't get initialized properly so we try them in different order
+ * until the problem has been resolved.
+ *
+ */
+static int
+ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty)
+{
+ int fdm;
+
+#ifdef HAVE__GETPTY
+ {
+ char *p = _getpty(&fdm, O_RDWR, 0600, 1);
+ if (p) {
+ *streams_pty = 1;
+ strlcpy (pts_name, p, pts_name_sz);
+ return fdm;
+ }
+ }
+#endif
+
+#ifdef STREAMSPTY
+ fdm = ptym_open_streams_flavor(pts_name, pts_name_sz, streams_pty);
+ if (fdm >= 0)
+ {
+ *streams_pty = 1;
+ return fdm;
+ }
+#endif
+
+ fdm = ptym_open_bsd_flavor(pts_name, pts_name_sz, streams_pty);
+ if (fdm >= 0)
+ {
+ *streams_pty = 0;
+ return fdm;
+ }
+
+#ifndef STREAMSPTY
+ fdm = ptym_open_streams_flavor(pts_name, pts_name_sz, streams_pty);
+ if (fdm >= 0)
+ {
+ *streams_pty = 1;
+ return fdm;
+ }
+#endif
+
+ return -1;
+}
+
+static int
+maybe_push_modules(int fd, char **modules)
+{
+#ifdef I_PUSH
+ char **p;
+ int err;
+
+ for(p=modules; *p; p++){
+ err=ioctl(fd, I_FIND, *p);
+ if(err == 1)
+ break;
+ if(err < 0 && errno != EINVAL)
+ return -17;
+ /* 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)
+ return -17;
+ }
+#endif
+ return 0;
+}
+
+static int
+ptys_open(int fdm, char *pts_name, int streams_pty)
+{
+ int fds;
+
+ if (streams_pty) {
+ /* Streams style slave ptys */
+ if ( (fds = open(pts_name, O_RDWR)) < 0) {
+ close(fdm);
+ return(-5);
+ }
+
+ {
+ char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL };
+ char *ptymodules[] = { "pckt", NULL };
+
+ if(maybe_push_modules(fds, ttymodules)<0){
+ close(fdm);
+ close(fds);
+ return -6;
+ }
+ if(maybe_push_modules(fdm, ptymodules)<0){
+ close(fdm);
+ close(fds);
+ return -7;
+ }
+ }
+ } else {
+ /* BSD style slave ptys */
+ struct group *grptr;
+ int gid;
+ if ( (grptr = getgrnam("tty")) != NULL)
+ gid = grptr->gr_gid;
+ else
+ gid = -1; /* group tty is not in the group file */
+
+ /* Grant access to slave */
+ 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);
+ return(-1);
+ }
+ }
+ return(fds);
+}
+
+int
+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;
+ char pts_name[20];
+
+ if (!forkpty_ok)
+ fatal(0, "Protocol not yet supported, use telnet", 0);
+
+ if ( (fdm = ptym_open(pts_name, sizeof(pts_name), &streams_pty)) < 0)
+ return -1;
+
+ if (slave_name != NULL)
+ /* Return name of slave */
+ strlcpy(slave_name, pts_name, slave_name_sz);
+
+ pid = fork();
+ if (pid < 0)
+ return(-1);
+ else if (pid == 0) { /* Child */
+ if (setsid() < 0)
+ fatal(0, "setsid() failure", errno);
+
+ revoke(slave_name);
+
+#if defined(NeXT) || defined(ultrix)
+ /* The NeXT is severely broken, this makes things slightly
+ * better but we still doesn't get a working pty. If there
+ * where a TIOCSCTTY we could perhaps fix things but... The
+ * same problem also exists in xterm! */
+ if (setpgrp(0, 0) < 0)
+ fatal(0, "NeXT kludge failed setpgrp", errno);
+#endif
+
+ /* SVR4 acquires controlling terminal on open() */
+ if ( (fds = ptys_open(fdm, pts_name, streams_pty)) < 0)
+ return -1;
+ close(fdm); /* All done with master in child */
+
+#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(__hpux)
+ /* 44BSD way to acquire controlling terminal */
+ /* !CIBAUD to avoid doing this under SunOS */
+ if (ioctl(fds, TIOCSCTTY, (char *) 0) < 0)
+ return -1;
+#endif
+#if defined(NeXT)
+ {
+ int t = open("/dev/tty", O_RDWR);
+ if (t < 0)
+ fatal(0, "Failed to open /dev/tty", errno);
+ close(fds);
+ fds = t;
+ }
+#endif
+ /* Set slave's termios and window size */
+ if (slave_termios != NULL) {
+ if (tcsetattr(fds, TCSANOW, slave_termios) < 0)
+ return -1;
+ }
+#ifdef TIOCSWINSZ
+ if (slave_winsize != NULL) {
+ if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)
+ return -1;
+ }
+#endif
+ /* slave becomes stdin/stdout/stderr of child */
+ if (dup2(fds, STDIN_FILENO) != STDIN_FILENO)
+ return -1;
+ if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO)
+ return -1;
+ if (dup2(fds, STDERR_FILENO) != STDERR_FILENO)
+ return -1;
+ if (fds > STDERR_FILENO)
+ close(fds);
+ return(0); /* child returns 0 just like fork() */
+ }
+ else { /* Parent */
+ *ptrfdm = fdm; /* Return fd of master */
+ 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
new file mode 100644
index 0000000..93b2b70
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/kcmd.c
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: kcmd.c,v 1.20.4.1 2000/10/10 12:55:55 assar Exp $");
+
+#define START_PORT 5120 /* arbitrary */
+
+static int
+getport(int *alport)
+{
+ struct sockaddr_in sin;
+ int s;
+
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ return (-1);
+ for (;;) {
+ sin.sin_port = htons((u_short)*alport);
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
+ close(s);
+ return (-1);
+ }
+ (*alport)--;
+#ifdef ATHENA_COMPAT
+ if (*alport == IPPORT_RESERVED/2) {
+#else
+ if (*alport == IPPORT_RESERVED) {
+#endif
+ close(s);
+ errno = EAGAIN; /* close */
+ return (-1);
+ }
+ }
+}
+
+int
+kcmd(int *sock,
+ char **ahost,
+ u_int16_t rport,
+ char *locuser,
+ char *remuser,
+ char *cmd,
+ int *fd2p,
+ KTEXT ticket,
+ char *service,
+ char *realm,
+ CREDENTIALS *cred,
+ Key_schedule schedule,
+ MSG_DAT *msg_data,
+ struct sockaddr_in *laddr,
+ struct sockaddr_in *faddr,
+ int32_t authopts)
+{
+ int s, timo = 1;
+ pid_t pid;
+ struct sockaddr_in sin, from;
+ char c;
+#ifdef ATHENA_COMPAT
+ int lport = IPPORT_RESERVED - 1;
+#else
+ int lport = START_PORT;
+#endif
+ struct hostent *hp;
+ int rc;
+ char *host_save;
+ int status;
+ char **h_addr_list;
+
+ pid = getpid();
+ hp = gethostbyname(*ahost);
+ if (hp == NULL) {
+ /* fprintf(stderr, "%s: unknown host\n", *ahost); */
+ return (-1);
+ }
+
+ host_save = strdup(hp->h_name);
+ 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')
+ realm = krb_realmofhost(host_save);
+
+ for (;;) {
+ s = getport(&lport);
+ if (s < 0) {
+ if (errno == EAGAIN)
+ warnx("kcmd(socket): All ports in use\n");
+ else
+ warn("kcmd: socket");
+ return (-1);
+ }
+ sin.sin_family = hp->h_addrtype;
+ 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;
+ close(s);
+ if (errno == EADDRINUSE) {
+ lport--;
+ continue;
+ }
+ /*
+ * don't wait very long for Kerberos rcmd.
+ */
+ if (errno == ECONNREFUSED && timo <= 4) {
+ /* sleep(timo); don't wait at all here */
+ timo *= 2;
+ continue;
+ }
+ if (h_addr_list[1] != NULL) {
+ warn ("kcmd: connect (%s)",
+ inet_ntoa(sin.sin_addr));
+ h_addr_list++;
+ memcpy(&sin.sin_addr,
+ *h_addr_list,
+ sizeof(sin.sin_addr));
+ fprintf(stderr, "Trying %s...\n",
+ inet_ntoa(sin.sin_addr));
+ continue;
+ }
+ if (errno != ECONNREFUSED)
+ warn ("connect(%s)", hp->h_name);
+ return (-1);
+ }
+ lport--;
+ if (fd2p == 0) {
+ write(s, "", 1);
+ lport = 0;
+ } else {
+ char num[8];
+ int s2 = getport(&lport), s3;
+ int len = sizeof(from);
+
+ if (s2 < 0) {
+ status = -1;
+ goto bad;
+ }
+ listen(s2, 1);
+ snprintf(num, sizeof(num), "%d", lport);
+ if (write(s, num, strlen(num) + 1) != strlen(num) + 1) {
+ warn("kcmd(write): setting up stderr");
+ close(s2);
+ status = -1;
+ goto bad;
+ }
+ {
+ fd_set fds;
+ FD_ZERO(&fds);
+ if (s >= FD_SETSIZE || s2 >= FD_SETSIZE) {
+ warnx("file descriptor too large");
+ close(s);
+ close(s2);
+ status = -1;
+ goto bad;
+ }
+
+ FD_SET(s, &fds);
+ FD_SET(s2, &fds);
+ status = select(FD_SETSIZE, &fds, NULL, NULL, NULL);
+ if(FD_ISSET(s, &fds)){
+ warnx("kcmd: connection unexpectedly closed.");
+ close(s2);
+ status = -1;
+ goto bad;
+ }
+ }
+ s3 = accept(s2, (struct sockaddr *)&from, &len);
+ close(s2);
+ if (s3 < 0) {
+ warn ("kcmd: accept");
+ lport = 0;
+ status = -1;
+ goto bad;
+ }
+
+ *fd2p = s3;
+ from.sin_port = ntohs((u_short)from.sin_port);
+ if (from.sin_family != AF_INET ||
+ from.sin_port >= IPPORT_RESERVED) {
+ warnx("kcmd(socket): "
+ "protocol failure in circuit setup.");
+ status = -1;
+ goto bad2;
+ }
+ }
+ /*
+ * Kerberos-authenticated service. Don't have to send locuser,
+ * since its already in the ticket, and we'll extract it on
+ * the other side.
+ */
+ /* write(s, locuser, strlen(locuser)+1); */
+
+ /* set up the needed stuff for mutual auth, but only if necessary */
+ if (authopts & KOPT_DO_MUTUAL) {
+ int sin_len;
+ *faddr = sin;
+
+ sin_len = sizeof(struct sockaddr_in);
+ if (getsockname(s, (struct sockaddr *)laddr, &sin_len) < 0) {
+ warn("kcmd(getsockname)");
+ status = -1;
+ goto bad2;
+ }
+ }
+ if ((status = krb_sendauth(authopts, s, ticket, service, *ahost,
+ realm, (unsigned long) getpid(), msg_data,
+ cred, schedule,
+ laddr,
+ faddr,
+ "KCMDV0.1")) != KSUCCESS)
+ goto bad2;
+
+ write(s, remuser, strlen(remuser)+1);
+ write(s, cmd, strlen(cmd)+1);
+
+ if ((rc = read(s, &c, 1)) != 1) {
+ if (rc == -1)
+ warn("read(%s)", *ahost);
+ else
+ warnx("kcmd: bad connection with remote host");
+ status = -1;
+ goto bad2;
+ }
+ if (c != '\0') {
+ while (read(s, &c, 1) == 1) {
+ write(2, &c, 1);
+ if (c == '\n')
+ break;
+ }
+ status = -1;
+ goto bad2;
+ }
+ *sock = s;
+ return (KSUCCESS);
+bad2:
+ if (lport)
+ close(*fd2p);
+bad:
+ close(s);
+ return (status);
+}
diff --git a/crypto/kerberosIV/appl/bsd/klogin.c b/crypto/kerberosIV/appl/bsd/klogin.c
new file mode 100644
index 0000000..df21dbf
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/klogin.c
@@ -0,0 +1,229 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * 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 "bsd_locl.h"
+
+RCSID("$Id: klogin.c,v 1.27 1999/10/04 16:11:48 bg Exp $");
+
+#ifdef KERBEROS
+
+#define VERIFY_SERVICE "rcmd"
+
+extern int notickets;
+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 ret;
+ int n;
+ char rlm[256];
+
+ /* First try to verify against the supplied realm. */
+ ret = krb_get_pw_in_tkt(name, instance, realm, service, realm, life,
+ password);
+ if(ret == 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) {
+ ret = krb_get_pw_in_tkt(name, instance, rlm,service, rlm,life, password);
+ if (ret == KSUCCESS)
+ return KSUCCESS;
+ }
+
+ return ret;
+}
+
+/*
+ * Attempt to log the user in using Kerberos authentication
+ *
+ * return 0 on success (will be logged in)
+ * 1 if Kerberos failed (try local password in login)
+ */
+int
+klogin(struct passwd *pw, char *instance, char *localhost, char *password)
+{
+ int kerror;
+ AUTH_DAT authdata;
+ KTEXT_ST ticket;
+ struct hostent *hp;
+ u_int32_t faddr;
+ char realm[REALM_SZ], savehost[MaxHostNameLen];
+ extern int noticketsdontcomplain;
+
+#ifdef KLOGIN_PARANOID
+ noticketsdontcomplain = 0; /* enable warning message */
+#endif
+ /*
+ * Root logins don't use Kerberos.
+ * If we have a realm, try getting a ticket-granting ticket
+ * and using it to authenticate. Otherwise, return
+ * failure so that we can try the normal passwd file
+ * for a password. If that's ok, log the user in
+ * without issuing any tickets.
+ */
+ if (strcmp(pw->pw_name, "root") == 0 ||
+ krb_get_lrealm(realm, 1) != KSUCCESS)
+ return (1);
+
+ noticketsdontcomplain = 0; /* enable warning message */
+
+ /*
+ * get TGT for local realm
+ * tickets are stored in a file named TKT_ROOT plus uid
+ * except for user.root tickets.
+ */
+
+ if (strcmp(instance, "root") != 0)
+ snprintf(tkt_location, sizeof(tkt_location),
+ "%s%u_%u",
+ TKT_ROOT, (unsigned)pw->pw_uid, (unsigned)getpid());
+ else {
+ snprintf(tkt_location, sizeof(tkt_location),
+ "%s_root_%d", TKT_ROOT,
+ (unsigned)pw->pw_uid);
+ }
+ krbtkfile_env = tkt_location;
+ krb_set_tkt_string(tkt_location);
+
+ /*
+ * 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
+ * ensure that we are not talking to a bogus Kerberos server.
+ *
+ * There are 2 cases where we still allow a login:
+ * 1: the VERIFY_SERVICE doesn't exist in the KDC
+ * 2: local host has no srvtab, as (hopefully) indicated by a
+ * return value of RD_AP_UNDEC from krb_rd_req().
+ */
+ if (kerror != INTK_OK) {
+ if (kerror != INTK_BADPW && kerror != KDC_PR_UNKNOWN) {
+ syslog(LOG_ERR, "Kerberos intkt error: %s",
+ krb_get_err_text(kerror));
+ dest_tkt();
+ }
+ return (1);
+ }
+
+ if (chown(TKT_FILE, pw->pw_uid, pw->pw_gid) < 0)
+ syslog(LOG_ERR, "chown tkfile (%s): %m", TKT_FILE);
+
+ strlcpy(savehost, krb_get_phost(localhost), sizeof(savehost));
+
+#ifdef KLOGIN_PARANOID
+ /*
+ * if the "VERIFY_SERVICE" doesn't exist in the KDC for this host,
+ * don't allow kerberos login, also log the error condition.
+ */
+
+ kerror = krb_mk_req(&ticket, VERIFY_SERVICE, savehost, realm, 33);
+ if (kerror == KDC_PR_UNKNOWN) {
+ syslog(LOG_NOTICE,
+ "warning: TGT not verified (%s); %s.%s not registered, or srvtab is wrong?",
+ krb_get_err_text(kerror), VERIFY_SERVICE, savehost);
+ notickets = 0;
+ return (1);
+ }
+
+ if (kerror != KSUCCESS) {
+ warnx("unable to use TGT: (%s)", krb_get_err_text(kerror));
+ syslog(LOG_NOTICE, "unable to use TGT: (%s)",
+ krb_get_err_text(kerror));
+ dest_tkt();
+ return (1);
+ }
+
+ if (!(hp = gethostbyname(localhost))) {
+ syslog(LOG_ERR, "couldn't get local host address");
+ dest_tkt();
+ return (1);
+ }
+
+ memcpy(&faddr, hp->h_addr, sizeof(faddr));
+
+ kerror = krb_rd_req(&ticket, VERIFY_SERVICE, savehost, faddr,
+ &authdata, "");
+
+ if (kerror == KSUCCESS) {
+ notickets = 0;
+ return (0);
+ }
+
+ /* undecipherable: probably didn't have a srvtab on the local host */
+ if (kerror == RD_AP_UNDEC) {
+ syslog(LOG_NOTICE, "krb_rd_req: (%s)\n", krb_get_err_text(kerror));
+ dest_tkt();
+ return (1);
+ }
+ /* failed for some other reason */
+ warnx("unable to verify %s ticket: (%s)", VERIFY_SERVICE,
+ krb_get_err_text(kerror));
+ syslog(LOG_NOTICE, "couldn't verify %s ticket: %s", VERIFY_SERVICE,
+ krb_get_err_text(kerror));
+ dest_tkt();
+ return (1);
+#else
+ notickets = 0;
+ return (0);
+#endif
+}
+#endif
diff --git a/crypto/kerberosIV/appl/bsd/krcmd.c b/crypto/kerberosIV/appl/bsd/krcmd.c
new file mode 100644
index 0000000..8c3c6f3
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/krcmd.c
@@ -0,0 +1,117 @@
+/*
+ * 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 "bsd_locl.h"
+
+RCSID("$Id: krcmd.c,v 1.10 1997/03/30 18:20:18 joda Exp $");
+
+#define SERVICE_NAME "rcmd"
+
+/*
+ * krcmd: simplified version of Athena's "kcmd"
+ * returns a socket attached to the destination, -1 or krb error on error
+ * if fd2p is non-NULL, another socket is filled in for it
+ */
+
+int
+krcmd(char **ahost, u_short rport, char *remuser, char *cmd, int *fd2p, char *realm)
+{
+ int sock = -1, err = 0;
+ KTEXT_ST ticket;
+ long authopts = 0L;
+
+ err = kcmd(
+ &sock,
+ ahost,
+ rport,
+ NULL, /* locuser not used */
+ remuser,
+ cmd,
+ fd2p,
+ &ticket,
+ SERVICE_NAME,
+ realm,
+ (CREDENTIALS *) NULL, /* credentials not used */
+ 0, /* key schedule not used */
+ (MSG_DAT *) NULL, /* MSG_DAT not used */
+ (struct sockaddr_in *) NULL, /* local addr not used */
+ (struct sockaddr_in *) NULL, /* foreign addr not used */
+ authopts
+ );
+
+ if (err > KSUCCESS && err < MAX_KRB_ERRORS) {
+ warning("krcmd: %s", krb_get_err_text(err));
+ return(-1);
+ }
+ if (err < 0)
+ return(-1);
+ return(sock);
+}
+
+int
+krcmd_mutual(char **ahost, u_short rport, char *remuser, char *cmd, int *fd2p, char *realm, CREDENTIALS *cred, Key_schedule sched)
+{
+ int sock, err;
+ KTEXT_ST ticket;
+ MSG_DAT msg_dat;
+ struct sockaddr_in laddr, faddr;
+ long authopts = KOPT_DO_MUTUAL;
+
+ err = kcmd(
+ &sock,
+ ahost,
+ rport,
+ NULL, /* locuser not used */
+ remuser,
+ cmd,
+ fd2p,
+ &ticket,
+ SERVICE_NAME,
+ realm,
+ cred, /* filled in */
+ sched, /* filled in */
+ &msg_dat, /* filled in */
+ &laddr, /* filled in */
+ &faddr, /* filled in */
+ authopts
+ );
+
+ if (err > KSUCCESS && err < MAX_KRB_ERRORS) {
+ warnx("krcmd_mutual: %s", krb_get_err_text(err));
+ return(-1);
+ }
+
+ if (err < 0)
+ return (-1);
+ return(sock);
+}
diff --git a/crypto/kerberosIV/appl/bsd/login.c b/crypto/kerberosIV/appl/bsd/login.c
new file mode 100644
index 0000000..f2f0873
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/login.c
@@ -0,0 +1,1118 @@
+/*-
+ * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
+ * 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.
+ */
+
+/*
+ * login [ name ]
+ * login -h hostname (for telnetd, etc.)
+ * login -f name (for pre-authenticated login: datakit, xterm, etc.)
+ */
+
+#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.125.2.2 2000/06/23 02:33:07 assar Exp $");
+
+#ifdef OTP
+#include <otp.h>
+#endif
+
+#include "sysv_default.h"
+#ifdef SYSV_SHADOW
+#include "sysv_shadow.h"
+#endif
+
+static void badlogin (char *);
+static void checknologin (void);
+static void dolastlog (int);
+static void getloginname (int);
+static int rootterm (char *);
+static char *stypeof (char *);
+static RETSIGTYPE timedout (int);
+static int doremotelogin (char *);
+void login_fbtab (char *, uid_t, gid_t);
+#ifdef KERBEROS
+int klogin (struct passwd *, char *, char *, char *);
+#endif
+
+#define TTYGRPNAME "tty" /* name of group to own ttys */
+
+/*
+ * This bounds the time given to login. Change it in
+ * `/etc/default/login'.
+ */
+
+static u_int login_timeout;
+
+#ifdef KERBEROS
+int notickets = 1;
+int noticketsdontcomplain = 1;
+char *instance;
+char *krbtkfile_env;
+int authok;
+#endif
+
+#ifdef HAVE_SHADOW_H
+static struct spwd *spwd = NULL;
+#endif
+
+static char *ttyprompt;
+
+static struct passwd *pwd;
+static int failures;
+static char term[64], *hostname, *username, *tty;
+
+static char rusername[100], lusername[100];
+
+static int
+change_passwd(struct passwd *who)
+{
+ 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:
+ waitpid(pid, &status, 0);
+ return (status);
+ }
+}
+
+#ifndef NO_MOTD /* message of the day stuff */
+
+jmp_buf motdinterrupt;
+
+static RETSIGTYPE
+sigint(int signo)
+{
+ longjmp(motdinterrupt, 1);
+}
+
+static void
+motd(void)
+{
+ int fd, nchars;
+ RETSIGTYPE (*oldint)();
+ char tbuf[8192];
+
+ if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+ return;
+ oldint = signal(SIGINT, sigint);
+ if (setjmp(motdinterrupt) == 0)
+ while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+ write(fileno(stdout), tbuf, nchars);
+ signal(SIGINT, oldint);
+ close(fd);
+}
+
+#endif /* !NO_MOTD */
+
+#define AUTH_NONE 0
+#define AUTH_OTP 1
+
+/*
+ * getpwnam and try to detect the worst form of NIS attack.
+ */
+
+static struct passwd *
+paranoid_getpwnam (char *user)
+{
+ struct passwd *p;
+
+ p = k_getpwnam (user);
+ if (p == NULL)
+ return p;
+ if (p->pw_uid == 0 && strcmp (username, "root") != 0) {
+ syslog (LOG_ALERT,
+ "NIS attack, user %s has uid 0", username);
+ return NULL;
+ }
+ return p;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct group *gr;
+ int ask, ch, cnt, fflag, hflag, pflag, quietlog, nomailcheck;
+ int rootlogin, rval;
+ int rflag;
+ int changepass = 0;
+ uid_t uid;
+ char *domain, *p, passwd[128], *ttyn;
+ char tbuf[MaxPathLen + 2], tname[sizeof(_PATH_TTY) + 10];
+ 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 */
+
+ set_progname(argv[0]);
+
+ openlog("login", LOG_ODELAY, LOG_AUTH);
+
+ /* Read defaults file and set the login timeout period. */
+ sysv_defaults();
+ login_timeout = atoi(default_timeout);
+ maxtrys = atoi(default_maxtrys);
+ if (sscanf(default_umask, "%o", &mask) != 1 || (mask & ~0777))
+ syslog(LOG_WARNING, "bad umask default: %s", default_umask);
+ else
+ umask(mask);
+
+ signal(SIGALRM, timedout);
+ alarm(login_timeout);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ setpriority(PRIO_PROCESS, 0, 0);
+
+ /*
+ * -p is used by getty to tell login not to destroy the environment
+ * -f is used to skip a second login authentication
+ * -h is used by other servers to pass the name of the remote
+ * host to login so that it may be placed in utmp and wtmp
+ * -r is used by old-style rlogind to execute the autologin protocol
+ */
+
+ *full_hostname = '\0';
+ domain = NULL;
+ if (gethostname(localhost, sizeof(localhost)) < 0)
+ syslog(LOG_ERR, "couldn't get local hostname: %m");
+ else
+ domain = strchr(localhost, '.');
+
+ fflag = hflag = pflag = rflag = 0;
+ uid = getuid();
+ while ((ch = getopt(argc, argv, "a:d:fh:pr:")) != -1)
+ switch (ch) {
+ 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;
+ case 'd':
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'h':
+ if (rflag || hflag) {
+ printf("Only one of -r and -h allowed\n");
+ exit(1);
+ }
+ if (uid)
+ errx(1, "-h option: %s", strerror(EPERM));
+ hflag = 1;
+ strlcpy(full_hostname,
+ optarg,
+ sizeof(full_hostname));
+ if (domain && (p = strchr(optarg, '.')) &&
+ strcasecmp(p, domain) == 0)
+ *p = 0;
+ hostname = optarg;
+ break;
+ case 'p':
+ if (getuid()) {
+ warnx("-p for super-user only.");
+ exit(1);
+ }
+ pflag = 1;
+ break;
+ case 'r':
+ if (rflag || hflag) {
+ warnx("Only one of -r and -h allowed\n");
+ exit(1);
+ }
+ if (getuid()) {
+ warnx("-r for super-user only.");
+ exit(1);
+ }
+ rflag = 1;
+ strlcpy(full_hostname,
+ optarg,
+ sizeof(full_hostname));
+ if (domain && (p = strchr(optarg, '.')) &&
+ strcasecmp(p, domain) == 0)
+ *p = 0;
+ hostname = optarg;
+ fflag = (doremotelogin(full_hostname) == 0);
+ break;
+ case '?':
+ default:
+ if (!uid)
+ syslog(LOG_ERR, "invalid flag %c", ch);
+ fprintf(stderr,
+ "usage: login [-fp]"
+#ifdef OTP
+ " [-a otp]"
+#endif
+ " [-h hostname | -r hostname] [username]\n");
+ exit(1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (geteuid() != 0) {
+ warnx("only root may use login, use su");
+ /* Or install login setuid root, which is not necessary */
+ sleep(10);
+ exit(1);
+ }
+ /*
+ * Figure out if we should ask for the username or not. The name
+ * may be given on the command line or via the environment, and
+ * it may even be in the terminal input queue.
+ */
+ if (rflag) {
+ username = lusername;
+ ask = 0;
+ } else
+ if (*argv && strchr(*argv, '=')) {
+ ask = 1;
+ } else
+ if (*argv && strcmp(*argv, "-") == 0) {
+ argc--;
+ argv++;
+ ask = 1;
+ } else
+ if (*argv) {
+ username = *argv;
+ ask = 0;
+ argc--;
+ argv++;
+ } else if ((ttyprompt = getenv("TTYPROMPT")) && *ttyprompt) {
+ getloginname(0);
+ ask = 0;
+ } else
+ ask = 1;
+
+ /* Default tty settings. */
+ stty_default();
+
+ for (cnt = getdtablesize(); cnt > 2; cnt--)
+ close(cnt);
+
+ /*
+ * Determine the tty name. BSD takes the basename, SYSV4 takes
+ * whatever remains after stripping the "/dev/" prefix. The code
+ * below should produce sensible results in either environment.
+ */
+ ttyn = ttyname(STDIN_FILENO);
+ if (ttyn == NULL || *ttyn == '\0') {
+ snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
+ ttyn = tname;
+ }
+ if ((tty = strchr(ttyn + 1, '/')))
+ ++tty;
+ else
+ tty = ttyn;
+
+ for (cnt = 0;; ask = 1) {
+ char prompt[128], ss[256];
+ if (ask) {
+ fflag = 0;
+ getloginname(1);
+ }
+ rootlogin = 0;
+ rval = 1;
+#ifdef KERBEROS
+ if ((instance = strchr(username, '.')) != NULL) {
+ if (strcmp(instance, ".root") == 0)
+ rootlogin = 1;
+ *instance++ = '\0';
+ } else
+ instance = "";
+#endif
+ if (strlen(username) > UT_NAMESIZE)
+ username[UT_NAMESIZE] = '\0';
+
+ /*
+ * Note if trying multiple user names; log failures for
+ * previous user name, but don't bother logging one failure
+ * for nonexistent name (mistyped username).
+ */
+ if (failures && strcmp(tbuf, username)) {
+ if (failures > (pwd ? 0 : 1))
+ badlogin(tbuf);
+ failures = 0;
+ }
+ strlcpy(tbuf, username, sizeof(tbuf));
+
+ pwd = paranoid_getpwnam (username);
+
+ /*
+ * if we have a valid account name, and it doesn't have a
+ * password, or the -f option was specified and the caller
+ * is root or the caller isn't changing their uid, don't
+ * authenticate.
+ */
+ if (pwd) {
+ if (pwd->pw_uid == 0)
+ rootlogin = 1;
+
+ if (fflag && (uid == 0 || uid == pwd->pw_uid)) {
+ /* already authenticated */
+ break;
+ } else if (pwd->pw_passwd[0] == '\0') {
+ /* pretend password okay */
+ rval = 0;
+ goto ttycheck;
+ }
+ }
+
+ fflag = 0;
+
+ 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
+#endif
+ {
+ if (auth_level == AUTH_NONE)
+ snprintf(prompt, sizeof(prompt), "%s's Password: ",
+ username);
+ else {
+ char *s;
+
+ rval = 1;
+#ifdef OTP
+ s = otp_error(&otp_ctx);
+ if(s)
+ printf ("OTP: %s\n", s);
+#endif
+ continue;
+ }
+ }
+
+ if (des_read_pw_string (passwd, sizeof(passwd) - 1, prompt, 0))
+ continue;
+ passwd[sizeof(passwd) - 1] = '\0';
+
+ /* Verify it somehow */
+
+#ifdef OTP
+ if (otp_verify_user (&otp_ctx, passwd) == 0)
+ rval = 0;
+ else
+#endif
+ if (pwd == NULL)
+ ;
+ else if (auth_level == AUTH_NONE) {
+ uid_t pwd_uid = pwd->pw_uid;
+
+ rval = unix_verify_user (username, passwd);
+
+ if (rval == 0)
+ {
+ if (rootlogin && pwd_uid != 0)
+ rootlogin = 0;
+ }
+ else
+ {
+ rval = klogin(pwd, instance, localhost, passwd);
+ if (rval != 0 && rootlogin && pwd_uid != 0)
+ rootlogin = 0;
+ if (rval == 0)
+ authok = 1;
+ }
+ } else {
+ char *s;
+
+ rval = 1;
+#ifdef OTP
+ if ((s = otp_error(&otp_ctx)))
+ printf ("OTP: %s\n", s);
+#endif
+ }
+
+ memset (passwd, 0, sizeof(passwd));
+ setpriority (PRIO_PROCESS, 0, 0);
+
+ /*
+ * Santa Claus, give me a portable and reentrant getpwnam.
+ */
+ pwd = paranoid_getpwnam (username);
+
+ ttycheck:
+ /*
+ * If trying to log in as root without Kerberos,
+ * but with insecure terminal, refuse the login attempt.
+ */
+#ifdef KERBEROS
+ if (authok == 0)
+#endif
+ if (pwd && !rval && rootlogin && !rootterm(tty)
+ && !rootterm(ttyn)) {
+ warnx("%s login refused on this terminal.",
+ pwd->pw_name);
+ if (hostname)
+ syslog(LOG_NOTICE,
+ "LOGIN %s REFUSED FROM %s ON TTY %s",
+ pwd->pw_name, hostname, tty);
+ else
+ syslog(LOG_NOTICE,
+ "LOGIN %s REFUSED ON TTY %s",
+ pwd->pw_name, tty);
+ continue;
+ }
+
+ if (rval == 0)
+ break;
+
+ printf("Login incorrect\n");
+ failures++;
+
+ /* max number of attemps and delays taken from defaults file */
+ /* we allow maxtrys tries, but after 2 we start backing off */
+ if (++cnt > 2) {
+ if (cnt >= maxtrys) {
+ badlogin(username);
+ sleepexit(1);
+ }
+ sleep((u_int)((cnt - 2) * atoi(default_sleep)));
+ }
+ }
+
+ /* committed to login -- turn off timeout */
+ alarm(0);
+
+ endpwent();
+
+#if defined(HAVE_GETUDBNAM) && defined(HAVE_SETLIM)
+ {
+ 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)
+ 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 *= CLK_TCK;
+
+ if(limit(C_PROC, 0, L_CPU, t) < 0)
+ 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 *= 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");
+
+ /* 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]);
+ }
+#endif
+ /* if user not super-user, check for disabled logins */
+ if (!rootlogin)
+ checknologin();
+
+ if (chdir(pwd->pw_dir) < 0) {
+ printf("No home directory %s!\n", pwd->pw_dir);
+ if (chdir("/"))
+ exit(0);
+ pwd->pw_dir = "/";
+ printf("Logging in with home = \"/\".\n");
+ }
+
+ quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
+ nomailcheck = access(_PATH_NOMAILCHECK, F_OK) == 0;
+
+#if defined(HAVE_PASSWD_CHANGE) && defined(HAVE_PASSWD_EXPIRE)
+ if (pwd->pw_change || pwd->pw_expire)
+ gettimeofday(&tp, (struct timezone *)NULL);
+
+ if (pwd->pw_change) {
+ time_t t;
+
+ if (tp.tv_sec >= pwd->pw_change) {
+ printf("Sorry -- your password has expired.\n");
+ changepass=1;
+ } else if (pwd->pw_change - tp.tv_sec <
+ 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) {
+ t = pwd->pw_change;
+ printf("Warning: your password expires on %s",
+ ctime(&t));
+ }
+ if (pwd->pw_expire)
+ if (tp.tv_sec >= pwd->pw_expire) {
+ printf("Sorry -- your account has expired.\n");
+ sleepexit(1);
+ } else if (pwd->pw_expire - tp.tv_sec <
+ 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) {
+ t = pwd->pw_expire;
+ printf("Warning: your account expires on %s",
+ ctime(&t));
+ }
+#endif /* defined(HAVE_PASSWD_CHANGE) && defined(HAVE_PASSWD_EXPIRE) */
+
+ /* Nothing else left to fail -- really log in. */
+
+ /*
+ * Update the utmp files, both BSD and SYSV style.
+ */
+ if (utmpx_login(tty, username, hostname ? hostname : "") != 0
+ && !fflag) {
+ printf("No utmpx entry. You must exec \"login\" from the lowest level \"sh\".\n");
+ sleepexit(0);
+ }
+ utmp_login(ttyn, username, hostname ? hostname : "");
+ dolastlog(quietlog);
+
+ /*
+ * Set device protections, depending on what terminal the
+ * user is logged in. This feature is used on Suns to give
+ * console users better privacy.
+ */
+ login_fbtab(tty, pwd->pw_uid, pwd->pw_gid);
+
+ 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);
+
+ if (*pwd->pw_shell == '\0')
+ pwd->pw_shell = _PATH_BSHELL;
+
+ /*
+ * Set up a new environment. With SYSV, some variables are always
+ * preserved; some varables are never preserved, and some variables
+ * are always clobbered. With BSD, nothing is always preserved, and
+ * some variables are always clobbered. We add code to make sure
+ * that LD_* and IFS are never preserved.
+ */
+ if (term[0] == '\0')
+ strlcpy(term, stypeof(tty), sizeof(term));
+ /* set up a somewhat censored environment. */
+ sysv_newenv(argc, argv, pwd, term, pflag);
+#ifdef KERBEROS
+ if (krbtkfile_env)
+ setenv("KRBTKFILE", krbtkfile_env, 1);
+#endif
+
+ if (tty[sizeof("tty")-1] == 'd')
+ 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 (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)
+ printf("Warning: no Kerberos tickets issued.\n");
+#endif
+
+#ifdef LOGALL
+ /*
+ * Syslog each successful login, so we don't have to watch hundreds
+ * of wtmp or lastlogin files.
+ */
+ if (hostname) {
+ syslog(LOG_INFO, "login from %s as %s", hostname, pwd->pw_name);
+ } else {
+ syslog(LOG_INFO, "login on %s as %s", tty, pwd->pw_name);
+ }
+#endif
+
+#ifndef NO_MOTD
+ /*
+ * Optionally show the message of the day. System V login leaves
+ * motd and mail stuff up to the shell startup file.
+ */
+ if (!quietlog) {
+ struct stat st;
+#if 0
+ printf("%s\n\t%s %s\n\n",
+ "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
+ "The Regents of the University of California. ",
+ "All rights reserved.");
+#endif
+ motd();
+ if(!nomailcheck){
+ snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
+ if (stat(tbuf, &st) == 0 && st.st_size != 0)
+ printf("You have %smail.\n",
+ (st.st_mtime > st.st_atime) ? "new " : "");
+ }
+ }
+#endif /* NO_MOTD */
+
+#ifdef LOGIN_ACCESS
+ if (login_access(pwd, hostname ? full_hostname : tty) == 0) {
+ printf("Permission denied\n");
+ if (hostname)
+ syslog(LOG_NOTICE, "%s LOGIN REFUSED FROM %s",
+ pwd->pw_name, hostname);
+ else
+ syslog(LOG_NOTICE, "%s LOGIN REFUSED ON %s",
+ pwd->pw_name, tty);
+ sleepexit(1);
+ }
+#endif
+
+ signal(SIGALRM, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+#ifdef SIGTSTP
+ signal(SIGTSTP, SIG_IGN);
+#endif
+
+ 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)
+ syslog(LOG_ERR, "setlogin() failure: %m");
+#endif
+
+#ifdef HAVE_SETPCRED
+ if (setpcred (pwd->pw_name, NULL) == -1)
+ syslog(LOG_ERR, "setpcred() failure: %m");
+#endif /* HAVE_SETPCRED */
+
+#if defined(SYSV_SHADOW) && defined(HAVE_GETSPNAM)
+ 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;
+ if(setuid(uid) != 0){
+ warn("setuid(%d)", uid);
+ if(!rootlogin)
+ exit(1);
+ }
+ if (uid != 0 && setuid(0) != -1) {
+ syslog(LOG_ALERT | LOG_AUTH,
+ "Failed to drop privileges for user %d", uid);
+ errx(1, "Sorry");
+ }
+ }
+
+
+ /*
+ * After dropping privileges and after cleaning up the environment,
+ * optionally run, as the user, /bin/passwd.
+ */
+
+ if (pwd->pw_passwd[0] == 0 &&
+ strcasecmp(default_passreq, "YES") == 0) {
+ printf("You don't have a password. Choose one.\n");
+ if (change_passwd(pwd))
+ sleepexit(0);
+ changepass = 0;
+ }
+
+#ifdef SYSV_SHADOW
+ if (spwd && sysv_expire(spwd)) {
+ if (change_passwd(pwd))
+ sleepexit(0);
+ changepass = 0;
+ }
+#endif /* SYSV_SHADOW */
+ if (changepass) {
+ int res;
+ if ((res=system(_PATH_CHPASS)))
+ sleepexit(1);
+ }
+
+ 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(pw_dir, cell, sizeof(cell)) == 0)
+ krb_afslog(cell, 0);
+ krb_afslog(0, 0);
+ }
+
+ execlp(pwd->pw_shell, tbuf, 0);
+ if (getuid() == 0) {
+ warnx("Can't exec %s, trying %s\n",
+ pwd->pw_shell, _PATH_BSHELL);
+ execlp(_PATH_BSHELL, tbuf, 0);
+ err(1, "%s", _PATH_BSHELL);
+ }
+ err(1, "%s", pwd->pw_shell);
+ return 1;
+}
+
+#ifdef KERBEROS
+#define NBUFSIZ (UT_NAMESIZE + 1 + 5) /* .root suffix */
+#else
+#define NBUFSIZ (UT_NAMESIZE + 1)
+#endif
+
+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;
+ }
+ }
+ }
+}
+
+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)
+{
+#ifdef HAVE_TTYENT_H
+ {
+ struct ttyent *t;
+
+ 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
+timedout(int signo)
+{
+ fprintf(stderr, "Login timed out after %d seconds\n",
+ login_timeout);
+ exit(0);
+}
+
+static void
+checknologin(void)
+{
+ int fd, nchars;
+ char tbuf[8192];
+
+ if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
+ while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+ write(fileno(stdout), tbuf, nchars);
+ sleepexit(0);
+ }
+}
+
+static void
+dolastlog(int quiet)
+{
+#if defined(HAVE_LASTLOG_H) || defined(HAVE_LOGIN_H)
+ struct lastlog ll;
+ int fd;
+ time_t t;
+
+ if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
+ lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+#ifdef SYSV_SHADOW
+ if (read(fd, &ll, sizeof(ll)) == sizeof(ll) &&
+ ll.ll_time != 0) {
+ if (pwd->pw_uid && spwd && spwd->sp_inact > 0
+ && ll.ll_time / (24 * 60 * 60)
+ + spwd->sp_inact < time(0)) {
+ printf("Your account has been inactive too long.\n");
+ sleepexit(1);
+ }
+ if (!quiet) {
+ t = ll.ll_time;
+ printf("Last login: %.*s ", 24-5, ctime(&t));
+ if (*ll.ll_host != '\0') {
+ printf("from %.*s\n",
+ (int)sizeof(ll.ll_host),
+ ll.ll_host);
+ } else
+ printf("on %.*s\n",
+ (int)sizeof(ll.ll_line),
+ ll.ll_line);
+ }
+ }
+ lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+#else /* SYSV_SHADOW */
+ if (!quiet) {
+ if (read(fd, &ll, sizeof(ll)) == sizeof(ll) &&
+ ll.ll_time != 0) {
+ t = ll.ll_time;
+ printf("Last login: %.*s ", 24-5, ctime(&t));
+ if (*ll.ll_host != '\0')
+ printf("from %.*s\n",
+ (int)sizeof(ll.ll_host),
+ ll.ll_host);
+ else
+ printf("on %.*s\n",
+ (int)sizeof(ll.ll_line),
+ ll.ll_line);
+ }
+ lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+ }
+#endif /* SYSV_SHADOW */
+ memset(&ll, 0, sizeof(ll));
+ ll.ll_time = time(NULL);
+ strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+ if (hostname)
+ strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+ write(fd, &ll, sizeof(ll));
+ close(fd);
+ }
+#endif /* DOLASTLOG */
+}
+
+static void
+badlogin(char *name)
+{
+
+ if (failures == 0)
+ return;
+ if (hostname) {
+ syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
+ failures, failures > 1 ? "S" : "", hostname);
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "%d LOGIN FAILURE%s FROM %s, %s",
+ failures, failures > 1 ? "S" : "", hostname, name);
+ } else {
+ syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
+ failures, failures > 1 ? "S" : "", tty);
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "%d LOGIN FAILURE%s ON %s, %s",
+ failures, failures > 1 ? "S" : "", tty, name);
+ }
+}
+
+#undef UNKNOWN
+#define UNKNOWN "su"
+
+static char *
+stypeof(char *ttyid)
+{
+ /* TERM is probably a better guess than anything else. */
+ char *term = getenv("TERM");
+
+ if (term != 0 && term[0] != 0)
+ return term;
+
+ {
+#ifndef HAVE_TTYENT_H
+ return UNKNOWN;
+#else
+ struct ttyent *t;
+ return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
+#endif
+ }
+}
+
+static void
+xgetstr(char *buf, int cnt, char *err)
+{
+ char ch;
+
+ do {
+ if (read(0, &ch, sizeof(ch)) != sizeof(ch))
+ exit(1);
+ if (--cnt < 0) {
+ fprintf(stderr, "%s too long\r\n", err);
+ sleepexit(1);
+ }
+ *buf++ = ch;
+ } while (ch);
+}
+
+/*
+ * Some old rlogind's unknowingly pass remuser, locuser and
+ * terminal_type/speed so we need to take care of that part of the
+ * protocol here. Also, we can't make a getpeername(2) on the socket
+ * so we have to trust that rlogind resolved the name correctly.
+ */
+
+static int
+doremotelogin(char *host)
+{
+ int code;
+ char *cp;
+
+ xgetstr(rusername, sizeof (rusername), "remuser");
+ xgetstr(lusername, sizeof (lusername), "locuser");
+ xgetstr(term, sizeof(term), "Terminal type");
+ cp = strchr(term, '/');
+ if (cp != 0)
+ *cp = 0; /* For now ignore speed/bg */
+ pwd = k_getpwnam(lusername);
+ if (pwd == NULL)
+ return(-1);
+ code = ruserok(host, (pwd->pw_uid == 0), rusername, lusername);
+ if (code == 0)
+ syslog(LOG_NOTICE,
+ "Warning: An old rlogind accepted login probably from host %s",
+ host);
+ return(code);
+}
+
+void
+sleepexit(int eval)
+{
+
+ sleep(5);
+ exit(eval);
+}
diff --git a/crypto/kerberosIV/appl/bsd/login_access.c b/crypto/kerberosIV/appl/bsd/login_access.c
new file mode 100644
index 0000000..7b79dc8
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/login_access.c
@@ -0,0 +1,264 @@
+ /*
+ * This module implements a simple but effective form of login access
+ * control based on login names and on host (or domain) names, internet
+ * addresses (or network numbers), or on terminal line names in case of
+ * non-networked logins. Diagnostics are reported through syslog(3).
+ *
+ * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: login_access.c,v 1.19 1999/05/14 22:02:14 assar Exp $");
+
+#ifdef LOGIN_ACCESS
+
+ /* Delimiters for fields and for lists of users, ttys or hosts. */
+
+static char fs[] = ":"; /* field separator */
+static char sep[] = ", \t"; /* list-element separator */
+
+ /* Constants to be used in assignments only, not in comparisons... */
+
+#define YES 1
+#define NO 0
+
+ /*
+ * 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(struct passwd *user, char *from)
+{
+ struct login_info item;
+ FILE *fp;
+ char line[BUFSIZ];
+ char *perm; /* becomes permission field */
+ char *users; /* becomes list of login names */
+ char *froms; /* becomes list of terminals or hosts */
+ int match = NO;
+ int end;
+ int lineno = 0; /* for diagnostics */
+ 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
+ * mandatory. The first field should be a "+" or "-" character. A
+ * non-existing table means no access control.
+ */
+
+ if ((fp = fopen(_PATH_LOGACCESS, "r")) != 0) {
+ while (!match && fgets(line, sizeof(line), fp)) {
+ lineno++;
+ if (line[end = strlen(line) - 1] != '\n') {
+ syslog(LOG_ERR, "%s: line %d: missing newline or line too long",
+ _PATH_LOGACCESS, lineno);
+ continue;
+ }
+ if (line[0] == '#')
+ continue; /* comment line */
+ while (end > 0 && isspace((unsigned char)line[end - 1]))
+ end--;
+ line[end] = 0; /* strip trailing whitespace */
+ if (line[0] == 0) /* skip blank lines */
+ continue;
+ foo = NULL;
+ if (!(perm = strtok_r(line, fs, &foo))
+ || !(users = strtok_r(NULL, fs, &foo))
+ || !(froms = strtok_r(NULL, fs, &foo))
+ || strtok_r(NULL, fs, &foo)) {
+ syslog(LOG_ERR, "%s: line %d: bad field count",
+ _PATH_LOGACCESS,
+ lineno);
+ continue;
+ }
+ if (perm[0] != '+' && perm[0] != '-') {
+ syslog(LOG_ERR, "%s: line %d: bad first field",
+ _PATH_LOGACCESS,
+ lineno);
+ continue;
+ }
+ match = (list_match(froms, &item, from_match)
+ && list_match(users, &item, user_match));
+ }
+ fclose(fp);
+ } else if (errno != ENOENT) {
+ syslog(LOG_ERR, "cannot open %s: %m", _PATH_LOGACCESS);
+ }
+ return (match == 0 || (line[0] == '+'));
+}
+
+/* list_match - match an item against a list of tokens with exceptions */
+
+static int
+list_match(char *list,
+ struct login_info *item,
+ int (*match_fn)(char *, struct login_info *))
+{
+ char *tok;
+ int match = NO;
+ char *foo = NULL;
+
+ /*
+ * Process tokens one at a time. We have exhausted all possible matches
+ * when we reach an "EXCEPT" token or the end of the list. If we do find
+ * a match, look for an "EXCEPT" list and recurse to determine whether
+ * the match is affected by any exceptions.
+ */
+
+ for (tok = strtok_r(list, sep, &foo);
+ tok != NULL;
+ tok = strtok_r(NULL, sep, &foo)) {
+ if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
+ break;
+ if ((match = (*match_fn) (tok, item)) != 0) /* YES */
+ break;
+ }
+ /* Process exceptions to matches. */
+
+ if (match != NO) {
+ while ((tok = strtok_r(NULL, sep, &foo)) && strcasecmp(tok, "EXCEPT"))
+ /* VOID */ ;
+ if (tok == 0 || list_match(NULL, item, match_fn) == NO)
+ return (match);
+ }
+ 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)
+{
+#ifdef HAVE_YP_GET_DEFAULT_DOMAIN
+ static char *mydomain = 0;
+
+ if (mydomain == 0)
+ yp_get_default_domain(&mydomain);
+ return (innetgr(group, machine, user, mydomain));
+#else
+ syslog(LOG_ERR, "NIS netgroup support not configured");
+ return 0;
+#endif
+}
+
+/* user_match - match a username against one token */
+
+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, if the
+ * token is a group that contains the username, or if the token is the
+ * name of the user's primary group.
+ */
+
+ 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);
+ }
+ return (NO);
+}
+
+/* from_match - match a host or tty against a list of tokens */
+
+static int from_match(char *tok, struct login_info *item)
+{
+ char *string = item->from;
+ int tok_len;
+ int str_len;
+
+ /*
+ * If a token has the magic value "ALL" the match always succeeds. Return
+ * YES if the token fully matches the string. If the token is a domain
+ * name, return YES if it matches the last fields of the string. If the
+ * token has the magic value "LOCAL", return YES if the string does not
+ * contain a "." character. If the token is a network number, return YES
+ * if it matches the head of the string.
+ */
+
+ if (tok[0] == '@') { /* netgroup */
+ return (netgroup_match(tok + 1, string, (char *) 0));
+ } else if (string_match(tok, string)) { /* ALL or exact match */
+ return (YES);
+ } else if (tok[0] == '.') { /* domain: match last fields */
+ if ((str_len = strlen(string)) > (tok_len = strlen(tok))
+ && strcasecmp(tok, string + str_len - tok_len) == 0)
+ return (YES);
+ } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */
+ if (strchr(string, '.') == 0)
+ return (YES);
+ } else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */
+ && strncmp(tok, string, tok_len) == 0) {
+ return (YES);
+ }
+ return (NO);
+}
+
+/* string_match - match a string against one token */
+
+static int string_match(char *tok, char *string)
+{
+
+ /*
+ * If the token has the magic value "ALL" the match always succeeds.
+ * Otherwise, return YES if the token fully matches the string.
+ */
+
+ if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
+ return (YES);
+ } else if (strcasecmp(tok, string) == 0) { /* try exact match */
+ return (YES);
+ }
+ return (NO);
+}
+#endif /* LOGIN_ACCES */
diff --git a/crypto/kerberosIV/appl/bsd/login_fbtab.c b/crypto/kerberosIV/appl/bsd/login_fbtab.c
new file mode 100644
index 0000000..3aa5e4c
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/login_fbtab.c
@@ -0,0 +1,154 @@
+/************************************************************************
+* Copyright 1995 by Wietse Venema. All rights reserved.
+*
+* This material was originally written and compiled by Wietse Venema at
+* Eindhoven University of Technology, The Netherlands, in 1990, 1991,
+* 1992, 1993, 1994 and 1995.
+*
+* Redistribution and use in source and binary forms are permitted
+* provided that this entire copyright notice is duplicated in all such
+* copies.
+*
+* This software is provided "as is" and without any expressed or implied
+* warranties, including, without limitation, the implied warranties of
+* merchantibility and fitness for any particular purpose.
+************************************************************************/
+/*
+ SYNOPSIS
+ void login_fbtab(tty, uid, gid)
+ char *tty;
+ uid_t uid;
+ gid_t gid;
+
+ DESCRIPTION
+ This module implements device security as described in the
+ SunOS 4.1.x fbtab(5) and SunOS 5.x logindevperm(4) manual
+ pages. The program first looks for /etc/fbtab. If that file
+ cannot be opened it attempts to process /etc/logindevperm.
+ We expect entries with the folowing format:
+
+ Comments start with a # and extend to the end of the line.
+
+ Blank lines or lines with only a comment are ignored.
+
+ All other lines consist of three fields delimited by
+ whitespace: a login device (/dev/console), an octal
+ permission number (0600), and a ":"-delimited list of
+ devices (/dev/kbd:/dev/mouse). All device names are
+ absolute paths. A path that ends in "/*" refers to all
+ directory entries except "." and "..".
+
+ If the tty argument (relative path) matches a login device
+ name (absolute path), the permissions of the devices in the
+ ":"-delimited list are set as specified in the second
+ field, and their ownership is changed to that of the uid
+ and gid arguments.
+
+ DIAGNOSTICS
+ Problems are reported via the syslog daemon with severity
+ LOG_ERR.
+
+ BUGS
+
+ AUTHOR
+ Wietse Venema (wietse@wzv.win.tue.nl)
+ Eindhoven University of Technology
+ The Netherlands
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: login_fbtab.c,v 1.14 1999/09/16 20:37:24 assar Exp $");
+
+void login_protect (char *, char *, int, uid_t, gid_t);
+void login_fbtab (char *tty, uid_t uid, gid_t gid);
+
+#define WSPACE " \t\n"
+
+/* login_fbtab - apply protections specified in /etc/fbtab or logindevperm */
+
+void
+login_fbtab(char *tty, uid_t uid, gid_t gid)
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+ char *devname;
+ char *cp;
+ int prot;
+ char *table;
+ char *foo;
+
+ if ((fp = fopen(table = _PATH_FBTAB, "r")) == 0
+ && (fp = fopen(table = _PATH_LOGINDEVPERM, "r")) == 0)
+ return;
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if ((cp = strchr(buf, '#')) != 0)
+ *cp = 0; /* strip comment */
+ foo = NULL;
+ if ((cp = devname = strtok_r(buf, WSPACE, &foo)) == 0)
+ continue; /* empty or comment */
+ if (strncmp(devname, "/dev/", 5) != 0
+ || (cp = strtok_r(NULL, WSPACE, &foo)) == 0
+ || *cp != '0'
+ || sscanf(cp, "%o", &prot) == 0
+ || prot == 0
+ || (prot & 0777) != prot
+ || (cp = strtok_r(NULL, WSPACE, &foo)) == 0) {
+ syslog(LOG_ERR, "%s: bad entry: %s", table, cp ? cp : "(null)");
+ continue;
+ }
+ if (strcmp(devname + 5, tty) == 0) {
+ foo = NULL;
+ for (cp = strtok_r(cp, ":", &foo);
+ cp;
+ cp = strtok_r(NULL, ":", &foo)) {
+ login_protect(table, cp, prot, uid, gid);
+ }
+ }
+ }
+ fclose(fp);
+}
+
+/* login_protect - protect one device entry */
+
+void
+login_protect(char *table, char *path, int mask, uid_t uid, gid_t gid)
+{
+ char buf[BUFSIZ];
+ int pathlen = strlen(path);
+ struct dirent *ent;
+ DIR *dir;
+
+ if (strcmp("/*", path + pathlen - 2) != 0) {
+ if (chmod(path, mask) && errno != ENOENT)
+ syslog(LOG_ERR, "%s: chmod(%s): %m", table, path);
+ if (chown(path, uid, gid) && errno != ENOENT)
+ syslog(LOG_ERR, "%s: chown(%s): %m", table, path);
+ } else {
+ strlcpy (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) {
+ strlcpy (buf + pathlen - 1,
+ ent->d_name,
+ sizeof(buf) - (pathlen + 1));
+ login_protect(table, buf, mask, uid, gid);
+ }
+ }
+ closedir(dir);
+ }
+ }
+}
diff --git a/crypto/kerberosIV/appl/bsd/osfc2.c b/crypto/kerberosIV/appl/bsd/osfc2.c
new file mode 100644
index 0000000..fbfd742
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/osfc2.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "bsd_locl.h"
+RCSID("$Id: osfc2.c,v 1.2 1999/12/02 16:58:28 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_
new file mode 100644
index 0000000..6db8f68
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/pathnames.h_
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 1989 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.
+ *
+ * from: @(#)pathnames.h 5.2 (Berkeley) 4/9/90
+ * $Id: pathnames.h,v 1.25 1998/02/03 23:29:30 assar Exp $
+ * $FreeBSD$
+ */
+
+/******* First fix default path, we stick to _PATH_DEFPATH everywhere */
+
+#if !defined(_PATH_DEFPATH) && defined(_PATH_USERPATH)
+#define _PATH_DEFPATH _PATH_USERPATH
+#endif
+
+#if defined(_PATH_DEFPATH) && !defined(_DEF_PATH)
+#define _DEF_PATH _PATH_DEFPATH
+#endif
+
+#if !defined(_PATH_DEFPATH) && defined(_DEF_PATH)
+#define _PATH_DEFPATH _DEF_PATH
+#endif
+
+#ifndef _PATH_DEFPATH
+#define _PATH_DEFPATH "/usr/ucb:/usr/bin:/bin"
+#define _DEF_PATH _PATH_DEFPATH
+#endif /* !_PATH_DEFPATH */
+
+#ifndef _PATH_DEFSUPATH
+#define _PATH_DEFSUPATH "/usr/sbin:" _DEF_PATH
+#endif /* _PATH_DEFSUPATH */
+
+/******* Default PATH fixed! */
+
+#undef _PATH_RLOGIN /* Redifine rlogin */
+#define _PATH_RLOGIN BINDIR "/rlogin"
+
+#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"
+
+/******* The rest is fallback defaults */
+
+#ifndef _PATH_DEV
+#define _PATH_DEV "/dev/"
+#endif
+
+#ifndef _PATH_CP
+#define _PATH_CP "/bin/cp"
+#endif /* _PATH_CP */
+
+#ifndef _PATH_SHELLS
+#define _PATH_SHELLS "/etc/shells"
+#endif /* _PATH_SHELLS */
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif /* _PATH_BSHELL */
+
+#ifndef _PATH_CSHELL
+#define _PATH_CSHELL "/bin/csh"
+#endif /* _PATH_CSHELL */
+
+#ifndef _PATH_NOLOGIN
+#define _PATH_NOLOGIN "/etc/nologin"
+#endif /* _PATH_NOLOGIN */
+
+#ifndef _PATH_TTY
+#define _PATH_TTY "/dev/tty"
+#endif /* _PATH_TTY */
+
+#ifndef _PATH_HUSHLOGIN
+#define _PATH_HUSHLOGIN ".hushlogin"
+#endif /* _PATH_HUSHLOGIN */
+
+#ifndef _PATH_NOMAILCHECK
+#define _PATH_NOMAILCHECK ".nomailcheck"
+#endif /* _PATH_NOMAILCHECK */
+
+#ifndef _PATH_MOTDFILE
+#define _PATH_MOTDFILE "/etc/motd"
+#endif /* _PATH_MOTDFILE */
+
+#ifndef _PATH_LOGACCESS
+#define _PATH_LOGACCESS "/etc/login.access"
+#endif /* _PATH_LOGACCESS */
+
+#ifndef _PATH_HEQUIV
+#define _PATH_HEQUIV "/etc/hosts.equiv"
+#endif
+
+#ifndef _PATH_FBTAB
+#define _PATH_FBTAB "/etc/fbtab"
+#endif /* _PATH_FBTAB */
+
+#ifndef _PATH_LOGINDEVPERM
+#define _PATH_LOGINDEVPERM "/etc/logindevperm"
+#endif /* _PATH_LOGINDEVPERM */
+
+#ifndef _PATH_CHPASS
+#define _PATH_CHPASS "/usr/bin/passwd"
+#endif /* _PATH_CHPASS */
+
+#if defined(__hpux)
+#define __FALLBACK_MAILDIR__ "/usr/mail"
+#else
+#define __FALLBACK_MAILDIR__ "/usr/spool/mail"
+#endif
+
+#ifndef KRB4_MAILDIR
+#ifndef _PATH_MAILDIR
+#ifdef MAILDIR
+#define _PATH_MAILDIR MAILDIR
+#else
+#define _PATH_MAILDIR __FALLBACK_MAILDIR__
+#endif
+#endif /* _PATH_MAILDIR */
+#define KRB4_MAILDIR _PATH_MAILDIR
+#endif
+
+#ifndef _PATH_LASTLOG
+#define _PATH_LASTLOG "/var/adm/lastlog"
+#endif
+
+#if defined(UTMP_FILE) && !defined(_PATH_UTMP)
+#define _PATH_UTMP UTMP_FILE
+#endif
+
+#ifndef _PATH_UTMP
+#define _PATH_UTMP "/etc/utmp"
+#endif
+
+#if defined(WTMP_FILE) && !defined(_PATH_WTMP)
+#define _PATH_WTMP WTMP_FILE
+#endif
+
+#ifndef _PATH_WTMP
+#define _PATH_WTMP "/usr/adm/wtmp"
+#endif
+
+#ifndef _PATH_ETC_DEFAULT_LOGIN
+#define _PATH_ETC_DEFAULT_LOGIN "/etc/default/login"
+#endif
+
+#ifndef _PATH_ETC_ENVIRONMENT
+#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.
+ */
+#ifdef NeXT
+#undef _PATH_DEFSUPATH
+#define _PATH_DEFSUPATH "/usr/sbin:/usr/ucb:/usr/bin:/bin"
+#undef _PATH_RLOGIN
+#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
new file mode 100644
index 0000000..cd431e3
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rcmd_util.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: rcmd_util.c,v 1.19.2.1 2000/06/23 02:34:48 assar Exp $");
+
+int
+get_login_port(int kerberos, int encryption)
+{
+ char *service="login";
+ int port=htons(513);
+
+ if(kerberos && encryption){
+ service="eklogin";
+ port=htons(2105);
+ }
+
+ if(kerberos && !encryption){
+ service="klogin";
+ port=htons(543);
+ }
+ return k_getportbyname (service, "tcp", port);
+}
+
+int
+get_shell_port(int kerberos, int encryption)
+{
+ char *service="shell";
+ int port=htons(514);
+
+ if(kerberos && encryption){
+ service="ekshell";
+ port=htons(545);
+ }
+
+ if(kerberos && !encryption){
+ service="kshell";
+ port=htons(544);
+ }
+
+ return k_getportbyname (service, "tcp", port);
+}
+
+/*
+ * On reasonable systems, `cf[gs]et[io]speed' use values of bit/s
+ * directly, and the following functions are just identity functions.
+ * This is however a slower way of doing those
+ * should-be-but-are-not-always idenity functions.
+ */
+
+static struct { int speed; int bps; } conv[] = {
+#ifdef B0
+ {B0, 0},
+#endif
+#ifdef B50
+ {B50, 50},
+#endif
+#ifdef B75
+ {B75, 75},
+#endif
+#ifdef B110
+ {B110, 110},
+#endif
+#ifdef B134
+ {B134, 134},
+#endif
+#ifdef B150
+ {B150, 150},
+#endif
+#ifdef B200
+ {B200, 200},
+#endif
+#ifdef B300
+ {B300, 300},
+#endif
+#ifdef B600
+ {B600, 600},
+#endif
+#ifdef B1200
+ {B1200, 1200},
+#endif
+#ifdef B1800
+ {B1800, 1800},
+#endif
+#ifdef B2400
+ {B2400, 2400},
+#endif
+#ifdef B4800
+ {B4800, 4800},
+#endif
+#ifdef B9600
+ {B9600, 9600},
+#endif
+#ifdef B19200
+ {B19200, 19200},
+#endif
+#ifdef EXTA
+ {EXTA, 19200},
+#endif
+#ifdef B38400
+ {B38400, 38400},
+#endif
+#ifdef EXTB
+ {EXTB, 38400},
+#endif
+#ifdef B57600
+ {B57600, 57600},
+#endif
+#ifdef B115200
+ {B115200, 115200},
+#endif
+#ifdef B153600
+ {B153600, 153600},
+#endif
+#ifdef B230400
+ {B230400, 230400},
+#endif
+#ifdef B307200
+ {B307200, 307200},
+#endif
+#ifdef B460800
+ {B460800, 460800},
+#endif
+};
+
+#define N (sizeof(conv)/sizeof(*conv))
+
+int
+speed_t2int (speed_t s)
+{
+ int l, r, m;
+
+ l = 0;
+ r = N - 1;
+ while(l <= r) {
+ m = (l + r) / 2;
+ if (conv[m].speed == s)
+ return conv[m].bps;
+ else if(conv[m].speed < s)
+ l = m + 1;
+ else
+ r = m - 1;
+ }
+ return -1;
+}
+
+/*
+ *
+ */
+
+speed_t
+int2speed_t (int i)
+{
+ int l, r, m;
+
+ l = 0;
+ r = N - 1;
+ while(l <= r) {
+ m = (l + r) / 2;
+ if (conv[m].bps == i)
+ return conv[m].speed;
+ else if(conv[m].bps < i)
+ l = m + 1;
+ else
+ r = m - 1;
+ }
+ return -1;
+}
+
+/*
+ * If there are any IP options on `sock', die.
+ */
+
+void
+ip_options_and_die (int sock, struct sockaddr_in *fromp)
+{
+#if defined(IP_OPTIONS) && defined(HAVE_GETSOCKOPT)
+ u_char optbuf[BUFSIZ/3], *cp;
+ char lbuf[BUFSIZ], *lp;
+ int optsize = sizeof(optbuf), ipproto;
+ struct protoent *ip;
+
+ if ((ip = getprotobyname("ip")) != NULL)
+ ipproto = ip->p_proto;
+ else
+ ipproto = IPPROTO_IP;
+ if (getsockopt(sock, ipproto, IP_OPTIONS,
+ (void *)optbuf, &optsize) == 0 &&
+ optsize != 0) {
+ lp = lbuf;
+ for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
+ snprintf(lp, sizeof(lbuf) - (lp - lbuf), " %2.2x", *cp);
+ syslog(LOG_NOTICE,
+ "Connection received from %s using IP options (dead):%s",
+ inet_ntoa(fromp->sin_addr), lbuf);
+ exit(1);
+ }
+#endif
+}
+
+void
+warning(const char *fmt, ...)
+{
+ char *rstar_no_warn = getenv("RSTAR_NO_WARN");
+ va_list args;
+
+ va_start(args, fmt);
+ if (rstar_no_warn == NULL)
+ rstar_no_warn = "";
+ if (strncmp(rstar_no_warn, "yes", 3) != 0) {
+ /* XXX */
+ fprintf(stderr, "%s: warning, using standard ", __progname);
+ vwarnx(fmt, args);
+ }
+ va_end(args);
+}
+
+/*
+ * setuid but work-around Linux 2.2.15 bug with setuid and capabilities
+ */
+
+void
+paranoid_setuid (uid_t uid)
+{
+ if (setuid (uid) < 0)
+ err (1, "setuid");
+ if (uid != 0 && setuid (0) == 0) {
+ syslog(LOG_ALERT | LOG_AUTH,
+ "Failed to drop privileges for uid %u", (unsigned)uid);
+ err (1, "setuid");
+ }
+}
diff --git a/crypto/kerberosIV/appl/bsd/rcp.c b/crypto/kerberosIV/appl/bsd/rcp.c
new file mode 100644
index 0000000..660be91
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rcp.c
@@ -0,0 +1,1047 @@
+/*
+ * Copyright (c) 1983, 1990, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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 "bsd_locl.h"
+
+RCSID("$Id: rcp.c,v 1.52.2.1 2000/06/23 02:35:16 assar Exp $");
+
+/* Globals */
+static char dst_realm_buf[REALM_SZ];
+static char *dest_realm = NULL;
+static int use_kerberos = 1;
+
+static int doencrypt = 0;
+#define OPTIONS "dfKk:prtxl:"
+
+static char *user_name = NULL; /* Given as -l option. */
+
+static int errs, rem;
+static struct passwd *pwd;
+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" */
+
+void rsource(char *name, struct stat *statp);
+
+#define SERVICE_NAME "rcmd"
+
+CREDENTIALS cred;
+MSG_DAT msg_data;
+struct sockaddr_in foreign_addr, local_addr;
+Key_schedule schedule;
+
+KTEXT_ST ticket;
+AUTH_DAT kdata;
+
+static void
+send_auth(char *h, char *r)
+{
+ int lslen, fslen, status;
+ long opts;
+
+ lslen = sizeof(struct sockaddr_in);
+ if (getsockname(rem, (struct sockaddr *)&local_addr, &lslen) < 0)
+ err(1, "getsockname");
+ fslen = sizeof(struct sockaddr_in);
+ 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_addr,
+ &foreign_addr, "KCMDV0.1")) != KSUCCESS)
+ errx(1, "krb_sendauth failure: %s", krb_get_err_text(status));
+}
+
+static void
+answer_auth(void)
+{
+ int lslen, fslen, status;
+ long opts;
+ char inst[INST_SZ], v[9];
+
+ lslen = sizeof(struct sockaddr_in);
+ if (getsockname(rem, (struct sockaddr *)&local_addr, &lslen) < 0)
+ err(1, "getsockname");
+ fslen = sizeof(struct sockaddr_in);
+ 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_addr, &local_addr,
+ &kdata, "", schedule, v)) != KSUCCESS)
+ errx(1, "krb_recvauth failure: %s", krb_get_err_text(status));
+}
+
+static int
+des_read(int fd, char *buf, int len)
+{
+ if (doencrypt)
+ return(des_enc_read(fd, buf, len, schedule,
+ (iamremote? &kdata.session : &cred.session)));
+ else
+ return(read(fd, buf, len));
+}
+
+static int
+des_write(int fd, char *buf, int len)
+{
+ if (doencrypt)
+ return(des_enc_write(fd, buf, len, schedule,
+ (iamremote? &kdata.session : &cred.session)));
+ else
+ return(write(fd, buf, len));
+}
+
+static void run_err(const char *fmt, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+
+static void
+run_err(const char *fmt, ...)
+{
+ char errbuf[1024];
+
+ va_list args;
+ va_start(args, fmt);
+ ++errs;
+#define RCPERR "\001rcp: "
+ strlcpy (errbuf, RCPERR, sizeof(errbuf));
+ vsnprintf (errbuf + strlen(errbuf),
+ sizeof(errbuf) - strlen(errbuf),
+ fmt, args);
+ strlcat (errbuf, "\n", sizeof(errbuf));
+ des_write (rem, errbuf, strlen(errbuf));
+ if (!iamremote)
+ vwarnx(fmt, args);
+ va_end(args);
+}
+
+static void
+verifydir(char *cp)
+{
+ struct stat stb;
+
+ if (!stat(cp, &stb)) {
+ if (S_ISDIR(stb.st_mode))
+ return;
+ errno = ENOTDIR;
+ }
+ run_err("%s: %s", cp, strerror(errno));
+ exit(1);
+}
+
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+
+static BUF *
+allocbuf(BUF *bp, int fd, int blksize)
+{
+ struct stat stb;
+ size_t size;
+
+ if (fstat(fd, &stb) < 0) {
+ run_err("fstat: %s", strerror(errno));
+ return (0);
+ }
+#ifdef HAVE_ST_BLKSIZE
+ size = ROUNDUP(stb.st_blksize, blksize);
+#else
+ size = blksize;
+#endif
+ if (size == 0)
+ size = blksize;
+ if (bp->cnt >= size)
+ return (bp);
+ if (bp->buf == NULL)
+ bp->buf = malloc(size);
+ else
+ bp->buf = realloc(bp->buf, size);
+ if (bp->buf == NULL) {
+ bp->cnt = 0;
+ run_err("%s", strerror(errno));
+ return (0);
+ }
+ bp->cnt = size;
+ return (bp);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n\t%s\n",
+ "usage: rcp [-Kpx] [-k realm] f1 f2",
+ "or: rcp [-Kprx] [-k realm] f1 ... fn directory");
+ exit(1);
+}
+
+static void
+oldw(const char *s)
+{
+ char *rstar_no_warn = getenv("RSTAR_NO_WARN");
+ if (rstar_no_warn == 0)
+ rstar_no_warn = "";
+ if (strncmp(rstar_no_warn, "yes", 3) != 0)
+ warnx("%s, using standard rcp", s);
+}
+
+static RETSIGTYPE
+lostconn(int signo)
+{
+ if (!iamremote)
+ warnx("lost connection");
+ exit(1);
+}
+
+static int
+response(void)
+{
+ char ch, *cp, resp, rbuf[BUFSIZ];
+
+ if (des_read(rem, &resp, sizeof(resp)) != sizeof(resp))
+ lostconn(0);
+
+ cp = rbuf;
+ switch(resp) {
+ case 0: /* ok */
+ return (0);
+ default:
+ *cp++ = resp;
+ /* FALLTHROUGH */
+ case 1: /* error, followed by error msg */
+ case 2: /* fatal error, "" */
+ do {
+ if (des_read(rem, &ch, sizeof(ch)) != sizeof(ch))
+ lostconn(0);
+ *cp++ = ch;
+ } while (cp < &rbuf[BUFSIZ] && ch != '\n');
+
+ if (!iamremote)
+ write(STDERR_FILENO, rbuf, cp - rbuf);
+ ++errs;
+ if (resp == 1)
+ return (-1);
+ exit(1);
+ }
+ /* NOTREACHED */
+}
+
+static void
+source(int argc, char **argv)
+{
+ struct stat stb;
+ static BUF buffer;
+ BUF *bp;
+ off_t i;
+ int amt, fd, haderr, indx, result;
+ char *last, *name, buf[BUFSIZ];
+
+ for (indx = 0; indx < argc; ++indx) {
+ name = argv[indx];
+ if ((fd = open(name, O_RDONLY, 0)) < 0)
+ goto syserr;
+ if (fstat(fd, &stb)) {
+syserr: run_err("%s: %s", name, strerror(errno));
+ goto next;
+ }
+ switch (stb.st_mode & S_IFMT) {
+ case S_IFREG:
+ break;
+ case S_IFDIR:
+ if (iamrecursive) {
+ rsource(name, &stb);
+ goto next;
+ }
+ /* FALLTHROUGH */
+ default:
+ run_err("%s: not a regular file", name);
+ goto next;
+ }
+ if ((last = strrchr(name, '/')) == NULL)
+ last = name;
+ else
+ ++last;
+ if (pflag) {
+ /*
+ * Make it compatible with possible future
+ * versions expecting microseconds.
+ */
+ snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
+ (long)stb.st_mtime, (long)stb.st_atime);
+ des_write(rem, buf, strlen(buf));
+ if (response() < 0)
+ goto next;
+ }
+ snprintf(buf, sizeof(buf), "C%04o %ld %s\n",
+ (int)stb.st_mode & MODEMASK, (long) stb.st_size, last);
+ des_write(rem, buf, strlen(buf));
+ if (response() < 0)
+ goto next;
+ if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) {
+next: close(fd);
+ continue;
+ }
+
+ /* Keep writing after an error so that we stay sync'd up. */
+ for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
+ amt = bp->cnt;
+ if (i + amt > stb.st_size)
+ amt = stb.st_size - i;
+ if (!haderr) {
+ result = read(fd, bp->buf, amt);
+ if (result != amt)
+ haderr = result >= 0 ? EIO : errno;
+ }
+ if (haderr)
+ des_write(rem, bp->buf, amt);
+ else {
+ result = des_write(rem, bp->buf, amt);
+ if (result != amt)
+ haderr = result >= 0 ? EIO : errno;
+ }
+ }
+ if (close(fd) && !haderr)
+ haderr = errno;
+ if (!haderr)
+ des_write(rem, "", 1);
+ else
+ run_err("%s: %s", name, strerror(haderr));
+ response();
+ }
+}
+
+void
+rsource(char *name, struct stat *statp)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char *last, *vect[1], path[MaxPathLen];
+ 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;
+ else
+ last++;
+ if (pflag) {
+ snprintf(path, sizeof(path), "T%ld 0 %ld 0\n",
+ (long)statp->st_mtime, (long)statp->st_atime);
+ des_write(rem, path, strlen(path));
+ if (response() < 0) {
+ closedir(dirp);
+ return;
+ }
+ }
+ snprintf(path, sizeof(path),
+ "D%04o %d %s\n", (int)statp->st_mode & MODEMASK, 0, last);
+ des_write(rem, path, strlen(path));
+ if (response() < 0) {
+ closedir(dirp);
+ return;
+ }
+ while ((dp = readdir(dirp))) {
+ if (dp->d_ino == 0)
+ continue;
+ if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+ continue;
+ if (strlen(name) + 1 + strlen(dp->d_name) >= MaxPathLen - 1) {
+ run_err("%s/%s: name too long", name, dp->d_name);
+ continue;
+ }
+ if (snprintf(path, sizeof(path),
+ "%s/%s", name, dp->d_name) >= sizeof(path)) {
+ run_err("%s/%s: name too long", name, dp->d_name);
+ continue;
+ }
+ vect[0] = path;
+ source(1, vect);
+ }
+ closedir(dirp);
+ des_write(rem, "E\n", 2);
+ response();
+}
+
+static int
+kerberos(char **host, char *bp, char *locuser, char *user)
+{
+ int sock = -1, err;
+
+ if (use_kerberos) {
+ paranoid_setuid(getuid());
+ rem = KSUCCESS;
+ errno = 0;
+ if (dest_realm == NULL)
+ dest_realm = krb_realmofhost(*host);
+
+#if 0
+ rem = krcmd(host, port, user, bp, 0, dest_realm);
+#else
+ err = kcmd(
+ &sock,
+ host,
+ port,
+ NULL, /* locuser not used */
+ user,
+ bp,
+ 0,
+ &ticket,
+ SERVICE_NAME,
+ dest_realm,
+ (CREDENTIALS *) NULL, /* credentials not used */
+ 0, /* key schedule not used */
+ (MSG_DAT *) NULL, /* MSG_DAT not used */
+ (struct sockaddr_in *) NULL, /* local addr not used */
+ (struct sockaddr_in *) NULL, /* foreign addr not used */
+ 0L); /* authopts */
+ if (err > KSUCCESS && err < MAX_KRB_ERRORS) {
+ warnx("kcmd: %s", krb_get_err_text(err));
+ rem = -1;
+ } else if (err < 0)
+ rem = -1;
+ else
+ rem = sock;
+#endif
+ if (rem < 0) {
+ if (errno == ECONNREFUSED)
+ oldw("remote host doesn't support Kerberos");
+ else if (errno == ENOENT)
+ oldw("can't provide Kerberos authentication data");
+ execv(_PATH_RCP, argv_copy);
+ }
+ } else {
+ if (doencrypt)
+ errx(1,
+ "the -x option requires Kerberos authentication");
+ if (geteuid() != 0) {
+ errx(1, "not installed setuid root, "
+ "only root may use non kerberized rcp");
+ }
+ rem = rcmd(host, port, locuser, user, bp, 0);
+ }
+ return (rem);
+}
+
+static void
+toremote(char *targ, int argc, char **argv)
+{
+ int i, len;
+#ifdef IP_TOS
+ int tos;
+#endif
+ char *bp, *host, *src, *suser, *thost, *tuser;
+
+ *targ++ = 0;
+ if (*targ == 0)
+ targ = ".";
+
+ if ((thost = strchr(argv[argc - 1], '@'))) {
+ /* user@host */
+ *thost++ = 0;
+ tuser = argv[argc - 1];
+ if (*tuser == '\0')
+ tuser = NULL;
+ else if (!okname(tuser))
+ exit(1);
+ } else {
+ thost = argv[argc - 1];
+ tuser = user_name;
+ }
+
+ for (i = 0; i < argc - 1; i++) {
+ src = colon(argv[i]);
+ if (src) { /* remote to remote */
+ *src++ = 0;
+ if (*src == 0)
+ src = ".";
+ host = strchr(argv[i], '@');
+ if (host) {
+ *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
+ 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 */
+ if (rem == -1) {
+ len = strlen(targ) + CMDNEEDS + 20;
+ if (!(bp = malloc(len)))
+ err(1, " ");
+ snprintf(bp, len, "%s -t %s", cmd, targ);
+ host = thost;
+ if (use_kerberos)
+ rem = kerberos(&host, bp,
+#ifdef __CYGWIN32__
+ tuser,
+#else
+ pwd->pw_name,
+#endif
+ tuser ? tuser : pwd->pw_name);
+ else
+ rem = rcmd(&host, port,
+#ifdef __CYGWIN32__
+ tuser,
+#else
+ pwd->pw_name,
+#endif
+ tuser ? tuser : pwd->pw_name,
+ bp, 0);
+ if (rem < 0)
+ exit(1);
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ tos = IPTOS_THROUGHPUT;
+ if (setsockopt(rem, IPPROTO_IP, IP_TOS,
+ (void *)&tos, sizeof(int)) < 0)
+ warn("TOS (ignored)");
+#endif /* IP_TOS */
+ if (doencrypt)
+ send_auth(host, dest_realm);
+ if (response() < 0)
+ exit(1);
+ free(bp);
+ paranoid_setuid(userid);
+ }
+ source(1, argv+i);
+ }
+ }
+}
+
+static void
+sink(int argc, char **argv)
+{
+ static BUF buffer;
+ struct stat stb;
+ struct timeval tv[2];
+ enum { YES, NO, DISPLAYED } wrerr;
+ BUF *bp;
+ off_t i, j;
+ int amt, count, exists, first, mask, mode, ofd, omode;
+ int setimes, size, targisdir, wrerrno=0;
+ char ch, *cp, *np, *targ, *why, *vect[1], buf[BUFSIZ];
+
+#define atime tv[0]
+#define mtime tv[1]
+#define SCREWUP(str) { why = str; goto screwup; }
+
+ setimes = targisdir = 0;
+ mask = umask(0);
+ if (!pflag)
+ umask(mask);
+ if (argc != 1) {
+ run_err("ambiguous target");
+ exit(1);
+ }
+ targ = *argv;
+ if (targetshouldbedirectory)
+ verifydir(targ);
+ des_write(rem, "", 1);
+ if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
+ targisdir = 1;
+ for (first = 1;; first = 0) {
+ cp = buf;
+ if (des_read(rem, cp, 1) <= 0)
+ return;
+ if (*cp++ == '\n')
+ SCREWUP("unexpected <newline>");
+ do {
+ if (des_read(rem, &ch, sizeof(ch)) != sizeof(ch))
+ SCREWUP("lost connection");
+ *cp++ = ch;
+ } while (cp < &buf[BUFSIZ - 1] && ch != '\n');
+ *cp = 0;
+
+ if (buf[0] == '\01' || buf[0] == '\02') {
+ if (iamremote == 0)
+ write(STDERR_FILENO,
+ buf + 1, strlen(buf + 1));
+ if (buf[0] == '\02')
+ exit(1);
+ ++errs;
+ continue;
+ }
+ if (buf[0] == 'E') {
+ des_write(rem, "", 1);
+ return;
+ }
+
+ if (ch == '\n')
+ *--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++;
+ cp++;
+ getnum(mtime.tv_sec);
+ if (*cp++ != ' ')
+ SCREWUP("mtime.sec not delimited");
+ getnum(mtime.tv_usec);
+ if (*cp++ != ' ')
+ SCREWUP("mtime.usec not delimited");
+ getnum(atime.tv_sec);
+ if (*cp++ != ' ')
+ SCREWUP("atime.sec not delimited");
+ getnum(atime.tv_usec);
+ if (*cp++ != '\0')
+ SCREWUP("atime.usec not delimited");
+ des_write(rem, "", 1);
+ continue;
+ }
+ if (*cp != 'C' && *cp != 'D') {
+ /*
+ * Check for the case "rcp remote:foo\* local:bar".
+ * In this case, the line "No match." can be returned
+ * by the shell before the rcp command on the remote is
+ * executed so the ^Aerror_message convention isn't
+ * followed.
+ */
+ if (first) {
+ run_err("%s", cp);
+ exit(1);
+ }
+ SCREWUP("expected control record");
+ }
+ mode = 0;
+ for (++cp; cp < buf + 5; cp++) {
+ if (*cp < '0' || *cp > '7')
+ SCREWUP("bad mode");
+ mode = (mode << 3) | (*cp - '0');
+ }
+ if (*cp++ != ' ')
+ SCREWUP("mode not delimited");
+
+ for (size = 0; isdigit((unsigned char)*cp);)
+ size = size * 10 + (*cp++ - '0');
+ if (*cp++ != ' ')
+ SCREWUP("size not delimited");
+ if (targisdir) {
+ static char *namebuf;
+ static int cursize;
+ size_t need;
+
+ need = strlen(targ) + strlen(cp) + 250;
+ if (need > cursize) {
+ if (!(namebuf = malloc(need)))
+ run_err("%s", strerror(errno));
+ }
+ snprintf(namebuf, need, "%s%s%s", targ,
+ *targ ? "/" : "", cp);
+ np = namebuf;
+ } else
+ np = targ;
+ exists = stat(np, &stb) == 0;
+ if (buf[0] == 'D') {
+ int mod_flag = pflag;
+ if (exists) {
+ if (!S_ISDIR(stb.st_mode)) {
+ errno = ENOTDIR;
+ goto bad;
+ }
+ if (pflag)
+ chmod(np, mode);
+ } else {
+ /* Handle copying from a read-only directory */
+ mod_flag = 1;
+ if (mkdir(np, mode | S_IRWXU) < 0)
+ goto bad;
+ }
+ vect[0] = np;
+ sink(1, vect);
+ if (setimes) {
+ struct utimbuf times;
+ times.actime = atime.tv_sec;
+ times.modtime = mtime.tv_sec;
+ setimes = 0;
+ if (utime(np, &times) < 0)
+ run_err("%s: set times: %s",
+ np, strerror(errno));
+ }
+ if (mod_flag)
+ chmod(np, mode);
+ continue;
+ }
+ omode = mode;
+ mode |= S_IWRITE;
+ if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
+bad: run_err("%s: %s", np, strerror(errno));
+ continue;
+ }
+ des_write(rem, "", 1);
+ if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) {
+ close(ofd);
+ continue;
+ }
+ cp = bp->buf;
+ wrerr = NO;
+ for (count = i = 0; i < size; i += BUFSIZ) {
+ amt = BUFSIZ;
+ if (i + amt > size)
+ amt = size - i;
+ count += amt;
+ do {
+ j = des_read(rem, cp, amt);
+ if (j <= 0) {
+ run_err("%s", j ? strerror(errno) :
+ "dropped connection");
+ exit(1);
+ }
+ amt -= j;
+ cp += j;
+ } while (amt > 0);
+ if (count == bp->cnt) {
+ /* Keep reading so we stay sync'd up. */
+ if (wrerr == NO) {
+ j = write(ofd, bp->buf, count);
+ if (j != count) {
+ wrerr = YES;
+ wrerrno = j >= 0 ? EIO : errno;
+ }
+ }
+ count = 0;
+ cp = bp->buf;
+ }
+ }
+ if (count != 0 && wrerr == NO &&
+ (j = write(ofd, bp->buf, count)) != count) {
+ wrerr = YES;
+ wrerrno = j >= 0 ? EIO : errno;
+ }
+ if (ftruncate(ofd, size)) {
+ run_err("%s: truncate: %s", np, strerror(errno));
+ wrerr = DISPLAYED;
+ }
+ if (pflag) {
+ if (exists || omode != mode)
+#ifdef HAVE_FCHMOD
+ if (fchmod(ofd, omode))
+#else
+ if (chmod(np, omode))
+#endif
+ run_err("%s: set mode: %s",
+ np, strerror(errno));
+ } else {
+ if (!exists && omode != mode)
+#ifdef HAVE_FCHMOD
+ if (fchmod(ofd, omode & ~mask))
+#else
+ if (chmod(np, omode & ~mask))
+#endif
+ run_err("%s: set mode: %s",
+ np, strerror(errno));
+ }
+ close(ofd);
+ response();
+ if (setimes && wrerr == NO) {
+ struct utimbuf times;
+ times.actime = atime.tv_sec;
+ times.modtime = mtime.tv_sec;
+ setimes = 0;
+ if (utime(np, &times) < 0) {
+ run_err("%s: set times: %s",
+ np, strerror(errno));
+ wrerr = DISPLAYED;
+ }
+ }
+ switch(wrerr) {
+ case YES:
+ run_err("%s: %s", np, strerror(wrerrno));
+ break;
+ case NO:
+ des_write(rem, "", 1);
+ break;
+ case DISPLAYED:
+ break;
+ }
+ }
+screwup:
+ run_err("protocol error: %s", why);
+ exit(1);
+}
+
+static void
+tolocal(int argc, char **argv)
+{
+ int i, len;
+#ifdef IP_TOS
+ int tos;
+#endif
+ char *bp, *host, *src, *suser;
+
+ for (i = 0; i < argc - 1; i++) {
+ if (!(src = colon(argv[i]))) { /* Local to local. */
+ len = strlen(_PATH_CP) + strlen(argv[i]) +
+ strlen(argv[argc - 1]) + 20;
+ if (!(bp = malloc(len)))
+ err(1, " ");
+ snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP,
+ iamrecursive ? " -r" : "", pflag ? " -p" : "",
+ argv[i], argv[argc - 1]);
+ if (susystem(bp, userid))
+ ++errs;
+ free(bp);
+ continue;
+ }
+ *src++ = 0;
+ if (*src == 0)
+ src = ".";
+ if ((host = strchr(argv[i], '@')) == NULL) {
+#ifdef __CYGWIN32__
+ errx (1, "Sorry, you need to specify the username");
+#else
+ host = argv[i];
+ suser = pwd->pw_name;
+ if (user_name)
+ suser = user_name;
+#endif
+ } else {
+ *host++ = 0;
+ suser = argv[i];
+ if (*suser == '\0')
+#ifdef __CYGWIN32__
+ errx (1, "Sorry, you need to specify the username");
+#else
+ suser = pwd->pw_name;
+#endif
+ else if (!okname(suser))
+ continue;
+ }
+ len = strlen(src) + CMDNEEDS + 20;
+ if ((bp = malloc(len)) == NULL)
+ err(1, " ");
+ snprintf(bp, len, "%s -f %s", cmd, src);
+ rem =
+ use_kerberos ?
+ kerberos(&host, bp,
+#ifndef __CYGWIN32__
+ pwd->pw_name,
+#else
+ suser,
+#endif
+ suser) :
+ rcmd(&host, port,
+#ifndef __CYGWIN32__
+ pwd->pw_name,
+#else
+ suser,
+#endif
+ suser, bp, 0);
+ free(bp);
+ if (rem < 0) {
+ ++errs;
+ continue;
+ }
+ seteuid(userid);
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ tos = IPTOS_THROUGHPUT;
+ if (setsockopt(rem, IPPROTO_IP, IP_TOS, (void *)&tos,
+ sizeof(int)) < 0)
+ warn("TOS (ignored)");
+#endif /* IP_TOS */
+ if (doencrypt)
+ send_auth(host, dest_realm);
+ sink(1, argv + argc - 1);
+ seteuid(0);
+ close(rem);
+ rem = -1;
+ }
+}
+
+
+int
+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)) != -1)
+ switch(ch) { /* User-visible flags. */
+ case 'K':
+ use_kerberos = 0;
+ break;
+ case 'k':
+ dest_realm = dst_realm_buf;
+ strlcpy(dst_realm_buf, optarg, REALM_SZ);
+ break;
+ case 'x':
+ doencrypt = 1;
+ LEFT_JUSTIFIED = 1;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'r':
+ iamrecursive = 1;
+ break;
+ /* Server options. */
+ case 'd':
+ targetshouldbedirectory = 1;
+ break;
+ case 'f': /* "from" */
+ iamremote = 1;
+ fflag = 1;
+ break;
+ case 't': /* "to" */
+ iamremote = 1;
+ tflag = 1;
+ break;
+ case 'l':
+ user_name = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Rcp implements encrypted file transfer without using the
+ * kshell service, pass 0 for no encryption */
+ port = get_shell_port(use_kerberos, 0);
+
+ userid = getuid();
+
+#ifndef __CYGWIN32__
+ if ((pwd = k_getpwuid(userid)) == NULL)
+ errx(1, "unknown user %d", (int)userid);
+#endif
+
+ rem = STDIN_FILENO; /* XXX */
+
+ if (fflag || tflag) {
+ if (doencrypt)
+ answer_auth();
+ if(fflag)
+ response();
+ if(do_osfc2_magic(pwd->pw_uid))
+ exit(1);
+ paranoid_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);
+ else
+ sink(argc, argv);
+ exit(errs);
+ }
+
+ if (argc < 2)
+ usage();
+ if (argc > 2)
+ targetshouldbedirectory = 1;
+
+ rem = -1;
+ /* Command to be executed on remote system using "rsh". */
+ snprintf(cmd, sizeof(cmd),
+ "rcp%s%s%s%s", iamrecursive ? " -r" : "",
+ (doencrypt && use_kerberos ? " -x" : ""),
+ pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
+
+ signal(SIGPIPE, lostconn);
+
+ if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
+ toremote(targ, argc, argv);
+ else {
+ tolocal(argc, argv); /* Dest is local host. */
+ if (targetshouldbedirectory)
+ verifydir(argv[argc - 1]);
+ }
+ exit(errs);
+}
diff --git a/crypto/kerberosIV/appl/bsd/rcp_util.c b/crypto/kerberosIV/appl/bsd/rcp_util.c
new file mode 100644
index 0000000..54233af
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rcp_util.c
@@ -0,0 +1,99 @@
+/*-
+ * 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 "bsd_locl.h"
+
+RCSID("$Id: rcp_util.c,v 1.8 1998/09/28 11:45:21 joda Exp $");
+
+char *
+colon(char *cp)
+{
+ if (*cp == ':') /* Leading colon is part of file name. */
+ return (0);
+
+ for (; *cp; ++cp) {
+ if (*cp == ':')
+ return (cp);
+ if (*cp == '/')
+ return (0);
+ }
+ return (0);
+}
+
+int
+okname(char *cp0)
+{
+ int c;
+ char *cp;
+
+ cp = cp0;
+ do {
+ c = *cp;
+ if (c & 0200)
+ goto bad;
+ if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
+ goto bad;
+ } while (*++cp);
+ return (1);
+
+bad: warnx("%s: invalid user name", cp0);
+ return (0);
+}
+
+int
+susystem(char *s, int userid)
+{
+ RETSIGTYPE (*istat)(), (*qstat)();
+ int status;
+ pid_t pid;
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ return (127);
+
+ 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
new file mode 100644
index 0000000..60bed67
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rlogin.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * rlogin - remote login
+ */
+#include "bsd_locl.h"
+
+RCSID("$Id: rlogin.c,v 1.67.2.2 2000/10/10 12:54:26 assar Exp $");
+
+CREDENTIALS cred;
+Key_schedule schedule;
+int use_kerberos = 1, doencrypt;
+char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
+
+#ifndef CCEQ
+#define c2uc(x) ((unsigned char) x)
+#define CCEQ__(val, c) (c == val ? val != c2uc(_POSIX_VDISABLE) : 0)
+#define CCEQ(val, c) CCEQ__(c2uc(val), c2uc(c))
+#endif
+
+int eight, rem;
+struct termios deftty;
+
+int noescape;
+char escapechar = '~';
+
+struct winsize winsize;
+
+int parent, rcvcnt;
+char rcvbuf[8 * 1024];
+
+int child;
+
+static void
+echo(char c)
+{
+ char *p;
+ char buf[8];
+
+ p = buf;
+ c &= 0177;
+ *p++ = escapechar;
+ if (c < ' ') {
+ *p++ = '^';
+ *p++ = c + '@';
+ } else if (c == 0177) {
+ *p++ = '^';
+ *p++ = '?';
+ } else
+ *p++ = c;
+ *p++ = '\r';
+ *p++ = '\n';
+ write(STDOUT_FILENO, buf, p - buf);
+}
+
+static void
+mode(int f)
+{
+ struct termios tty;
+
+ switch (f) {
+ case 0:
+ tcsetattr(0, TCSANOW, &deftty);
+ break;
+ case 1:
+ tcgetattr(0, &deftty);
+ tty = deftty;
+ /* This is loosely derived from sys/compat/tty_compat.c. */
+ tty.c_lflag &= ~(ECHO|ICANON|ISIG|IEXTEN);
+ tty.c_iflag &= ~ICRNL;
+ tty.c_oflag &= ~OPOST;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+ if (eight) {
+ tty.c_iflag &= IXOFF;
+ tty.c_cflag &= ~(CSIZE|PARENB);
+ tty.c_cflag |= CS8;
+ }
+ tcsetattr(0, TCSANOW, &tty);
+ break;
+ default:
+ return;
+ }
+}
+
+static void
+done(int status)
+{
+ int w, wstatus;
+
+ mode(0);
+ if (child > 0) {
+ /* make sure catch_child does not snap it up */
+ signal(SIGCHLD, SIG_DFL);
+ if (kill(child, SIGKILL) >= 0)
+ while ((w = wait(&wstatus)) > 0 && w != child);
+ }
+ exit(status);
+}
+
+static
+RETSIGTYPE
+catch_child(int foo)
+{
+ int status;
+ int pid;
+
+ for (;;) {
+ pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
+ if (pid == 0)
+ return;
+ /* if the child (reader) dies, just quit */
+ if (pid < 0 || (pid == child && !WIFSTOPPED(status)))
+ done(WTERMSIG(status) | WEXITSTATUS(status));
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * There is a race in the SunOS5 rlogind. If the slave end has not yet
+ * been opened by the child when setting tty size the size is reset to
+ * zero when the child opens it. Therefore we send the window update
+ * twice.
+ */
+
+static int tty_kludge = 1;
+
+/* Return the number of OOB bytes processed. */
+static int
+oob_real(void)
+{
+ struct termios tty;
+ int atmark, n, out, rcvd;
+ char waste[BUFSIZ], mark;
+
+ out = O_RDWR;
+ rcvd = 0;
+ if (recv(rem, &mark, 1, MSG_OOB) < 0) {
+ return -1;
+ }
+ if (mark & TIOCPKT_WINDOW) {
+ /* Let server know about window size changes */
+ kill(parent, SIGUSR1);
+ } else if (tty_kludge) {
+ /* Let server know about window size changes */
+ kill(parent, SIGUSR1);
+ tty_kludge = 0;
+ }
+ if (!eight && (mark & TIOCPKT_NOSTOP)) {
+ tcgetattr(0, &tty);
+ tty.c_iflag &= ~IXON;
+ tcsetattr(0, TCSANOW, &tty);
+ }
+ if (!eight && (mark & TIOCPKT_DOSTOP)) {
+ tcgetattr(0, &tty);
+ tty.c_iflag |= (deftty.c_iflag & IXON);
+ tcsetattr(0, TCSANOW, &tty);
+ }
+ if (mark & TIOCPKT_FLUSHWRITE) {
+#ifdef TCOFLUSH
+ tcflush(1, TCOFLUSH);
+#else
+ ioctl(1, TIOCFLUSH, (char *)&out);
+#endif
+ for (;;) {
+ if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
+ warn("ioctl");
+ break;
+ }
+ if (atmark)
+ break;
+ n = read(rem, waste, sizeof (waste));
+ if (n <= 0)
+ break;
+ }
+ /*
+ * Don't want any pending data to be output, so clear the recv
+ * buffer. If we were hanging on a write when interrupted,
+ * don't want it to restart. If we were reading, restart
+ * anyway.
+ */
+ rcvcnt = 0;
+ }
+
+ /* oob does not do FLUSHREAD (alas!) */
+ return 1;
+}
+
+/* reader: read from remote: line -> 1 */
+static int
+reader(void)
+{
+ int n, remaining;
+ char *bufp;
+ int kludgep = 1;
+
+ bufp = rcvbuf;
+ for (;;) {
+ fd_set readfds, exceptfds;
+ while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
+ n = write(STDOUT_FILENO, bufp, remaining);
+ if (n < 0) {
+ if (errno != EINTR)
+ return (-1);
+ continue;
+ }
+ bufp += n;
+ }
+ bufp = rcvbuf;
+ rcvcnt = 0;
+
+ FD_ZERO (&readfds);
+ if (rem >= FD_SETSIZE)
+ errx (1, "fd too large");
+ FD_SET (rem, &readfds);
+ FD_ZERO (&exceptfds);
+ if (kludgep)
+ FD_SET (rem, &exceptfds);
+ if (select(rem+1, &readfds, 0, &exceptfds, 0) == -1) {
+ if (errno == EINTR)
+ continue; /* Got signal */
+ else
+ errx(1, "select failed mysteriously");
+ }
+
+ if (!FD_ISSET(rem, &exceptfds) && !FD_ISSET(rem, &readfds)) {
+ warnx("select: nothing to read?");
+ continue;
+ }
+
+ if (FD_ISSET(rem, &exceptfds)) {
+ int foo = oob_real ();
+ if (foo >= 1)
+ continue; /* First check if there is more OOB data. */
+ else if (foo < 0)
+ kludgep = 0;
+ }
+
+ if (!FD_ISSET(rem, &readfds))
+ continue; /* Nothing to read. */
+
+ kludgep = 1;
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ rcvcnt = des_enc_read(rem, rcvbuf,
+ sizeof(rcvbuf),
+ schedule, &cred.session);
+ else
+#endif
+ rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
+ if (rcvcnt == 0)
+ return (0);
+ if (rcvcnt < 0) {
+ if (errno == EINTR)
+ continue;
+ warn("read");
+ return (-1);
+ }
+ }
+}
+
+/*
+ * Send the window size to the server via the magic escape
+ */
+static void
+sendwindow(void)
+{
+ char obuf[4 + 4 * sizeof (u_int16_t)];
+ unsigned short *p;
+
+ p = (u_int16_t *)(obuf + 4);
+ obuf[0] = 0377;
+ obuf[1] = 0377;
+ obuf[2] = 's';
+ obuf[3] = 's';
+ *p++ = htons(winsize.ws_row);
+ *p++ = htons(winsize.ws_col);
+#ifdef HAVE_WS_XPIXEL
+ *p++ = htons(winsize.ws_xpixel);
+#else
+ *p++ = htons(0);
+#endif
+#ifdef HAVE_WS_YPIXEL
+ *p++ = htons(winsize.ws_ypixel);
+#else
+ *p++ = htons(0);
+#endif
+
+#ifndef NOENCRYPTION
+ if(doencrypt)
+ des_enc_write(rem, obuf, sizeof(obuf), schedule,
+ &cred.session);
+ else
+#endif
+ write(rem, obuf, sizeof(obuf));
+}
+
+static
+RETSIGTYPE
+sigwinch(int foo)
+{
+ struct winsize ws;
+
+ if (get_window_size(0, &ws) == 0 &&
+ memcmp(&ws, &winsize, sizeof(ws))) {
+ winsize = ws;
+ sendwindow();
+ }
+}
+
+static void
+stop(int all)
+{
+ mode(0);
+ signal(SIGCHLD, SIG_IGN);
+ kill(all ? 0 : getpid(), SIGTSTP);
+ signal(SIGCHLD, catch_child);
+ mode(1);
+#ifdef SIGWINCH
+ kill(SIGWINCH, getpid()); /* check for size changes, if caught */
+#endif
+}
+
+/*
+ * writer: write to remote: 0 -> line.
+ * ~. terminate
+ * ~^Z suspend rlogin process.
+ * ~<delayed-suspend char> suspend rlogin process, but leave reader alone.
+ */
+static void
+writer(void)
+{
+ int bol, local, n;
+ char c;
+
+ bol = 1; /* beginning of line */
+ local = 0;
+ for (;;) {
+ n = read(STDIN_FILENO, &c, 1);
+ if (n <= 0) {
+ if (n < 0 && errno == EINTR)
+ continue;
+ break;
+ }
+ /*
+ * If we're at the beginning of the line and recognize a
+ * command character, then we echo locally. Otherwise,
+ * characters are echo'd remotely. If the command character
+ * is doubled, this acts as a force and local echo is
+ * suppressed.
+ */
+ if (bol) {
+ bol = 0;
+ if (!noescape && c == escapechar) {
+ local = 1;
+ continue;
+ }
+ } else if (local) {
+ local = 0;
+ if (c == '.' || CCEQ(deftty.c_cc[VEOF], c)) {
+ echo(c);
+ break;
+ }
+ if (CCEQ(deftty.c_cc[VSUSP], c)) {
+ bol = 1;
+ echo(c);
+ stop(1);
+ continue;
+ }
+#ifdef VDSUSP
+ /* Is VDSUSP called something else on Linux?
+ * Perhaps VDELAY is a better thing? */
+ if (CCEQ(deftty.c_cc[VDSUSP], c)) {
+ bol = 1;
+ echo(c);
+ stop(0);
+ continue;
+ }
+#endif /* VDSUSP */
+ if (c != escapechar) {
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ des_enc_write(rem, &escapechar,1, schedule, &cred.session);
+ else
+#endif
+ write(rem, &escapechar, 1);
+ }
+ }
+
+ if (doencrypt) {
+#ifdef NOENCRYPTION
+ if (write(rem, &c, 1) == 0) {
+#else
+ if (des_enc_write(rem, &c, 1, schedule, &cred.session) == 0) {
+#endif
+ warnx("line gone");
+ break;
+ }
+ } else
+ if (write(rem, &c, 1) == 0) {
+ warnx("line gone");
+ break;
+ }
+ bol = CCEQ(deftty.c_cc[VKILL], c) ||
+ CCEQ(deftty.c_cc[VEOF], c) ||
+ CCEQ(deftty.c_cc[VINTR], c) ||
+ CCEQ(deftty.c_cc[VSUSP], c) ||
+ c == '\r' || c == '\n';
+ }
+}
+
+static
+RETSIGTYPE
+lostpeer(int foo)
+{
+ signal(SIGPIPE, SIG_IGN);
+ warnx("\aconnection closed.\r");
+ done(1);
+}
+
+/*
+ * This is called in the parent when the reader process gets the
+ * out-of-band (urgent) request to turn on the window-changing
+ * protocol. It is signalled from the child(reader).
+ */
+static
+RETSIGTYPE
+sigusr1(int foo)
+{
+ /*
+ * Now we now daemon supports winsize hack,
+ */
+ sendwindow();
+#ifdef SIGWINCH
+ signal(SIGWINCH, sigwinch); /* so we start to support it */
+#endif
+ SIGRETURN(0);
+}
+
+static void
+doit(void)
+{
+ signal(SIGINT, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+
+ signal(SIGCHLD, catch_child);
+
+ /*
+ * Child sends parent this signal for window size hack.
+ */
+ signal(SIGUSR1, sigusr1);
+
+ signal(SIGPIPE, lostpeer);
+
+ mode(1);
+ parent = getpid();
+ child = fork();
+ if (child == -1) {
+ warn("fork");
+ done(1);
+ }
+ if (child == 0) {
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ if (reader() == 0)
+ errx(1, "connection closed.\r");
+ sleep(1);
+ errx(1, "\aconnection closed.\r");
+ }
+
+ writer();
+ warnx("closed connection.\r");
+ done(0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n",
+ "8DEKLdx", " [-k realm] ");
+ exit(1);
+}
+
+static u_int
+getescape(char *p)
+{
+ long val;
+ int len;
+
+ if ((len = strlen(p)) == 1) /* use any single char, including '\' */
+ return ((u_int)*p);
+ /* otherwise, \nnn */
+ if (*p == '\\' && len >= 2 && len <= 4) {
+ val = strtol(++p, NULL, 8);
+ for (;;) {
+ if (!*++p)
+ return ((u_int)val);
+ if (*p < '0' || *p > '8')
+ break;
+ }
+ }
+ warnx("illegal option value -- e");
+ usage();
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct passwd *pw;
+ int sv_port, user_port = 0;
+ int argoff, ch, dflag, Dflag, one, uid;
+ char *host, *user, term[1024];
+
+ argoff = dflag = Dflag = 0;
+ one = 1;
+ host = user = NULL;
+
+ set_progname(argv[0]);
+
+ /* handle "rlogin host flags" */
+ if (argc > 2 && argv[1][0] != '-') {
+ host = argv[1];
+ argoff = 1;
+ }
+
+#define OPTIONS "8DEKLde:k:l:xp:"
+ while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != -1)
+ switch(ch) {
+ case '8':
+ eight = 1;
+ break;
+ case 'D':
+ Dflag = 1;
+ break;
+ case 'E':
+ noescape = 1;
+ break;
+ case 'K':
+ use_kerberos = 0;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'e':
+ noescape = 0;
+ escapechar = getescape(optarg);
+ break;
+ case 'k':
+ dest_realm = dst_realm_buf;
+ strlcpy(dest_realm, optarg, REALM_SZ);
+ break;
+ case 'l':
+ user = optarg;
+ break;
+ 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();
+ }
+ optind += argoff;
+
+ /* if haven't gotten a host yet, do so */
+ if (!host && !(host = argv[optind++]))
+ usage();
+
+ if (argv[optind])
+ usage();
+
+ if (!(pw = k_getpwuid(uid = getuid())))
+ errx(1, "unknown user id.");
+ if (!user)
+ user = pw->pw_name;
+
+ if (user_port)
+ sv_port = user_port;
+ else
+ sv_port = get_login_port(use_kerberos, doencrypt);
+
+ {
+ char *p = getenv("TERM");
+ struct termios tty;
+ int i;
+
+ if (p == NULL)
+ p = "network";
+
+ if (tcgetattr(0, &tty) == 0
+ && (i = speed_t2int (cfgetospeed(&tty))) > 0)
+ snprintf (term, sizeof(term),
+ "%s/%d",
+ p, i);
+ else
+ snprintf (term, sizeof(term),
+ "%s",
+ p);
+ }
+
+ get_window_size(0, &winsize);
+
+ if (use_kerberos) {
+ paranoid_setuid(getuid());
+ rem = KSUCCESS;
+ errno = 0;
+ if (dest_realm == NULL)
+ dest_realm = krb_realmofhost(host);
+
+ if (doencrypt)
+ rem = krcmd_mutual(&host, sv_port, user, term, 0,
+ dest_realm, &cred, schedule);
+ else
+ rem = krcmd(&host, sv_port, user, term, 0,
+ dest_realm);
+ if (rem < 0) {
+ 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)
+ errx(1, "the -x flag requires Kerberos authentication.");
+ if (geteuid() != 0)
+ errx(1, "not installed setuid root, "
+ "only root may use non kerberized rlogin");
+ rem = rcmd(&host, sv_port, pw->pw_name, user, term, 0);
+ }
+
+ if (rem < 0)
+ exit(1);
+
+#ifdef HAVE_SETSOCKOPT
+#ifdef SO_DEBUG
+ if (dflag &&
+ setsockopt(rem, SOL_SOCKET, SO_DEBUG, (void *)&one,
+ sizeof(one)) < 0)
+ warn("setsockopt");
+#endif
+#ifdef TCP_NODELAY
+ if (Dflag &&
+ setsockopt(rem, IPPROTO_TCP, TCP_NODELAY, (void *)&one,
+ sizeof(one)) < 0)
+ warn("setsockopt(TCP_NODELAY)");
+#endif
+#ifdef IP_TOS
+ one = IPTOS_LOWDELAY;
+ if (setsockopt(rem, IPPROTO_IP, IP_TOS, (void *)&one, sizeof(int)) < 0)
+ warn("setsockopt(IP_TOS)");
+#endif /* IP_TOS */
+#endif /* HAVE_SETSOCKOPT */
+
+ paranoid_setuid(uid);
+ doit();
+ return 0;
+}
diff --git a/crypto/kerberosIV/appl/bsd/rlogind.c b/crypto/kerberosIV/appl/bsd/rlogind.c
new file mode 100644
index 0000000..eae2dd6
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rlogind.c
@@ -0,0 +1,970 @@
+/*-
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+/*
+ * remote login server:
+ * \0
+ * remuser\0
+ * locuser\0
+ * terminal_type/speed\0
+ * data
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: rlogind.c,v 1.109.2.2 2000/06/23 02:37:06 assar Exp $");
+
+extern int __check_rhosts_file;
+
+char *INSECURE_MESSAGE =
+"\r\n*** Connection not encrypted! Communication may be eavesdropped. ***"
+"\r\n*** Use telnet or rlogin -x instead! ***\r\n";
+
+#ifndef NOENCRYPTION
+char *SECURE_MESSAGE =
+"This rlogin session is using DES encryption for all transmissions.\r\n";
+#else
+#define SECURE_MESSAGE INSECURE_MESSAGE
+#endif
+
+AUTH_DAT *kdata;
+KTEXT ticket;
+u_char auth_buf[sizeof(AUTH_DAT)];
+u_char tick_buf[sizeof(KTEXT_ST)];
+Key_schedule schedule;
+int doencrypt, retval, use_kerberos, vacuous;
+
+#define ARGSTR "Daip:lnkvxL:"
+
+char *env[2];
+#define NMAX 30
+char lusername[NMAX+1], rusername[NMAX+1];
+static char term[64] = "TERM=";
+#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */
+int keepalive = 1;
+int check_all = 0;
+int no_delay = 0;
+
+struct passwd *pwd;
+
+static const char *new_login = _PATH_LOGIN;
+
+static void doit (int, struct sockaddr_in *);
+static int control (int, char *, int);
+static void protocol (int, int);
+static RETSIGTYPE cleanup (int);
+void fatal (int, const char *, int);
+static int do_rlogin (struct sockaddr_in *);
+static void setup_term (int);
+static int do_krb_login (struct sockaddr_in *);
+static void usage (void);
+
+static int
+readstream(int p, char *ibuf, int bufsize)
+{
+#ifndef HAVE_GETMSG
+ return read(p, ibuf, bufsize);
+#else
+ static int flowison = -1; /* current state of flow: -1 is unknown */
+ static struct strbuf strbufc, strbufd;
+ static unsigned char ctlbuf[BUFSIZ];
+ static int use_read = 1;
+
+ int flags = 0;
+ int ret;
+ struct termios tsp;
+
+ struct iocblk ip;
+ char vstop, vstart;
+ int ixon;
+ int newflow;
+
+ if (use_read)
+ {
+ ret = read(p, ibuf, bufsize);
+ if (ret < 0 && errno == EBADMSG)
+ use_read = 0;
+ else
+ return ret;
+ }
+
+ 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:
+ memcpy(&ip, (ibuf+1), sizeof(ip));
+
+ switch (ip.ioc_cmd) {
+#ifdef TCSETS
+ case TCSETS:
+ case TCSETSW:
+ case TCSETSF:
+ memcpy(&tsp,
+ (ibuf+1 + sizeof(struct iocblk)),
+ sizeof(tsp));
+ vstop = tsp.c_cc[VSTOP];
+ vstart = tsp.c_cc[VSTART];
+ ixon = tsp.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
+}
+
+#ifdef HAVE_UTMPX_H
+static int
+rlogind_logout(const char *line)
+{
+ struct utmpx utmpx, *utxp;
+ int ret = 1;
+
+ setutxent ();
+ memset(&utmpx, 0, sizeof(utmpx));
+ utmpx.ut_type = USER_PROCESS;
+ strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
+ 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);
+#else
+ ret = 0;
+#endif
+ }
+ endutxent();
+ return ret;
+}
+#else
+static int
+rlogind_logout(const char *line)
+{
+ FILE *fp;
+ struct utmp ut;
+ int rval;
+
+ if (!(fp = fopen(_PATH_UTMP, "r+")))
+ return(0);
+ rval = 1;
+ while (fread(&ut, sizeof(struct utmp), 1, fp) == 1) {
+ if (!ut.ut_name[0] ||
+ strncmp(ut.ut_line, line, sizeof(ut.ut_line)))
+ continue;
+ memset(ut.ut_name, 0, sizeof(ut.ut_name));
+#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
+ ut.ut_time = time(NULL);
+ fseek(fp, (long)-sizeof(struct utmp), SEEK_CUR);
+ fwrite(&ut, sizeof(struct utmp), 1, fp);
+ fseek(fp, (long)0, SEEK_CUR);
+ rval = 0;
+ }
+ fclose(fp);
+ return(rval);
+}
+#endif
+
+#ifndef HAVE_LOGWTMP
+static void
+logwtmp(const char *line, const char *name, const char *host)
+{
+ struct utmp ut;
+ struct stat buf;
+ int fd;
+
+ memset (&ut, 0, sizeof(ut));
+ if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
+ return;
+ if (!fstat(fd, &buf)) {
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+#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_STRUCT_UTMP_UT_PID
+ ut.ut_pid = getpid();
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ if(name[0])
+ ut.ut_type = USER_PROCESS;
+ else
+ ut.ut_type = DEAD_PROCESS;
+#endif
+ ut.ut_time = time(NULL);
+ if (write(fd, &ut, sizeof(struct utmp)) !=
+ sizeof(struct utmp))
+ ftruncate(fd, buf.st_size);
+ }
+ close(fd);
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ struct sockaddr_in from;
+ int ch, fromlen, on;
+ int interactive = 0;
+ int portnum = 0;
+
+ set_progname(argv[0]);
+
+ openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
+
+ opterr = 0;
+ while ((ch = getopt(argc, argv, ARGSTR)) != -1)
+ switch (ch) {
+ case 'D':
+ no_delay = 1;
+ break;
+ case 'a':
+ break;
+ case 'i':
+ interactive = 1;
+ break;
+ case 'p':
+ portnum = htons(atoi(optarg));
+ break;
+ case 'l':
+ __check_rhosts_file = 0;
+ break;
+ case 'n':
+ keepalive = 0;
+ break;
+ case 'k':
+ use_kerberos = 1;
+ break;
+ case 'v':
+ vacuous = 1;
+ break;
+ case 'x':
+ doencrypt = 1;
+ break;
+ case 'L':
+ new_login = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (use_kerberos && vacuous) {
+ usage();
+ fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
+ }
+ if (interactive) {
+ if(portnum == 0)
+ portnum = get_login_port (use_kerberos, doencrypt);
+ mini_inetd (portnum);
+ }
+
+ fromlen = sizeof (from);
+ if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+ syslog(LOG_ERR,"Can't get peer name of remote host: %m");
+ fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
+ }
+ on = 1;
+#ifdef HAVE_SETSOCKOPT
+#ifdef SO_KEEPALIVE
+ if (keepalive &&
+ setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
+ sizeof (on)) < 0)
+ syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+#endif
+#ifdef TCP_NODELAY
+ if (no_delay &&
+ setsockopt(0, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
+ sizeof(on)) < 0)
+ syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
+#endif
+
+#ifdef IP_TOS
+ on = IPTOS_LOWDELAY;
+ if (setsockopt(0, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(int)) < 0)
+ syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+#endif /* HAVE_SETSOCKOPT */
+ doit(0, &from);
+ return 0;
+}
+
+int child;
+int netf;
+char line[MaxPathLen];
+int confirmed;
+
+struct winsize win = { 0, 0, 0, 0 };
+
+
+static void
+doit(int f, struct sockaddr_in *fromp)
+{
+ int master, pid, on = 1;
+ int authenticated = 0;
+ char hostname[2 * MaxHostNameLen + 1];
+ char c;
+
+ alarm(60);
+ read(f, &c, 1);
+
+ if (c != 0)
+ exit(1);
+ if (vacuous)
+ fatal(f, "Remote host requires Kerberos authentication", 0);
+
+ alarm(0);
+ inaddr2str (fromp->sin_addr, hostname, sizeof(hostname));
+
+ if (use_kerberos) {
+ retval = do_krb_login(fromp);
+ if (retval == 0)
+ authenticated++;
+ else if (retval > 0)
+ fatal(f, krb_get_err_text(retval), 0);
+ write(f, &c, 1);
+ confirmed = 1; /* we sent the null! */
+ } else {
+ fromp->sin_port = ntohs((u_short)fromp->sin_port);
+ if (fromp->sin_family != AF_INET ||
+ fromp->sin_port >= IPPORT_RESERVED ||
+ fromp->sin_port < IPPORT_RESERVED/2) {
+ syslog(LOG_NOTICE, "Connection from %s on illegal port",
+ inet_ntoa(fromp->sin_addr));
+ fatal(f, "Permission denied", 0);
+ }
+ ip_options_and_die (0, fromp);
+ if (do_rlogin(fromp) == 0)
+ authenticated++;
+ }
+ if (confirmed == 0) {
+ write(f, "", 1);
+ confirmed = 1; /* we sent the null! */
+ }
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ des_enc_write(f, SECURE_MESSAGE,
+ strlen(SECURE_MESSAGE),
+ schedule, &kdata->session);
+ else
+#endif
+ 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);
+ else
+ fatal(f, "Forkpty", 1);
+ }
+ if (pid == 0) {
+ if (f > 2) /* f should always be 0, but... */
+ close(f);
+ setup_term(0);
+ if (lusername[0] == '-'){
+ syslog(LOG_ERR, "tried to pass user \"%s\" to login",
+ lusername);
+ fatal(STDERR_FILENO, "invalid user", 0);
+ }
+ if (authenticated) {
+ if (use_kerberos && (pwd->pw_uid == 0))
+ syslog(LOG_INFO|LOG_AUTH,
+ "ROOT Kerberos login from %s on %s\n",
+ krb_unparse_name_long(kdata->pname,
+ kdata->pinst,
+ kdata->prealm),
+ hostname);
+
+ execl(new_login, "login", "-p",
+ "-h", hostname, "-f", "--", lusername, 0);
+ } else if (use_kerberos) {
+ fprintf(stderr, "User `%s' is not authorized to login as `%s'!\n",
+ krb_unparse_name_long(kdata->pname,
+ kdata->pinst,
+ kdata->prealm),
+ lusername);
+ exit(1);
+ } else
+ execl(new_login, "login", "-p",
+ "-h", hostname, "--", lusername, 0);
+ fatal(STDERR_FILENO, new_login, 1);
+ /*NOTREACHED*/
+ }
+ /*
+ * If encrypted, don't turn on NBIO or the des read/write
+ * routines will croak.
+ */
+
+ if (!doencrypt)
+ 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);
+ signal(SIGCHLD, SIG_IGN);
+ cleanup(0);
+}
+
+const char magic[2] = { 0377, 0377 };
+
+/*
+ * Handle a "control" request (signaled by magic being present)
+ * in the data stream. For now, we are only willing to handle
+ * window size changes.
+ */
+static int
+control(int master, char *cp, int n)
+{
+ struct winsize w;
+ char *p;
+ u_int32_t tmp;
+
+ if (n < 4 + 4 * sizeof (u_int16_t) || cp[2] != 's' || cp[3] != 's')
+ return (0);
+#ifdef TIOCSWINSZ
+ p = cp + 4;
+ p += krb_get_int(p, &tmp, 2, 0);
+ w.ws_row = tmp;
+ p += krb_get_int(p, &tmp, 2, 0);
+ w.ws_col = tmp;
+
+ p += krb_get_int(p, &tmp, 2, 0);
+#ifdef HAVE_WS_XPIXEL
+ w.ws_xpixel = tmp;
+#endif
+ p += krb_get_int(p, &tmp, 2, 0);
+#ifdef HAVE_WS_YPIXEL
+ w.ws_ypixel = tmp;
+#endif
+ ioctl(master, TIOCSWINSZ, &w);
+#endif
+ return p - cp;
+}
+
+static
+void
+send_oob(int fd, char c)
+{
+ static char last_oob = 0xFF;
+
+#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
+ * TIOCPKT_DOSTOP into the first TIOCPKT_WINDOW.
+ */
+ static int oob_kludge = 2;
+ if (oob_kludge == 2)
+ {
+ oob_kludge--; /* First time send nothing */
+ return;
+ }
+ else if (oob_kludge == 1)
+ {
+ oob_kludge--; /* Second time merge TIOCPKT_WINDOW */
+ c |= TIOCPKT_WINDOW;
+ }
+#endif
+
+#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
+ c = pkcontrol(c);
+ /* Multiple OOB data breaks on Linux, avoid it when possible. */
+ if (c != last_oob)
+ send(fd, &c, 1, MSG_OOB);
+ last_oob = c;
+}
+
+/*
+ * rlogin "protocol" machine.
+ */
+static void
+protocol(int f, int master)
+{
+ char pibuf[1024+1], fibuf[1024], *pbp, *fbp;
+ int pcc = 0, fcc = 0;
+ int cc, nfd, n;
+ 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 */
+
+ if (f > master)
+ nfd = f + 1;
+ else
+ nfd = master + 1;
+ if (nfd > FD_SETSIZE) {
+ syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE");
+ fatal(f, "internal error (select mask too small)", 0);
+ }
+ for (;;) {
+ fd_set ibits, obits, ebits, *omask;
+
+ FD_ZERO(&ebits);
+ FD_ZERO(&ibits);
+ FD_ZERO(&obits);
+ omask = (fd_set *)NULL;
+ if (fcc) {
+ FD_SET(master, &obits);
+ omask = &obits;
+ } else
+ FD_SET(f, &ibits);
+ 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)
+ continue;
+ fatal(f, "select", 1);
+ }
+ if (n == 0) {
+ /* shouldn't happen... */
+ sleep(5);
+ continue;
+ }
+ if (FD_ISSET(master, &ebits)) {
+ cc = readstream(master, &cntl, 1);
+ if (cc == 1 && pkcontrol(cntl)) {
+#if 0 /* Kludge around */
+ send_oob(f, cntl);
+#endif
+ oob_queue = cntl;
+ if (cntl & TIOCPKT_FLUSHWRITE) {
+ pcc = 0;
+ FD_CLR(master, &ibits);
+ }
+ }
+ }
+ if (FD_ISSET(f, &ibits)) {
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ fcc = des_enc_read(f, fibuf,
+ sizeof(fibuf),
+ schedule, &kdata->session);
+ else
+#endif
+ fcc = read(f, fibuf, sizeof(fibuf));
+ if (fcc < 0 && errno == EWOULDBLOCK)
+ fcc = 0;
+ else {
+ char *cp;
+ int left, n;
+
+ if (fcc <= 0)
+ break;
+ fbp = fibuf;
+
+ top:
+ for (cp = fibuf; cp < fibuf+fcc-1; cp++)
+ if (cp[0] == magic[0] &&
+ cp[1] == magic[1]) {
+ left = fcc - (cp-fibuf);
+ n = control(master, cp, left);
+ if (n) {
+ left -= n;
+ if (left > 0)
+ memmove(cp, cp+n, left);
+ fcc -= n;
+ goto top; /* n^2 */
+ }
+ }
+ FD_SET(master, &obits); /* try write */
+ }
+ }
+
+ if (FD_ISSET(master, &obits) && fcc > 0) {
+ cc = write(master, fbp, fcc);
+ if (cc > 0) {
+ fcc -= cc;
+ fbp += cc;
+ }
+ }
+
+ if (FD_ISSET(master, &ibits)) {
+ pcc = readstream(master, pibuf, sizeof (pibuf));
+ pbp = pibuf;
+ if (pcc < 0 && errno == EWOULDBLOCK)
+ pcc = 0;
+ else if (pcc <= 0)
+ break;
+ else if (pibuf[0] == 0) {
+ pbp++, pcc--;
+ if (!doencrypt)
+ FD_SET(f, &obits); /* try write */
+ } else {
+ if (pkcontrol(pibuf[0])) {
+ oob_queue = pibuf[0];
+#if 0 /* Kludge around */
+ send_oob(f, pibuf[0]);
+#endif
+ }
+ pcc = 0;
+ }
+ }
+ if ((FD_ISSET(f, &obits)) && pcc > 0) {
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ cc = des_enc_write(f, pbp, pcc, schedule, &kdata->session);
+ else
+#endif
+ cc = write(f, pbp, pcc);
+ if (cc < 0 && errno == EWOULDBLOCK) {
+ /*
+ * This happens when we try write after read
+ * from p, but some old kernels balk at large
+ * writes even when select returns true.
+ */
+ if (!FD_ISSET(master, &ibits))
+ sleep(5);
+ continue;
+ }
+ if (cc > 0) {
+ pcc -= cc;
+ pbp += cc;
+ /* Only send urg data when normal data
+ * has just been sent.
+ * Linux has deep problems with more
+ * than one byte of OOB data.
+ */
+ if (oob_queue) {
+ send_oob (f, oob_queue);
+ oob_queue = 0;
+ }
+ }
+ }
+ }
+}
+
+static RETSIGTYPE
+cleanup(int signo)
+{
+ char *p = clean_ttyname (line);
+
+ if (rlogind_logout(p) == 0)
+ logwtmp(p, "", "");
+ chmod(line, 0666);
+ chown(line, 0, 0);
+ *p = 'p';
+ chmod(line, 0666);
+ chown(line, 0, 0);
+ shutdown(netf, 2);
+ signal(SIGHUP, SIG_IGN);
+#ifdef HAVE_VHANGUP
+ vhangup();
+#endif /* HAVE_VHANGUP */
+ exit(1);
+}
+
+void
+fatal(int f, const char *msg, int syserr)
+{
+ int len;
+ char buf[BUFSIZ], *bp = buf;
+
+ /*
+ * Prepend binary one to message if we haven't sent
+ * the magic null as confirmation.
+ */
+ if (!confirmed)
+ *bp++ = '\01'; /* error indicator */
+ if (syserr)
+ snprintf(bp, sizeof(buf) - (bp - buf),
+ "rlogind: %s: %s.\r\n",
+ msg, strerror(errno));
+ else
+ snprintf(bp, sizeof(buf) - (bp - buf),
+ "rlogind: %s.\r\n", msg);
+ len = strlen(bp);
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ des_enc_write(f, buf, bp + len - buf, schedule, &kdata->session);
+ else
+#endif
+ write(f, buf, bp + len - buf);
+ exit(1);
+}
+
+static void
+xgetstr(char *buf, int cnt, char *errmsg)
+{
+ char c;
+
+ do {
+ if (read(0, &c, 1) != 1)
+ exit(1);
+ if (--cnt < 0)
+ fatal(STDOUT_FILENO, errmsg, 0);
+ *buf++ = c;
+ } while (c != 0);
+}
+
+static int
+do_rlogin(struct sockaddr_in *dest)
+{
+ xgetstr(rusername, sizeof(rusername), "remuser too long");
+ xgetstr(lusername, sizeof(lusername), "locuser too long");
+ xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
+
+ pwd = k_getpwnam(lusername);
+ if (pwd == NULL)
+ return (-1);
+ if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0)
+ {
+ syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername);
+ return (-1);
+ }
+ return (iruserok(dest->sin_addr.s_addr,
+ (pwd->pw_uid == 0),
+ rusername,
+ lusername));
+}
+
+static void
+setup_term(int fd)
+{
+ char *cp = strchr(term+ENVSIZE, '/');
+ char *speed;
+ struct termios tt;
+
+ tcgetattr(fd, &tt);
+ if (cp) {
+ int s;
+
+ *cp++ = '\0';
+ speed = cp;
+ cp = strchr(speed, '/');
+ if (cp)
+ *cp++ = '\0';
+ s = int2speed_t (atoi (speed));
+ if (s > 0) {
+ cfsetospeed (&tt, s);
+ cfsetispeed (&tt, s);
+ }
+ }
+
+ tt.c_iflag &= ~INPCK;
+ tt.c_iflag |= ICRNL|IXON;
+ tt.c_oflag |= OPOST|ONLCR;
+#ifdef TAB3
+ tt.c_oflag |= TAB3;
+#endif /* TAB3 */
+#ifdef ONLRET
+ tt.c_oflag &= ~ONLRET;
+#endif /* ONLRET */
+ tt.c_lflag |= (ECHO|ECHOE|ECHOK|ISIG|ICANON);
+ tt.c_cflag &= ~PARENB;
+ tt.c_cflag |= CS8;
+ tt.c_cc[VMIN] = 1;
+ tt.c_cc[VTIME] = 0;
+ tt.c_cc[VEOF] = CEOF;
+ tcsetattr(fd, TCSAFLUSH, &tt);
+
+ env[0] = term;
+ env[1] = 0;
+ environ = env;
+}
+
+#define VERSION_SIZE 9
+
+/*
+ * Do the remote kerberos login to the named host with the
+ * given inet address
+ *
+ * Return 0 on valid authorization
+ * Return -1 on valid authentication, no authorization
+ * Return >0 for error conditions
+ */
+static int
+do_krb_login(struct sockaddr_in *dest)
+{
+ int rc;
+ char instance[INST_SZ], version[VERSION_SIZE];
+ long authopts = 0L; /* !mutual */
+ struct sockaddr_in faddr;
+
+ kdata = (AUTH_DAT *) auth_buf;
+ ticket = (KTEXT) tick_buf;
+
+ k_getsockinst(0, instance, sizeof(instance));
+
+ if (doencrypt) {
+ rc = sizeof(faddr);
+ if (getsockname(0, (struct sockaddr *)&faddr, &rc))
+ return (-1);
+ authopts = KOPT_DO_MUTUAL;
+ rc = krb_recvauth(
+ authopts, 0,
+ ticket, "rcmd",
+ instance, dest, &faddr,
+ kdata, "", schedule, version);
+ des_set_key(&kdata->session, schedule);
+
+ } else
+ rc = krb_recvauth(
+ authopts, 0,
+ ticket, "rcmd",
+ instance, dest, (struct sockaddr_in *) 0,
+ kdata, "", 0, version);
+
+ if (rc != KSUCCESS)
+ return (rc);
+
+ xgetstr(lusername, sizeof(lusername), "locuser");
+ /* get the "cmd" in the rcmd protocol */
+ xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
+
+ pwd = k_getpwnam(lusername);
+ if (pwd == NULL)
+ return (-1);
+ if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0)
+ {
+ syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername);
+ return (-1);
+ }
+
+ /* returns nonzero for no access */
+ if (kuserok(kdata, lusername) != 0)
+ return (-1);
+
+ return (0);
+
+}
+
+static void
+usage(void)
+{
+ syslog(LOG_ERR,
+ "usage: rlogind [-Dailn] [-p port] [-x] [-L login] [-k | -v]");
+ exit(1);
+}
diff --git a/crypto/kerberosIV/appl/bsd/rsh.c b/crypto/kerberosIV/appl/bsd/rsh.c
new file mode 100644
index 0000000..a18f775
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rsh.c
@@ -0,0 +1,384 @@
+/*-
+ * Copyright (c) 1983, 1990 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 "bsd_locl.h"
+
+RCSID("$Id: rsh.c,v 1.43.2.2 2000/10/10 12:53:50 assar Exp $");
+
+CREDENTIALS cred;
+Key_schedule schedule;
+int use_kerberos = 1, doencrypt;
+char dst_realm_buf[REALM_SZ], *dest_realm;
+
+/*
+ * rsh - remote shell
+ */
+int rfd2;
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: rsh [-ndKx] [-k realm] [-p port] [-l login] host [command]\n");
+ exit(1);
+}
+
+static char *
+copyargs(char **argv)
+{
+ int cc;
+ char **ap, *p;
+ char *args;
+
+ cc = 0;
+ for (ap = argv; *ap; ++ap)
+ cc += strlen(*ap) + 1;
+ args = malloc(cc);
+ if (args == NULL)
+ errx(1, "Out of memory.");
+ for (p = args, ap = argv; *ap; ++ap) {
+ strcpy(p, *ap);
+ while(*p)
+ ++p;
+ if (ap[1])
+ *p++ = ' ';
+ }
+ return(args);
+}
+
+static RETSIGTYPE
+sendsig(int signo_)
+{
+ char signo = signo_;
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ des_enc_write(rfd2, &signo, 1, schedule, &cred.session);
+ else
+#endif
+ write(rfd2, &signo, 1);
+}
+
+static void
+talk(int nflag, sigset_t omask, int pid, int rem)
+{
+ int cc, wc;
+ char *bp;
+ fd_set readfrom, ready, rembits;
+ char buf[DES_RW_MAXWRITE];
+
+ if (pid == 0) {
+ if (nflag)
+ goto done;
+
+ close(rfd2);
+
+ reread: errno = 0;
+ if ((cc = read(0, buf, sizeof buf)) <= 0)
+ goto done;
+ bp = buf;
+
+ rewrite:
+ FD_ZERO(&rembits);
+ if (rem >= FD_SETSIZE)
+ errx(1, "fd too large");
+ FD_SET(rem, &rembits);
+ if (select(rem + 1, 0, &rembits, 0, 0) < 0) {
+ if (errno != EINTR)
+ err(1, "select");
+ goto rewrite;
+ }
+ if (!FD_ISSET(rem, &rembits))
+ goto rewrite;
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ wc = des_enc_write(rem, bp, cc, schedule, &cred.session);
+ else
+#endif
+ wc = write(rem, bp, cc);
+ if (wc < 0) {
+ if (errno == EWOULDBLOCK)
+ goto rewrite;
+ goto done;
+ }
+ bp += wc;
+ cc -= wc;
+ if (cc == 0)
+ goto reread;
+ goto rewrite;
+ done:
+ shutdown(rem, 1);
+ exit(0);
+ }
+
+ if (sigprocmask(SIG_SETMASK, &omask, 0) != 0)
+ warn("sigprocmask");
+ FD_ZERO(&readfrom);
+ if (rem >= FD_SETSIZE || rfd2 >= FD_SETSIZE)
+ errx(1, "fd too large");
+ FD_SET(rem, &readfrom);
+ FD_SET(rfd2, &readfrom);
+ do {
+ ready = readfrom;
+ if (select(max(rem,rfd2)+1, &ready, 0, 0, 0) < 0) {
+ if (errno != EINTR)
+ err(1, "select");
+ continue;
+ }
+ if (FD_ISSET(rfd2, &ready)) {
+ errno = 0;
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ cc = des_enc_read(rfd2, buf, sizeof buf,
+ schedule, &cred.session);
+ else
+#endif
+ cc = read(rfd2, buf, sizeof buf);
+ if (cc <= 0) {
+ if (errno != EWOULDBLOCK)
+ FD_CLR(rfd2, &readfrom);
+ } else
+ write(2, buf, cc);
+ }
+ if (FD_ISSET(rem, &ready)) {
+ errno = 0;
+#ifndef NOENCRYPTION
+ if (doencrypt)
+ cc = des_enc_read(rem, buf, sizeof buf,
+ schedule, &cred.session);
+ else
+#endif
+ cc = read(rem, buf, sizeof buf);
+ if (cc <= 0) {
+ if (errno != EWOULDBLOCK)
+ FD_CLR(rem, &readfrom);
+ } else
+ write(1, buf, cc);
+ }
+ } while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom));
+}
+
+int
+main(int argc, char **argv)
+{
+ struct passwd *pw;
+ 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;
+
+ argoff = dflag = nflag = nfork = 0;
+ one = 1;
+ host = user = NULL;
+ pid = 1;
+
+ set_progname(argv[0]);
+
+ /* handle "rsh host flags" */
+ if (argc > 2 && argv[1][0] != '-') {
+ host = argv[1];
+ argoff = 1;
+ }
+
+#define OPTIONS "+8KLde:k:l:np:wx"
+ while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != -1)
+ switch(ch) {
+ case 'K':
+ use_kerberos = 0;
+ break;
+ case 'L': /* -8Lew are ignored to allow rlogin aliases */
+ case 'e':
+ case 'w':
+ case '8':
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'l':
+ user = optarg;
+ break;
+ case 'k':
+ dest_realm = dst_realm_buf;
+ strlcpy(dest_realm, optarg, REALM_SZ);
+ break;
+ case 'n':
+ nflag = nfork = 1;
+ break;
+ 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();
+ }
+ optind += argoff;
+
+ /* if haven't gotten a host yet, do so */
+ if (!host && !(host = argv[optind++]))
+ usage();
+
+ /* if no further arguments, must have been called as rlogin. */
+ if (!argv[optind]) {
+ *argv = "rlogin";
+ paranoid_setuid (getuid ());
+ execv(_PATH_RLOGIN, argv);
+ err(1, "can't exec %s", _PATH_RLOGIN);
+ }
+
+#ifndef __CYGWIN32__
+ if (!(pw = k_getpwuid(uid = getuid())))
+ errx(1, "unknown user id.");
+ local_user = pw->pw_name;
+ if (!user)
+ user = local_user;
+#else
+ if (!user)
+ errx(1, "Sorry, you need to specify the username (with -l)");
+ local_user = user;
+#endif
+
+ /* -n must still fork but does not turn of the -n functionality */
+ if (doencrypt)
+ nfork = 0;
+
+ args = copyargs(argv+optind);
+
+ if (user_port)
+ sv_port = user_port;
+ else
+ sv_port = get_shell_port(use_kerberos, doencrypt);
+
+ if (use_kerberos) {
+ paranoid_setuid(getuid());
+ rem = KSUCCESS;
+ errno = 0;
+ if (dest_realm == NULL)
+ dest_realm = krb_realmofhost(host);
+
+ if (doencrypt)
+ rem = krcmd_mutual(&host, sv_port, user, args,
+ &rfd2, dest_realm, &cred, schedule);
+ else
+ 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");
+ 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)
+ errx(1, "the -x flag requires Kerberos authentication.");
+ if (geteuid() != 0)
+ errx(1, "not installed setuid root, "
+ "only root may use non kerberized rsh");
+ rem = rcmd(&host, sv_port, local_user, user, args, &rfd2);
+ }
+
+ if (rem < 0)
+ exit(1);
+
+ if (rfd2 < 0)
+ errx(1, "can't establish stderr.");
+#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
+ if (dflag) {
+ if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, (void *)&one,
+ sizeof(one)) < 0)
+ warn("setsockopt");
+ if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, (void *)&one,
+ sizeof(one)) < 0)
+ warn("setsockopt");
+ }
+#endif
+
+ paranoid_setuid(uid);
+ {
+ sigset_t sigmsk;
+ sigemptyset(&sigmsk);
+ sigaddset(&sigmsk, SIGINT);
+ sigaddset(&sigmsk, SIGQUIT);
+ sigaddset(&sigmsk, SIGTERM);
+ if (sigprocmask(SIG_BLOCK, &sigmsk, &omask) != 0)
+ warn("sigprocmask");
+ }
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, sendsig);
+ if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+ signal(SIGQUIT, sendsig);
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+ signal(SIGTERM, sendsig);
+ signal(SIGPIPE, SIG_IGN);
+
+ if (!nfork) {
+ pid = fork();
+ if (pid < 0)
+ err(1, "fork");
+ }
+
+ if (!doencrypt) {
+ ioctl(rfd2, FIONBIO, &one);
+ ioctl(rem, FIONBIO, &one);
+ }
+
+ talk(nflag, omask, pid, rem);
+
+ if (!nflag)
+ kill(pid, SIGKILL);
+ exit(0);
+}
diff --git a/crypto/kerberosIV/appl/bsd/rshd.c b/crypto/kerberosIV/appl/bsd/rshd.c
new file mode 100644
index 0000000..496fa88
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rshd.c
@@ -0,0 +1,652 @@
+/*-
+ * Copyright (c) 1988, 1989, 1992, 1993, 1994
+ * 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.
+ */
+
+/*
+ * remote shell server:
+ * [port]\0
+ * remuser\0
+ * locuser\0
+ * command\0
+ * data
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: rshd.c,v 1.60.2.3 2000/10/18 20:39:12 assar Exp $");
+
+extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
+extern int __check_rhosts_file;
+
+static int keepalive = 1;
+static int log_success; /* If TRUE, log all successful accesses */
+static int new_pag = 1; /* Put process in new PAG by default */
+static int no_inetd = 0;
+static int sent_null;
+
+static void doit (struct sockaddr_in *);
+static void error (const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+static void usage (void);
+
+#define VERSION_SIZE 9
+#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n"
+#define OPTIONS "alnkvxLp:Pi"
+AUTH_DAT authbuf;
+KTEXT_ST tickbuf;
+int doencrypt, use_kerberos, vacuous;
+Key_schedule schedule;
+
+int
+main(int argc, char *argv[])
+{
+ struct linger linger;
+ int ch, on = 1, fromlen;
+ struct sockaddr_in from;
+ int portnum = 0;
+
+ set_progname(argv[0]);
+
+ openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+
+ opterr = 0;
+ while ((ch = getopt(argc, argv, OPTIONS)) != -1)
+ switch (ch) {
+ case 'a':
+ break;
+ case 'l':
+ __check_rhosts_file = 0;
+ break;
+ case 'n':
+ keepalive = 0;
+ break;
+ case 'k':
+ use_kerberos = 1;
+ break;
+
+ case 'v':
+ vacuous = 1;
+ break;
+
+ case 'x':
+ doencrypt = 1;
+ break;
+ case 'L':
+ log_success = 1;
+ break;
+ case 'p':
+ portnum = htons(atoi(optarg));
+ break;
+ case 'P':
+ new_pag = 0;
+ break;
+ case 'i':
+ no_inetd = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (use_kerberos && vacuous) {
+ syslog(LOG_ERR, "only one of -k and -v allowed");
+ exit(2);
+ }
+ if (doencrypt && !use_kerberos) {
+ syslog(LOG_ERR, "-k is required for -x");
+ exit(2);
+ }
+
+ if (no_inetd) {
+ if(portnum == 0)
+ portnum = get_shell_port (use_kerberos, doencrypt);
+ mini_inetd (portnum);
+ }
+
+ fromlen = sizeof (from);
+ if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+ syslog(LOG_ERR, "getpeername: %m");
+ _exit(1);
+ }
+#ifdef HAVE_SETSOCKOPT
+#ifdef SO_KEEPALIVE
+ if (keepalive &&
+ setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
+ sizeof(on)) < 0)
+ syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+#endif
+#ifdef SO_LINGER
+ linger.l_onoff = 1;
+ linger.l_linger = 60; /* XXX */
+ if (setsockopt(0, SOL_SOCKET, SO_LINGER, (void *)&linger,
+ sizeof (linger)) < 0)
+ syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
+#endif
+#endif /* HAVE_SETSOCKOPT */
+ doit(&from);
+ /* NOTREACHED */
+ return 0;
+}
+
+char username[20] = "USER=";
+char homedir[64] = "HOME=";
+char shell[64] = "SHELL=";
+char path[100] = "PATH=";
+char *envinit[] =
+{homedir, shell, path, username, 0};
+
+static void
+xgetstr(char *buf, int cnt, char *err)
+{
+ char c;
+
+ do {
+ if (read(STDIN_FILENO, &c, 1) != 1)
+ exit(1);
+ *buf++ = c;
+ if (--cnt == 0) {
+ error("%s too long\n", err);
+ exit(1);
+ }
+ } while (c != 0);
+}
+
+static void
+doit(struct sockaddr_in *fromp)
+{
+ struct passwd *pwd;
+ u_short port;
+ fd_set ready, readfrom;
+ int cc, nfd, pv[2], pid, s;
+ int one = 1;
+ const char *errorhost = "";
+ char *errorstr;
+ char *cp, sig, buf[DES_RW_MAXWRITE];
+ char cmdbuf[NCARGS+1], locuser[16], remuser[16];
+ char remotehost[2 * MaxHostNameLen + 1];
+ uid_t uid;
+ char shell_path[MAXPATHLEN];
+
+ AUTH_DAT *kdata;
+ KTEXT ticket;
+ char instance[INST_SZ], version[VERSION_SIZE];
+ struct sockaddr_in fromaddr;
+ int rc;
+ long authopts;
+ int pv1[2], pv2[2];
+ fd_set wready, writeto;
+
+ fromaddr = *fromp;
+
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+#ifdef DEBUG
+ { int t = open(_PATH_TTY, 2);
+ if (t >= 0) {
+ ioctl(t, TIOCNOTTY, (char *)0);
+ close(t);
+ }
+ }
+#endif
+ fromp->sin_port = ntohs((u_short)fromp->sin_port);
+ if (fromp->sin_family != AF_INET) {
+ syslog(LOG_ERR, "malformed \"from\" address (af %d)\n",
+ fromp->sin_family);
+ exit(1);
+ }
+
+
+ if (!use_kerberos) {
+ ip_options_and_die (0, fromp);
+ if (fromp->sin_port >= IPPORT_RESERVED ||
+ fromp->sin_port < IPPORT_RESERVED/2) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "Connection from %s on illegal port %u",
+ inet_ntoa(fromp->sin_addr),
+ fromp->sin_port);
+ exit(1);
+ }
+ }
+
+ alarm(60);
+ port = 0;
+ for (;;) {
+ char c;
+ if ((cc = read(STDIN_FILENO, &c, 1)) != 1) {
+ if (cc < 0)
+ syslog(LOG_NOTICE, "read: %m");
+ shutdown(0, 1+1);
+ exit(1);
+ }
+ if (c== 0)
+ break;
+ port = port * 10 + c - '0';
+ }
+
+ alarm(0);
+ if (port != 0) {
+ int lport = IPPORT_RESERVED - 1;
+ s = rresvport(&lport);
+ if (s < 0) {
+ syslog(LOG_ERR, "can't get stderr port: %m");
+ exit(1);
+ }
+ if (!use_kerberos)
+ if (port >= IPPORT_RESERVED) {
+ syslog(LOG_ERR, "2nd port not reserved\n");
+ exit(1);
+ }
+ fromp->sin_port = htons(port);
+ if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) {
+ syslog(LOG_INFO, "connect second port %d: %m", port);
+ exit(1);
+ }
+ }
+
+ if (vacuous) {
+ error("rshd: Remote host requires Kerberos authentication.\n");
+ exit(1);
+ }
+
+ errorstr = NULL;
+ inaddr2str (fromp->sin_addr, remotehost, sizeof(remotehost));
+
+ if (use_kerberos) {
+ kdata = &authbuf;
+ ticket = &tickbuf;
+ authopts = 0L;
+ k_getsockinst(0, instance, sizeof(instance));
+ version[VERSION_SIZE - 1] = '\0';
+ if (doencrypt) {
+ struct sockaddr_in local_addr;
+ rc = sizeof(local_addr);
+ if (getsockname(0, (struct sockaddr *)&local_addr,
+ &rc) < 0) {
+ syslog(LOG_ERR, "getsockname: %m");
+ error("rshd: getsockname: %m");
+ exit(1);
+ }
+ authopts = KOPT_DO_MUTUAL;
+ rc = krb_recvauth(authopts, 0, ticket,
+ "rcmd", instance, &fromaddr,
+ &local_addr, kdata, "", schedule,
+ version);
+#ifndef NOENCRYPTION
+ des_set_key(&kdata->session, schedule);
+#else
+ memset(schedule, 0, sizeof(schedule));
+#endif
+ } else
+ rc = krb_recvauth(authopts, 0, ticket, "rcmd",
+ instance, &fromaddr,
+ (struct sockaddr_in *) 0,
+ kdata, "", 0, version);
+ if (rc != KSUCCESS) {
+ error("Kerberos authentication failure: %s\n",
+ krb_get_err_text(rc));
+ exit(1);
+ }
+ } else
+ xgetstr(remuser, sizeof(remuser), "remuser");
+
+ xgetstr(locuser, sizeof(locuser), "locuser");
+ xgetstr(cmdbuf, sizeof(cmdbuf), "command");
+ setpwent();
+ pwd = k_getpwnam(locuser);
+ if (pwd == NULL) {
+ syslog(LOG_INFO|LOG_AUTH,
+ "%s@%s as %s: unknown login. cmd='%.80s'",
+ remuser, remotehost, locuser, cmdbuf);
+ if (errorstr == NULL)
+ errorstr = "Login incorrect.\n";
+ goto fail;
+ }
+ if (pwd->pw_uid == 0 && strcmp("root", locuser) != 0)
+ {
+ syslog(LOG_ALERT, "NIS attack, user %s has uid 0", locuser);
+ if (errorstr == NULL)
+ errorstr = "Login incorrect.\n";
+ goto fail;
+ }
+ if (chdir(pwd->pw_dir) < 0) {
+ chdir("/");
+#ifdef notdef
+ syslog(LOG_INFO|LOG_AUTH,
+ "%s@%s as %s: no home directory. cmd='%.80s'",
+ remuser, remotehost, locuser, cmdbuf);
+ error("No remote directory.\n");
+ exit(1);
+#endif
+ }
+
+ if (use_kerberos) {
+ if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
+ if (kuserok(kdata, locuser) != 0) {
+ syslog(LOG_INFO|LOG_AUTH,
+ "Kerberos rsh denied to %s",
+ krb_unparse_name_long(kdata->pname,
+ kdata->pinst,
+ kdata->prealm));
+ error("Permission denied.\n");
+ exit(1);
+ }
+ }
+ } else
+
+ if (errorstr ||
+ (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
+ iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0,
+ remuser, locuser) < 0)) {
+ if (__rcmd_errstr)
+ syslog(LOG_INFO|LOG_AUTH,
+ "%s@%s as %s: permission denied (%s). cmd='%.80s'",
+ remuser, remotehost, locuser,
+ __rcmd_errstr, cmdbuf);
+ else
+ syslog(LOG_INFO|LOG_AUTH,
+ "%s@%s as %s: permission denied. cmd='%.80s'",
+ remuser, remotehost, locuser, cmdbuf);
+ fail:
+ if (errorstr == NULL)
+ errorstr = "Permission denied.\n";
+ error(errorstr, errorhost);
+ exit(1);
+ }
+
+ if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) {
+ error("Logins currently disabled.\n");
+ exit(1);
+ }
+
+ write(STDERR_FILENO, "\0", 1);
+ sent_null = 1;
+
+ if (port) {
+ if (pipe(pv) < 0) {
+ error("Can't make pipe.\n");
+ exit(1);
+ }
+ if (doencrypt) {
+ if (pipe(pv1) < 0) {
+ error("Can't make 2nd pipe.\n");
+ exit(1);
+ }
+ if (pipe(pv2) < 0) {
+ error("Can't make 3rd pipe.\n");
+ exit(1);
+ }
+ }
+ pid = fork();
+ if (pid == -1) {
+ error("Can't fork; try again.\n");
+ exit(1);
+ }
+ if (pid) {
+ if (doencrypt) {
+ static char msg[] = SECURE_MESSAGE;
+ close(pv1[1]);
+ close(pv2[0]);
+#ifndef NOENCRYPTION
+ des_enc_write(s, msg, sizeof(msg) - 1, schedule, &kdata->session);
+#else
+ write(s, msg, sizeof(msg) - 1);
+#endif
+ } else {
+ close(0);
+ close(1);
+ }
+ close(2);
+ close(pv[1]);
+
+ if (s >= FD_SETSIZE || pv[0] >= FD_SETSIZE) {
+ error ("fd too large\n");
+ exit (1);
+ }
+
+ FD_ZERO(&readfrom);
+ FD_SET(s, &readfrom);
+ FD_SET(pv[0], &readfrom);
+ if (pv[0] > s)
+ nfd = pv[0];
+ else
+ nfd = s;
+ if (doencrypt) {
+ if (pv2[1] >= FD_SETSIZE || pv1[0] >= FD_SETSIZE) {
+ error ("fd too large\n");
+ exit (1);
+ }
+
+ FD_ZERO(&writeto);
+ FD_SET(pv2[1], &writeto);
+ FD_SET(pv1[0], &readfrom);
+ FD_SET(STDIN_FILENO, &readfrom);
+
+ nfd = max(nfd, pv2[1]);
+ nfd = max(nfd, pv1[0]);
+ } else
+ ioctl(pv[0], FIONBIO, (char *)&one);
+
+ /* should set s nbio! */
+ nfd++;
+ do {
+ ready = readfrom;
+ if (doencrypt) {
+ wready = writeto;
+ if (select(nfd, &ready,
+ &wready, 0,
+ (struct timeval *) 0) < 0)
+ break;
+ } else
+ if (select(nfd, &ready, 0,
+ 0, (struct timeval *)0) < 0)
+ break;
+ if (FD_ISSET(s, &ready)) {
+ int ret;
+ if (doencrypt)
+#ifndef NOENCRYPTION
+ ret = des_enc_read(s, &sig, 1, schedule, &kdata->session);
+#else
+ ret = read(s, &sig, 1);
+#endif
+ else
+ ret = read(s, &sig, 1);
+ if (ret <= 0)
+ FD_CLR(s, &readfrom);
+ else
+ kill(-pid, sig);
+ }
+ if (FD_ISSET(pv[0], &ready)) {
+ errno = 0;
+ cc = read(pv[0], buf, sizeof(buf));
+ if (cc <= 0) {
+ shutdown(s, 1+1);
+ FD_CLR(pv[0], &readfrom);
+ } else {
+ if (doencrypt)
+#ifndef NOENCRYPTION
+ des_enc_write(s, buf, cc, schedule, &kdata->session);
+#else
+ write(s, buf, cc);
+#endif
+ else
+ (void)
+ write(s, buf, cc);
+ }
+ }
+ if (doencrypt && FD_ISSET(pv1[0], &ready)) {
+ errno = 0;
+ cc = read(pv1[0], buf, sizeof(buf));
+ if (cc <= 0) {
+ shutdown(pv1[0], 1+1);
+ FD_CLR(pv1[0], &readfrom);
+ } else
+#ifndef NOENCRYPTION
+ des_enc_write(STDOUT_FILENO, buf, cc, schedule, &kdata->session);
+#else
+ write(STDOUT_FILENO, buf, cc);
+#endif
+ }
+
+ if (doencrypt
+ && FD_ISSET(STDIN_FILENO, &ready)
+ && FD_ISSET(pv2[1], &wready)) {
+ errno = 0;
+#ifndef NOENCRYPTION
+ cc = des_enc_read(STDIN_FILENO, buf, sizeof(buf), schedule, &kdata->session);
+#else
+ cc = read(STDIN_FILENO, buf, sizeof(buf));
+#endif
+ if (cc <= 0) {
+ shutdown(STDIN_FILENO, 0);
+ FD_CLR(STDIN_FILENO, &readfrom);
+ close(pv2[1]);
+ FD_CLR(pv2[1], &writeto);
+ } else
+ write(pv2[1], buf, cc);
+ }
+
+ } while (FD_ISSET(s, &readfrom) ||
+ (doencrypt && FD_ISSET(pv1[0], &readfrom)) ||
+ FD_ISSET(pv[0], &readfrom));
+ exit(0);
+ }
+ setsid();
+ close(s);
+ close(pv[0]);
+ if (doencrypt) {
+ close(pv1[0]);
+ close(pv2[1]);
+ dup2(pv1[1], 1);
+ dup2(pv2[0], 0);
+ close(pv1[1]);
+ close(pv2[0]);
+ }
+ dup2(pv[1], 2);
+ close(pv[1]);
+ }
+ if (*pwd->pw_shell == '\0')
+ pwd->pw_shell = _PATH_BSHELL;
+#ifdef HAVE_SETLOGIN
+ if (setlogin(pwd->pw_name) < 0)
+ syslog(LOG_ERR, "setlogin() failed: %m");
+#endif
+
+#ifdef HAVE_SETPCRED
+ 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);
+ strlcat(homedir, pwd->pw_dir, sizeof(homedir));
+
+ /* Need to prepend path with BINDIR (/usr/athena/bin) to find rcp */
+ snprintf(path, sizeof(path), "PATH=%s:%s", BINDIR, _PATH_DEFPATH);
+
+ strlcat(shell, pwd->pw_shell, sizeof(shell));
+ strlcpy(shell_path, pwd->pw_shell, sizeof(shell_path));
+ strlcat(username, pwd->pw_name, sizeof(username));
+ uid = pwd->pw_uid;
+ cp = strrchr(pwd->pw_shell, '/');
+ if (cp)
+ cp++;
+ else
+ cp = pwd->pw_shell;
+ endpwent();
+ if (log_success || uid == 0) {
+ if (use_kerberos)
+ syslog(LOG_INFO|LOG_AUTH,
+ "Kerberos shell from %s on %s as %s, cmd='%.80s'",
+ krb_unparse_name_long(kdata->pname,
+ kdata->pinst,
+ kdata->prealm),
+ remotehost, locuser, cmdbuf);
+ else
+ syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",
+ remuser, remotehost, locuser, cmdbuf);
+ }
+ if (k_hasafs()) {
+ char cell[64];
+
+ if (new_pag)
+ k_setpag(); /* Put users process in an new pag */
+ if (k_afs_cell_of_file (homedir, cell, sizeof(cell)) == 0)
+ krb_afslog_uid_home (cell, NULL, uid, homedir);
+ krb_afslog_uid_home(NULL, NULL, uid, homedir);
+ }
+ execle(shell_path, cp, "-c", cmdbuf, 0, envinit);
+ err(1, "%s", shell_path);
+}
+
+/*
+ * Report error to client. Note: can't be used until second socket has
+ * connected to client, or older clients will hang waiting for that
+ * connection first.
+ */
+
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+ char *bp, buf[BUFSIZ];
+
+ va_start(ap, fmt);
+ bp = buf;
+ if (sent_null == 0) {
+ *bp++ = 1;
+ len = 1;
+ } else
+ len = 0;
+ len += vsnprintf(bp, sizeof(buf) - len, fmt, ap);
+ write(STDERR_FILENO, buf, len);
+ va_end(ap);
+}
+
+static void
+usage()
+{
+
+ syslog(LOG_ERR,
+ "usage: rshd [-alnkvxLPi] [-p port]");
+ exit(2);
+}
diff --git a/crypto/kerberosIV/appl/bsd/stty_default.c b/crypto/kerberosIV/appl/bsd/stty_default.c
new file mode 100644
index 0000000..0135823
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/stty_default.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: stty_default.c,v 1.7 1999/12/02 16:58:28 joda Exp $");
+
+#include <termios.h>
+
+/* HP-UX 9.0 termios doesn't define these */
+#ifndef FLUSHO
+#define FLUSHO 0
+#endif
+
+#ifndef XTABS
+#define XTABS 0
+#endif
+
+#ifndef OXTABS
+#define OXTABS XTABS
+#endif
+
+/* Ultrix... */
+#ifndef ECHOPRT
+#define ECHOPRT 0
+#endif
+
+#ifndef ECHOCTL
+#define ECHOCTL 0
+#endif
+
+#ifndef ECHOKE
+#define ECHOKE 0
+#endif
+
+#ifndef IMAXBEL
+#define IMAXBEL 0
+#endif
+
+#define Ctl(x) ((x) ^ 0100)
+
+void
+stty_default(void)
+{
+ struct termios termios;
+
+ /*
+ * Finalize the terminal settings. Some systems default to 8 bits,
+ * others to 7, so we should leave that alone.
+ */
+ tcgetattr(0, &termios);
+
+ termios.c_iflag |= (BRKINT|IGNPAR|ICRNL|IXON|IMAXBEL);
+ termios.c_iflag &= ~IXANY;
+
+ termios.c_lflag |= (ISIG|IEXTEN|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
+ termios.c_lflag &= ~(ECHOPRT|TOSTOP|FLUSHO);
+
+ termios.c_oflag |= (OPOST|ONLCR);
+ termios.c_oflag &= ~OXTABS;
+
+ termios.c_cc[VINTR] = Ctl('C');
+ termios.c_cc[VERASE] = Ctl('H');
+ termios.c_cc[VKILL] = Ctl('U');
+ termios.c_cc[VEOF] = Ctl('D');
+
+ termios.c_cc[VSUSP] = Ctl('Z');
+
+ tcsetattr(0, TCSANOW, &termios);
+}
diff --git a/crypto/kerberosIV/appl/bsd/su.c b/crypto/kerberosIV/appl/bsd/su.c
new file mode 100644
index 0000000..7fc63ee
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/su.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 1988 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 "bsd_locl.h"
+
+RCSID ("$Id: su.c,v 1.70.2.2 2000/12/07 14:04:19 assar Exp $");
+
+#ifdef SYSV_SHADOW
+#include "sysv_shadow.h"
+#endif
+
+static int kerberos (char *username, char *user, char *realm, int uid);
+static int chshell (char *sh);
+static char *ontty (void);
+static int koktologin (char *name, char *realm, char *toname);
+static int chshell (char *sh);
+
+/* Handle '-' option after all the getopt options */
+#define ARGSTR "Kkflmti:r:"
+
+int destroy_tickets = 0;
+static int use_kerberos = 1;
+static char *root_inst = "root";
+
+int
+main (int argc, char **argv)
+{
+ struct passwd *pwd;
+ char *p, **g;
+ struct group *gr;
+ uid_t ruid;
+ int asme, ch, asthem, fastlogin, prio;
+ enum { UNSET, YES, NO } iscsh = UNSET;
+ char *user, *shell, *avshell, *username, **np;
+ char shellbuf[MaxPathLen], avshellbuf[MaxPathLen];
+ char *realm = NULL;
+
+ set_progname (argv[0]);
+
+ if (getuid() == 0)
+ use_kerberos = 0;
+
+ asme = asthem = fastlogin = 0;
+ while ((ch = getopt (argc, argv, ARGSTR)) != -1)
+ switch ((char) ch) {
+ case 'K':
+ use_kerberos = 0;
+ break;
+ case 'k':
+ use_kerberos = 1;
+ break;
+ case 'f':
+ fastlogin = 1;
+ break;
+ case 'l':
+ asme = 0;
+ asthem = 1;
+ break;
+ case 'm':
+ asme = 1;
+ asthem = 0;
+ break;
+ case 't':
+ destroy_tickets = 1;
+ break;
+ case 'i':
+ root_inst = optarg;
+ break;
+ case 'r':
+ realm = optarg;
+ break;
+ case '?':
+ default:
+ fprintf (stderr,
+ "usage: su [-Kkflmt] [-i root-instance] [-r realm] [-] [login]\n");
+ exit (1);
+ }
+ /* Don't handle '-' option with getopt */
+ if (optind < argc && strcmp (argv[optind], "-") == 0) {
+ asme = 0;
+ asthem = 1;
+ optind++;
+ }
+ argv += optind;
+
+ if (use_kerberos) {
+ int fd = open (KEYFILE, O_RDONLY);
+
+ if (fd >= 0)
+ close (fd);
+ else
+ use_kerberos = 0;
+ }
+ errno = 0;
+ prio = getpriority (PRIO_PROCESS, 0);
+ if (errno)
+ prio = 0;
+ setpriority (PRIO_PROCESS, 0, -2);
+ openlog ("su", LOG_CONS, LOG_AUTH);
+
+ /* get current login name and shell */
+ ruid = getuid ();
+ username = getlogin ();
+ if (username == NULL || (pwd = k_getpwnam (username)) == NULL ||
+ pwd->pw_uid != ruid)
+ pwd = k_getpwuid (ruid);
+ if (pwd == NULL)
+ errx (1, "who are you?");
+ username = strdup (pwd->pw_name);
+ if (username == NULL)
+ errx (1, "strdup: out of memory");
+ if (asme) {
+ if (pwd->pw_shell && *pwd->pw_shell) {
+ strlcpy (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";
+ np = *argv ? argv : argv - 1;
+
+ pwd = k_getpwnam (user);
+ if (pwd == NULL)
+ errx (1, "unknown login %s", user);
+ if (pwd->pw_uid == 0 && strcmp ("root", user) != 0) {
+ syslog (LOG_ALERT, "NIS attack, user %s has uid 0", user);
+ errx (1, "unknown login %s", user);
+ }
+ if (!use_kerberos || kerberos (username, user, realm, pwd->pw_uid)) {
+#ifndef PASSWD_FALLBACK
+ errx (1, "won't use /etc/passwd authentication");
+#endif
+ /* getpwnam() is not reentrant and kerberos might use it! */
+ pwd = k_getpwnam (user);
+ if (pwd == NULL)
+ errx (1, "unknown login %s", user);
+ /* only allow those in group zero to su to root. */
+ if (pwd->pw_uid == 0 && (gr = getgrgid ((gid_t) 0)))
+ for (g = gr->gr_mem;; ++g) {
+ if (!*g) {
+#if 1
+ /* if group 0 is empty or only
+ contains root su is still ok. */
+ if (gr->gr_mem[0] == 0)
+ break; /* group 0 is empty */
+ if (gr->gr_mem[1] == 0 &&
+ strcmp (gr->gr_mem[0], "root") == 0)
+ break; /* only root in group 0 */
+#endif
+ errx (1, "you are not in the correct group to su %s.",
+ user);
+ }
+ if (!strcmp (username, *g))
+ break;
+ }
+ /* if target requires a password, verify it */
+ if (ruid && *pwd->pw_passwd) {
+ char prompt[128];
+ char passwd[256];
+
+ snprintf (prompt, sizeof(prompt), "%s's Password: ", pwd->pw_name);
+ if (des_read_pw_string (passwd, sizeof (passwd),
+ prompt, 0)) {
+ memset (passwd, 0, sizeof (passwd));
+ exit (1);
+ }
+ if (strcmp (pwd->pw_passwd,
+ crypt (passwd, pwd->pw_passwd))) {
+ memset (passwd, 0, sizeof (passwd));
+ syslog (LOG_AUTH | LOG_WARNING,
+ "BAD SU %s to %s%s", username,
+ user, ontty ());
+ errx (1, "Sorry");
+ }
+ memset (passwd, 0, sizeof (passwd));
+ }
+ }
+ if (asme) {
+ /* if asme and non-standard target shell, must be root */
+ if (!chshell (pwd->pw_shell) && ruid)
+ errx (1, "permission denied (shell '%s' not in /etc/shells).",
+ pwd->pw_shell);
+ } else if (pwd->pw_shell && *pwd->pw_shell) {
+ shell = pwd->pw_shell;
+ iscsh = UNSET;
+ } else {
+ shell = _PATH_BSHELL;
+ iscsh = NO;
+ }
+
+ if ((p = strrchr (shell, '/')) != 0)
+ avshell = p + 1;
+ else
+ avshell = shell;
+
+ /* if we're forking a csh, we want to slightly muck the args */
+ if (iscsh == UNSET)
+ iscsh = strcmp (avshell, "csh") ? NO : YES;
+
+ /* set permissions */
+
+ if (setgid (pwd->pw_gid) < 0)
+ err (1, "setgid");
+ if (initgroups (user, pwd->pw_gid)) {
+ if (errno == E2BIG) /* Member of too many groups! */
+ warn("initgroups failed.");
+ else
+ errx(1, "initgroups failed.");
+ }
+
+ if (setuid (pwd->pw_uid) < 0)
+ err (1, "setuid");
+
+ if (pwd->pw_uid != 0 && setuid(0) != -1) {
+ syslog(LOG_ALERT | LOG_AUTH,
+ "Failed to drop privileges for user %s", pwd->pw_name);
+ errx(1, "Sorry");
+ }
+
+ if (!asme) {
+ if (asthem) {
+ char *k = getenv ("KRBTKFILE");
+ 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)
+ setenv ("TERM", t, 1);
+ if (k)
+ setenv ("KRBTKFILE", k, 1);
+ if (chdir (pwd->pw_dir) < 0)
+ errx (1, "no directory");
+ }
+ if (asthem || pwd->pw_uid)
+ setenv ("USER", pwd->pw_name, 1);
+ setenv ("HOME", pwd->pw_dir, 1);
+ setenv ("SHELL", shell, 1);
+ }
+ if (iscsh == YES) {
+ if (fastlogin)
+ *np-- = "-f";
+ if (asme)
+ *np-- = "-m";
+ }
+ if (asthem) {
+ snprintf (avshellbuf, sizeof(avshellbuf),
+ "-%s", avshell);
+ avshell = avshellbuf;
+ } else if (iscsh == YES) {
+ /* csh strips the first character... */
+ snprintf (avshellbuf, sizeof(avshellbuf),
+ "_%s", avshell);
+ avshell = avshellbuf;
+ }
+ *np = avshell;
+
+ if (ruid != 0)
+ syslog (LOG_NOTICE | LOG_AUTH, "%s to %s%s",
+ username, user, ontty ());
+
+ setpriority (PRIO_PROCESS, 0, prio);
+
+ if (k_hasafs ()) {
+ int code;
+
+ if (k_setpag () != 0)
+ warn ("setpag");
+ code = krb_afslog (0, 0);
+ if (code != KSUCCESS && code != KDC_PR_UNKNOWN)
+ warnx ("afsklog: %s", krb_get_err_text (code));
+ }
+ if (destroy_tickets)
+ dest_tkt ();
+ execv (shell, np);
+ warn ("execv(%s)", shell);
+ if (getuid () == 0) {
+ execv (_PATH_BSHELL, np);
+ warn ("execv(%s)", _PATH_BSHELL);
+ }
+ exit (1);
+}
+
+static int
+chshell (char *sh)
+{
+ char *cp;
+
+ while ((cp = getusershell ()) != NULL)
+ if (!strcmp (cp, sh))
+ return (1);
+ return (0);
+}
+
+static char *
+ontty (void)
+{
+ char *p;
+ static char buf[MaxPathLen + 4];
+
+ buf[0] = 0;
+ if ((p = ttyname (STDERR_FILENO)) != 0)
+ snprintf (buf, sizeof(buf), " on %s", p);
+ return (buf);
+}
+
+static int
+kerberos (char *username, char *user, char *lrealm, int uid)
+{
+ KTEXT_ST ticket;
+ AUTH_DAT authdata;
+ struct hostent *hp;
+ int kerno;
+ u_long faddr;
+ char tmp_realm[REALM_SZ], krbtkfile[MaxPathLen];
+ char hostname[MaxHostNameLen], savehost[MaxHostNameLen];
+ int n;
+ int allowed = 0;
+
+ if (lrealm != NULL) {
+ allowed = koktologin (username, lrealm, user) == 0;
+ } else {
+ for (n = 1; !allowed && krb_get_lrealm (tmp_realm, n) == KSUCCESS; ++n)
+ allowed = koktologin (username, tmp_realm, user) == 0;
+ lrealm = tmp_realm;
+ }
+ if (!allowed && !uid) {
+#ifndef PASSWD_FALLBACK
+ warnx ("not in %s's ACL.", user);
+#endif
+ return (1);
+ }
+ snprintf (krbtkfile, sizeof(krbtkfile),
+ "%s_%s_to_%s_%u", TKT_ROOT, username, user,
+ (unsigned) getpid ());
+
+ 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
+ * yyy represents the name of the person being su'd to, and the instance
+ * is null
+ *
+ * We should have a way to set the ticket lifetime, with a system default
+ * for root.
+ */
+ {
+ char prompt[128];
+ char passw[256];
+
+ snprintf (prompt, sizeof(prompt),
+ "%s's Password: ",
+ krb_unparse_name_long ((uid == 0 ? username : user),
+ (uid == 0 ? root_inst : ""),
+ lrealm));
+ if (des_read_pw_string (passw, sizeof (passw), prompt, 0)) {
+ memset (passw, 0, sizeof (passw));
+ return (1);
+ }
+ if (strlen(passw) == 0)
+ return (1); /* Empty passwords is not allowed */
+ kerno = krb_get_pw_in_tkt ((uid == 0 ? username : user),
+ (uid == 0 ? root_inst : ""), lrealm,
+ KRB_TICKET_GRANTING_TICKET,
+ lrealm,
+ DEFAULT_TKT_LIFE,
+ passw);
+ memset (passw, 0, strlen (passw));
+ }
+
+ if (kerno != KSUCCESS) {
+ if (kerno == KDC_PR_UNKNOWN) {
+ warnx ("principal unknown: %s",
+ krb_unparse_name_long ((uid == 0 ? username : user),
+ (uid == 0 ? root_inst : ""),
+ lrealm));
+ return (1);
+ }
+ warnx ("unable to su: %s", krb_get_err_text (kerno));
+ syslog (LOG_NOTICE | LOG_AUTH,
+ "BAD SU: %s to %s%s: %s",
+ username, user, ontty (), krb_get_err_text (kerno));
+ return (1);
+ }
+ if (chown (krbtkfile, uid, -1) < 0) {
+ warn ("chown");
+ unlink (krbtkfile);
+ return (1);
+ }
+ setpriority (PRIO_PROCESS, 0, -2);
+
+ if (gethostname (hostname, sizeof (hostname)) == -1) {
+ warn ("gethostname");
+ dest_tkt ();
+ return (1);
+ }
+ strlcpy (savehost, krb_get_phost (hostname), sizeof (savehost));
+
+ for (n = 1; krb_get_lrealm (tmp_realm, n) == KSUCCESS; ++n) {
+ kerno = krb_mk_req (&ticket, "rcmd", savehost, tmp_realm, 33);
+ if (kerno == 0)
+ break;
+ }
+
+ if (kerno == KDC_PR_UNKNOWN) {
+ warnx ("Warning: TGT not verified.");
+ syslog (LOG_NOTICE | LOG_AUTH,
+ "%s to %s%s, TGT not verified (%s); "
+ "%s.%s not registered?",
+ username, user, ontty (), krb_get_err_text (kerno),
+ "rcmd", savehost);
+#ifdef KLOGIN_PARANOID
+ /*
+ * if the "VERIFY_SERVICE" doesn't exist in the KDC for this host, *
+ * don't allow kerberos login, also log the error condition.
+ */
+ warnx ("Trying local password!");
+ return (1);
+#endif
+ } else if (kerno != KSUCCESS) {
+ warnx ("Unable to use TGT: %s", krb_get_err_text (kerno));
+ syslog (LOG_NOTICE | LOG_AUTH, "failed su: %s to %s%s: %s",
+ username, user, ontty (), krb_get_err_text (kerno));
+ dest_tkt ();
+ return (1);
+ } else {
+ if (!(hp = gethostbyname (hostname))) {
+ warnx ("can't get addr of %s", hostname);
+ dest_tkt ();
+ return (1);
+ }
+ memcpy (&faddr, hp->h_addr, sizeof (faddr));
+
+ if ((kerno = krb_rd_req (&ticket, "rcmd", savehost, faddr,
+ &authdata, "")) != KSUCCESS) {
+ warnx ("unable to verify rcmd ticket: %s",
+ krb_get_err_text (kerno));
+ syslog (LOG_NOTICE | LOG_AUTH,
+ "failed su: %s to %s%s: %s", username,
+ user, ontty (), krb_get_err_text (kerno));
+ dest_tkt ();
+ return (1);
+ }
+ }
+ if (!destroy_tickets)
+ fprintf (stderr, "Don't forget to kdestroy before exiting the shell.\n");
+ return (0);
+}
+
+static int
+koktologin (char *name, char *realm, char *toname)
+{
+ return krb_kuserok (name,
+ strcmp (toname, "root") == 0 ? root_inst : "",
+ realm,
+ toname);
+}
diff --git a/crypto/kerberosIV/appl/bsd/sysv_default.c b/crypto/kerberosIV/appl/bsd/sysv_default.c
new file mode 100644
index 0000000..e6b28a7
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/sysv_default.c
@@ -0,0 +1,95 @@
+/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: sysv_default.c,v 1.11 1999/03/13 21:15:24 assar Exp $");
+
+#include "sysv_default.h"
+
+ /*
+ * Default values for stuff that can be read from the defaults file. The
+ * SunOS 5.1 documentation is incomplete and often disagrees with reality.
+ */
+
+static char default_umask_value[] = "022";
+
+char *default_console = 0;
+char *default_altsh = "YES";
+char *default_passreq = "NO";
+char *default_timezone= 0;
+char *default_hz = 0;
+char *default_path = _PATH_DEFPATH;
+char *default_supath = _PATH_DEFSUPATH;
+char *default_ulimit = 0;
+char *default_timeout = "180";
+char *default_umask = default_umask_value;
+char *default_sleep = "4";
+char *default_maxtrys = "5";
+
+static struct sysv_default {
+ char **valptr;
+ char *prefix;
+ int prefix_len;
+} defaults[] = {
+ {&default_console, "CONSOLE=", sizeof("CONSOLE=") -1},
+ {&default_altsh, "ALTSHELL=", sizeof("ALTSHELL=") -1},
+ {&default_passreq, "PASSREQ=", sizeof("PASSREQ=") -1},
+ {&default_timezone, "TIMEZONE=", sizeof("TIMEZONE=") -1},
+ {&default_hz, "HZ=", sizeof("HZ=") -1},
+ {&default_path, "PATH=", sizeof("PATH=") -1},
+ {&default_supath, "SUPATH=", sizeof("SUPATH=") -1},
+ {&default_ulimit, "ULIMIT=", sizeof("ULIMIT=") -1},
+ {&default_timeout, "TIMEOUT=", sizeof("TIMEOUT=") -1},
+ {&default_umask, "UMASK=", sizeof("UMASK=") -1},
+ {&default_sleep, "SLEEPTIME=", sizeof("SLEEPTIME=") -1},
+ {&default_maxtrys, "MAXTRYS=", sizeof("MAXTRYS=") -1},
+ {0},
+};
+
+#define trim(s) { \
+ char *cp = s + strlen(s); \
+ while (cp > s && isspace((unsigned char)cp[-1])) \
+ cp--; \
+ *cp = 0; \
+}
+
+/* sysv_defaults - read login defaults file */
+
+void
+sysv_defaults()
+{
+ struct sysv_default *dp;
+ FILE *fp;
+ char buf[BUFSIZ];
+
+ if ((fp = fopen(_PATH_ETC_DEFAULT_LOGIN, "r"))) {
+
+ /* Stupid quadratic algorithm. */
+
+ while (fgets(buf, sizeof(buf), fp)) {
+
+ /* Skip comments and blank lines. */
+
+ if (buf[0] == '#')
+ continue;
+ trim(buf);
+ if (buf[0] == 0)
+ continue;
+
+ /* Assign defaults from file. */
+
+#define STREQN(x,y,l) (x[0] == y[0] && strncmp(x,y,l) == 0)
+
+ for (dp = defaults; dp->valptr; dp++) {
+ if (STREQN(buf, dp->prefix, dp->prefix_len)) {
+ if ((*(dp->valptr) = strdup(buf + dp->prefix_len)) == 0) {
+ warnx("Insufficient memory resources - try later.");
+ sleepexit(1);
+ }
+ break;
+ }
+ }
+ }
+ fclose(fp);
+ }
+}
diff --git a/crypto/kerberosIV/appl/bsd/sysv_default.h b/crypto/kerberosIV/appl/bsd/sysv_default.h
new file mode 100644
index 0000000..0056059
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/sysv_default.h
@@ -0,0 +1,18 @@
+/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */
+
+/* $Id: sysv_default.h,v 1.5 1996/10/27 23:51:14 assar Exp $ */
+
+extern char *default_console;
+extern char *default_altsh;
+extern char *default_passreq;
+extern char *default_timezone;
+extern char *default_hz;
+extern char *default_path;
+extern char *default_supath;
+extern char *default_ulimit;
+extern char *default_timeout;
+extern char *default_umask;
+extern char *default_sleep;
+extern char *default_maxtrys;
+
+void sysv_defaults(void);
diff --git a/crypto/kerberosIV/appl/bsd/sysv_environ.c b/crypto/kerberosIV/appl/bsd/sysv_environ.c
new file mode 100644
index 0000000..3df800e
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/sysv_environ.c
@@ -0,0 +1,193 @@
+/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: sysv_environ.c,v 1.23 1997/12/14 23:50:44 assar Exp $");
+
+#ifdef HAVE_ULIMIT_H
+#include <ulimit.h>
+#endif
+
+#ifndef UL_SETFSIZE
+#define UL_SETFSIZE 2
+#endif
+
+#include "sysv_default.h"
+
+/*
+ * Set
+ */
+
+static void
+read_etc_environment (void)
+{
+ FILE *f;
+ char buf[BUFSIZ];
+
+ f = fopen(_PATH_ETC_ENVIRONMENT, "r");
+ if (f) {
+ char *val;
+
+ while (fgets (buf, sizeof(buf), f) != NULL) {
+ if (buf[0] == '\n' || buf[0] == '#')
+ continue;
+ buf[strlen(buf) - 1] = '\0';
+ val = strchr (buf, '=');
+ if (val == NULL)
+ continue;
+ *val = '\0';
+ setenv(buf, val + 1, 1);
+ }
+ fclose (f);
+ }
+}
+
+ /*
+ * Environment variables that are preserved (but may still be overruled by
+ * other means). Only TERM and TZ appear to survive (SunOS 5.1). These are
+ * typically inherited from the ttymon process.
+ */
+
+static struct preserved {
+ char *name;
+ char *value;
+} preserved[] = {
+ {"TZ", 0},
+ {"TERM", 0},
+ {0},
+};
+
+ /*
+ * Environment variables that are not preserved and that cannot be specified
+ * via commandline or stdin. Except for the LD_xxx (runtime linker) stuff,
+ * the list applies to most SYSV systems. The manpage mentions only that
+ * SHELL and PATH are censored. HOME, LOGNAME and MAIL are always
+ * overwritten; they are in the list to make the censoring explicit.
+ */
+
+static struct censored {
+ char *prefix;
+ int length;
+} censored[] = {
+ {"SHELL=", sizeof("SHELL=") - 1},
+ {"HOME=", sizeof("HOME=") - 1},
+ {"LOGNAME=", sizeof("LOGNAME=") - 1},
+ {"MAIL=", sizeof("MAIL=") - 1},
+ {"CDPATH=", sizeof("CDPATH=") - 1},
+ {"IFS=", sizeof("IFS=") - 1},
+ {"PATH=", sizeof("PATH=") - 1},
+ {"LD_", sizeof("LD_") - 1},
+ {0},
+};
+
+/* sysv_newenv - set up final environment after logging in */
+
+void sysv_newenv(int argc, char **argv, struct passwd *pwd,
+ char *term, int pflag)
+{
+ unsigned umask_val;
+ char buf[BUFSIZ];
+ int count = 0;
+ struct censored *cp;
+ struct preserved *pp;
+
+ /* Preserve a selection of the environment. */
+
+ for (pp = preserved; pp->name; pp++)
+ pp->value = getenv(pp->name);
+
+ /*
+ * Note: it is a bad idea to assign a static array to the global environ
+ * variable. Reason is that putenv() can run into problems when it tries
+ * to realloc() the environment table. Instead, we just clear environ[0]
+ * and let putenv() work things out.
+ */
+
+ if (!pflag && environ)
+ environ[0] = 0;
+
+ /* Restore preserved environment variables. */
+
+ for (pp = preserved; pp->name; pp++)
+ if (pp->value)
+ setenv(pp->name, pp->value, 1);
+
+ /* The TERM definition from e.g. rlogind can override an existing one. */
+
+ if (term[0])
+ setenv("TERM", term, 1);
+
+ /*
+ * Environment definitions from the command line overrule existing ones,
+ * but can be overruled by definitions from stdin. Some variables are
+ * censored.
+ *
+ * Omission: we do not support environment definitions from stdin.
+ */
+
+#define STREQN(x,y,l) (x[0] == y[0] && strncmp(x,y,l) == 0)
+
+ while (argc && *argv) {
+ if (strchr(*argv, '=') == 0) {
+ snprintf(buf, sizeof(buf), "L%d", count++);
+ setenv(buf, *argv, 1);
+ } else {
+ for (cp = censored; cp->prefix; cp++)
+ if (STREQN(*argv, cp->prefix, cp->length))
+ break;
+ if (cp->prefix == 0)
+ putenv(*argv);
+ }
+ argc--, argv++;
+ }
+
+ /* PATH is always reset. */
+
+ setenv("PATH", pwd->pw_uid ? default_path : default_supath, 1);
+
+ /* Undocumented: HOME, MAIL and LOGNAME are always reset (SunOS 5.1). */
+
+ setenv("HOME", pwd->pw_dir, 1);
+ {
+ char *sep = "/";
+ if(KRB4_MAILDIR[strlen(KRB4_MAILDIR) - 1] == '/')
+ sep = "";
+ roken_concat(buf, sizeof(buf), KRB4_MAILDIR, sep, pwd->pw_name, NULL);
+ }
+ setenv("MAIL", buf, 1);
+ setenv("LOGNAME", pwd->pw_name, 1);
+ setenv("USER", pwd->pw_name, 1);
+
+ /*
+ * Variables that may be set according to specifications in the defaults
+ * file. HZ and TZ are set only if they are still uninitialized.
+ *
+ * Extension: when ALTSHELL=YES, we set the SHELL variable even if it is
+ * /bin/sh.
+ */
+
+ if (strcasecmp(default_altsh, "YES") == 0)
+ setenv("SHELL", pwd->pw_shell, 1);
+ if (default_hz)
+ setenv("HZ", default_hz, 0);
+ if (default_timezone)
+ setenv("TZ", default_timezone, 0);
+
+ /* Non-environment stuff. */
+
+ if (default_umask) {
+ if (sscanf(default_umask, "%o", &umask_val) == 1 && umask_val)
+ umask(umask_val);
+ }
+#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);
+ }
+#endif
+ read_etc_environment();
+}
+
diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.c b/crypto/kerberosIV/appl/bsd/sysv_shadow.c
new file mode 100644
index 0000000..99794bd
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.c
@@ -0,0 +1,45 @@
+/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: sysv_shadow.c,v 1.8 1997/12/29 19:56:07 bg Exp $");
+
+#ifdef SYSV_SHADOW
+
+#include <sysv_shadow.h>
+
+/* sysv_expire - check account and password expiration times */
+
+int
+sysv_expire(struct spwd *spwd)
+{
+ long today;
+
+ tzset();
+ today = time(0)/(60*60*24); /* In days since Jan. 1, 1970 */
+
+ if (spwd->sp_expire > 0) {
+ if (today > spwd->sp_expire) {
+ printf("Your account has expired.\n");
+ sleepexit(1);
+ } else if (spwd->sp_expire - today < 14) {
+ printf("Your account will expire in %d days.\n",
+ (int)(spwd->sp_expire - today));
+ return (0);
+ }
+ }
+ if (spwd->sp_max > 0) {
+ if (today > (spwd->sp_lstchg + spwd->sp_max)) {
+ printf("Your password has expired. Choose a new one.\n");
+ return (1);
+ } else if (spwd->sp_warn > 0
+ && (today > (spwd->sp_lstchg + spwd->sp_max - spwd->sp_warn))) {
+ printf("Your password will expire in %d days.\n",
+ (int)(spwd->sp_lstchg + spwd->sp_max - today));
+ return (0);
+ }
+ }
+ return (0);
+}
+
+#endif /* SYSV_SHADOW */
diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.h b/crypto/kerberosIV/appl/bsd/sysv_shadow.h
new file mode 100644
index 0000000..339035b
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.h
@@ -0,0 +1,5 @@
+/* $Id: sysv_shadow.h,v 1.7 1999/03/13 21:15:43 assar Exp $ */
+
+#include <shadow.h>
+
+int sysv_expire(struct spwd *);
diff --git a/crypto/kerberosIV/appl/bsd/tty.c b/crypto/kerberosIV/appl/bsd/tty.c
new file mode 100644
index 0000000..2a903db
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/tty.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: tty.c,v 1.3 1999/12/02 16:58:28 joda Exp $");
+
+/*
+ * Clean the tty name. Return a pointer to the cleaned version.
+ */
+
+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'.
+ */
+
+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;
+}
diff --git a/crypto/kerberosIV/appl/bsd/utmp_login.c b/crypto/kerberosIV/appl/bsd/utmp_login.c
new file mode 100644
index 0000000..d2879fe
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/utmp_login.c
@@ -0,0 +1,118 @@
+/*
+ * 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. 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: utmp_login.c,v 1.16 1999/12/02 16:58:29 joda Exp $");
+
+#ifdef HAVE_UTMP_H
+void
+prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname)
+{
+ char *ttyx = clean_ttyname (tty);
+
+ memset(utmp, 0, sizeof(*utmp));
+ utmp->ut_time = time(NULL);
+ strncpy(utmp->ut_line, ttyx, sizeof(utmp->ut_line));
+ strncpy(utmp->ut_name, username, sizeof(utmp->ut_name));
+
+# ifdef HAVE_STRUCT_UTMP_UT_USER
+ strncpy(utmp->ut_user, username, sizeof(utmp->ut_user));
+# endif
+
+# ifdef HAVE_STRUCT_UTMP_UT_ADDR
+ if (hostname[0]) {
+ struct hostent *he;
+ if ((he = gethostbyname(hostname)))
+ memcpy(&utmp->ut_addr, he->h_addr_list[0],
+ sizeof(utmp->ut_addr));
+ }
+# endif
+
+# ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(utmp->ut_host, hostname, sizeof(utmp->ut_host));
+# endif
+
+# ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ utmp->ut_type = USER_PROCESS;
+# endif
+
+# ifdef HAVE_STRUCT_UTMP_UT_PID
+ utmp->ut_pid = getpid();
+# endif
+
+# 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; }
+#else
+
+/* update utmp and wtmp - the BSD way */
+
+void utmp_login(char *tty, char *username, char *hostname)
+{
+ struct utmp utmp;
+ int fd;
+
+ prepare_utmp (&utmp, tty, username, hostname);
+
+#ifdef HAVE_SETUTENT
+ utmpname(_PATH_UTMP);
+ setutent();
+ pututline(&utmp);
+ endutent();
+#else
+
+#ifdef HAVE_TTYSLOT
+ {
+ int ttyno;
+ ttyno = ttyslot();
+ if (ttyno > 0 && (fd = open(_PATH_UTMP, O_WRONLY, 0)) >= 0) {
+ lseek(fd, (long)(ttyno * sizeof(struct utmp)), SEEK_SET);
+ write(fd, &utmp, sizeof(struct utmp));
+ close(fd);
+ }
+ }
+#endif /* HAVE_TTYSLOT */
+#endif /* HAVE_SETUTENT */
+
+ if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) {
+ write(fd, &utmp, sizeof(struct utmp));
+ close(fd);
+ }
+}
+#endif /* !HAVE_UTMPX_H */
diff --git a/crypto/kerberosIV/appl/bsd/utmpx_login.c b/crypto/kerberosIV/appl/bsd/utmpx_login.c
new file mode 100644
index 0000000..acc6a154
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/utmpx_login.c
@@ -0,0 +1,88 @@
+/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: utmpx_login.c,v 1.21 1999/03/29 17:57:31 joda Exp $");
+
+/* utmpx_login - update utmp and wtmp after login */
+
+#ifndef HAVE_UTMPX_H
+int utmpx_login(char *line, char *user, char *host) { return 0; }
+#else
+
+static void
+utmpx_update(struct utmpx *ut, char *line, char *user, char *host)
+{
+ struct timeval tmp;
+ char *clean_tty = clean_ttyname(line);
+
+ strncpy(ut->ut_line, clean_tty, sizeof(ut->ut_line));
+#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_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);
+#endif
+ ut->ut_type = USER_PROCESS;
+ gettimeofday (&tmp, 0);
+ ut->ut_tv.tv_sec = tmp.tv_sec;
+ ut->ut_tv.tv_usec = tmp.tv_usec;
+ pututxline(ut);
+#ifdef WTMPX_FILE
+ updwtmpx(WTMPX_FILE, ut);
+#elif defined(WTMP_FILE)
+ {
+ struct utmp utmp;
+ int fd;
+
+ prepare_utmp (&utmp, line, user, host);
+ if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) {
+ write(fd, &utmp, sizeof(struct utmp));
+ close(fd);
+ }
+ }
+#endif
+}
+
+int
+utmpx_login(char *line, char *user, char *host)
+{
+ struct utmpx *ut;
+ pid_t mypid = getpid();
+ int ret = (-1);
+
+ /*
+ * SYSV4 ttymon and login use tty port names with the "/dev/" prefix
+ * stripped off. Rlogind and telnetd, on the other hand, make utmpx
+ * entries with device names like /dev/pts/nnn. We therefore cannot use
+ * getutxline(). Return nonzero if no utmp entry was found with our own
+ * process ID for a login or user process.
+ */
+
+ while ((ut = getutxent())) {
+ /* Try to find a reusable entry */
+ if (ut->ut_pid == mypid
+ && ( ut->ut_type == INIT_PROCESS
+ || ut->ut_type == LOGIN_PROCESS
+ || ut->ut_type == USER_PROCESS)) {
+ utmpx_update(ut, line, user, host);
+ ret = 0;
+ break;
+ }
+ }
+ if (ret == -1) {
+ /* Grow utmpx file by one record. */
+ struct utmpx newut;
+ memset(&newut, 0, sizeof(newut));
+ newut.ut_pid = mypid;
+ utmpx_update(&newut, line, user, host);
+ ret = 0;
+ }
+ endutxent();
+ return (ret);
+}
+#endif /* HAVE_UTMPX_H */
diff --git a/crypto/kerberosIV/appl/ftp/ChangeLog b/crypto/kerberosIV/appl/ftp/ChangeLog
new file mode 100644
index 0000000..0136a4b
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ChangeLog
@@ -0,0 +1,384 @@
+2000-03-26 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c, ftpd/ftpcmd.y, ftp/cmds.c: make sure to always call
+ time, ctime, and gmtime with `time_t's. there were some types
+ (like in lastlog) that we believed to always be time_t. this has
+ proven wrong on Solaris 8 in 64-bit mode, where they are stored as
+ 32-bit quantities but time_t has gone up to 64 bits
+
+1999-11-30 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (getdatasock): make sure to keep the port-number of
+ the outgoing connections. It has to be `ftp-data' or some people
+ might get upset.
+
+ * ftpd/ftpd.c (args): set correct variable when `-l' so that
+ logging actually works
+
+1999-11-29 Assar Westerlund <assar@sics.se>
+
+ * ftp/security.c (sec_login): check return value from realloc
+ (sec_end): set app_data to NULL
+
+1999-11-25 Assar Westerlund <assar@sics.se>
+
+ * ftp/krb4.c (krb4_auth): obtain the `local' address when doing
+ NAT. also turn on passive mode. From <thn@stacken.kth.se>
+
+1999-11-20 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (make_fileinfo): cast to allow for non-const
+ prototypes of readlink
+
+1999-11-12 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (args): use arg_counter for `l'
+
+1999-11-04 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (S_ISSOCK, S_ISLNK): fallback definitions for systems
+ that don't have them (such as ultrix)
+
+1999-10-29 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (make_fileinfo): cast uid's and gid's to unsigned in
+ printf, we don't know what types they might be.
+ (lstat_file): conditionalize the kafs part on KRB4
+
+ * ftpd/ftpd_locl.h: <sys/ioccom.h> is needed for kafs.h
+
+1999-10-28 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (lstat_file): don't set st_mode, it should already be
+ correct
+
+ * ftpd/ls.c: don't use warnx to print errors
+
+ * ftpd/ls.c (builtin_ls): fix typo, 'd' shouldn't imply 'f'
+
+ * ftpd/ls.c (lstat_file): new function for avoiding stating AFS
+ mount points. From Love <lha@s3.kth.se>
+ (list_files): use `lstat_file'
+
+ * ftpd/ftpd.c: some const-poisoning
+
+ * ftpd/ftpd.c (args): add `-B' as an alias for `--builtin-ls' to
+ allow for stupid inetds that only support two arguments. From
+ Love <lha@s3.kth.se>
+
+1999-10-26 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y (help): it's unnecessary to interpret help strings
+ as printf commands
+
+ * ftpd/ftpd.c (show_issue): don't interpret contents of
+ /etc/issue* as printf commands. From Brian A May
+ <bmay@dgs.monash.edu.au>
+
+1999-10-21 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/kauth.c (kauth): complain if protection level isn't
+ `private'
+
+ * ftp/krb4.c (krb4_decode): syslog failure reason
+
+ * ftp/kauth.c (kauth): set private level earlier
+
+ * ftp/security.c: get_command_prot; (sec_prot): partially match
+ `command' and `data'
+
+1999-10-18 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpd.c: change `-l' flag to use arg_collect (this makes
+ `-ll' work again)
+
+ * ftpd/ftpd.c (list_file): pass filename to ls
+
+1999-10-04 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpcmd.y: FEAT
+
+1999-10-03 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c: fall-back definitions for constans and casts for
+ printfs
+
+1999-10-03 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpd.c (main): make this use getarg; add `list_file'
+
+ * ftpd/ftpcmd.y (LIST): call list_file
+
+ * ftpd/ls.c: add simple built-in ls
+
+ * ftp/security.c: add `sec_vfprintf2' and `sec_fprintf2' that
+ prints to the data stream
+
+ * ftp/kauth.c (kauth): make sure we're using private protection
+ level
+
+ * ftp/security.c (set_command_prot): set command protection level
+
+ * ftp/security.c: make it possible to set the command protection
+ level with `prot'
+
+1999-09-30 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd_locl.h: add prototype for fclose to make sunos happy
+
+1999-08-19 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpd.c (do_login): show issue-file
+ (send_data): change handling of zero-byte files
+
+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-08-13 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (send_data): avoid calling mmap with `len == 0'.
+ Some mmap:s rather dislike that (Solaris) and some munmap (Linux)
+ get grumpy later.
+
+ * ftp/ftp.c (copy_stream): avoid calling mmap with `len == 0'.
+ Some mmap:s rather dislike that (Solaris) and some munmap (Linux)
+ get grumpy later.
+
+1999-08-03 Assar Westerlund <assar@sics.se>
+
+ * ftp/ftp.c (active_mode): hide failure of EPRT by setting verbose
+
+ * ftp/gssapi.c (gss_auth): initialize application_data in bindings
+
+1999-08-02 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y: save file names when doing commands that might
+ get aborted (and longjmp:ed out of) to avoid overwriting them also
+ remove extra closing brace
+
+1999-08-01 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpcmd.y: change `site find' to `site locate' (to match
+ what it does, and other implementations) keep find as an alias
+
+1999-07-28 Assar Westerlund <assar@sics.se>
+
+ * common/socket.c: moved to roken
+
+ * common/socket.c: new file with generic socket functions
+
+ * ftpd/ftpd.c: make it more AF-neutral and v6-capable
+
+ * ftpd/ftpcmd.y: add EPRT and EPSV
+
+ * ftpd/extern.h: update prototypes and variables
+
+ * ftp/krb4.c: update to new types of addresses
+
+ * ftp/gssapi.c: add support for both AF_INET and AF_INET6
+ addresses
+
+ * ftp/ftp.c: make it more AF-neutral and v6-capable
+
+ * ftp/extern.h (hookup): change prototype
+
+ * common/common.h: add prototypes for functions in socket.c
+
+ * common/Makefile.am (libcommon_a_SOURCES): add socket.c
+
+ * ftp/gssapi.c (gss_auth): check return value from
+ `gss_import_name' and print error messages if it fails
+
+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
new file mode 100644
index 0000000..68546ab
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/Makefile.in
@@ -0,0 +1,44 @@
+# $Id: Makefile.in,v 1.12 1999/03/10 19:01:11 joda Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SHELL = /bin/sh
+
+@SET_MAKE@
+
+CC = @CC@
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+
+INSTALL = @INSTALL@
+
+prefix = @prefix@
+
+SUBDIRS=common ftp ftpd
+
+all:
+ for i in $(SUBDIRS); \
+ do (cd $$i && $(MAKE) $(MFLAGS) all); done
+
+install: all
+ 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/ftp/common/Makefile.am b/crypto/kerberosIV/appl/ftp/common/Makefile.am
new file mode 100644
index 0000000..4fab07b
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/Makefile.am
@@ -0,0 +1,12 @@
+# $Id: Makefile.am,v 1.9 1999/07/28 21:15:06 assar 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
new file mode 100644
index 0000000..b00bd0a
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/Makefile.in
@@ -0,0 +1,55 @@
+# $Id: Makefile.in,v 1.23 1999/03/10 19:01:11 joda Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+
+INSTALL = @INSTALL@
+
+prefix = @prefix@
+
+SOURCES = sockbuf.c buffer.c
+OBJECTS = $(libcommon_OBJS)
+
+libcommon_OBJS = sockbuf.o buffer.o
+
+LIBNAME = $(LIBPREFIX)common
+LIBEXT = a
+LIBPREFIX = @LIBPREFIX@
+LIB = $(LIBNAME).$(LIBEXT)
+
+all: $(LIB)
+
+.c.o:
+ $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $<
+
+$(LIB): $(libcommon_OBJS)
+ rm -f $@
+ ar cr $@ $(libcommon_OBJS)
+ -$(RANLIB) $@
+
+install:
+
+uninstall:
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+clean cleandir:
+ rm -f *~ *.o libcommon.a core \#*
+
+distclean:
+ rm -f Makefile
+
+$(OBJECTS): ../../../include/config.h
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/ftp/common/base64.c b/crypto/kerberosIV/appl/ftp/common/base64.c
new file mode 100644
index 0000000..648f32d
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/base64.c
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: base64.c,v 1.6 1997/05/30 17:24:06 assar Exp $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "base64.h"
+
+static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static int pos(char c)
+{
+ char *p;
+ for(p = base64; *p; p++)
+ if(*p == c)
+ return p - base64;
+ return -1;
+}
+
+int base64_encode(const void *data, int size, char **str)
+{
+ char *s, *p;
+ int i;
+ int c;
+ unsigned char *q;
+
+ p = s = (char*)malloc(size*4/3+4);
+ q = (unsigned char*)data;
+ i=0;
+ for(i = 0; i < size;){
+ c=q[i++];
+ c*=256;
+ if(i < size)
+ c+=q[i];
+ i++;
+ c*=256;
+ if(i < size)
+ c+=q[i];
+ i++;
+ p[0]=base64[(c&0x00fc0000) >> 18];
+ p[1]=base64[(c&0x0003f000) >> 12];
+ p[2]=base64[(c&0x00000fc0) >> 6];
+ p[3]=base64[(c&0x0000003f) >> 0];
+ if(i > size)
+ p[3]='=';
+ if(i > size+1)
+ p[2]='=';
+ p+=4;
+ }
+ *p=0;
+ *str = s;
+ return strlen(s);
+}
+
+int base64_decode(const char *str, void *data)
+{
+ const char *p;
+ unsigned char *q;
+ int c;
+ int x;
+ int done = 0;
+ q=(unsigned char*)data;
+ for(p=str; *p && !done; p+=4){
+ x = pos(p[0]);
+ if(x >= 0)
+ c = x;
+ else{
+ done = 3;
+ break;
+ }
+ c*=64;
+
+ x = pos(p[1]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ c*=64;
+
+ if(p[2] == '=')
+ done++;
+ else{
+ x = pos(p[2]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ }
+ c*=64;
+
+ if(p[3] == '=')
+ done++;
+ else{
+ if(done)
+ return -1;
+ x = pos(p[3]);
+ if(x >= 0)
+ c += x;
+ else
+ return -1;
+ }
+ if(done < 3)
+ *q++=(c&0x00ff0000)>>16;
+
+ if(done < 2)
+ *q++=(c&0x0000ff00)>>8;
+ if(done < 1)
+ *q++=(c&0x000000ff)>>0;
+ }
+ return q - (unsigned char*)data;
+}
diff --git a/crypto/kerberosIV/appl/ftp/common/base64.h b/crypto/kerberosIV/appl/ftp/common/base64.h
new file mode 100644
index 0000000..fe799a2
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/base64.h
@@ -0,0 +1,47 @@
+/*
+ * 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: base64.h,v 1.5 1997/04/01 08:17:19 joda Exp $ */
+
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+int base64_encode(const void *data, int size, char **str);
+int base64_decode(const char *str, void *data);
+
+#endif
diff --git a/crypto/kerberosIV/appl/ftp/common/buffer.c b/crypto/kerberosIV/appl/ftp/common/buffer.c
new file mode 100644
index 0000000..0385d49
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/buffer.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "common.h"
+#include <stdio.h>
+#include <err.h>
+#include "roken.h"
+
+RCSID("$Id: buffer.c,v 1.3 1999/12/02 16:58:29 joda Exp $");
+
+/*
+ * Allocate a buffer enough to handle st->st_blksize, if
+ * there is such a field, otherwise BUFSIZ.
+ */
+
+void *
+alloc_buffer (void *oldbuf, size_t *sz, struct stat *st)
+{
+ size_t new_sz;
+
+ new_sz = BUFSIZ;
+#ifdef HAVE_ST_BLKSIZE
+ if (st)
+ new_sz = max(BUFSIZ, st->st_blksize);
+#endif
+ if(new_sz > *sz) {
+ if (oldbuf)
+ free (oldbuf);
+ oldbuf = malloc (new_sz);
+ if (oldbuf == NULL) {
+ warn ("malloc");
+ *sz = 0;
+ return NULL;
+ }
+ *sz = new_sz;
+ }
+ return oldbuf;
+}
+
diff --git a/crypto/kerberosIV/appl/ftp/common/common.h b/crypto/kerberosIV/appl/ftp/common/common.h
new file mode 100644
index 0000000..5949b25
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/common.h
@@ -0,0 +1,60 @@
+/*
+ * 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. 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: common.h,v 1.12 1999/12/02 16:58:29 joda Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include "base64.h"
+
+void set_buffer_size(int, int);
+
+#include <stdlib.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+void *alloc_buffer (void *oldbuf, size_t *sz, struct stat *st);
+
+#endif /* __COMMON_H__ */
diff --git a/crypto/kerberosIV/appl/ftp/common/glob.c b/crypto/kerberosIV/appl/ftp/common/glob.c
new file mode 100644
index 0000000..8f19d7c
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/glob.c
@@ -0,0 +1,835 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ */
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ * Escaping convention: \ inhibits any special meaning the following
+ * character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
+ * not contain any magic characters. [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ * Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "glob.h"
+#include "roken.h"
+
+#define CHAR_DOLLAR '$'
+#define CHAR_DOT '.'
+#define CHAR_EOS '\0'
+#define CHAR_LBRACKET '['
+#define CHAR_NOT '!'
+#define CHAR_QUESTION '?'
+#define CHAR_QUOTE '\\'
+#define CHAR_RANGE '-'
+#define CHAR_RBRACKET ']'
+#define CHAR_SEP '/'
+#define CHAR_STAR '*'
+#define CHAR_TILDE '~'
+#define CHAR_UNDERSCORE '_'
+#define CHAR_LBRACE '{'
+#define CHAR_RBRACE '}'
+#define CHAR_SLASH '/'
+#define CHAR_COMMA ','
+
+#ifndef DEBUG
+
+#define M_QUOTE 0x8000
+#define M_PROTECT 0x4000
+#define M_MASK 0xffff
+#define M_ASCII 0x00ff
+
+typedef u_short Char;
+
+#else
+
+#define M_QUOTE 0x80
+#define M_PROTECT 0x40
+#define M_MASK 0xff
+#define M_ASCII 0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define CHAR(c) ((Char)((c)&M_ASCII))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define M_ALL META('*')
+#define M_END META(']')
+#define M_NOT META('!')
+#define M_ONE META('?')
+#define M_RNG META('-')
+#define M_SET META('[')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+
+
+static int compare (const void *, const void *);
+static void g_Ctoc (const Char *, char *);
+static int g_lstat (Char *, struct stat *, glob_t *);
+static DIR *g_opendir (Char *, glob_t *);
+static Char *g_strchr (Char *, int);
+#ifdef notdef
+static Char *g_strcat (Char *, const Char *);
+#endif
+static int g_stat (Char *, struct stat *, glob_t *);
+static int glob0 (const Char *, glob_t *);
+static int glob1 (Char *, glob_t *);
+static int glob2 (Char *, Char *, Char *, glob_t *);
+static int glob3 (Char *, Char *, Char *, Char *, glob_t *);
+static int globextend (const Char *, glob_t *);
+static const Char * globtilde (const Char *, Char *, glob_t *);
+static int globexp1 (const Char *, glob_t *);
+static int globexp2 (const Char *, const Char *, glob_t *, int *);
+static int match (Char *, Char *, Char *);
+#ifdef DEBUG
+static void qprintf (const char *, Char *);
+#endif
+
+int
+glob(const char *pattern,
+ int flags,
+ int (*errfunc)(const char *, int),
+ glob_t *pglob)
+{
+ const u_char *patnext;
+ int c;
+ Char *bufnext, *bufend, patbuf[MaxPathLen+1];
+
+ patnext = (u_char *) pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ bufnext = patbuf;
+ bufend = bufnext + MaxPathLen;
+ if (flags & GLOB_QUOTE) {
+ /* Protect the quoted characters. */
+ while (bufnext < bufend && (c = *patnext++) != CHAR_EOS)
+ if (c == CHAR_QUOTE) {
+ if ((c = *patnext++) == CHAR_EOS) {
+ c = CHAR_QUOTE;
+ --patnext;
+ }
+ *bufnext++ = c | M_PROTECT;
+ }
+ else
+ *bufnext++ = c;
+ }
+ else
+ while (bufnext < bufend && (c = *patnext++) != CHAR_EOS)
+ *bufnext++ = c;
+ *bufnext = CHAR_EOS;
+
+ if (flags & GLOB_BRACE)
+ return globexp1(patbuf, pglob);
+ else
+ return glob0(patbuf, pglob);
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int globexp1(const Char *pattern, glob_t *pglob)
+{
+ const Char* ptr = pattern;
+ int rv;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == CHAR_LBRACE && pattern[1] == CHAR_RBRACE && pattern[2] == CHAR_EOS)
+ return glob0(pattern, pglob);
+
+ while ((ptr = (const Char *) g_strchr((Char *) ptr, CHAR_LBRACE)) != NULL)
+ if (!globexp2(ptr, pattern, pglob, &rv))
+ return rv;
+
+ return glob0(pattern, pglob);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int globexp2(const Char *ptr, const Char *pattern,
+ glob_t *pglob, int *rv)
+{
+ int i;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pl;
+ Char patbuf[MaxPathLen + 1];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe; pe++)
+ if (*pe == CHAR_LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != CHAR_RBRACKET && *pe != CHAR_EOS; pe++)
+ continue;
+ if (*pe == CHAR_EOS) {
+ /*
+ * We could not find a matching CHAR_RBRACKET.
+ * Ignore and just look for CHAR_RBRACE
+ */
+ pe = pm;
+ }
+ }
+ else if (*pe == CHAR_LBRACE)
+ i++;
+ else if (*pe == CHAR_RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == CHAR_EOS) {
+ *rv = glob0(patbuf, pglob);
+ return 0;
+ }
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+ switch (*pm) {
+ case CHAR_LBRACKET:
+ /* Ignore everything between [] */
+ for (pl = pm++; *pm != CHAR_RBRACKET && *pm != CHAR_EOS; pm++)
+ continue;
+ if (*pm == CHAR_EOS) {
+ /*
+ * We could not find a matching CHAR_RBRACKET.
+ * Ignore and just look for CHAR_RBRACE
+ */
+ pm = pl;
+ }
+ break;
+
+ case CHAR_LBRACE:
+ i++;
+ break;
+
+ case CHAR_RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case CHAR_COMMA:
+ if (i && *pm == CHAR_COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != CHAR_EOS;)
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ *rv = globexp1(patbuf, pglob);
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *rv = 0;
+ return 0;
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, glob_t *pglob)
+{
+ struct passwd *pwd;
+ char *h;
+ const Char *p;
+ Char *b;
+
+ if (*pattern != CHAR_TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return pattern;
+
+ /* Copy up to the end of the string or / */
+ for (p = pattern + 1, h = (char *) patbuf; *p && *p != CHAR_SLASH;
+ *h++ = *p++)
+ continue;
+
+ *h = CHAR_EOS;
+
+ if (((char *) patbuf)[0] == CHAR_EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME
+ * first and then trying the password file
+ */
+ if ((h = getenv("HOME")) == NULL) {
+ if ((pwd = k_getpwuid(getuid())) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+ }
+ else {
+ /*
+ * Expand a ~user
+ */
+ if ((pwd = k_getpwnam((char*) patbuf)) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+
+ /* Copy the home directory */
+ for (b = patbuf; *h; *b++ = *h++)
+ continue;
+
+ /* Append the rest of the pattern */
+ while ((*b++ = *p++) != CHAR_EOS)
+ continue;
+
+ return patbuf;
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
+ */
+static int
+glob0(const Char *pattern, glob_t *pglob)
+{
+ const Char *qpatnext;
+ int c, err, oldpathc;
+ Char *bufnext, patbuf[MaxPathLen+1];
+
+ qpatnext = globtilde(pattern, patbuf, pglob);
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != CHAR_EOS) {
+ switch (c) {
+ case CHAR_LBRACKET:
+ c = *qpatnext;
+ if (c == CHAR_NOT)
+ ++qpatnext;
+ if (*qpatnext == CHAR_EOS ||
+ g_strchr((Char *) qpatnext+1, CHAR_RBRACKET) == NULL) {
+ *bufnext++ = CHAR_LBRACKET;
+ if (c == CHAR_NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == CHAR_NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == CHAR_RANGE &&
+ (c = qpatnext[1]) != CHAR_RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != CHAR_RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case CHAR_QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case CHAR_STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = CHAR_EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(patbuf, pglob)) != 0)
+ return(err);
+
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the pattern did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if (pglob->gl_pathc == oldpathc &&
+ ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR))))
+ return(globextend(pattern, pglob));
+ else if (!(pglob->gl_flags & GLOB_NOSORT))
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+ return(0);
+}
+
+static int
+compare(const void *p, const void *q)
+{
+ return(strcmp(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(Char *pattern, glob_t *pglob)
+{
+ Char pathbuf[MaxPathLen+1];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == CHAR_EOS)
+ return(0);
+ return(glob2(pathbuf, pathbuf, pattern, pglob));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+
+#ifndef S_ISLNK
+#if defined(S_IFLNK) && defined(S_IFMT)
+#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#else
+#define S_ISLNK(mode) 0
+#endif
+#endif
+
+static int
+glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob)
+{
+ struct stat sb;
+ Char *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == CHAR_EOS) { /* End of pattern? */
+ *pathend = CHAR_EOS;
+ if (g_lstat(pathbuf, &sb, pglob))
+ return(0);
+
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ pathend[-1] != CHAR_SEP) && (S_ISDIR(sb.st_mode)
+ || (S_ISLNK(sb.st_mode) &&
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
+ S_ISDIR(sb.st_mode)))) {
+ *pathend++ = CHAR_SEP;
+ *pathend = CHAR_EOS;
+ }
+ ++pglob->gl_matchc;
+ return(globextend(pathbuf, pglob));
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != CHAR_EOS && *p != CHAR_SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (*pattern == CHAR_SEP)
+ *pathend++ = *pattern++;
+ } else /* Need expansion, recurse. */
+ return(glob3(pathbuf, pathend, pattern, p, pglob));
+ }
+ /* CHAR_NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathend, Char *pattern, Char *restpattern,
+ glob_t *pglob)
+{
+ struct dirent *dp;
+ DIR *dirp;
+ int err;
+ char buf[MaxPathLen];
+
+ /*
+ * The readdirfunc declaration can't be prototyped, because it is
+ * assigned, below, to two functions which are prototyped in glob.h
+ * and dirent.h as taking pointers to differently typed opaque
+ * structures.
+ */
+ struct dirent *(*readdirfunc)(void *);
+
+ *pathend = CHAR_EOS;
+ errno = 0;
+
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ /* TODO: don't call for ENOENT or ENOTDIR? */
+ if (pglob->gl_errfunc) {
+ g_Ctoc(pathbuf, buf);
+ if (pglob->gl_errfunc(buf, errno) ||
+ pglob->gl_flags & GLOB_ERR)
+ return (GLOB_ABEND);
+ }
+ return(0);
+ }
+
+ err = 0;
+
+ /* Search directory for matching names. */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc = pglob->gl_readdir;
+ else
+ readdirfunc = (struct dirent *(*)(void *))readdir;
+ while ((dp = (*readdirfunc)(dirp))) {
+ u_char *sc;
+ Char *dc;
+
+ /* Initial CHAR_DOT must be matched literally. */
+ if (dp->d_name[0] == CHAR_DOT && *pattern != CHAR_DOT)
+ continue;
+ for (sc = (u_char *) dp->d_name, dc = pathend;
+ (*dc++ = *sc++) != CHAR_EOS;)
+ continue;
+ if (!match(pathend, pattern, restpattern)) {
+ *pathend = CHAR_EOS;
+ continue;
+ }
+ err = glob2(pathbuf, --dc, restpattern, pglob);
+ if (err)
+ break;
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ closedir(dirp);
+ return(err);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob_t *pglob)
+{
+ char **pathv;
+ int i;
+ u_int newsize;
+ char *copy;
+ const Char *p;
+
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ pathv = pglob->gl_pathv ?
+ realloc(pglob->gl_pathv, newsize) :
+ malloc(newsize);
+ if (pathv == NULL)
+ return(GLOB_NOSPACE);
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs; --i >= 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ continue;
+ if ((copy = malloc(p - path)) != NULL) {
+ g_Ctoc(path, copy);
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ return(copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+ int ok, negate_range;
+ Char c, k;
+
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return(1);
+ do
+ if (match(name, pat, patend))
+ return(1);
+ while (*name++ != CHAR_EOS);
+ return(0);
+ case M_ONE:
+ if (*name++ == CHAR_EOS)
+ return(0);
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == CHAR_EOS)
+ return(0);
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != CHAR_EOS)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (c <= k && k <= pat[1])
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ if (ok == negate_range)
+ return(0);
+ break;
+ default:
+ if (*name++ != c)
+ return(0);
+ break;
+ }
+ }
+ return(*name == CHAR_EOS);
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void
+globfree(glob_t *pglob)
+{
+ int i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ }
+}
+
+static DIR *
+g_opendir(Char *str, glob_t *pglob)
+{
+ char buf[MaxPathLen];
+
+ if (!*str)
+ strcpy(buf, ".");
+ else
+ g_Ctoc(str, buf);
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_opendir)(buf));
+
+ return(opendir(buf));
+}
+
+static int
+g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MaxPathLen];
+
+ g_Ctoc(fn, buf);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_lstat)(buf, sb));
+ return(lstat(buf, sb));
+}
+
+static int
+g_stat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MaxPathLen];
+
+ g_Ctoc(fn, buf);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_stat)(buf, sb));
+ return(stat(buf, sb));
+}
+
+static Char *
+g_strchr(Char *str, int ch)
+{
+ do {
+ if (*str == ch)
+ return (str);
+ } while (*str++);
+ return (NULL);
+}
+
+#ifdef notdef
+static Char *
+g_strcat(Char *dst, const Char *src)
+{
+ Char *sdst = dst;
+
+ while (*dst++)
+ continue;
+ --dst;
+ while((*dst++ = *src++) != CHAR_EOS)
+ continue;
+
+ return (sdst);
+}
+#endif
+
+static void
+g_Ctoc(const Char *str, char *buf)
+{
+ char *dc;
+
+ for (dc = buf; (*dc++ = *str++) != CHAR_EOS;)
+ continue;
+}
+
+#ifdef DEBUG
+static void
+qprintf(const Char *str, Char *s)
+{
+ Char *p;
+
+ printf("%s:\n", str);
+ for (p = s; *p; p++)
+ printf("%c", CHAR(*p));
+ printf("\n");
+ for (p = s; *p; p++)
+ printf("%c", *p & M_PROTECT ? '"' : ' ');
+ printf("\n");
+ for (p = s; *p; p++)
+ printf("%c", ismeta(*p) ? '_' : ' ');
+ printf("\n");
+}
+#endif
diff --git a/crypto/kerberosIV/appl/ftp/common/glob.h b/crypto/kerberosIV/appl/ftp/common/glob.h
new file mode 100644
index 0000000..bece48a
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/glob.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _GLOB_H_
+#define _GLOB_H_
+
+struct stat;
+typedef struct {
+ int gl_pathc; /* Count of total paths so far. */
+ int gl_matchc; /* Count of paths matching pattern. */
+ int gl_offs; /* Reserved at beginning of gl_pathv. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ char **gl_pathv; /* List of paths matching pattern. */
+ /* Copy of errfunc parameter to glob. */
+ int (*gl_errfunc) (const char *, int);
+
+ /*
+ * Alternate filesystem access methods for glob; replacement
+ * versions of closedir(3), readdir(3), opendir(3), stat(2)
+ * and lstat(2).
+ */
+ void (*gl_closedir) (void *);
+ struct dirent *(*gl_readdir) (void *);
+ void *(*gl_opendir) (const char *);
+ int (*gl_lstat) (const char *, struct stat *);
+ int (*gl_stat) (const char *, struct stat *);
+} glob_t;
+
+#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
+#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
+#define GLOB_ERR 0x0004 /* Return on error. */
+#define GLOB_MARK 0x0008 /* Append / to matching directories. */
+#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
+#define GLOB_NOSORT 0x0020 /* Don't sort. */
+
+#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
+#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
+#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
+#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
+#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
+#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
+
+#define GLOB_NOSPACE (-1) /* Malloc call failed. */
+#define GLOB_ABEND (-2) /* Unignored error. */
+
+int glob (const char *, int, int (*)(const char *, int), glob_t *);
+void globfree (glob_t *);
+
+#endif /* !_GLOB_H_ */
diff --git a/crypto/kerberosIV/appl/ftp/common/sockbuf.c b/crypto/kerberosIV/appl/ftp/common/sockbuf.c
new file mode 100644
index 0000000..460cc6f
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/common/sockbuf.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "common.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+RCSID("$Id: sockbuf.c,v 1.3 1999/12/02 16:58:29 joda Exp $");
+
+void
+set_buffer_size(int fd, int read)
+{
+#if defined(SO_RCVBUF) && defined(SO_SNDBUF) && defined(HAVE_SETSOCKOPT)
+ size_t size = 4194304;
+ while(size >= 131072 &&
+ setsockopt(fd, SOL_SOCKET, read ? SO_RCVBUF : SO_SNDBUF,
+ (void *)&size, sizeof(size)) < 0)
+ size /= 2;
+#endif
+}
+
+
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
new file mode 100644
index 0000000..637d553
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in
@@ -0,0 +1,102 @@
+#
+# $Id: Makefile.in,v 1.32 1999/03/11 13:58:09 joda Exp $
+#
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+top_builddir = ../../..
+
+CC = @CC@
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+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@
+MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+INCTOP = $(top_builddir)/include
+
+LIBTOP = $(top_builddir)/lib
+
+PROGS = ftp$(EXECSUFFIX)
+
+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)
+
+all: $(PROGS)
+
+.c.o:
+ $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $<
+
+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
+
+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)
+ etags $(SOURCES)
+
+clean:
+ rm -f *~ *.o core ftp$(EXECSUFFIX) \#*
+
+mostlyclean: clean
+
+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
new file mode 100644
index 0000000..1b98932
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/cmds.c
@@ -0,0 +1,2117 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ */
+
+/*
+ * FTP User Program -- Command Routines.
+ */
+
+#include "ftp_locl.h"
+RCSID("$Id: cmds.c,v 1.36.2.2 2000/06/23 02:43:49 assar Exp $");
+
+typedef void (*sighand)(int);
+
+jmp_buf jabort;
+char *mname;
+char *home = "/";
+
+/*
+ * `Another' gets another argument, and stores the new argc and argv.
+ * It reverts to the top level (via main.c's intr()) on EOF/error.
+ *
+ * Returns false if no new arguments have been added.
+ */
+int
+another(int *pargc, char ***pargv, char *prompt)
+{
+ int len = strlen(line), ret;
+
+ if (len >= sizeof(line) - 3) {
+ printf("sorry, arguments too long\n");
+ intr(0);
+ }
+ printf("(%s) ", prompt);
+ line[len++] = ' ';
+ if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
+ intr(0);
+ len += strlen(&line[len]);
+ if (len > 0 && line[len - 1] == '\n')
+ line[len - 1] = '\0';
+ makeargv();
+ ret = margc > *pargc;
+ *pargc = margc;
+ *pargv = margv;
+ return (ret);
+}
+
+/*
+ * Connect to peer server and
+ * auto-login, if possible.
+ */
+void
+setpeer(int argc, char **argv)
+{
+ char *host;
+ short port;
+ struct servent *sp;
+
+ if (connected) {
+ printf("Already connected to %s, use close first.\n",
+ hostname);
+ code = -1;
+ return;
+ }
+ if (argc < 2)
+ another(&argc, &argv, "to");
+ if (argc < 2 || argc > 3) {
+ printf("usage: %s host-name [port]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ sp = getservbyname("ftp", "tcp");
+ if (sp == NULL)
+ errx(1, "You bastard. You removed ftp/tcp from services");
+ port = sp->s_port;
+ if (argc > 2) {
+ port = atoi(argv[2]);
+ if (port <= 0) {
+ printf("%s: bad port number-- %s\n", argv[1], argv[2]);
+ printf ("usage: %s host-name [port]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ port = htons(port);
+ }
+ host = hookup(argv[1], port);
+ if (host) {
+ int overbose;
+
+ connected = 1;
+ /*
+ * Set up defaults for FTP.
+ */
+ strlcpy(typename, "ascii", sizeof(typename));
+ type = TYPE_A;
+ curtype = TYPE_A;
+ strlcpy(formname, "non-print", sizeof(formname));
+ form = FORM_N;
+ strlcpy(modename, "stream", sizeof(modename));
+ mode = MODE_S;
+ strlcpy(structname, "file", sizeof(structname));
+ stru = STRU_F;
+ strlcpy(bytename, "8", sizeof(bytename));
+ bytesize = 8;
+ if (autologin)
+ login(argv[1]);
+
+#if (defined(unix) || defined(__unix__) || defined(__unix) || defined(_AIX) || defined(_CRAY)) && NBBY == 8
+/*
+ * this ifdef is to keep someone form "porting" this to an incompatible
+ * system and not checking this out. This way they have to think about it.
+ */
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+ if (command("SYST") == COMPLETE && overbose) {
+ char *cp, c;
+ cp = strchr(reply_string+4, ' ');
+ if (cp == NULL)
+ cp = strchr(reply_string+4, '\r');
+ if (cp) {
+ if (cp[-1] == '.')
+ cp--;
+ c = *cp;
+ *cp = '\0';
+ }
+
+ printf("Remote system type is %s.\n",
+ reply_string+4);
+ if (cp)
+ *cp = c;
+ }
+ if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
+ if (proxy)
+ unix_proxy = 1;
+ else
+ unix_server = 1;
+ /*
+ * Set type to 0 (not specified by user),
+ * meaning binary by default, but don't bother
+ * telling server. We can use binary
+ * for text files unless changed by the user.
+ */
+ type = 0;
+ strlcpy(typename, "binary", sizeof(typename));
+ if (overbose)
+ printf("Using %s mode to transfer files.\n",
+ typename);
+ } else {
+ if (proxy)
+ unix_proxy = 0;
+ else
+ unix_server = 0;
+ if (overbose &&
+ !strncmp(reply_string, "215 TOPS20", 10))
+ printf(
+"Remember to set tenex mode when transfering binary files from this machine.\n");
+ }
+ verbose = overbose;
+#endif /* unix */
+ }
+}
+
+struct types {
+ char *t_name;
+ char *t_mode;
+ int t_type;
+ char *t_arg;
+} types[] = {
+ { "ascii", "A", TYPE_A, 0 },
+ { "binary", "I", TYPE_I, 0 },
+ { "image", "I", TYPE_I, 0 },
+ { "ebcdic", "E", TYPE_E, 0 },
+ { "tenex", "L", TYPE_L, bytename },
+ { NULL }
+};
+
+/*
+ * Set transfer type.
+ */
+void
+settype(int argc, char **argv)
+{
+ struct types *p;
+ int comret;
+
+ if (argc > 2) {
+ char *sep;
+
+ printf("usage: %s [", argv[0]);
+ sep = " ";
+ for (p = types; p->t_name; p++) {
+ printf("%s%s", sep, p->t_name);
+ sep = " | ";
+ }
+ printf(" ]\n");
+ code = -1;
+ return;
+ }
+ if (argc < 2) {
+ printf("Using %s mode to transfer files.\n", typename);
+ code = 0;
+ return;
+ }
+ for (p = types; p->t_name; p++)
+ if (strcmp(argv[1], p->t_name) == 0)
+ break;
+ if (p->t_name == 0) {
+ printf("%s: unknown mode\n", argv[1]);
+ code = -1;
+ return;
+ }
+ if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
+ comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
+ else
+ comret = command("TYPE %s", p->t_mode);
+ if (comret == COMPLETE) {
+ strlcpy(typename, p->t_name, sizeof(typename));
+ curtype = type = p->t_type;
+ }
+}
+
+/*
+ * Internal form of settype; changes current type in use with server
+ * without changing our notion of the type for data transfers.
+ * Used to change to and from ascii for listings.
+ */
+void
+changetype(int newtype, int show)
+{
+ struct types *p;
+ int comret, oldverbose = verbose;
+
+ if (newtype == 0)
+ newtype = TYPE_I;
+ if (newtype == curtype)
+ return;
+ if (debug == 0 && show == 0)
+ verbose = 0;
+ for (p = types; p->t_name; p++)
+ if (newtype == p->t_type)
+ break;
+ if (p->t_name == 0) {
+ printf("ftp: internal error: unknown type %d\n", newtype);
+ return;
+ }
+ if (newtype == TYPE_L && bytename[0] != '\0')
+ comret = command("TYPE %s %s", p->t_mode, bytename);
+ else
+ comret = command("TYPE %s", p->t_mode);
+ if (comret == COMPLETE)
+ curtype = newtype;
+ verbose = oldverbose;
+}
+
+char *stype[] = {
+ "type",
+ "",
+ 0
+};
+
+/*
+ * Set binary transfer type.
+ */
+/*VARARGS*/
+void
+setbinary(int argc, char **argv)
+{
+
+ stype[1] = "binary";
+ settype(2, stype);
+}
+
+/*
+ * Set ascii transfer type.
+ */
+/*VARARGS*/
+void
+setascii(int argc, char **argv)
+{
+
+ stype[1] = "ascii";
+ settype(2, stype);
+}
+
+/*
+ * Set tenex transfer type.
+ */
+/*VARARGS*/
+void
+settenex(int argc, char **argv)
+{
+
+ stype[1] = "tenex";
+ settype(2, stype);
+}
+
+/*
+ * Set file transfer mode.
+ */
+/*ARGSUSED*/
+void
+setftmode(int argc, char **argv)
+{
+
+ printf("We only support %s mode, sorry.\n", modename);
+ code = -1;
+}
+
+/*
+ * Set file transfer format.
+ */
+/*ARGSUSED*/
+void
+setform(int argc, char **argv)
+{
+
+ printf("We only support %s format, sorry.\n", formname);
+ code = -1;
+}
+
+/*
+ * Set file transfer structure.
+ */
+/*ARGSUSED*/
+void
+setstruct(int argc, char **argv)
+{
+
+ printf("We only support %s structure, sorry.\n", structname);
+ code = -1;
+}
+
+/*
+ * Send a single file.
+ */
+void
+put(int argc, char **argv)
+{
+ char *cmd;
+ int loc = 0;
+ char *oldargv1, *oldargv2;
+
+ if (argc == 2) {
+ argc++;
+ argv[2] = argv[1];
+ loc++;
+ }
+ if (argc < 2 && !another(&argc, &argv, "local-file"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "remote-file")) {
+usage:
+ printf("usage: %s local-file remote-file\n", argv[0]);
+ code = -1;
+ return;
+ }
+ oldargv1 = argv[1];
+ oldargv2 = argv[2];
+ if (!globulize(&argv[1])) {
+ code = -1;
+ return;
+ }
+ /*
+ * If "globulize" modifies argv[1], and argv[2] is a copy of
+ * the old argv[1], make it a copy of the new argv[1].
+ */
+ if (argv[1] != oldargv1 && argv[2] == oldargv1) {
+ argv[2] = argv[1];
+ }
+ cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
+ if (loc && ntflag) {
+ argv[2] = dotrans(argv[2]);
+ }
+ if (loc && mapflag) {
+ argv[2] = domap(argv[2]);
+ }
+ sendrequest(cmd, argv[1], argv[2],
+ curtype == TYPE_I ? "rb" : "r",
+ argv[1] != oldargv1 || argv[2] != oldargv2);
+}
+
+/* ARGSUSED */
+static RETSIGTYPE
+mabort(int signo)
+{
+ int ointer;
+
+ printf("\n");
+ fflush(stdout);
+ if (mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", mname)) {
+ interactive = ointer;
+ longjmp(jabort,0);
+ }
+ interactive = ointer;
+ }
+ mflag = 0;
+ longjmp(jabort,0);
+}
+
+/*
+ * Send multiple files.
+ */
+void
+mput(int argc, char **argv)
+{
+ 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];
+
+ 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,
+ 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, curtype == TYPE_I ? "r+wb" : "r+w");
+}
+
+void
+get(int argc, char **argv)
+{
+ char *mode;
+
+ 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);
+}
+
+/*
+ * Receive one file.
+ */
+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")) ||
+ (argc < 3 && !another(&argc, &argv, "local-file"))) {
+ printf("usage: %s remote-file [ local-file ]\n", argv[0]);
+ code = -1;
+ return (0);
+ }
+ oldargv1 = argv[1];
+ oldargv2 = argv[2];
+ if (!globulize(&argv[2])) {
+ code = -1;
+ return (0);
+ }
+ if (loc && mcase) {
+ char *tp = argv[1], *tp2, tmpbuf[MaxPathLen];
+
+ while (*tp && !islower(*tp)) {
+ tp++;
+ }
+ if (!*tp) {
+ tp = argv[2];
+ tp2 = tmpbuf;
+ while ((*tp2 = *tp) != '\0') {
+ if (isupper(*tp2)) {
+ *tp2 = 'a' + *tp2 - 'A';
+ }
+ tp++;
+ tp2++;
+ }
+ argv[2] = tmpbuf;
+ }
+ }
+ if (loc && ntflag)
+ argv[2] = dotrans(argv[2]);
+ if (loc && mapflag)
+ argv[2] = domap(argv[2]);
+ if (restartit) {
+ struct stat stbuf;
+ int ret;
+
+ ret = stat(argv[2], &stbuf);
+ if (restartit == 1) {
+ if (ret < 0) {
+ warn("local: %s", argv[2]);
+ return (0);
+ }
+ restart_point = stbuf.st_size;
+ } else if (ret == 0) {
+ int overbose;
+ int cmdret;
+ int yy, mo, day, hour, min, sec;
+ struct tm *tm;
+ time_t mtime = stbuf.st_mtime;
+
+ 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(&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, local_given);
+ restart_point = 0;
+ return (0);
+}
+
+static int
+suspicious_filename(const char *fn)
+{
+ return strstr(fn, "../") != NULL || *fn == '/';
+}
+
+/*
+ * Get multiple files.
+ */
+void
+mget(int argc, char **argv)
+{
+ sighand oldintr;
+ int ch, ointer;
+ char *cp, *tp, *tp2, tmpbuf[MaxPathLen];
+
+ 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,proxy)) != NULL) {
+ if (*cp == '\0') {
+ mflag = 0;
+ continue;
+ }
+ if (mflag && suspicious_filename(cp))
+ printf("*** Suspicious filename: %s\n", cp);
+ if (mflag && confirm(argv[0], cp)) {
+ tp = cp;
+ if (mcase) {
+ for (tp2 = tmpbuf; (ch = *tp++);)
+ *tp2++ = isupper(ch) ? tolower(ch) : ch;
+ *tp2 = '\0';
+ tp = tmpbuf;
+ }
+ if (ntflag) {
+ tp = dotrans(tp);
+ }
+ if (mapflag) {
+ tp = domap(tp);
+ }
+ recvrequest("RETR", tp, cp,
+ curtype == TYPE_I ? "wb" : "w",
+ tp != cp || !interactive, 0);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mget")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ signal(SIGINT,oldintr);
+ mflag = 0;
+}
+
+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;
+
+ if (!mflag) {
+ if (!doglob) {
+ args = NULL;
+ }
+ else {
+ if (ftemp) {
+ fclose(ftemp);
+ ftemp = NULL;
+ }
+ }
+ return (NULL);
+ }
+ if (!doglob) {
+ if (args == NULL)
+ args = argv;
+ if ((cp = *++args) == NULL)
+ args = NULL;
+ return (cp);
+ }
+ if (ftemp == NULL) {
+ int fd;
+ strlcpy(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';
+ if(!interactive && suspicious_filename(buf)){
+ printf("Ignoring remote globbed file `%s'\n", buf);
+ continue;
+ }
+ return buf;
+ }
+ fclose(ftemp);
+ ftemp = NULL;
+ return (NULL);
+}
+
+char *
+onoff(int bool)
+{
+
+ return (bool ? "on" : "off");
+}
+
+/*
+ * Show status.
+ */
+/*ARGSUSED*/
+void
+status(int argc, char **argv)
+{
+ int i;
+
+ if (connected)
+ printf("Connected to %s.\n", hostname);
+ else
+ printf("Not connected.\n");
+ if (!proxy) {
+ pswitch(1);
+ if (connected) {
+ printf("Connected for proxy commands to %s.\n", hostname);
+ }
+ else {
+ printf("No proxy connection.\n");
+ }
+ pswitch(0);
+ }
+ sec_status();
+ printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
+ modename, typename, formname, structname);
+ printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
+ onoff(verbose), onoff(bell), onoff(interactive),
+ onoff(doglob));
+ printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
+ onoff(runique));
+ printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
+ if (ntflag) {
+ printf("Ntrans: (in) %s (out) %s\n", ntin,ntout);
+ }
+ else {
+ printf("Ntrans: off\n");
+ }
+ if (mapflag) {
+ printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
+ }
+ else {
+ printf("Nmap: off\n");
+ }
+ printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
+ onoff(hash), onoff(sendport));
+ if (macnum > 0) {
+ printf("Macros:\n");
+ for (i=0; i<macnum; i++) {
+ printf("\t%s\n",macros[i].mac_name);
+ }
+ }
+ code = 0;
+}
+
+/*
+ * Set beep on cmd completed mode.
+ */
+/*VARARGS*/
+void
+setbell(int argc, char **argv)
+{
+
+ bell = !bell;
+ printf("Bell mode %s.\n", onoff(bell));
+ code = bell;
+}
+
+/*
+ * Turn on packet tracing.
+ */
+/*VARARGS*/
+void
+settrace(int argc, char **argv)
+{
+
+ trace = !trace;
+ printf("Packet tracing %s.\n", onoff(trace));
+ code = trace;
+}
+
+/*
+ * Toggle hash mark printing during transfers.
+ */
+/*VARARGS*/
+void
+sethash(int argc, char **argv)
+{
+
+ hash = !hash;
+ printf("Hash mark printing %s", onoff(hash));
+ code = hash;
+ if (hash)
+ printf(" (%d bytes/hash mark)", 1024);
+ printf(".\n");
+}
+
+/*
+ * Turn on printing of server echo's.
+ */
+/*VARARGS*/
+void
+setverbose(int argc, char **argv)
+{
+
+ verbose = !verbose;
+ printf("Verbose mode %s.\n", onoff(verbose));
+ code = verbose;
+}
+
+/*
+ * Toggle PORT cmd use before each data connection.
+ */
+/*VARARGS*/
+void
+setport(int argc, char **argv)
+{
+
+ sendport = !sendport;
+ printf("Use of PORT cmds %s.\n", onoff(sendport));
+ code = sendport;
+}
+
+/*
+ * Turn on interactive prompting
+ * during mget, mput, and mdelete.
+ */
+/*VARARGS*/
+void
+setprompt(int argc, char **argv)
+{
+
+ interactive = !interactive;
+ printf("Interactive mode %s.\n", onoff(interactive));
+ code = interactive;
+}
+
+/*
+ * Toggle metacharacter interpretation
+ * on local file names.
+ */
+/*VARARGS*/
+void
+setglob(int argc, char **argv)
+{
+
+ doglob = !doglob;
+ printf("Globbing %s.\n", onoff(doglob));
+ code = doglob;
+}
+
+/*
+ * Set debugging mode on/off and/or
+ * set level of debugging.
+ */
+/*VARARGS*/
+void
+setdebug(int argc, char **argv)
+{
+ int val;
+
+ if (argc > 1) {
+ val = atoi(argv[1]);
+ if (val < 0) {
+ printf("%s: bad debugging value.\n", argv[1]);
+ code = -1;
+ return;
+ }
+ } else
+ val = !debug;
+ debug = val;
+ if (debug)
+ options |= SO_DEBUG;
+ else
+ options &= ~SO_DEBUG;
+ printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
+ code = debug > 0;
+}
+
+/*
+ * Set current working directory
+ * on remote machine.
+ */
+void
+cd(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "remote-directory")) {
+ printf("usage: %s remote-directory\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("CWD %s", argv[1]) == ERROR && code == 500) {
+ if (verbose)
+ printf("CWD command not recognized, trying XCWD\n");
+ command("XCWD %s", argv[1]);
+ }
+}
+
+/*
+ * Set current working directory
+ * on local machine.
+ */
+void
+lcd(int argc, char **argv)
+{
+ char buf[MaxPathLen];
+
+ if (argc < 2)
+ argc++, argv[1] = home;
+ if (argc != 2) {
+ printf("usage: %s local-directory\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (!globulize(&argv[1])) {
+ code = -1;
+ return;
+ }
+ if (chdir(argv[1]) < 0) {
+ warn("local: %s", argv[1]);
+ code = -1;
+ return;
+ }
+ if (getcwd(buf, sizeof(buf)) != NULL)
+ printf("Local directory now %s\n", buf);
+ else
+ warnx("getwd: %s", buf);
+ code = 0;
+}
+
+/*
+ * Delete a single file.
+ */
+void
+delete(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "remote-file")) {
+ printf("usage: %s remote-file\n", argv[0]);
+ code = -1;
+ return;
+ }
+ command("DELE %s", argv[1]);
+}
+
+/*
+ * Delete multiple files.
+ */
+void
+mdelete(int argc, char **argv)
+{
+ 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;
+ }
+ }
+ }
+ signal(SIGINT, oldintr);
+ mflag = 0;
+}
+
+/*
+ * Rename a remote file.
+ */
+void
+renamefile(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "from-name"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "to-name")) {
+usage:
+ printf("%s from-name to-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("RNFR %s", argv[1]) == CONTINUE)
+ command("RNTO %s", argv[2]);
+}
+
+/*
+ * Get a directory listing
+ * of remote files.
+ */
+void
+ls(int argc, char **argv)
+{
+ char *cmd;
+
+ if (argc < 2)
+ argc++, argv[1] = NULL;
+ if (argc < 3)
+ argc++, argv[2] = "-";
+ if (argc > 3) {
+ printf("usage: %s remote-directory local-file\n", argv[0]);
+ code = -1;
+ return;
+ }
+ cmd = argv[0][0] == 'n' ? "NLST" : "LIST";
+ if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
+ code = -1;
+ 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, 1);
+}
+
+/*
+ * Get a directory listing
+ * of multiple remote files.
+ */
+void
+mls(int argc, char **argv)
+{
+ sighand oldintr;
+ int ointer, i;
+ char *cmd, mode[1], *dest;
+
+ if (argc < 2 && !another(&argc, &argv, "remote-files"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+ printf("usage: %s remote-files local-file\n", argv[0]);
+ code = -1;
+ return;
+ }
+ dest = argv[argc - 1];
+ argv[argc - 1] = NULL;
+ if (strcmp(dest, "-") && *dest != '|')
+ if (!globulize(&dest) ||
+ !confirm("output to local-file:", dest)) {
+ code = -1;
+ return;
+ }
+ cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
+ mname = argv[0];
+ mflag = 1;
+ oldintr = signal(SIGINT, mabort);
+ setjmp(jabort);
+ for (i = 1; mflag && i < argc-1; ++i) {
+ *mode = (i == 1) ? 'w' : 'a';
+ recvrequest(cmd, dest, argv[i], mode, 0, 1);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", argv[0])) {
+ mflag ++;
+ }
+ interactive = ointer;
+ }
+ }
+ signal(SIGINT, oldintr);
+ mflag = 0;
+}
+
+/*
+ * Do a shell escape
+ */
+/*ARGSUSED*/
+void
+shell(int argc, char **argv)
+{
+ pid_t pid;
+ RETSIGTYPE (*old1)(), (*old2)();
+ char shellnam[40], *shell, *namep;
+ int status;
+
+ old1 = signal (SIGINT, SIG_IGN);
+ old2 = signal (SIGQUIT, SIG_IGN);
+ if ((pid = fork()) == 0) {
+ for (pid = 3; pid < 20; pid++)
+ close(pid);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ shell = getenv("SHELL");
+ if (shell == NULL)
+ shell = _PATH_BSHELL;
+ namep = strrchr(shell,'/');
+ if (namep == NULL)
+ namep = shell;
+ snprintf (shellnam, sizeof(shellnam),
+ "-%s", ++namep);
+ if (strcmp(namep, "sh") != 0)
+ shellnam[0] = '+';
+ if (debug) {
+ printf ("%s\n", shell);
+ fflush (stdout);
+ }
+ if (argc > 1) {
+ execl(shell,shellnam,"-c",altarg,(char *)0);
+ }
+ else {
+ execl(shell,shellnam,(char *)0);
+ }
+ warn("%s", shell);
+ code = -1;
+ exit(1);
+ }
+ if (pid > 0)
+ while (waitpid(-1, &status, 0) != pid)
+ ;
+ signal(SIGINT, old1);
+ signal(SIGQUIT, old2);
+ if (pid == -1) {
+ warn("%s", "Try again later");
+ code = -1;
+ }
+ else {
+ code = 0;
+ }
+}
+
+/*
+ * Send new user information (re-login)
+ */
+void
+user(int argc, char **argv)
+{
+ char acct[80];
+ int n, aflag = 0;
+ char tmp[256];
+
+ if (argc < 2)
+ another(&argc, &argv, "username");
+ if (argc < 2 || argc > 4) {
+ printf("usage: %s username [password] [account]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ n = command("USER %s", argv[1]);
+ if (n == CONTINUE) {
+ if (argc < 3 ) {
+ des_read_pw_string (tmp,
+ sizeof(tmp),
+ "Password: ", 0);
+ argv[2] = tmp;
+ argc++;
+ }
+ n = command("PASS %s", argv[2]);
+ }
+ if (n == CONTINUE) {
+ if (argc < 4) {
+ printf("Account: "); fflush(stdout);
+ fgets(acct, sizeof(acct) - 1, stdin);
+ acct[strlen(acct) - 1] = '\0';
+ argv[3] = acct; argc++;
+ }
+ n = command("ACCT %s", argv[3]);
+ aflag++;
+ }
+ if (n != COMPLETE) {
+ fprintf(stdout, "Login failed.\n");
+ return;
+ }
+ if (!aflag && argc == 4) {
+ command("ACCT %s", argv[3]);
+ }
+}
+
+/*
+ * Print working directory.
+ */
+/*VARARGS*/
+void
+pwd(int argc, char **argv)
+{
+ int oldverbose = verbose;
+
+ /*
+ * If we aren't verbose, this doesn't do anything!
+ */
+ verbose = 1;
+ if (command("PWD") == ERROR && code == 500) {
+ printf("PWD command not recognized, trying XPWD\n");
+ command("XPWD");
+ }
+ verbose = oldverbose;
+}
+
+/*
+ * Make a directory.
+ */
+void
+makedir(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+ printf("usage: %s directory-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("MKD %s", argv[1]) == ERROR && code == 500) {
+ if (verbose)
+ printf("MKD command not recognized, trying XMKD\n");
+ command("XMKD %s", argv[1]);
+ }
+}
+
+/*
+ * Remove a directory.
+ */
+void
+removedir(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+ printf("usage: %s directory-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("RMD %s", argv[1]) == ERROR && code == 500) {
+ if (verbose)
+ printf("RMD command not recognized, trying XRMD\n");
+ command("XRMD %s", argv[1]);
+ }
+}
+
+/*
+ * Send a line, verbatim, to the remote machine.
+ */
+void
+quote(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "command line to send")) {
+ printf("usage: %s line-to-send\n", argv[0]);
+ code = -1;
+ return;
+ }
+ quote1("", argc, argv);
+}
+
+/*
+ * Send a SITE command to the remote machine. The line
+ * is sent verbatim to the remote machine, except that the
+ * word "SITE" is added at the front.
+ */
+void
+site(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
+ printf("usage: %s line-to-send\n", argv[0]);
+ code = -1;
+ return;
+ }
+ quote1("SITE ", argc, argv);
+}
+
+/*
+ * Turn argv[1..argc) into a space-separated string, then prepend initial text.
+ * Send the result as a one-line command and get response.
+ */
+void
+quote1(char *initial, int argc, char **argv)
+{
+ int i;
+ char buf[BUFSIZ]; /* must be >= sizeof(line) */
+
+ strlcpy(buf, initial, sizeof(buf));
+ for(i = 1; i < argc; i++) {
+ if(i > 1)
+ strlcat(buf, " ", sizeof(buf));
+ strlcat(buf, argv[i], sizeof(buf));
+ }
+ if (command("%s", buf) == PRELIM) {
+ while (getreply(0) == PRELIM)
+ continue;
+ }
+}
+
+void
+do_chmod(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "mode"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "file-name")) {
+usage:
+ printf("usage: %s mode file-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ command("SITE CHMOD %s %s", argv[1], argv[2]);
+}
+
+void
+do_umask(int argc, char **argv)
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
+ verbose = oldverbose;
+}
+
+void
+ftp_idle(int argc, char **argv)
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
+ verbose = oldverbose;
+}
+
+/*
+ * Ask the other side for help.
+ */
+void
+rmthelp(int argc, char **argv)
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
+ verbose = oldverbose;
+}
+
+/*
+ * Terminate session and exit.
+ */
+/*VARARGS*/
+void
+quit(int argc, char **argv)
+{
+
+ if (connected)
+ disconnect(0, 0);
+ pswitch(1);
+ if (connected) {
+ disconnect(0, 0);
+ }
+ exit(0);
+}
+
+/*
+ * Terminate session, but don't exit.
+ */
+void
+disconnect(int argc, char **argv)
+{
+
+ if (!connected)
+ return;
+ command("QUIT");
+ if (cout) {
+ fclose(cout);
+ }
+ cout = NULL;
+ connected = 0;
+ sec_end();
+ data = -1;
+ if (!proxy) {
+ macnum = 0;
+ }
+}
+
+int
+confirm(char *cmd, char *file)
+{
+ char line[BUFSIZ];
+
+ if (!interactive)
+ return (1);
+ printf("%s %s? ", cmd, file);
+ fflush(stdout);
+ if (fgets(line, sizeof line, stdin) == NULL)
+ return (0);
+ return (*line == 'y' || *line == 'Y');
+}
+
+void
+fatal(char *msg)
+{
+
+ errx(1, "%s", msg);
+}
+
+/*
+ * Glob a local file name specification with
+ * the expectation of a single return value.
+ * Can't control multiple values being expanded
+ * from the expression, we return only the first.
+ */
+int
+globulize(char **cpp)
+{
+ glob_t gl;
+ int flags;
+
+ if (!doglob)
+ return (1);
+
+ flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+ memset(&gl, 0, sizeof(gl));
+ if (glob(*cpp, flags, NULL, &gl) ||
+ gl.gl_pathc == 0) {
+ warnx("%s: not found", *cpp);
+ globfree(&gl);
+ return (0);
+ }
+ *cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */
+ globfree(&gl);
+ return (1);
+}
+
+void
+account(int argc, char **argv)
+{
+ char acct[50];
+
+ if (argc > 1) {
+ ++argv;
+ --argc;
+ strlcpy (acct, *argv, sizeof(acct));
+ while (argc > 1) {
+ --argc;
+ ++argv;
+ strlcat(acct, *argv, sizeof(acct));
+ }
+ }
+ else {
+ des_read_pw_string(acct, sizeof(acct), "Account:", 0);
+ }
+ command("ACCT %s", acct);
+}
+
+jmp_buf abortprox;
+
+static RETSIGTYPE
+proxabort(int sig)
+{
+
+ if (!proxy) {
+ pswitch(1);
+ }
+ if (connected) {
+ proxflag = 1;
+ }
+ else {
+ proxflag = 0;
+ }
+ pswitch(0);
+ longjmp(abortprox,1);
+}
+
+void
+doproxy(int argc, char **argv)
+{
+ struct cmd *c;
+ RETSIGTYPE (*oldintr)();
+
+ if (argc < 2 && !another(&argc, &argv, "command")) {
+ printf("usage: %s command\n", argv[0]);
+ code = -1;
+ return;
+ }
+ c = getcmd(argv[1]);
+ if (c == (struct cmd *) -1) {
+ printf("?Ambiguous command\n");
+ fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (!c->c_proxy) {
+ printf("?Invalid proxy command\n");
+ fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (setjmp(abortprox)) {
+ code = -1;
+ return;
+ }
+ oldintr = signal(SIGINT, proxabort);
+ pswitch(1);
+ if (c->c_conn && !connected) {
+ printf("Not connected\n");
+ fflush(stdout);
+ pswitch(0);
+ signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ (*c->c_handler)(argc-1, argv+1);
+ if (connected) {
+ proxflag = 1;
+ }
+ else {
+ proxflag = 0;
+ }
+ pswitch(0);
+ signal(SIGINT, oldintr);
+}
+
+void
+setcase(int argc, char **argv)
+{
+
+ mcase = !mcase;
+ printf("Case mapping %s.\n", onoff(mcase));
+ code = mcase;
+}
+
+void
+setcr(int argc, char **argv)
+{
+
+ crflag = !crflag;
+ printf("Carriage Return stripping %s.\n", onoff(crflag));
+ code = crflag;
+}
+
+void
+setntrans(int argc, char **argv)
+{
+ if (argc == 1) {
+ ntflag = 0;
+ printf("Ntrans off.\n");
+ code = ntflag;
+ return;
+ }
+ ntflag++;
+ code = ntflag;
+ strlcpy (ntin, argv[1], 17);
+ if (argc == 2) {
+ ntout[0] = '\0';
+ return;
+ }
+ strlcpy (ntout, argv[2], 17);
+}
+
+char *
+dotrans(char *name)
+{
+ static char new[MaxPathLen];
+ char *cp1, *cp2 = new;
+ int i, ostop, found;
+
+ for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
+ continue;
+ for (cp1 = name; *cp1; cp1++) {
+ found = 0;
+ for (i = 0; *(ntin + i) && i < 16; i++) {
+ if (*cp1 == *(ntin + i)) {
+ found++;
+ if (i < ostop) {
+ *cp2++ = *(ntout + i);
+ }
+ break;
+ }
+ }
+ if (!found) {
+ *cp2++ = *cp1;
+ }
+ }
+ *cp2 = '\0';
+ return (new);
+}
+
+void
+setnmap(int argc, char **argv)
+{
+ char *cp;
+
+ if (argc == 1) {
+ mapflag = 0;
+ printf("Nmap off.\n");
+ code = mapflag;
+ return;
+ }
+ if (argc < 3 && !another(&argc, &argv, "mapout")) {
+ printf("Usage: %s [mapin mapout]\n",argv[0]);
+ code = -1;
+ return;
+ }
+ mapflag = 1;
+ code = 1;
+ cp = strchr(altarg, ' ');
+ if (proxy) {
+ while(*++cp == ' ')
+ continue;
+ altarg = cp;
+ cp = strchr(altarg, ' ');
+ }
+ *cp = '\0';
+ strlcpy(mapin, altarg, MaxPathLen);
+ while (*++cp == ' ')
+ continue;
+ strlcpy(mapout, cp, MaxPathLen);
+}
+
+char *
+domap(char *name)
+{
+ static char new[MaxPathLen];
+ char *cp1 = name, *cp2 = mapin;
+ char *tp[9], *te[9];
+ int i, toks[9], toknum = 0, match = 1;
+
+ for (i=0; i < 9; ++i) {
+ toks[i] = 0;
+ }
+ while (match && *cp1 && *cp2) {
+ switch (*cp2) {
+ case '\\':
+ if (*++cp2 != *cp1) {
+ match = 0;
+ }
+ break;
+ case '$':
+ if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
+ if (*cp1 != *(++cp2+1)) {
+ toks[toknum = *cp2 - '1']++;
+ tp[toknum] = cp1;
+ while (*++cp1 && *(cp2+1)
+ != *cp1);
+ te[toknum] = cp1;
+ }
+ cp2++;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if (*cp2 != *cp1) {
+ match = 0;
+ }
+ break;
+ }
+ if (match && *cp1) {
+ cp1++;
+ }
+ if (match && *cp2) {
+ cp2++;
+ }
+ }
+ if (!match && *cp1) /* last token mismatch */
+ {
+ toks[toknum] = 0;
+ }
+ cp1 = new;
+ *cp1 = '\0';
+ cp2 = mapout;
+ while (*cp2) {
+ match = 0;
+ switch (*cp2) {
+ case '\\':
+ if (*(cp2 + 1)) {
+ *cp1++ = *++cp2;
+ }
+ break;
+ case '[':
+LOOP:
+ if (*++cp2 == '$' && isdigit(*(cp2+1))) {
+ if (*++cp2 == '0') {
+ char *cp3 = name;
+
+ while (*cp3) {
+ *cp1++ = *cp3++;
+ }
+ match = 1;
+ }
+ else if (toks[toknum = *cp2 - '1']) {
+ char *cp3 = tp[toknum];
+
+ while (cp3 != te[toknum]) {
+ *cp1++ = *cp3++;
+ }
+ match = 1;
+ }
+ }
+ else {
+ while (*cp2 && *cp2 != ',' &&
+ *cp2 != ']') {
+ if (*cp2 == '\\') {
+ cp2++;
+ }
+ else if (*cp2 == '$' &&
+ isdigit(*(cp2+1))) {
+ if (*++cp2 == '0') {
+ char *cp3 = name;
+
+ while (*cp3) {
+ *cp1++ = *cp3++;
+ }
+ }
+ else if (toks[toknum =
+ *cp2 - '1']) {
+ char *cp3=tp[toknum];
+
+ while (cp3 !=
+ te[toknum]) {
+ *cp1++ = *cp3++;
+ }
+ }
+ }
+ else if (*cp2) {
+ *cp1++ = *cp2++;
+ }
+ }
+ if (!*cp2) {
+ printf("nmap: unbalanced brackets\n");
+ return (name);
+ }
+ match = 1;
+ cp2--;
+ }
+ if (match) {
+ while (*++cp2 && *cp2 != ']') {
+ if (*cp2 == '\\' && *(cp2 + 1)) {
+ cp2++;
+ }
+ }
+ if (!*cp2) {
+ printf("nmap: unbalanced brackets\n");
+ return (name);
+ }
+ break;
+ }
+ switch (*++cp2) {
+ case ',':
+ goto LOOP;
+ case ']':
+ break;
+ default:
+ cp2--;
+ goto LOOP;
+ }
+ break;
+ case '$':
+ if (isdigit(*(cp2 + 1))) {
+ if (*++cp2 == '0') {
+ char *cp3 = name;
+
+ while (*cp3) {
+ *cp1++ = *cp3++;
+ }
+ }
+ else if (toks[toknum = *cp2 - '1']) {
+ char *cp3 = tp[toknum];
+
+ while (cp3 != te[toknum]) {
+ *cp1++ = *cp3++;
+ }
+ }
+ break;
+ }
+ /* intentional drop through */
+ default:
+ *cp1++ = *cp2;
+ break;
+ }
+ cp2++;
+ }
+ *cp1 = '\0';
+ if (!*new) {
+ return (name);
+ }
+ return (new);
+}
+
+void
+setpassive(int argc, char **argv)
+{
+
+ passivemode = !passivemode;
+ printf("Passive mode %s.\n", onoff(passivemode));
+ code = passivemode;
+}
+
+void
+setsunique(int argc, char **argv)
+{
+
+ sunique = !sunique;
+ printf("Store unique %s.\n", onoff(sunique));
+ code = sunique;
+}
+
+void
+setrunique(int argc, char **argv)
+{
+
+ runique = !runique;
+ printf("Receive unique %s.\n", onoff(runique));
+ code = runique;
+}
+
+/* change directory to perent directory */
+void
+cdup(int argc, char **argv)
+{
+
+ if (command("CDUP") == ERROR && code == 500) {
+ if (verbose)
+ printf("CDUP command not recognized, trying XCUP\n");
+ command("XCUP");
+ }
+}
+
+/* restart transfer at specific point */
+void
+restart(int argc, char **argv)
+{
+
+ if (argc != 2)
+ printf("restart: offset not specified\n");
+ else {
+ restart_point = atol(argv[1]);
+ printf("restarting at %ld. %s\n", (long)restart_point,
+ "execute get, put or append to initiate transfer");
+ }
+}
+
+/* show remote system type */
+void
+syst(int argc, char **argv)
+{
+
+ command("SYST");
+}
+
+void
+macdef(int argc, char **argv)
+{
+ char *tmp;
+ int c;
+
+ if (macnum == 16) {
+ printf("Limit of 16 macros have already been defined\n");
+ code = -1;
+ return;
+ }
+ if (argc < 2 && !another(&argc, &argv, "macro name")) {
+ printf("Usage: %s macro_name\n",argv[0]);
+ code = -1;
+ return;
+ }
+ if (interactive) {
+ printf("Enter macro line by line, terminating it with a null line\n");
+ }
+ strlcpy(macros[macnum].mac_name,
+ argv[1],
+ sizeof(macros[macnum].mac_name));
+ 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 = getchar()) == EOF) {
+ printf("macdef:end of file encountered\n");
+ code = -1;
+ return;
+ }
+ if ((*tmp = c) == '\n') {
+ if (tmp == macros[macnum].mac_start) {
+ macros[macnum++].mac_end = tmp;
+ code = 0;
+ return;
+ }
+ if (*(tmp-1) == '\0') {
+ macros[macnum++].mac_end = tmp - 1;
+ code = 0;
+ return;
+ }
+ *tmp = '\0';
+ }
+ tmp++;
+ }
+ while (1) {
+ while ((c = getchar()) != '\n' && c != EOF)
+ /* LOOP */;
+ if (c == EOF || getchar() == '\n') {
+ printf("Macro not defined - 4k buffer exceeded\n");
+ code = -1;
+ return;
+ }
+ }
+}
+
+/*
+ * get size of file on remote machine
+ */
+void
+sizecmd(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "filename")) {
+ printf("usage: %s filename\n", argv[0]);
+ code = -1;
+ return;
+ }
+ command("SIZE %s", argv[1]);
+}
+
+/*
+ * get last modification time of file on remote machine
+ */
+void
+modtime(int argc, char **argv)
+{
+ int overbose;
+
+ if (argc < 2 && !another(&argc, &argv, "filename")) {
+ printf("usage: %s filename\n", argv[0]);
+ code = -1;
+ return;
+ }
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+ if (command("MDTM %s", argv[1]) == COMPLETE) {
+ int yy, mo, day, hour, min, sec;
+ sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
+ &day, &hour, &min, &sec);
+ /* might want to print this in local time */
+ printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
+ mo, day, yy, hour, min, sec);
+ } else
+ printf("%s\n", reply_string);
+ verbose = overbose;
+}
+
+/*
+ * show status on reomte machine
+ */
+void
+rmtstatus(int argc, char **argv)
+{
+
+ command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
+}
+
+/*
+ * get file if modtime is more recent than current file
+ */
+void
+newer(int argc, char **argv)
+{
+
+ 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
new file mode 100644
index 0000000..5dc96ef
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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 "ftp_locl.h"
+
+/*
+ * User FTP -- Command Tables.
+ */
+
+char accounthelp[] = "send account command to remote server";
+char appendhelp[] = "append to a file";
+char asciihelp[] = "set ascii transfer type";
+char beephelp[] = "beep when command completed";
+char binaryhelp[] = "set binary transfer type";
+char casehelp[] = "toggle mget upper/lower case id mapping";
+char cdhelp[] = "change remote working directory";
+char cduphelp[] = "change remote working directory to parent directory";
+char chmodhelp[] = "change file permissions of remote file";
+char connecthelp[] = "connect to remote tftp";
+char crhelp[] = "toggle carriage return stripping on ascii gets";
+char deletehelp[] = "delete remote file";
+char debughelp[] = "toggle/set debugging mode";
+char dirhelp[] = "list contents of remote directory";
+char disconhelp[] = "terminate ftp session";
+char domachelp[] = "execute macro";
+char formhelp[] = "set file transfer format";
+char globhelp[] = "toggle metacharacter expansion of local file names";
+char hashhelp[] = "toggle printing `#' for each buffer transferred";
+char helphelp[] = "print local help information";
+char idlehelp[] = "get (set) idle timer on remote side";
+char lcdhelp[] = "change local working directory";
+char lshelp[] = "list contents of remote directory";
+char macdefhelp[] = "define a macro";
+char mdeletehelp[] = "delete multiple files";
+char mdirhelp[] = "list contents of multiple remote directories";
+char mgethelp[] = "get multiple files";
+char mkdirhelp[] = "make directory on the remote machine";
+char mlshelp[] = "list contents of multiple remote directories";
+char modtimehelp[] = "show last modification time of remote file";
+char modehelp[] = "set file transfer mode";
+char mputhelp[] = "send multiple files";
+char newerhelp[] = "get file if remote file is newer than local file ";
+char nlisthelp[] = "nlist contents of remote directory";
+char nmaphelp[] = "set templates for default file name mapping";
+char ntranshelp[] = "set translation table for default file name mapping";
+char porthelp[] = "toggle use of PORT cmd for each data connection";
+char prompthelp[] = "force interactive prompting on multiple commands";
+char proxyhelp[] = "issue command on alternate connection";
+char pwdhelp[] = "print working directory on remote machine";
+char quithelp[] = "terminate ftp session and exit";
+char quotehelp[] = "send arbitrary ftp command";
+char receivehelp[] = "receive file";
+char regethelp[] = "get file restarting at end of local file";
+char remotehelp[] = "get help from remote server";
+char renamehelp[] = "rename file";
+char restarthelp[]= "restart file transfer at bytecount";
+char rmdirhelp[] = "remove directory on the remote machine";
+char rmtstatushelp[]="show status of remote machine";
+char runiquehelp[] = "toggle store unique for local files";
+char resethelp[] = "clear queued command replies";
+char sendhelp[] = "send one file";
+char passivehelp[] = "enter passive transfer mode";
+char sitehelp[] = "send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information";
+char shellhelp[] = "escape to the shell";
+char sizecmdhelp[] = "show size of remote file";
+char statushelp[] = "show current status";
+char structhelp[] = "set file transfer structure";
+char suniquehelp[] = "toggle store unique on remote machine";
+char systemhelp[] = "show remote system type";
+char tenexhelp[] = "set tenex file transfer type";
+char tracehelp[] = "toggle packet tracing";
+char typehelp[] = "set file transfer type";
+char umaskhelp[] = "get (set) umask on remote side";
+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 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 },
+ { "$", domachelp, 1, 0, 0, domacro },
+ { "account", accounthelp, 0, 1, 1, account},
+ { "append", appendhelp, 1, 1, 1, put },
+ { "ascii", asciihelp, 0, 1, 1, setascii },
+ { "bell", beephelp, 0, 0, 0, setbell },
+ { "binary", binaryhelp, 0, 1, 1, setbinary },
+ { "bye", quithelp, 0, 0, 0, quit },
+ { "case", casehelp, 0, 0, 1, setcase },
+ { "cd", cdhelp, 0, 1, 1, cd },
+ { "cdup", cduphelp, 0, 1, 1, cdup },
+ { "chmod", chmodhelp, 0, 1, 1, do_chmod },
+ { "close", disconhelp, 0, 1, 1, disconnect },
+ { "cr", crhelp, 0, 0, 0, setcr },
+ { "delete", deletehelp, 0, 1, 1, delete },
+ { "debug", debughelp, 0, 0, 0, setdebug },
+ { "dir", dirhelp, 1, 1, 1, ls },
+ { "disconnect", disconhelp, 0, 1, 1, disconnect },
+ { "form", formhelp, 0, 1, 1, setform },
+ { "get", receivehelp, 1, 1, 1, get },
+ { "glob", globhelp, 0, 0, 0, setglob },
+ { "hash", hashhelp, 0, 0, 0, sethash },
+ { "help", helphelp, 0, 0, 1, help },
+ { "idle", idlehelp, 0, 1, 1, ftp_idle },
+ { "image", binaryhelp, 0, 1, 1, setbinary },
+ { "lcd", lcdhelp, 0, 0, 0, lcd },
+ { "ls", lshelp, 1, 1, 1, ls },
+ { "macdef", macdefhelp, 0, 0, 0, macdef },
+ { "mdelete", mdeletehelp, 1, 1, 1, mdelete },
+ { "mdir", mdirhelp, 1, 1, 1, mls },
+ { "mget", mgethelp, 1, 1, 1, mget },
+ { "mkdir", mkdirhelp, 0, 1, 1, makedir },
+ { "mls", mlshelp, 1, 1, 1, mls },
+ { "mode", modehelp, 0, 1, 1, setftmode },
+ { "modtime", modtimehelp, 0, 1, 1, modtime },
+ { "mput", mputhelp, 1, 1, 1, mput },
+ { "newer", newerhelp, 1, 1, 1, newer },
+ { "nmap", nmaphelp, 0, 0, 1, setnmap },
+ { "nlist", nlisthelp, 1, 1, 1, ls },
+ { "ntrans", ntranshelp, 0, 0, 1, setntrans },
+ { "open", connecthelp, 0, 0, 1, setpeer },
+ { "passive", passivehelp, 0, 0, 0, setpassive },
+ { "prompt", prompthelp, 0, 0, 0, setprompt },
+ { "proxy", proxyhelp, 0, 0, 1, doproxy },
+ { "sendport", porthelp, 0, 0, 0, setport },
+ { "put", sendhelp, 1, 1, 1, put },
+ { "pwd", pwdhelp, 0, 1, 1, pwd },
+ { "quit", quithelp, 0, 0, 0, quit },
+ { "quote", quotehelp, 1, 1, 1, quote },
+ { "recv", receivehelp, 1, 1, 1, get },
+ { "reget", regethelp, 1, 1, 1, reget },
+ { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus },
+ { "rhelp", remotehelp, 0, 1, 1, rmthelp },
+ { "rename", renamehelp, 0, 1, 1, renamefile },
+ { "reset", resethelp, 0, 1, 1, reset },
+ { "restart", restarthelp, 1, 1, 1, restart },
+ { "rmdir", rmdirhelp, 0, 1, 1, removedir },
+ { "runique", runiquehelp, 0, 0, 1, setrunique },
+ { "send", sendhelp, 1, 1, 1, put },
+ { "site", sitehelp, 0, 1, 1, site },
+ { "size", sizecmdhelp, 1, 1, 1, sizecmd },
+ { "status", statushelp, 0, 0, 1, status },
+ { "struct", structhelp, 0, 1, 1, setstruct },
+ { "system", systemhelp, 0, 1, 1, syst },
+ { "sunique", suniquehelp, 0, 0, 1, setsunique },
+ { "tenex", tenexhelp, 0, 1, 1, settenex },
+ { "trace", tracehelp, 0, 0, 0, settrace },
+ { "type", typehelp, 0, 1, 1, settype },
+ { "user", userhelp, 0, 1, 1, user },
+ { "umask", umaskhelp, 0, 1, 1, do_umask },
+ { "verbose", verbosehelp, 0, 0, 0, setverbose },
+ { "?", 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 },
+};
+
+int NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1;
diff --git a/crypto/kerberosIV/appl/ftp/ftp/domacro.c b/crypto/kerberosIV/appl/ftp/ftp/domacro.c
new file mode 100644
index 0000000..d91660d
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/domacro.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1985, 1993, 1994
+ * 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 "ftp_locl.h"
+RCSID("$Id: domacro.c,v 1.7 1999/09/16 20:37:29 assar Exp $");
+
+void
+domacro(int argc, char **argv)
+{
+ int i, j, count = 2, loopflg = 0;
+ char *cp1, *cp2, line2[200];
+ struct cmd *c;
+
+ if (argc < 2 && !another(&argc, &argv, "macro name")) {
+ printf("Usage: %s macro_name.\n", argv[0]);
+ code = -1;
+ return;
+ }
+ for (i = 0; i < macnum; ++i) {
+ if (!strncmp(argv[1], macros[i].mac_name, 9)) {
+ break;
+ }
+ }
+ if (i == macnum) {
+ printf("'%s' macro not found.\n", argv[1]);
+ code = -1;
+ return;
+ }
+ strlcpy(line2, line, sizeof(line2));
+TOP:
+ cp1 = macros[i].mac_start;
+ while (cp1 != macros[i].mac_end) {
+ while (isspace(*cp1)) {
+ cp1++;
+ }
+ cp2 = line;
+ while (*cp1 != '\0') {
+ switch(*cp1) {
+ case '\\':
+ *cp2++ = *++cp1;
+ break;
+ case '$':
+ if (isdigit(*(cp1+1))) {
+ j = 0;
+ while (isdigit(*++cp1)) {
+ j = 10*j + *cp1 - '0';
+ }
+ cp1--;
+ if (argc - 2 >= j) {
+ strcpy(cp2, argv[j+1]);
+ cp2 += strlen(argv[j+1]);
+ }
+ break;
+ }
+ if (*(cp1+1) == 'i') {
+ loopflg = 1;
+ cp1++;
+ if (count < argc) {
+ strcpy(cp2, argv[count]);
+ cp2 += strlen(argv[count]);
+ }
+ break;
+ }
+ /* intentional drop through */
+ default:
+ *cp2++ = *cp1;
+ break;
+ }
+ if (*cp1 != '\0') {
+ cp1++;
+ }
+ }
+ *cp2 = '\0';
+ makeargv();
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ code = -1;
+ }
+ else if (c == 0) {
+ printf("?Invalid command\n");
+ code = -1;
+ }
+ else if (c->c_conn && !connected) {
+ printf("Not connected.\n");
+ code = -1;
+ }
+ else {
+ if (verbose) {
+ printf("%s\n",line);
+ }
+ (*c->c_handler)(margc, margv);
+ if (bell && c->c_bell) {
+ putchar('\007');
+ }
+ strcpy(line, line2);
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if (cp1 != macros[i].mac_end) {
+ cp1++;
+ }
+ }
+ if (loopflg && ++count < argc) {
+ goto TOP;
+ }
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/extern.h b/crypto/kerberosIV/appl/ftp/ftp/extern.h
new file mode 100644
index 0000000..d488ecd
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/extern.h
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 1994 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 10/9/94
+ */
+
+/* $Id: extern.h,v 1.18 1999/10/28 20:49:10 assar Exp $ */
+
+#include <setjmp.h>
+#include <stdlib.h>
+#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_SELECT_H
+#include <sys/select.h>
+#endif
+
+void abort_remote (FILE *);
+void abortpt (int);
+void abortrecv (int);
+void account (int, char **);
+int another (int *, char ***, char *);
+void blkfree (char **);
+void cd (int, char **);
+void cdup (int, char **);
+void changetype (int, int);
+void cmdabort (int);
+void cmdscanner (int);
+int command (char *fmt, ...);
+int confirm (char *, char *);
+FILE *dataconn (const char *);
+void delete (int, char **);
+void disconnect (int, char **);
+void do_chmod (int, char **);
+void do_umask (int, char **);
+void domacro (int, char **);
+char *domap (char *);
+void doproxy (int, char **);
+char *dotrans (char *);
+int empty (fd_set *, int);
+void fatal (char *);
+void get (int, char **);
+struct cmd *getcmd (char *);
+int getit (int, char **, int, char *);
+int getreply (int);
+int globulize (char **);
+char *gunique (char *);
+void help (int, char **);
+char *hookup (const char *, int);
+void ftp_idle (int, char **);
+int initconn (void);
+void intr (int);
+void lcd (int, char **);
+int login (char *);
+RETSIGTYPE lostpeer (int);
+void ls (int, char **);
+void macdef (int, char **);
+void makeargv (void);
+void makedir (int, char **);
+void mdelete (int, char **);
+void mget (int, char **);
+void mls (int, char **);
+void modtime (int, char **);
+void mput (int, char **);
+char *onoff (int);
+void newer (int, char **);
+void proxtrans (char *, char *, char *);
+void psabort (int);
+void pswitch (int);
+void ptransfer (char *, long, struct timeval *, struct timeval *);
+void put (int, char **);
+void pwd (int, char **);
+void quit (int, char **);
+void quote (int, char **);
+void quote1 (char *, int, char **);
+void recvrequest (char *, char *, char *, char *, int, int);
+void reget (int, char **);
+char *remglob (char **, int);
+void removedir (int, char **);
+void renamefile (int, char **);
+void reset (int, char **);
+void restart (int, char **);
+void rmthelp (int, char **);
+void rmtstatus (int, char **);
+int ruserpass (char *, char **, char **, char **);
+void sendrequest (char *, char *, char *, char *, int);
+void setascii (int, char **);
+void setbell (int, char **);
+void setbinary (int, char **);
+void setcase (int, char **);
+void setcr (int, char **);
+void setdebug (int, char **);
+void setform (int, char **);
+void setftmode (int, char **);
+void setglob (int, char **);
+void sethash (int, char **);
+void setnmap (int, char **);
+void setntrans (int, char **);
+void setpassive (int, char **);
+void setpeer (int, char **);
+void setport (int, char **);
+void setprompt (int, char **);
+void setrunique (int, char **);
+void setstruct (int, char **);
+void setsunique (int, char **);
+void settenex (int, char **);
+void settrace (int, char **);
+void settype (int, char **);
+void setverbose (int, char **);
+void shell (int, char **);
+void site (int, char **);
+void sizecmd (int, char **);
+char *slurpstring (void);
+void status (int, char **);
+void syst (int, char **);
+void tvsub (struct timeval *, struct timeval *, struct timeval *);
+void user (int, char **);
+
+extern jmp_buf abortprox;
+extern int abrtflag;
+extern struct cmd cmdtab[];
+extern FILE *cout;
+extern int data;
+extern char *home;
+extern jmp_buf jabort;
+extern int proxy;
+extern char reply_string[];
+extern off_t restart_point;
+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
new file mode 100644
index 0000000..848debd
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/ftp.c
@@ -0,0 +1,1752 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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 "ftp_locl.h"
+RCSID ("$Id: ftp.c,v 1.60.2.1 2000/06/23 02:45:40 assar Exp $");
+
+struct sockaddr_storage hisctladdr_ss;
+struct sockaddr *hisctladdr = (struct sockaddr *)&hisctladdr_ss;
+struct sockaddr_storage data_addr_ss;
+struct sockaddr *data_addr = (struct sockaddr *)&data_addr_ss;
+struct sockaddr_storage myctladdr_ss;
+struct sockaddr *myctladdr = (struct sockaddr *)&myctladdr_ss;
+int data = -1;
+int abrtflag = 0;
+jmp_buf ptabort;
+int ptabflg;
+int ptflag = 0;
+off_t restart_point = 0;
+
+
+FILE *cin, *cout;
+
+typedef void (*sighand) (int);
+
+char *
+hookup (const char *host, int port)
+{
+ struct hostent *hp = NULL;
+ int s, len;
+ static char hostnamebuf[MaxHostNameLen];
+ int error;
+ int af;
+ char **h;
+ int ret;
+
+#ifdef HAVE_IPV6
+ if (hp == NULL)
+ hp = getipnodebyname (host, AF_INET6, 0, &error);
+#endif
+ if (hp == NULL)
+ hp = getipnodebyname (host, AF_INET, 0, &error);
+
+ if (hp == NULL) {
+ warnx ("%s: %s", host, hstrerror(error));
+ code = -1;
+ return NULL;
+ }
+ strlcpy (hostnamebuf, hp->h_name, sizeof(hostnamebuf));
+ hostname = hostnamebuf;
+ af = hisctladdr->sa_family = hp->h_addrtype;
+
+ for (h = hp->h_addr_list;
+ *h != NULL;
+ ++h) {
+
+ s = socket (af, SOCK_STREAM, 0);
+ if (s < 0) {
+ warn ("socket");
+ code = -1;
+ freehostent (hp);
+ return (0);
+ }
+
+ socket_set_address_and_port (hisctladdr, *h, port);
+
+ ret = connect (s, hisctladdr, socket_sockaddr_size(hisctladdr));
+ if (ret < 0) {
+ char addr[256];
+
+ if (inet_ntop (af, socket_get_address(hisctladdr),
+ addr, sizeof(addr)) == NULL)
+ strlcpy (addr, "unknown address",
+ sizeof(addr));
+ warn ("connect %s", addr);
+ close (s);
+ continue;
+ }
+ break;
+ }
+ freehostent (hp);
+ if (ret < 0) {
+ code = -1;
+ close (s);
+ return NULL;
+ }
+
+ len = sizeof(myctladdr_ss);
+ if (getsockname (s, myctladdr, &len) < 0) {
+ warn ("getsockname");
+ code = -1;
+ close (s);
+ return NULL;
+ }
+#ifdef IPTOS_LOWDELAY
+ socket_set_tos (s, IPTOS_LOWDELAY);
+#endif
+ cin = fdopen (s, "r");
+ cout = fdopen (s, "w");
+ if (cin == NULL || cout == NULL) {
+ warnx ("fdopen failed.");
+ if (cin)
+ fclose (cin);
+ if (cout)
+ fclose (cout);
+ code = -1;
+ goto bad;
+ }
+ if (verbose)
+ printf ("Connected to %s.\n", hostname);
+ if (getreply (0) > 2) { /* read startup message from server */
+ if (cin)
+ fclose (cin);
+ if (cout)
+ fclose (cout);
+ code = -1;
+ goto bad;
+ }
+#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
+ {
+ int on = 1;
+
+ if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on))
+ < 0 && debug) {
+ warn ("setsockopt");
+ }
+ }
+#endif /* SO_OOBINLINE */
+
+ return (hostname);
+bad:
+ close (s);
+ return NULL;
+}
+
+int
+login (char *host)
+{
+ char tmp[80];
+ char defaultpass[128];
+ char *user, *pass, *acct;
+ int n, aflag = 0;
+
+ char *myname = NULL;
+ struct passwd *pw = k_getpwuid(getuid());
+
+ if (pw != NULL)
+ myname = pw->pw_name;
+
+ user = pass = acct = 0;
+
+ if(sec_login(host))
+ printf("\n*** Using plaintext user and password ***\n\n");
+ else{
+ printf("Authentication successful.\n\n");
+ }
+
+ if (ruserpass (host, &user, &pass, &acct) < 0) {
+ code = -1;
+ return (0);
+ }
+ while (user == NULL) {
+ if (myname)
+ printf ("Name (%s:%s): ", host, myname);
+ else
+ printf ("Name (%s): ", host);
+ *tmp = '\0';
+ if (fgets (tmp, sizeof (tmp) - 1, stdin) != NULL)
+ tmp[strlen (tmp) - 1] = '\0';
+ if (*tmp == '\0')
+ user = myname;
+ else
+ user = tmp;
+ }
+ strlcpy(username, user, sizeof(username));
+ n = command("USER %s", user);
+ if (n == CONTINUE) {
+ 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);
+ } else if (sec_complete) {
+ pass = myname;
+ } else {
+ *defaultpass = '\0';
+ snprintf(prompt, sizeof(prompt), "Password: ");
+ }
+ if (pass == NULL) {
+ pass = defaultpass;
+ des_read_pw_string (tmp, sizeof (tmp), prompt, 0);
+ if (tmp[0])
+ pass = tmp;
+ }
+ }
+ n = command ("PASS %s", pass);
+ }
+ if (n == CONTINUE) {
+ aflag++;
+ acct = tmp;
+ des_read_pw_string (acct, 128, "Account:", 0);
+ n = command ("ACCT %s", acct);
+ }
+ if (n != COMPLETE) {
+ warnx ("Login failed.");
+ return (0);
+ }
+ if (!aflag && acct != NULL)
+ command ("ACCT %s", acct);
+ if (proxy)
+ return (1);
+ for (n = 0; n < macnum; ++n) {
+ if (!strcmp("init", macros[n].mac_name)) {
+ strlcpy (line, "$init", sizeof (line));
+ makeargv();
+ domacro(margc, margv);
+ break;
+ }
+ }
+ sec_set_protection_level ();
+ return (1);
+}
+
+void
+cmdabort (int sig)
+{
+
+ printf ("\n");
+ fflush (stdout);
+ abrtflag++;
+ if (ptflag)
+ longjmp (ptabort, 1);
+}
+
+int
+command (char *fmt,...)
+{
+ va_list ap;
+ int r;
+ sighand oldintr;
+
+ abrtflag = 0;
+ if (cout == NULL) {
+ warn ("No control connection for command");
+ code = -1;
+ return (0);
+ }
+ oldintr = signal(SIGINT, cmdabort);
+ va_start(ap, fmt);
+ if(debug){
+ printf("---> ");
+ if (strncmp("PASS ", fmt, 5) == 0)
+ printf("PASS XXXX");
+ else
+ vfprintf(stdout, fmt, ap);
+ va_start(ap, fmt);
+ }
+ sec_vfprintf(cout, fmt, ap);
+ va_end(ap);
+ if(debug){
+ printf("\n");
+ fflush(stdout);
+ }
+ fprintf (cout, "\r\n");
+ fflush (cout);
+ cpend = 1;
+ r = getreply (!strcmp (fmt, "QUIT"));
+ if (abrtflag && oldintr != SIG_IGN)
+ (*oldintr) (SIGINT);
+ signal (SIGINT, oldintr);
+ return (r);
+}
+
+char reply_string[BUFSIZ]; /* last line of previous reply */
+
+int
+getreply (int expecteof)
+{
+ char *p;
+ char *lead_string;
+ int c;
+ struct sigaction sa, osa;
+ char buf[1024];
+
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = cmdabort;
+ sigaction (SIGINT, &sa, &osa);
+
+ p = buf;
+
+ while (1) {
+ c = getc (cin);
+ switch (c) {
+ case EOF:
+ if (expecteof) {
+ sigaction (SIGINT, &osa, NULL);
+ code = 221;
+ return 0;
+ }
+ lostpeer (0);
+ if (verbose) {
+ printf ("421 Service not available, "
+ "remote server has closed connection\n");
+ fflush (stdout);
+ }
+ code = 421;
+ return (4);
+ 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));
+ continue;
+ case '\n':
+ *p++ = '\0';
+ if(isdigit(buf[0])){
+ sscanf(buf, "%d", &code);
+ if(code == 631){
+ sec_read_msg(buf, prot_safe);
+ sscanf(buf, "%d", &code);
+ lead_string = "S:";
+ } else if(code == 632){
+ sec_read_msg(buf, prot_private);
+ sscanf(buf, "%d", &code);
+ lead_string = "P:";
+ }else if(code == 633){
+ 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 (code >= 200)
+ cpend = 0;
+ sigaction (SIGINT, &osa, NULL);
+ if (code == 421)
+ lostpeer (0);
+#if 1
+ if (abrtflag &&
+ osa.sa_handler != cmdabort &&
+ osa.sa_handler != SIG_IGN)
+ osa.sa_handler (SIGINT);
+#endif
+ if (code == 227 || code == 229) {
+ char *p, *q;
+
+ pasv[0] = 0;
+ p = strchr (reply_string, '(');
+ if (p) {
+ p++;
+ q = strchr(p, ')');
+ if(q){
+ memcpy (pasv, p, q - p);
+ pasv[q - p] = 0;
+ }
+ }
+ }
+ return code / 100;
+ }
+ }else{
+ if(verbose > 0 || (verbose > -1 && code > 499)){
+ if(sec_complete)
+ fprintf(stdout, "!!");
+ fprintf(stdout, "%s\n", buf);
+ }
+ }
+ p = buf;
+ continue;
+ default:
+ *p++ = c;
+ }
+ }
+
+}
+
+
+#if 0
+int
+getreply (int expecteof)
+{
+ int c, n;
+ int dig;
+ int originalcode = 0, continuation = 0;
+ sighand oldintr;
+ int pflag = 0;
+ char *cp, *pt = pasv;
+
+ 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)) {
+ case WILL:
+ case WONT:
+ 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);
+ break;
+ default:
+ break;
+ }
+ continue;
+ }
+ dig++;
+ if (c == EOF) {
+ if (expecteof) {
+ signal (SIGINT, oldintr);
+ code = 221;
+ return (0);
+ }
+ lostpeer (0);
+ if (verbose) {
+ printf ("421 Service not available, remote server has closed connection\n");
+ fflush (stdout);
+ }
+ code = 421;
+ return (4);
+ }
+ if (c != '\r' && (verbose > 0 ||
+ (verbose > -1 && n == '5' && dig > 4))) {
+ if (proxflag &&
+ (dig == 1 || dig == 5 && verbose == 0))
+ printf ("%s:", hostname);
+ putchar (c);
+ }
+ if (dig < 4 && isdigit (c))
+ code = code * 10 + (c - '0');
+ if (!pflag && code == 227)
+ pflag = 1;
+ if (dig > 4 && pflag == 1 && isdigit (c))
+ pflag = 2;
+ if (pflag == 2) {
+ if (c != '\r' && c != ')')
+ *pt++ = c;
+ else {
+ *pt = '\0';
+ pflag = 3;
+ }
+ }
+ if (dig == 4 && c == '-') {
+ if (continuation)
+ code = 0;
+ continuation++;
+ }
+ if (n == 0)
+ n = c;
+ if (cp < &reply_string[sizeof (reply_string) - 1])
+ *cp++ = c;
+ }
+ if (verbose > 0 || verbose > -1 && n == '5') {
+ putchar (c);
+ fflush (stdout);
+ }
+ if (continuation && code != originalcode) {
+ if (originalcode == 0)
+ originalcode = code;
+ continue;
+ }
+ *cp = '\0';
+ if(sec_complete){
+ if(code == 631)
+ 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);
+ if (code == 421 || originalcode == 421)
+ lostpeer (0);
+ if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
+ (*oldintr) (SIGINT);
+ return (n - '0');
+ }
+}
+
+#endif
+
+int
+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));
+}
+
+jmp_buf sendabort;
+
+static RETSIGTYPE
+abortsend (int sig)
+{
+
+ mflag = 0;
+ abrtflag = 0;
+ 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)
+{
+ static size_t bufsize;
+ static char *buf;
+ int n;
+ int bytes = 0;
+ int werr = 0;
+ int hashbytes = HASHBYTES;
+ struct stat st;
+
+#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)) {
+ /*
+ * mmap zero bytes has potential of loosing, don't do it.
+ */
+ if (st.st_size == 0)
+ return 0;
+ 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)
+ warn ("munmap");
+ sec_fflush (to);
+ return res;
+ }
+ }
+#endif
+
+ buf = alloc_buffer (buf, &bufsize,
+ 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)
+ break;
+ bytes += werr;
+ while (hash && bytes > hashbytes) {
+ putchar ('#');
+ hashbytes += HASHBYTES;
+ }
+ }
+ sec_fflush (to);
+ if (n < 0)
+ warn ("local");
+
+ if (werr < 0) {
+ if (errno != EPIPE)
+ warn ("netout");
+ bytes = -1;
+ }
+ return bytes;
+}
+
+void
+sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
+{
+ struct stat st;
+ struct timeval start, stop;
+ int c, d;
+ FILE *fin, *dout = 0;
+ int (*closefunc) (FILE *);
+ RETSIGTYPE (*oldintr)(), (*oldintp)();
+ long bytes = 0, hashbytes = HASHBYTES;
+ char *rmode = "w";
+
+ if (verbose && printnames) {
+ if (local && strcmp (local, "-") != 0)
+ printf ("local: %s ", local);
+ if (remote)
+ printf ("remote: %s\n", remote);
+ }
+ if (proxy) {
+ proxtrans (cmd, local, remote);
+ return;
+ }
+ if (curtype != type)
+ changetype (type, 0);
+ closefunc = NULL;
+ oldintr = NULL;
+ oldintp = NULL;
+
+ if (setjmp (sendabort)) {
+ while (cpend) {
+ getreply (0);
+ }
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (oldintr)
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ code = -1;
+ return;
+ }
+ oldintr = signal (SIGINT, abortsend);
+ if (strcmp (local, "-") == 0)
+ fin = stdin;
+ else if (*local == '|') {
+ oldintp = signal (SIGPIPE, SIG_IGN);
+ fin = popen (local + 1, lmode);
+ if (fin == NULL) {
+ warn ("%s", local + 1);
+ signal (SIGINT, oldintr);
+ signal (SIGPIPE, oldintp);
+ code = -1;
+ return;
+ }
+ closefunc = pclose;
+ } else {
+ fin = fopen (local, lmode);
+ if (fin == NULL) {
+ 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);
+ code = -1;
+ return;
+ }
+ }
+ if (initconn ()) {
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ code = -1;
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ return;
+ }
+ if (setjmp (sendabort))
+ goto abort;
+
+ if (restart_point &&
+ (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) {
+ int rc;
+
+ switch (curtype) {
+ case TYPE_A:
+ rc = fseek (fin, (long) restart_point, SEEK_SET);
+ break;
+ case TYPE_I:
+ case TYPE_L:
+ rc = lseek (fileno (fin), restart_point, SEEK_SET);
+ break;
+ }
+ if (rc < 0) {
+ warn ("local: %s", local);
+ restart_point = 0;
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ return;
+ }
+ if (command ("REST %ld", (long) restart_point)
+ != CONTINUE) {
+ restart_point = 0;
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ return;
+ }
+ restart_point = 0;
+ rmode = "r+w";
+ }
+ if (remote) {
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ return;
+ }
+ } else if (command ("%s", cmd) != PRELIM) {
+ signal(SIGINT, oldintr);
+ if (oldintp)
+ signal(SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ return;
+ }
+ dout = dataconn(rmode);
+ if (dout == NULL)
+ goto abort;
+ 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);
+ break;
+
+ case TYPE_A:
+ while ((c = getc (fin)) != EOF) {
+ if (c == '\n') {
+ while (hash && (bytes >= hashbytes)) {
+ putchar ('#');
+ fflush (stdout);
+ hashbytes += HASHBYTES;
+ }
+ if (ferror (dout))
+ break;
+ sec_putc ('\r', dout);
+ bytes++;
+ }
+ sec_putc (c, dout);
+ bytes++;
+ }
+ sec_fflush (dout);
+ if (hash) {
+ if (bytes < hashbytes)
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
+ }
+ if (ferror (fin))
+ warn ("local: %s", local);
+ if (ferror (dout)) {
+ if (errno != EPIPE)
+ warn ("netout");
+ bytes = -1;
+ }
+ break;
+ }
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ fclose (dout);
+ gettimeofday (&stop, (struct timezone *) 0);
+ getreply (0);
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ if (bytes > 0)
+ ptransfer ("sent", bytes, &start, &stop);
+ return;
+abort:
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ if (!cpend) {
+ code = -1;
+ return;
+ }
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (dout)
+ fclose (dout);
+ getreply (0);
+ code = -1;
+ if (closefunc != NULL && fin != NULL)
+ (*closefunc) (fin);
+ gettimeofday (&stop, (struct timezone *) 0);
+ if (bytes > 0)
+ ptransfer ("sent", bytes, &start, &stop);
+}
+
+jmp_buf recvabort;
+
+void
+abortrecv (int sig)
+{
+
+ mflag = 0;
+ abrtflag = 0;
+ 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, int local_given)
+{
+ FILE *fout, *din = 0;
+ int (*closefunc) (FILE *);
+ sighand oldintr, oldintp;
+ int c, d, is_retr, tcrflag, bare_lfs = 0;
+ static size_t bufsize;
+ static char *buf;
+ long bytes = 0, hashbytes = HASHBYTES;
+ struct timeval start, stop;
+ struct stat st;
+
+ is_retr = strcmp (cmd, "RETR") == 0;
+ if (is_retr && verbose && printnames) {
+ if (local && strcmp (local, "-") != 0)
+ printf ("local: %s ", local);
+ if (remote)
+ printf ("remote: %s\n", remote);
+ }
+ if (proxy && is_retr) {
+ proxtrans (cmd, local, remote);
+ return;
+ }
+ closefunc = NULL;
+ oldintr = NULL;
+ oldintp = NULL;
+ tcrflag = !crflag && is_retr;
+ if (setjmp (recvabort)) {
+ while (cpend) {
+ getreply (0);
+ }
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (oldintr)
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ 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);
+ code = -1;
+ return;
+ }
+ if (dir != NULL)
+ *dir = 0;
+ d = access (dir ? local : ".", 2);
+ if (dir != NULL)
+ *dir = '/';
+ if (d < 0) {
+ 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);
+ code = -1;
+ return;
+ }
+ if (runique && errno == EACCES &&
+ (local = gunique (local)) == NULL) {
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ } else if (runique && (local = gunique (local)) == NULL) {
+ signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ }
+ if (!is_retr) {
+ if (curtype != TYPE_A)
+ changetype (TYPE_A, 0);
+ } else if (curtype != type)
+ changetype (type, 0);
+ if (initconn ()) {
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (setjmp (recvabort))
+ goto abort;
+ if (is_retr && restart_point &&
+ command ("REST %ld", (long) restart_point) != CONTINUE)
+ return;
+ if (remote) {
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
+ return;
+ }
+ } else {
+ if (command ("%s", cmd) != PRELIM) {
+ signal (SIGINT, oldintr);
+ return;
+ }
+ }
+ din = dataconn ("r");
+ if (din == NULL)
+ goto abort;
+ set_buffer_size (fileno (din), 1);
+ if (local_given && strcmp (local, "-") == 0)
+ fout = stdout;
+ else if (local_given && *local == '|') {
+ oldintp = signal (SIGPIPE, SIG_IGN);
+ fout = popen (local + 1, "w");
+ if (fout == NULL) {
+ warn ("%s", local + 1);
+ goto abort;
+ }
+ closefunc = pclose;
+ } else {
+ fout = fopen (local, lmode);
+ if (fout == NULL) {
+ warn ("local: %s", local);
+ goto abort;
+ }
+ closefunc = fclose;
+ }
+ buf = alloc_buffer (buf, &bufsize,
+ fstat (fileno (fout), &st) >= 0 ? &st : NULL);
+ if (buf == NULL)
+ goto abort;
+
+ 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);
+ if (closefunc != NULL)
+ (*closefunc) (fout);
+ return;
+ }
+ errno = d = 0;
+ 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 ('#');
+ hashbytes += HASHBYTES;
+ }
+ fflush (stdout);
+ }
+ }
+ if (hash && bytes > 0) {
+ if (bytes < HASHBYTES)
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
+ }
+ if (c < 0) {
+ if (errno != EPIPE)
+ warn ("netin");
+ bytes = -1;
+ }
+ if (d < c) {
+ if (d < 0)
+ warn ("local: %s", local);
+ else
+ warnx ("%s: short write", local);
+ }
+ break;
+
+ case TYPE_A:
+ if (restart_point) {
+ int i, n, ch;
+
+ if (fseek (fout, 0L, SEEK_SET) < 0)
+ goto done;
+ n = restart_point;
+ for (i = 0; i++ < n;) {
+ 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 (closefunc != NULL)
+ (*closefunc) (fout);
+ return;
+ }
+ }
+ while ((c = sec_getc(din)) != EOF) {
+ if (c == '\n')
+ bare_lfs++;
+ while (c == '\r') {
+ while (hash && (bytes >= hashbytes)) {
+ putchar ('#');
+ fflush (stdout);
+ hashbytes += HASHBYTES;
+ }
+ bytes++;
+ if ((c = sec_getc (din)) != '\n' || tcrflag) {
+ if (ferror (fout))
+ goto break2;
+ putc ('\r', fout);
+ if (c == '\0') {
+ bytes++;
+ goto contin2;
+ }
+ if (c == EOF)
+ goto contin2;
+ }
+ }
+ putc (c, fout);
+ bytes++;
+ contin2:;
+ }
+break2:
+ if (bare_lfs) {
+ 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);
+ }
+ if (ferror (din)) {
+ if (errno != EPIPE)
+ warn ("netin");
+ bytes = -1;
+ }
+ if (ferror (fout))
+ warn ("local: %s", local);
+ break;
+ }
+ if (closefunc != NULL)
+ (*closefunc) (fout);
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ fclose (din);
+ gettimeofday (&stop, (struct timezone *) 0);
+ getreply (0);
+ if (bytes > 0 && is_retr)
+ ptransfer ("received", bytes, &start, &stop);
+ return;
+abort:
+
+ /* abort using RFC959 recommended IP,SYNC sequence */
+
+ if (oldintp)
+ signal (SIGPIPE, oldintr);
+ signal (SIGINT, SIG_IGN);
+ if (!cpend) {
+ code = -1;
+ signal (SIGINT, oldintr);
+ return;
+ }
+ abort_remote(din);
+ code = -1;
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (closefunc != NULL && fout != NULL)
+ (*closefunc) (fout);
+ if (din)
+ fclose (din);
+ gettimeofday (&stop, (struct timezone *) 0);
+ if (bytes > 0)
+ ptransfer ("received", bytes, &start, &stop);
+ signal (SIGINT, oldintr);
+}
+
+static int
+parse_epsv (const char *str)
+{
+ char sep;
+ char *end;
+ int port;
+
+ if (*str == '\0')
+ return -1;
+ sep = *str++;
+ if (sep != *str++)
+ return -1;
+ if (sep != *str++)
+ return -1;
+ port = strtol (str, &end, 0);
+ if (str == end)
+ return -1;
+ if (end[0] != sep || end[1] != '\0')
+ return -1;
+ return htons(port);
+}
+
+static int
+parse_pasv (struct sockaddr_in *sin, const char *str)
+{
+ int a0, a1, a2, a3, p0, p1;
+
+ /*
+ * 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 (str, "%d,%d,%d,%d,%d,%d",
+ &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
+ printf ("Passive mode address scan failure. "
+ "Shouldn't happen!\n");
+ return -1;
+ }
+ 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");
+ return -1;
+ }
+ memset (sin, 0, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) |
+ (a2 << 8) | a3);
+ sin->sin_port = htons ((p0 << 8) | p1);
+ return 0;
+}
+
+static int
+passive_mode (void)
+{
+ int port;
+
+ data = socket (myctladdr->sa_family, SOCK_STREAM, 0);
+ if (data < 0) {
+ warn ("socket");
+ return (1);
+ }
+ if (options & SO_DEBUG)
+ socket_set_debug (data);
+ if (command ("EPSV") != COMPLETE) {
+ if (command ("PASV") != COMPLETE) {
+ printf ("Passive mode refused.\n");
+ goto bad;
+ }
+ }
+
+ /*
+ * Parse the reply to EPSV or PASV
+ */
+
+ port = parse_epsv (pasv);
+ if (port > 0) {
+ data_addr->sa_family = myctladdr->sa_family;
+ socket_set_address_and_port (data_addr,
+ socket_get_address (hisctladdr),
+ port);
+ } else {
+ if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0)
+ goto bad;
+ }
+
+ if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
+ warn ("connect");
+ goto bad;
+ }
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (data, IPTOS_THROUGHPUT);
+#endif
+ return (0);
+bad:
+ close (data);
+ data = -1;
+ sendport = 1;
+ return (1);
+}
+
+
+static int
+active_mode (void)
+{
+ int tmpno = 0;
+ int len;
+ int result;
+
+noport:
+ data_addr->sa_family = myctladdr->sa_family;
+ socket_set_address_and_port (data_addr, socket_get_address (myctladdr),
+ sendport ? 0 : socket_get_port (myctladdr));
+
+ if (data != -1)
+ close (data);
+ data = socket (data_addr->sa_family, SOCK_STREAM, 0);
+ if (data < 0) {
+ warn ("socket");
+ if (tmpno)
+ sendport = 1;
+ return (1);
+ }
+ if (!sendport)
+ socket_set_reuseaddr (data, 1);
+ if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
+ warn ("bind");
+ goto bad;
+ }
+ if (options & SO_DEBUG)
+ socket_set_debug (data);
+ len = sizeof (data_addr_ss);
+ if (getsockname (data, data_addr, &len) < 0) {
+ warn ("getsockname");
+ goto bad;
+ }
+ if (listen (data, 1) < 0)
+ warn ("listen");
+ if (sendport) {
+ char *cmd;
+ char addr_str[256];
+ int inet_af;
+ int overbose;
+
+ if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr),
+ addr_str, sizeof(addr_str)) == NULL)
+ errx (1, "inet_ntop failed");
+ switch (data_addr->sa_family) {
+ case AF_INET :
+ inet_af = 1;
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+ inet_af = 2;
+ break;
+#endif
+ default :
+ errx (1, "bad address family %d", data_addr->sa_family);
+ }
+
+ asprintf (&cmd, "EPRT |%d|%s|%d|",
+ inet_af, addr_str, ntohs(socket_get_port (data_addr)));
+
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+
+ result = command (cmd);
+
+ verbose = overbose;
+
+ if (result == ERROR) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)data_addr;
+
+ unsigned int a = ntohl(sin->sin_addr.s_addr);
+ unsigned int p = ntohs(sin->sin_port);
+
+ if (data_addr->sa_family != AF_INET) {
+ warnx ("remote server doesn't support EPRT");
+ goto bad;
+ }
+
+ result = command("PORT %d,%d,%d,%d,%d,%d",
+ (a >> 24) & 0xff,
+ (a >> 16) & 0xff,
+ (a >> 8) & 0xff,
+ a & 0xff,
+ (p >> 8) & 0xff,
+ p & 0xff);
+ if (result == ERROR && sendport == -1) {
+ sendport = 0;
+ tmpno = 1;
+ goto noport;
+ }
+ return (result != COMPLETE);
+ }
+ return result != COMPLETE;
+ }
+ if (tmpno)
+ sendport = 1;
+
+
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (data, IPTOS_THROUGHPUT);
+#endif
+ return (0);
+bad:
+ close (data);
+ data = -1;
+ if (tmpno)
+ sendport = 1;
+ return (1);
+}
+
+/*
+ * Need to start a listen on the data channel before we send the command,
+ * otherwise the server's connect may fail.
+ */
+int
+initconn (void)
+{
+ if (passivemode)
+ return passive_mode ();
+ else
+ return active_mode ();
+}
+
+FILE *
+dataconn (const char *lmode)
+{
+ struct sockaddr_storage from_ss;
+ struct sockaddr *from = (struct sockaddr *)&from_ss;
+ int s, fromlen = sizeof (from_ss);
+
+ if (passivemode)
+ return (fdopen (data, lmode));
+
+ s = accept (data, from, &fromlen);
+ if (s < 0) {
+ warn ("accept");
+ close (data), data = -1;
+ return (NULL);
+ }
+ close (data);
+ data = s;
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (s, IPTOS_THROUGHPUT);
+#endif
+ return (fdopen (data, lmode));
+}
+
+void
+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) {
+ td.tv_sec--;
+ td.tv_usec += 1000000;
+ }
+ s = td.tv_sec + (td.tv_usec / 1000000.);
+ bs = bytes / (s ? s : 1);
+ if (bs >= 1048576) {
+ bs /= 1048576;
+ unit = "M";
+ prec = 2;
+ } else if (bs >= 1024) {
+ bs /= 1024;
+ unit = "k";
+ prec = 1;
+ } else {
+ unit = "";
+ prec = 0;
+ }
+
+ printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
+ bytes, direction, s, prec, bs, unit);
+ }
+}
+
+void
+psabort (int sig)
+{
+
+ abrtflag++;
+}
+
+void
+pswitch (int flag)
+{
+ sighand oldintr;
+ static struct comvars {
+ int connect;
+ char name[MaxHostNameLen];
+ struct sockaddr_storage mctl;
+ struct sockaddr_storage hctl;
+ FILE *in;
+ FILE *out;
+ int tpe;
+ int curtpe;
+ int cpnd;
+ int sunqe;
+ int runqe;
+ int mcse;
+ int ntflg;
+ char nti[17];
+ char nto[17];
+ int mapflg;
+ char mi[MaxPathLen];
+ char mo[MaxPathLen];
+ } proxstruct, tmpstruct;
+ struct comvars *ip, *op;
+
+ abrtflag = 0;
+ oldintr = signal (SIGINT, psabort);
+ if (flag) {
+ if (proxy)
+ return;
+ ip = &tmpstruct;
+ op = &proxstruct;
+ proxy++;
+ } else {
+ if (!proxy)
+ return;
+ ip = &proxstruct;
+ op = &tmpstruct;
+ proxy = 0;
+ }
+ ip->connect = connected;
+ connected = op->connect;
+ if (hostname) {
+ strlcpy (ip->name, hostname, sizeof (ip->name));
+ } else
+ ip->name[0] = 0;
+ hostname = op->name;
+ ip->hctl = hisctladdr_ss;
+ hisctladdr_ss = op->hctl;
+ ip->mctl = myctladdr_ss;
+ myctladdr_ss = op->mctl;
+ ip->in = cin;
+ cin = op->in;
+ ip->out = cout;
+ cout = op->out;
+ ip->tpe = type;
+ type = op->tpe;
+ ip->curtpe = curtype;
+ curtype = op->curtpe;
+ ip->cpnd = cpend;
+ cpend = op->cpnd;
+ ip->sunqe = sunique;
+ sunique = op->sunqe;
+ ip->runqe = runique;
+ runique = op->runqe;
+ ip->mcse = mcase;
+ mcase = op->mcse;
+ ip->ntflg = ntflag;
+ ntflag = op->ntflg;
+ strlcpy (ip->nti, ntin, sizeof (ip->nti));
+ strlcpy (ntin, op->nti, 17);
+ strlcpy (ip->nto, ntout, sizeof (ip->nto));
+ strlcpy (ntout, op->nto, 17);
+ ip->mapflg = mapflag;
+ mapflag = op->mapflg;
+ strlcpy (ip->mi, mapin, MaxPathLen);
+ strlcpy (mapin, op->mi, MaxPathLen);
+ strlcpy (ip->mo, mapout, MaxPathLen);
+ strlcpy (mapout, op->mo, MaxPathLen);
+ signal(SIGINT, oldintr);
+ if (abrtflag) {
+ abrtflag = 0;
+ (*oldintr) (SIGINT);
+ }
+}
+
+void
+abortpt (int sig)
+{
+
+ printf ("\n");
+ fflush (stdout);
+ ptabflg++;
+ mflag = 0;
+ abrtflag = 0;
+ longjmp (ptabort, 1);
+}
+
+void
+proxtrans (char *cmd, char *local, char *remote)
+{
+ sighand oldintr;
+ int secndflag = 0, prox_type, nfnd;
+ char *cmd2;
+ fd_set mask;
+
+ if (strcmp (cmd, "RETR"))
+ cmd2 = "RETR";
+ else
+ cmd2 = runique ? "STOU" : "STOR";
+ if ((prox_type = type) == 0) {
+ if (unix_server && unix_proxy)
+ prox_type = TYPE_I;
+ else
+ 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");
+ return;
+ }
+ pswitch (0);
+ if (!connected) {
+ 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);
+ return;
+ }
+ if (setjmp (ptabort))
+ goto abort;
+ oldintr = signal (SIGINT, abortpt);
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
+ pswitch (1);
+ return;
+ }
+ sleep (2);
+ pswitch (1);
+ secndflag++;
+ if (command ("%s %s", cmd2, local) != PRELIM)
+ goto abort;
+ ptflag++;
+ getreply (0);
+ pswitch (0);
+ getreply (0);
+ signal (SIGINT, oldintr);
+ pswitch (1);
+ ptflag = 0;
+ printf ("local: %s remote: %s\n", local, remote);
+ return;
+abort:
+ 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 (cpend)
+ abort_remote ((FILE *) NULL);
+ }
+ pswitch (1);
+ if (ptabflg)
+ code = -1;
+ 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);
+ if (cpend)
+ abort_remote ((FILE *) NULL);
+ pswitch (1);
+ if (ptabflg)
+ code = -1;
+ signal (SIGINT, oldintr);
+ return;
+ }
+ }
+ if (cpend)
+ abort_remote ((FILE *) NULL);
+ pswitch (!proxy);
+ if (cpend) {
+ FD_ZERO (&mask);
+ FD_SET (fileno (cin), &mask);
+ if ((nfnd = empty (&mask, 10)) <= 0) {
+ if (nfnd < 0) {
+ warn ("abort");
+ }
+ if (ptabflg)
+ code = -1;
+ lostpeer (0);
+ }
+ getreply (0);
+ getreply (0);
+ }
+ if (proxy)
+ pswitch (0);
+ pswitch (1);
+ if (ptabflg)
+ code = -1;
+ signal (SIGINT, oldintr);
+}
+
+void
+reset (int argc, char **argv)
+{
+ fd_set mask;
+ int nfnd = 1;
+
+ FD_ZERO (&mask);
+ while (nfnd > 0) {
+ FD_SET (fileno (cin), &mask);
+ if ((nfnd = empty (&mask, 0)) < 0) {
+ warn ("reset");
+ code = -1;
+ lostpeer(0);
+ } else if (nfnd) {
+ getreply(0);
+ }
+ }
+}
+
+char *
+gunique (char *local)
+{
+ static char new[MaxPathLen];
+ char *cp = strrchr (local, '/');
+ int d, count = 0;
+ char ext = '1';
+
+ if (cp)
+ *cp = '\0';
+ d = access (cp ? local : ".", 2);
+ if (cp)
+ *cp = '/';
+ if (d < 0) {
+ warn ("local: %s", local);
+ return NULL;
+ }
+ strlcpy (new, local, sizeof(new));
+ cp = new + strlen(new);
+ *cp++ = '.';
+ while (!d) {
+ if (++count == 100) {
+ printf ("runique: can't find unique file name.\n");
+ return NULL;
+ }
+ *cp++ = ext;
+ *cp = '\0';
+ if (ext == '9')
+ ext = '0';
+ else
+ ext++;
+ if ((d = access (new, 0)) < 0)
+ break;
+ if (ext != '0')
+ cp--;
+ else if (*(cp - 2) == '.')
+ *(cp - 1) = '1';
+ else {
+ *(cp - 2) = *(cp - 2) + 1;
+ cp--;
+ }
+ }
+ return (new);
+}
+
+void
+abort_remote (FILE * din)
+{
+ char buf[BUFSIZ];
+ int nfnd;
+ fd_set mask;
+
+ /*
+ * 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) {
+ if (nfnd < 0) {
+ warn ("abort");
+ }
+ if (ptabflg)
+ code = -1;
+ lostpeer (0);
+ }
+ if (din && FD_ISSET (fileno (din), &mask)) {
+ while (read (fileno (din), buf, BUFSIZ) > 0)
+ /* LOOP */ ;
+ }
+ if (getreply (0) == ERROR && code == 552) {
+ /* 552 needed for nic style abort */
+ getreply (0);
+ }
+ getreply (0);
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h
new file mode 100644
index 0000000..c0d6cae
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h
@@ -0,0 +1,140 @@
+/*
+ * 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. 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: ftp_locl.h,v 1.34 1999/12/02 16:58:29 joda Exp $ */
+/* $FreeBSD$ */
+
+#ifndef __FTP_LOCL_H__
+#define __FTP_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#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_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.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_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_ARPA_FTP_H
+#include <arpa/ftp.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+
+#include <errno.h>
+#include <ctype.h>
+#include <glob.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include <err.h>
+
+#ifdef SOCKS
+#include <socks.h>
+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"
+#include "extern.h"
+#include "common.h"
+#include "pathnames.h"
+
+#include "roken.h"
+#include "security.h"
+#include <openssl/des.h> /* for des_read_pw_string */
+
+#if defined(__sun__) && !defined(__svr4)
+int fclose(FILE*);
+int pclose(FILE*);
+#endif
+
+#endif /* __FTP_LOCL_H__ */
diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp_var.h b/crypto/kerberosIV/appl/ftp/ftp/ftp_var.h
new file mode 100644
index 0000000..ffac59a
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/ftp_var.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ *
+ * @(#)ftp_var.h 8.4 (Berkeley) 10/9/94
+ */
+
+/*
+ * FTP global variables.
+ */
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <setjmp.h>
+
+/*
+ * Options and other state info.
+ */
+extern int trace; /* trace packets exchanged */
+extern int hash; /* print # for each buffer transferred */
+extern int sendport; /* use PORT cmd for each data connection */
+extern int verbose; /* print messages coming back from server */
+extern int connected; /* connected to server */
+extern int fromatty; /* input is from a terminal */
+extern int interactive; /* interactively prompt on m* cmds */
+extern int debug; /* debugging level */
+extern int bell; /* ring bell on cmd completion */
+extern int doglob; /* glob local file names */
+extern int autologin; /* establish user account on connection */
+extern int proxy; /* proxy server connection active */
+extern int proxflag; /* proxy connection exists */
+extern int sunique; /* store files on server with unique name */
+extern int runique; /* store local files with unique name */
+extern int mcase; /* map upper to lower case for mget names */
+extern int ntflag; /* use ntin ntout tables for name translation */
+extern int mapflag; /* use mapin mapout templates on file names */
+extern int code; /* return/reply code for ftp command */
+extern int crflag; /* if 1, strip car. rets. on ascii gets */
+extern char pasv[64]; /* passive port for proxy data connection */
+extern int passivemode; /* passive mode enabled */
+extern char *altarg; /* argv[1] with no shell-like preprocessing */
+extern char ntin[17]; /* input translation table */
+extern char ntout[17]; /* output translation table */
+extern char mapin[MaxPathLen]; /* input map template */
+extern char mapout[MaxPathLen]; /* output map template */
+extern char typename[32]; /* name of file transfer type */
+extern int type; /* requested file transfer type */
+extern int curtype; /* current file transfer type */
+extern char structname[32]; /* name of file transfer structure */
+extern int stru; /* file transfer structure */
+extern char formname[32]; /* name of file transfer format */
+extern int form; /* file transfer format */
+extern char modename[32]; /* name of file transfer mode */
+extern int mode; /* file transfer mode */
+extern char bytename[32]; /* local byte size in ascii */
+extern int bytesize; /* local byte size in binary */
+
+extern char *hostname; /* name of host connected to */
+extern int unix_server; /* server is unix, can use binary for ascii */
+extern int unix_proxy; /* proxy is unix, can use binary for ascii */
+
+extern jmp_buf toplevel; /* non-local goto stuff for cmd scanner */
+
+extern char line[200]; /* input line buffer */
+extern char *stringbase; /* current scan point in line buffer */
+extern char argbuf[200]; /* argument storage buffer */
+extern char *argbase; /* current storage point in arg buffer */
+extern int margc; /* count of arguments on input line */
+extern char **margv; /* args parsed from input line */
+extern int margvlen; /* how large margv is currently */
+extern int cpend; /* flag: if != 0, then pending server reply */
+extern int mflag; /* flag: if != 0, then active multi command */
+
+extern int options; /* used during socket creation */
+
+/*
+ * Format of command table.
+ */
+struct cmd {
+ char *c_name; /* name of command */
+ char *c_help; /* help string */
+ char c_bell; /* give bell when command completes */
+ char c_conn; /* must be connected to use command */
+ char c_proxy; /* proxy server may execute */
+ void (*c_handler) (int, char **); /* function to call */
+};
+
+struct macel {
+ char mac_name[9]; /* macro name */
+ char *mac_start; /* start of macro in macbuf */
+ char *mac_end; /* end of macro in macbuf */
+};
+
+extern int macnum; /* number of defined macros */
+extern struct macel macros[16];
+extern char macbuf[4096];
+
+
diff --git a/crypto/kerberosIV/appl/ftp/ftp/globals.c b/crypto/kerberosIV/appl/ftp/ftp/globals.c
new file mode 100644
index 0000000..7199e65
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/globals.c
@@ -0,0 +1,76 @@
+#include "ftp_locl.h"
+RCSID("$Id: globals.c,v 1.6 1996/08/26 22:46:26 assar Exp $");
+
+/*
+ * Options and other state info.
+ */
+int trace; /* trace packets exchanged */
+int hash; /* print # for each buffer transferred */
+int sendport; /* use PORT cmd for each data connection */
+int verbose; /* print messages coming back from server */
+int connected; /* connected to server */
+int fromatty; /* input is from a terminal */
+int interactive; /* interactively prompt on m* cmds */
+int debug; /* debugging level */
+int bell; /* ring bell on cmd completion */
+int doglob; /* glob local file names */
+int autologin; /* establish user account on connection */
+int proxy; /* proxy server connection active */
+int proxflag; /* proxy connection exists */
+int sunique; /* store files on server with unique name */
+int runique; /* store local files with unique name */
+int mcase; /* map upper to lower case for mget names */
+int ntflag; /* use ntin ntout tables for name translation */
+int mapflag; /* use mapin mapout templates on file names */
+int code; /* return/reply code for ftp command */
+int crflag; /* if 1, strip car. rets. on ascii gets */
+char pasv[64]; /* passive port for proxy data connection */
+int passivemode; /* passive mode enabled */
+char *altarg; /* argv[1] with no shell-like preprocessing */
+char ntin[17]; /* input translation table */
+char ntout[17]; /* output translation table */
+char mapin[MaxPathLen]; /* input map template */
+char mapout[MaxPathLen]; /* output map template */
+char typename[32]; /* name of file transfer type */
+int type; /* requested file transfer type */
+int curtype; /* current file transfer type */
+char structname[32]; /* name of file transfer structure */
+int stru; /* file transfer structure */
+char formname[32]; /* name of file transfer format */
+int form; /* file transfer format */
+char modename[32]; /* name of file transfer mode */
+int mode; /* file transfer mode */
+char bytename[32]; /* local byte size in ascii */
+int bytesize; /* local byte size in binary */
+
+char *hostname; /* name of host connected to */
+int unix_server; /* server is unix, can use binary for ascii */
+int unix_proxy; /* proxy is unix, can use binary for ascii */
+
+jmp_buf toplevel; /* non-local goto stuff for cmd scanner */
+
+char line[200]; /* input line buffer */
+char *stringbase; /* current scan point in line buffer */
+char argbuf[200]; /* argument storage buffer */
+char *argbase; /* current storage point in arg buffer */
+int margc; /* count of arguments on input line */
+char **margv; /* args parsed from input line */
+int margvlen; /* how large margv is currently */
+int cpend; /* flag: if != 0, then pending server reply */
+int mflag; /* flag: if != 0, then active multi command */
+
+int options; /* used during socket creation */
+
+/*
+ * Format of command table.
+ */
+
+int macnum; /* number of defined macros */
+struct macel macros[16];
+char macbuf[4096];
+
+char username[32];
+
+/* these are set in ruserpass */
+char myhostname[MaxHostNameLen];
+char *mydomain;
diff --git a/crypto/kerberosIV/appl/ftp/ftp/gssapi.c b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c
new file mode 100644
index 0000000..d06b5d6
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c
@@ -0,0 +1,379 @@
+/*
+ * 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. 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.13 1999/12/02 16:58:29 joda 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;
+}
+
+static void
+sockaddr_to_gss_address (const struct sockaddr *sa,
+ OM_uint32 *addr_type,
+ gss_buffer_desc *gss_addr)
+{
+ switch (sa->sa_family) {
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+ gss_addr->length = 16;
+ gss_addr->value = &sin6->sin6_addr;
+ *addr_type = GSS_C_AF_INET6;
+ break;
+ }
+#endif
+ case AF_INET : {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+ gss_addr->length = 4;
+ gss_addr->value = &sin->sin_addr;
+ *addr_type = GSS_C_AF_INET;
+ break;
+ }
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+
+ }
+}
+
+/* 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));
+ sockaddr_to_gss_address (his_addr,
+ &bindings->initiator_addrtype,
+ &bindings->initiator_address);
+ sockaddr_to_gss_address (ctrl_addr,
+ &bindings->acceptor_addrtype,
+ &bindings->acceptor_address);
+
+ 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 *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);
+ if (GSS_ERROR(maj_stat)) {
+ OM_uint32 new_stat;
+ OM_uint32 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 importing name %s: %s\n",
+ (char *)name.value,
+ (char *)status_string.value);
+ gss_release_buffer(&new_stat, &status_string);
+ return AUTH_ERROR;
+ }
+ free(name.value);
+
+
+ input.length = 0;
+ input.value = NULL;
+
+ bindings = malloc(sizeof(*bindings));
+
+ sockaddr_to_gss_address (myctladdr,
+ &bindings->initiator_addrtype,
+ &bindings->initiator_address);
+ sockaddr_to_gss_address (hisctladdr,
+ &bindings->acceptor_addrtype,
+ &bindings->acceptor_address);
+
+ 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)) {
+ OM_uint32 new_stat;
+ OM_uint32 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
new file mode 100644
index 0000000..613593a
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/kauth.c
@@ -0,0 +1,198 @@
+/*
+ * 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. 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 "ftp_locl.h"
+#include <krb.h>
+RCSID("$Id: kauth.c,v 1.20 1999/12/02 16:58:29 joda Exp $");
+
+void
+kauth(int argc, char **argv)
+{
+ int ret;
+ char buf[1024];
+ des_cblock key;
+ des_key_schedule schedule;
+ KTEXT_ST tkt, tktcopy;
+ char *name;
+ char *p;
+ int overbose;
+ char passwd[100];
+ int tmp;
+
+ int save;
+
+ if(argc > 2){
+ printf("usage: %s [principal]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if(argc == 2)
+ name = argv[1];
+ else
+ name = username;
+
+ overbose = verbose;
+ verbose = 0;
+
+ save = set_command_prot(prot_private);
+ ret = command("SITE KAUTH %s", name);
+ if(ret != CONTINUE){
+ verbose = overbose;
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ verbose = overbose;
+ p = strstr(reply_string, "T=");
+ if(!p){
+ printf("Bad reply from server.\n");
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ p += 2;
+ tmp = base64_decode(p, &tkt.dat);
+ if(tmp < 0){
+ printf("Failed to decode base64 in reply.\n");
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ tkt.length = tmp;
+ tktcopy.length = tkt.length;
+
+ p = strstr(reply_string, "P=");
+ if(!p){
+ printf("Bad reply from server.\n");
+ verbose = overbose;
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ name = p + 2;
+ for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
+ *p = 0;
+
+ snprintf(buf, sizeof(buf), "Password for %s:", name);
+ if (des_read_pw_string (passwd, sizeof(passwd)-1, buf, 0))
+ *passwd = '\0';
+ des_string_to_key (passwd, &key);
+
+ des_key_sched(&key, schedule);
+
+ des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
+ tkt.length,
+ schedule, &key, DES_DECRYPT);
+ if (strcmp ((char*)tktcopy.dat + 8,
+ KRB_TICKET_GRANTING_TICKET) != 0) {
+ afs_string_to_key (passwd, krb_realmofhost(hostname), &key);
+ des_key_sched (&key, schedule);
+ des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
+ tkt.length,
+ schedule, &key, DES_DECRYPT);
+ }
+ memset(key, 0, sizeof(key));
+ memset(schedule, 0, sizeof(schedule));
+ memset(passwd, 0, sizeof(passwd));
+ if(base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
+ printf("Out of memory base64-encoding.\n");
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ memset (tktcopy.dat, 0, tktcopy.length);
+ ret = command("SITE KAUTH %s %s", name, p);
+ free(p);
+ set_command_prot(save);
+ if(ret != COMPLETE){
+ code = -1;
+ return;
+ }
+ code = 0;
+}
+
+void
+klist(int argc, char **argv)
+{
+ int ret;
+ if(argc != 1){
+ printf("usage: %s\n", argv[0]);
+ code = -1;
+ return;
+ }
+
+ 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
new file mode 100644
index 0000000..aa30c1b
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/krb4.c
@@ -0,0 +1,334 @@
+/*
+ * 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. 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 <krb.h>
+
+RCSID("$Id: krb4.c,v 1.36.2.1 1999/12/06 17:29:45 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 *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 int
+krb4_check_prot(void *app_data, int level)
+{
+ if(level == prot_confidential)
+ return -1;
+ return 0;
+}
+
+static int
+krb4_decode(void *app_data, void *buf, int len, int level)
+{
+ MSG_DAT m;
+ int e;
+ struct krb4_data *d = app_data;
+
+ if(level == prot_safe)
+ e = krb_rd_safe(buf, len, &d->key,
+ (struct sockaddr_in *)REMOTE_ADDR,
+ (struct sockaddr_in *)LOCAL_ADDR, &m);
+ else
+ e = krb_rd_priv(buf, len, d->schedule, &d->key,
+ (struct sockaddr_in *)REMOTE_ADDR,
+ (struct sockaddr_in *)LOCAL_ADDR, &m);
+ if(e){
+ syslog(LOG_ERR, "krb4_decode: %s", krb_get_err_text(e));
+ return -1;
+ }
+ memmove(buf, m.app_data, m.app_length);
+ return m.app_length;
+}
+
+static int
+krb4_overhead(void *app_data, int level, int len)
+{
+ return 31;
+}
+
+static int
+krb4_encode(void *app_data, void *from, int length, int level, void **to)
+{
+ struct krb4_data *d = app_data;
+ *to = malloc(length + 31);
+ if(level == prot_safe)
+ return krb_mk_safe(from, *to, length, &d->key,
+ (struct sockaddr_in *)LOCAL_ADDR,
+ (struct sockaddr_in *)REMOTE_ADDR);
+ else if(level == prot_private)
+ return krb_mk_priv(from, *to, length, d->schedule, &d->key,
+ (struct sockaddr_in *)LOCAL_ADDR,
+ (struct sockaddr_in *)REMOTE_ADDR);
+ else
+ return -1;
+}
+
+#ifdef FTP_SERVER
+
+static int
+krb4_adat(void *app_data, void *buf, size_t len)
+{
+ 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];
+ struct sockaddr_in *his_addr_sin = (struct sockaddr_in *)his_addr;
+
+ memcpy(tkt.dat, buf, len);
+ tkt.length = len;
+
+ k_getsockinst(0, inst, sizeof(inst));
+ kerror = krb_rd_req(&tkt, "ftp", inst,
+ his_addr_sin->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->sin_addr.s_addr, &auth_dat, "");
+ }
+
+ if(kerror){
+ reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
+ return -1;
+ }
+
+ memcpy(d->key, auth_dat.session, sizeof(d->key));
+ des_set_key(&d->key, d->schedule);
+
+ strlcpy(d->name, auth_dat.pname, sizeof(d->name));
+ strlcpy(d->instance, auth_dat.pinst, sizeof(d->instance));
+ strlcpy(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,
+ (struct sockaddr_in *)LOCAL_ADDR,
+ (struct sockaddr_in *)REMOTE_ADDR);
+ }
+ if(tmp_len < 0){
+ reply(535, "Error creating reply: %s.", strerror(errno));
+ return -1;
+ }
+ len = tmp_len;
+ if(base64_encode(msg, len, &p) < 0) {
+ reply(535, "Out of memory base64-encoding.");
+ return -1;
+ }
+ reply(235, "ADAT=%s", p);
+ sec_complete = 1;
+ free(p);
+ return 0;
+}
+
+static int
+krb4_userok(void *app_data, char *user)
+{
+ struct krb4_data *d = app_data;
+ return krb_kuserok(d->name, d->instance, d->realm, user);
+}
+
+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
+};
+
+#else /* FTP_SERVER */
+
+static int
+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];
+
+ strlcpy(sname, service, sizeof(sname));
+ strlcpy(inst, krb_get_phost(host), sizeof(inst));
+ strlcpy(realm, krb_realmofhost(host), sizeof(realm));
+ ret = krb_mk_req(adat, sname, inst, realm, checksum);
+ if(ret)
+ return ret;
+ strlcpy(sname, service, sizeof(sname));
+ strlcpy(inst, krb_get_phost(host), sizeof(inst));
+ strlcpy(realm, krb_realmofhost(host), sizeof(realm));
+ ret = krb_get_cred(sname, inst, realm, &cred);
+ memmove(&d->key, &cred.session, sizeof(des_cblock));
+ des_key_sched(&d->key, d->schedule);
+ memset(&cred, 0, sizeof(cred));
+ return ret;
+}
+
+static int
+krb4_auth(void *app_data, char *host)
+{
+ int ret;
+ char *p;
+ int len;
+ KTEXT_ST adat;
+ MSG_DAT msg_data;
+ int checksum;
+ u_int32_t cs;
+ struct krb4_data *d = app_data;
+ struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
+ struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR;
+
+ checksum = getpid();
+ ret = mk_auth(d, &adat, "ftp", host, checksum);
+ if(ret == KDC_PR_UNKNOWN)
+ ret = mk_auth(d, &adat, "rcmd", host, checksum);
+ if(ret){
+ printf("%s\n", krb_get_err_text(ret));
+ return AUTH_CONTINUE;
+ }
+
+#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
+ if (krb_get_config_bool("nat_in_use")) {
+ struct in_addr natAddr;
+
+ if (krb_get_our_ip_for_realm(krb_realmofhost(host),
+ &natAddr) != KSUCCESS
+ && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
+ printf("Can't get address for realm %s\n",
+ krb_realmofhost(host));
+ else {
+ if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
+ printf("Using NAT IP address (%s) for kerberos 4\n",
+ inet_ntoa(natAddr));
+ localaddr->sin_addr = natAddr;
+
+ /*
+ * This not the best place to do this, but it
+ * is here we know that (probably) NAT is in
+ * use!
+ */
+
+ passivemode = 1;
+ printf("Setting: Passive mode on.\n");
+ }
+ }
+ }
+#endif
+
+ printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));
+ printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));
+
+ 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");
+ return AUTH_ERROR;
+ }
+
+ p = strstr(reply_string, "ADAT=");
+ if(!p){
+ printf("Remote host didn't send adat reply.\n");
+ return AUTH_ERROR;
+ }
+ p += 5;
+ len = base64_decode(p, adat.dat);
+ if(len < 0){
+ printf("Failed to decode base64 from server.\n");
+ return AUTH_ERROR;
+ }
+ adat.length = len;
+ ret = krb_rd_safe(adat.dat, adat.length, &d->key,
+ (struct sockaddr_in *)hisctladdr,
+ (struct sockaddr_in *)myctladdr, &msg_data);
+ if(ret){
+ printf("Error reading reply from server: %s.\n",
+ krb_get_err_text(ret));
+ return AUTH_ERROR;
+ }
+ krb_get_int(msg_data.app_data, &cs, 4, 0);
+ if(cs - checksum != 1){
+ printf("Bad checksum returned from server.\n");
+ return AUTH_ERROR;
+ }
+ 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
+};
+
+#endif /* FTP_SERVER */
diff --git a/crypto/kerberosIV/appl/ftp/ftp/krb4.h b/crypto/kerberosIV/appl/ftp/ftp/krb4.h
new file mode 100644
index 0000000..7cf8cec
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/krb4.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: krb4.h,v 1.10 1997/04/01 08:17:22 joda Exp $ */
+
+#ifndef __KRB4_H__
+#define __KRB4_H__
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern int auth_complete;
+
+void sec_status(void);
+
+enum { prot_clear, prot_safe, prot_confidential, prot_private };
+
+void sec_prot(int, char**);
+
+int sec_getc(FILE *F);
+int sec_putc(int c, FILE *F);
+int sec_fflush(FILE *F);
+int sec_read(int fd, void *data, int length);
+int sec_write(int fd, char *data, int length);
+
+int krb4_getc(FILE *F);
+int krb4_read(int fd, char *data, int length);
+
+
+
+void sec_set_protection_level(void);
+int sec_request_prot(char *level);
+
+void kauth(int, char **);
+void klist(int, char **);
+
+void krb4_quit(void);
+
+int krb4_write_enc(FILE *F, char *fmt, va_list ap);
+int krb4_read_msg(char *s, int priv);
+int krb4_read_mic(char *s);
+int krb4_read_enc(char *s);
+
+int do_klogin(char *host);
+
+#endif /* __KRB4_H__ */
diff --git a/crypto/kerberosIV/appl/ftp/ftp/main.c b/crypto/kerberosIV/appl/ftp/ftp/main.c
new file mode 100644
index 0000000..929acac
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/main.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ */
+
+/*
+ * FTP User Program -- Command Interface.
+ */
+
+#include "ftp_locl.h"
+RCSID("$Id: main.c,v 1.27.2.1 2000/10/10 13:01:50 assar Exp $");
+
+int
+main(int argc, char **argv)
+{
+ int ch, top;
+ struct passwd *pw = NULL;
+ char homedir[MaxPathLen];
+ struct servent *sp;
+
+ set_progname(argv[0]);
+
+ sp = getservbyname("ftp", "tcp");
+ if (sp == 0)
+ errx(1, "ftp/tcp: unknown service");
+ doglob = 1;
+ interactive = 1;
+ autologin = 1;
+ passivemode = 0; /* passive mode not active */
+
+ while ((ch = getopt(argc, argv, "dginptv")) != -1) {
+ switch (ch) {
+ case 'd':
+ options |= SO_DEBUG;
+ debug++;
+ break;
+
+ case 'g':
+ doglob = 0;
+ break;
+
+ case 'i':
+ interactive = 0;
+ break;
+
+ case 'n':
+ autologin = 0;
+ break;
+
+ case 'p':
+ passivemode = 1;
+ break;
+ case 't':
+ trace++;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ default:
+ fprintf(stderr,
+ "usage: ftp [-dginptv] [host [port]]\n");
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ fromatty = isatty(fileno(stdin));
+ if (fromatty)
+ verbose++;
+ cpend = 0; /* no pending replies */
+ proxy = 0; /* proxy not active */
+ crflag = 1; /* strip c.r. on ascii gets */
+ sendport = -1; /* not using ports */
+ /*
+ * Set up the home directory in case we're globbing.
+ */
+ pw = k_getpwuid(getuid());
+ if (pw != NULL) {
+ strlcpy(homedir, pw->pw_dir, sizeof(homedir));
+ home = homedir;
+ }
+ if (argc > 0) {
+ char *xargv[5];
+
+ if (setjmp(toplevel))
+ exit(0);
+ signal(SIGINT, intr);
+ signal(SIGPIPE, lostpeer);
+ xargv[0] = (char*)__progname;
+ xargv[1] = argv[0];
+ xargv[2] = argv[1];
+ xargv[3] = argv[2];
+ xargv[4] = NULL;
+ setpeer(argc+1, xargv);
+ }
+ if(setjmp(toplevel) == 0)
+ top = 1;
+ else
+ top = 0;
+ if (top) {
+ signal(SIGINT, intr);
+ signal(SIGPIPE, lostpeer);
+ }
+ for (;;) {
+ cmdscanner(top);
+ top = 1;
+ }
+}
+
+void
+intr(int sig)
+{
+
+ longjmp(toplevel, 1);
+}
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+RETSIGTYPE
+lostpeer(int sig)
+{
+
+ if (connected) {
+ if (cout != NULL) {
+ shutdown(fileno(cout), SHUT_RDWR);
+ fclose(cout);
+ cout = NULL;
+ }
+ if (data >= 0) {
+ shutdown(data, SHUT_RDWR);
+ close(data);
+ data = -1;
+ }
+ connected = 0;
+ }
+ pswitch(1);
+ if (connected) {
+ if (cout != NULL) {
+ shutdown(fileno(cout), SHUT_RDWR);
+ fclose(cout);
+ cout = NULL;
+ }
+ connected = 0;
+ }
+ proxflag = 0;
+ pswitch(0);
+ sec_end();
+ SIGRETURN(0);
+}
+
+/*
+char *
+tail(filename)
+ char *filename;
+{
+ char *s;
+
+ while (*filename) {
+ s = strrchr(filename, '/');
+ if (s == NULL)
+ break;
+ if (s[1])
+ return (s + 1);
+ *s = '\0';
+ }
+ return (filename);
+}
+*/
+
+#ifndef HAVE_READLINE
+
+static char *
+readline(char *prompt)
+{
+ char buf[BUFSIZ];
+ printf ("%s", prompt);
+ fflush (stdout);
+ if(fgets(buf, sizeof(buf), stdin) == NULL)
+ return NULL;
+ if (buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+ return strdup(buf);
+}
+
+static void
+add_history(char *p)
+{
+}
+
+#else
+
+/* These should not really be here */
+
+char *readline(char *);
+void add_history(char *);
+
+#endif
+
+/*
+ * Command parser.
+ */
+void
+cmdscanner(int top)
+{
+ struct cmd *c;
+ int l;
+
+ if (!top)
+ putchar('\n');
+ for (;;) {
+ if (fromatty) {
+ char *p;
+ p = readline("ftp> ");
+ if(p == NULL) {
+ printf("\n");
+ quit(0, 0);
+ }
+ strlcpy(line, p, sizeof(line));
+ add_history(p);
+ free(p);
+ } else{
+ if (fgets(line, sizeof line, stdin) == NULL)
+ quit(0, 0);
+ }
+ /* XXX will break on long lines */
+ l = strlen(line);
+ if (l == 0)
+ break;
+ if (line[--l] == '\n') {
+ if (l == 0)
+ break;
+ line[l] = '\0';
+ } else if (l == sizeof(line) - 2) {
+ printf("sorry, input line too long\n");
+ while ((l = getchar()) != '\n' && l != EOF)
+ /* void */;
+ break;
+ } /* else it was a line without a newline */
+ makeargv();
+ if (margc == 0) {
+ continue;
+ }
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ if (c->c_conn && !connected) {
+ printf("Not connected.\n");
+ continue;
+ }
+ (*c->c_handler)(margc, margv);
+ if (bell && c->c_bell)
+ putchar('\007');
+ if (c->c_handler != help)
+ break;
+ }
+ signal(SIGINT, intr);
+ signal(SIGPIPE, lostpeer);
+}
+
+struct cmd *
+getcmd(char *name)
+{
+ char *p, *q;
+ struct cmd *c, *found;
+ int nmatches, longest;
+
+ longest = 0;
+ nmatches = 0;
+ found = 0;
+ for (c = cmdtab; (p = c->c_name); c++) {
+ for (q = name; *q == *p++; q++)
+ if (*q == 0) /* exact match? */
+ return (c);
+ if (!*q) { /* the name was a prefix */
+ if (q - name > longest) {
+ longest = q - name;
+ nmatches = 1;
+ found = c;
+ } else if (q - name == longest)
+ nmatches++;
+ }
+ }
+ if (nmatches > 1)
+ return ((struct cmd *)-1);
+ return (found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+
+int slrflag;
+
+void
+makeargv(void)
+{
+ char **argp;
+
+ argp = margv;
+ stringbase = line; /* scan from first of buffer */
+ argbase = argbuf; /* store from first of buffer */
+ slrflag = 0;
+ 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;
+ }
+
+ if ((*argp++ = slurpstring()) == NULL)
+ break;
+ }
+
+}
+
+/*
+ * Parse string into argbuf;
+ * implemented with FSM to
+ * handle quoting and strings
+ */
+char *
+slurpstring(void)
+{
+ int got_one = 0;
+ char *sb = stringbase;
+ char *ap = argbase;
+ char *tmp = argbase; /* will return this if token found */
+
+ if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
+ switch (slrflag) { /* and $ as token for macro invoke */
+ case 0:
+ slrflag++;
+ stringbase++;
+ return ((*sb == '!') ? "!" : "$");
+ /* NOTREACHED */
+ case 1:
+ slrflag++;
+ altarg = stringbase;
+ break;
+ default:
+ break;
+ }
+ }
+
+S0:
+ switch (*sb) {
+
+ case '\0':
+ goto OUT;
+
+ case ' ':
+ case '\t':
+ sb++; goto S0;
+
+ default:
+ switch (slrflag) {
+ case 0:
+ slrflag++;
+ break;
+ case 1:
+ slrflag++;
+ altarg = sb;
+ break;
+ default:
+ break;
+ }
+ goto S1;
+ }
+
+S1:
+ switch (*sb) {
+
+ case ' ':
+ case '\t':
+ case '\0':
+ goto OUT; /* end of token */
+
+ case '\\':
+ sb++; goto S2; /* slurp next character */
+
+ case '"':
+ sb++; goto S3; /* slurp quoted string */
+
+ default:
+ *ap++ = *sb++; /* add character to token */
+ got_one = 1;
+ goto S1;
+ }
+
+S2:
+ switch (*sb) {
+
+ case '\0':
+ goto OUT;
+
+ default:
+ *ap++ = *sb++;
+ got_one = 1;
+ goto S1;
+ }
+
+S3:
+ switch (*sb) {
+
+ case '\0':
+ goto OUT;
+
+ case '"':
+ sb++; goto S1;
+
+ default:
+ *ap++ = *sb++;
+ got_one = 1;
+ goto S3;
+ }
+
+OUT:
+ if (got_one)
+ *ap++ = '\0';
+ argbase = ap; /* update storage pointer */
+ stringbase = sb; /* update scan pointer */
+ if (got_one) {
+ return (tmp);
+ }
+ switch (slrflag) {
+ case 0:
+ slrflag++;
+ break;
+ case 1:
+ slrflag++;
+ altarg = (char *) 0;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+#define HELPINDENT ((int) sizeof ("directory"))
+
+/*
+ * Help command.
+ * Call each command handler with argc == 0 and argv[0] == name.
+ */
+void
+help(int argc, char **argv)
+{
+ struct cmd *c;
+
+ if (argc == 1) {
+ int i, j, w, k;
+ int columns, width = 0, lines;
+
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+ int len = strlen(c->c_name);
+
+ if (len > width)
+ width = len;
+ }
+ width = (width + 8) &~ 7;
+ columns = 80 / width;
+ if (columns == 0)
+ columns = 1;
+ lines = (NCMDS + columns - 1) / columns;
+ for (i = 0; i < lines; i++) {
+ for (j = 0; j < columns; j++) {
+ c = cmdtab + j * lines + i;
+ if (c->c_name && (!proxy || c->c_proxy)) {
+ printf("%s", c->c_name);
+ }
+ else if (c->c_name) {
+ for (k=0; k < strlen(c->c_name); k++) {
+ putchar(' ');
+ }
+ }
+ if (c + lines >= &cmdtab[NCMDS]) {
+ printf("\n");
+ break;
+ }
+ w = strlen(c->c_name);
+ while (w < width) {
+ w = (w + 8) &~ 7;
+ putchar('\t');
+ }
+ }
+ }
+ return;
+ }
+ while (--argc > 0) {
+ char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == (struct cmd *)-1)
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == (struct cmd *)0)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%-*s\t%s\n", HELPINDENT,
+ c->c_name, c->c_help);
+ }
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/pathnames.h b/crypto/kerberosIV/appl/ftp/ftp/pathnames.h
new file mode 100644
index 0000000..f7c1fb3
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/pathnames.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#define _PATH_TMP_XXX "/tmp/ftpXXXXXX"
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
diff --git a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c
new file mode 100644
index 0000000..c687a59
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 1985, 1993, 1994
+ * 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 "ftp_locl.h"
+RCSID("$Id: ruserpass.c,v 1.16 1999/09/16 20:37:31 assar Exp $");
+
+static int token (void);
+static FILE *cfile;
+
+#define DEFAULT 1
+#define LOGIN 2
+#define PASSWD 3
+#define ACCOUNT 4
+#define MACDEF 5
+#define PROT 6
+#define ID 10
+#define MACH 11
+
+static char tokval[100];
+
+static struct toktab {
+ char *tokstr;
+ int tval;
+} toktab[]= {
+ { "default", DEFAULT },
+ { "login", LOGIN },
+ { "password", PASSWD },
+ { "passwd", PASSWD },
+ { "account", ACCOUNT },
+ { "machine", MACH },
+ { "macdef", MACDEF },
+ { "prot", PROT },
+ { 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) {
+ strlcpy (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) {
+ strlcpy (hostname, he->h_name, sz);
+ return dot + 1;
+ }
+ for (aliases = he->h_aliases; (a = *aliases) != NULL; ++aliases) {
+ dot = strchr (a, '.');
+ if (dot != NULL) {
+ strlcpy (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;
+
+ 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) {
+
+ 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 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);
+ break;
+ }
+ goto done;
+ }
+done:
+ fclose(cfile);
+ return (0);
+bad:
+ fclose(cfile);
+ return (-1);
+}
+
+static int
+token(void)
+{
+ char *cp;
+ int c;
+ struct toktab *t;
+
+ if (feof(cfile) || ferror(cfile))
+ return (0);
+ while ((c = getc(cfile)) != EOF &&
+ (c == '\n' || c == '\t' || c == ' ' || c == ','))
+ continue;
+ if (c == EOF)
+ return (0);
+ cp = tokval;
+ if (c == '"') {
+ while ((c = getc(cfile)) != EOF && c != '"') {
+ if (c == '\\')
+ c = getc(cfile);
+ *cp++ = c;
+ }
+ } else {
+ *cp++ = c;
+ while ((c = getc(cfile)) != EOF
+ && c != '\n' && c != '\t' && c != ' ' && c != ',') {
+ if (c == '\\')
+ c = getc(cfile);
+ *cp++ = c;
+ }
+ }
+ *cp = 0;
+ if (tokval[0] == 0)
+ return (0);
+ for (t = toktab; t->tokstr; t++)
+ if (!strcmp(t->tokstr, tokval))
+ return (t->tval);
+ return (ID);
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftp/security.c b/crypto/kerberosIV/appl/ftp/ftp/security.c
new file mode 100644
index 0000000..ca7eb00
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/security.c
@@ -0,0 +1,785 @@
+/*
+ * 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. 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.15 1999/12/02 16:58:30 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 0;
+ else 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;
+ int b;
+
+ b = block_read(fd, &len, sizeof(len));
+ if (b == 0)
+ return 0;
+ else if (b < 0)
+ return -1;
+ len = ntohl(len);
+ buf->data = realloc(buf->data, len);
+ b = block_read(fd, buf->data, len);
+ if (b == 0)
+ return 0;
+ else if (b < 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_vfprintf2(FILE *f, const char *fmt, va_list ap)
+{
+ char *buf;
+ int ret;
+ if(data_prot == prot_clear)
+ return vfprintf(f, fmt, ap);
+ else {
+ vasprintf(&buf, fmt, ap);
+ ret = buffer_write(&out_buffer, buf, strlen(buf));
+ free(buf);
+ return ret;
+ }
+}
+
+int
+sec_fprintf2(FILE *f, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = sec_vfprintf2(f, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+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;
+}
+
+enum protection_level
+get_command_prot(void)
+{
+ return command_prot;
+}
+
+#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;
+}
+
+enum protection_level
+set_command_prot(enum protection_level level)
+{
+ enum protection_level old = command_prot;
+ command_prot = level;
+ return old;
+}
+
+void
+sec_prot(int argc, char **argv)
+{
+ int level = -1;
+
+ if(argc < 2 || argc > 3)
+ goto usage;
+ if(!sec_complete) {
+ printf("No security data exchange has taken place.\n");
+ code = -1;
+ return;
+ }
+ level = name_to_level(argv[argc - 1]);
+
+ if(level == -1)
+ goto usage;
+
+ 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(argc == 2 || strncasecmp(argv[1], "data", strlen(argv[1])) == 0) {
+ if(sec_prot_internal(level) < 0){
+ code = -1;
+ return;
+ }
+ } else if(strncasecmp(argv[1], "command", strlen(argv[1])) == 0)
+ set_command_prot(level);
+ else
+ goto usage;
+ code = 0;
+ return;
+ usage:
+ printf("usage: %s [command|data] [clear|safe|confidential|private]\n",
+ argv[0]);
+ code = -1;
+}
+
+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++) {
+ void *tmp;
+
+ tmp = realloc(app_data, (*m)->size);
+ if (tmp == NULL) {
+ warnx ("realloc %u failed", (*m)->size);
+ return -1;
+ }
+ app_data = tmp;
+
+ 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);
+ app_data = NULL;
+ }
+ 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..6fe0694
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftp/security.h
@@ -0,0 +1,131 @@
+/*
+ * 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. 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.7 1999/12/02 16:58:30 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_fprintf2(FILE *f, const char *fmt, ...);
+int sec_vfprintf2(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);
+enum protection_level get_command_prot(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);
+
+enum protection_level set_command_prot(enum protection_level);
+
+#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..282cb3a
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am
@@ -0,0 +1,54 @@
+# $Id: Makefile.am,v 1.20 1999/10/03 16:38:53 joda 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 \
+ ls.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
new file mode 100644
index 0000000..bc5c12e
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in
@@ -0,0 +1,102 @@
+#
+# $Id: Makefile.in,v 1.41 1999/10/03 16:39:27 joda Exp $
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+top_builddir = ../../..
+
+SHELL = /bin/sh
+
+CC = @CC@
+YACC = @YACC@
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+WFLAGS = @WFLAGS@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+LD_FLAGS = @LD_FLAGS@
+LIBS = @LIBS@
+LIB_DBM = @LIB_DBM@
+MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+LN_S = @LN_S@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+libexecdir = @libexecdir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+ATHENA = ../../..
+
+INCTOP = $(ATHENA)/include
+
+LIBTOP = $(ATHENA)/lib
+
+LIBKAFS = @KRB_KAFS_LIB@
+LIBKRB = -L$(LIBTOP)/krb -lkrb
+LIBDES = -L$(LIBTOP)/des -ldes
+LIBOTP = @LIB_otp@
+LIBROKEN= -L$(LIBTOP)/roken -lroken
+
+PROGS = ftpd$(EXECSUFFIX)
+
+ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c ls.c popen.c security.c krb4.c kauth.c
+ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o ls.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 -DFTP_SERVER -I. -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $(CFLAGS) $(CPPFLAGS) $<
+
+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
+
+ftpd$(EXECSUFFIX): $(ftpd_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(ftpd_OBJS) -L../common -lcommon $(LIBKAFS) $(LIBKRB) $(LIBOTP) $(LIBDES) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN)
+
+ftpcmd.c: ftpcmd.y
+ $(YACC) $(YFLAGS) $<
+ chmod a-w y.tab.c
+ mv -f y.tab.c ftpcmd.c
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+CLEANFILES = ftpd$(EXECSUFFIX) ftpcmd.c security.c security.h krb4.c gssapi.c
+
+clean cleandir:
+ rm -f *~ *.o core \#* $(CLEANFILES)
+
+distclean:
+ rm -f Makefile
+
+.PHONY: all install uninstall clean cleandir distclean
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/auth.c b/crypto/kerberosIV/appl/ftp/ftpd/auth.c
new file mode 100644
index 0000000..862eb6d
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/auth.c
@@ -0,0 +1,249 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: auth.c,v 1.11 1997/05/04 23:09:00 assar Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 != 4
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "extern.h"
+#include "krb4.h"
+#include "auth.h"
+
+static struct at auth_types [] = {
+ { "KERBEROS_V4", krb4_auth, krb4_adat, krb4_pbsz, krb4_prot, krb4_ccc,
+ krb4_mic, krb4_conf, krb4_enc, krb4_read, krb4_write, krb4_userok,
+ krb4_vprintf },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+};
+
+struct at *ct;
+
+int data_protection;
+int buffer_size;
+unsigned char *data_buffer;
+int auth_complete;
+
+
+char *protection_names[] = {
+ "clear", "safe",
+ "confidential", "private"
+};
+
+
+void auth_init(void)
+{
+}
+
+char *ftp_command;
+int prot_level;
+
+void new_ftp_command(char *command)
+{
+ ftp_command = command;
+}
+
+void delete_ftp_command(void)
+{
+ if(ftp_command){
+ free(ftp_command);
+ ftp_command = NULL;
+ }
+}
+
+int auth_ok(void)
+{
+ return ct && auth_complete;
+}
+
+void auth(char *auth)
+{
+ for(ct=auth_types; ct->name; ct++){
+ if(!strcasecmp(auth, ct->name)){
+ ct->auth(auth);
+ return;
+ }
+ }
+ reply(504, "%s is not a known security mechanism", auth);
+}
+
+void adat(char *auth)
+{
+ if(ct && !auth_complete)
+ ct->adat(auth);
+ else
+ reply(503, "You must (re)issue an AUTH first.");
+}
+
+void pbsz(int size)
+{
+ int old = buffer_size;
+ if(auth_ok())
+ ct->pbsz(size);
+ else
+ reply(503, "Incomplete security data exchange.");
+ if(buffer_size != old){
+ if(data_buffer)
+ free(data_buffer);
+ data_buffer = malloc(buffer_size + 4);
+ }
+}
+
+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;
+
+ if(!strcasecmp(pl, "S"))
+ p = prot_safe;
+
+ if(!strcasecmp(pl, "E"))
+ p = prot_confidential;
+
+ if(!strcasecmp(pl, "P"))
+ p = prot_private;
+
+ if(p == -1){
+ reply(504, "Unrecognized protection level.");
+ return;
+ }
+
+ if(auth_ok()){
+ if(ct->prot(p)){
+ reply(536, "%s does not support %s protection.",
+ ct->name, protection_names[p]);
+ }else{
+ data_protection = p;
+ reply(200, "Data protection is %s.",
+ protection_names[data_protection]);
+ }
+ }else{
+ reply(503, "Incomplete security data exchange.");
+ }
+}
+
+void ccc(void)
+{
+ if(auth_ok()){
+ if(!ct->ccc())
+ prot_level = prot_clear;
+ }else
+ reply(503, "Incomplete security data exchange.");
+}
+
+void mic(char *msg)
+{
+ if(auth_ok()){
+ if(!ct->mic(msg))
+ prot_level = prot_safe;
+ }else
+ reply(503, "Incomplete security data exchange.");
+}
+
+void conf(char *msg)
+{
+ if(auth_ok()){
+ if(!ct->conf(msg))
+ prot_level = prot_confidential;
+ }else
+ reply(503, "Incomplete security data exchange.");
+}
+
+void enc(char *msg)
+{
+ if(auth_ok()){
+ if(!ct->enc(msg))
+ prot_level = prot_private;
+ }else
+ reply(503, "Incomplete security data exchange.");
+}
+
+int auth_read(int fd, void *data, int length)
+{
+ if(auth_ok() && data_protection)
+ return ct->read(fd, data, length);
+ else
+ return read(fd, data, length);
+}
+
+int auth_write(int fd, void *data, int length)
+{
+ if(auth_ok() && data_protection)
+ return ct->write(fd, data, length);
+ else
+ return write(fd, data, length);
+}
+
+void auth_vprintf(const char *fmt, va_list ap)
+{
+ if(auth_ok() && prot_level){
+ ct->vprintf(fmt, ap);
+ }else
+ vprintf(fmt, ap);
+}
+
+void auth_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ auth_vprintf(fmt, ap);
+ va_end(ap);
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/auth.h b/crypto/kerberosIV/appl/ftp/ftpd/auth.h
new file mode 100644
index 0000000..17d9a13
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/auth.h
@@ -0,0 +1,109 @@
+/*
+ * 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: auth.h,v 1.9 1997/05/11 11:04:28 assar Exp $ */
+
+#ifndef __AUTH_H__
+#define __AUTH_H__
+
+#include <stdarg.h>
+
+struct at {
+ char *name;
+ int (*auth)(char*);
+ int (*adat)(char*);
+ int (*pbsz)(int);
+ int (*prot)(int);
+ int (*ccc)(void);
+ int (*mic)(char*);
+ int (*conf)(char*);
+ int (*enc)(char*);
+ int (*read)(int, void*, int);
+ int (*write)(int, void*, int);
+ int (*userok)(char*);
+ int (*vprintf)(const char*, va_list);
+};
+
+extern struct at *ct;
+
+enum protection_levels {
+ prot_clear, prot_safe, prot_confidential, prot_private
+};
+
+extern char *protection_names[];
+
+extern char *ftp_command;
+extern int prot_level;
+
+void delete_ftp_command(void);
+
+extern int data_protection;
+extern int buffer_size;
+extern unsigned char *data_buffer;
+extern int auth_complete;
+
+void auth_init(void);
+
+int auth_ok(void);
+
+void auth(char*);
+void adat(char*);
+void pbsz(int);
+void prot(char*);
+void ccc(void);
+void mic(char*);
+void conf(char*);
+void enc(char*);
+
+int auth_read(int, void*, int);
+int auth_write(int, void*, int);
+
+void auth_vprintf(const char *fmt, va_list ap)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 0)))
+#endif
+;
+void auth_printf(const char *fmt, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+void new_ftp_command(char *command);
+
+#endif /* __AUTH_H__ */
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/extern.h b/crypto/kerberosIV/appl/ftp/ftpd/extern.h
new file mode 100644
index 0000000..2e1e0d0
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/extern.h
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.2 (Berkeley) 4/4/94
+ */
+
+#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
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef NBBY
+#define NBBY CHAR_BIT
+#endif
+
+void abor(void);
+void blkfree(char **);
+char **copyblk(char **);
+void cwd(char *);
+void do_delete(char *);
+void dologout(int);
+void eprt(char *);
+void epsv(char *);
+void fatal(char *);
+int filename_check(char *);
+int ftpd_pclose(FILE *);
+FILE *ftpd_popen(char *, char *, int, int);
+char *ftpd_getline(char *, int);
+void ftpd_logwtmp(char *, char *, char *);
+void lreply(int, const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 2, 3)))
+#endif
+;
+void makedir(char *);
+void nack(char *);
+void nreply(const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+void pass(char *);
+void pasv(void);
+void perror_reply(int, const char *);
+void pwd(void);
+void removedir(char *);
+void renamecmd(char *, char *);
+char *renamefrom(char *);
+void reply(int, const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 2, 3)))
+#endif
+;
+void retrieve(const char *, char *);
+void send_file_list(char *);
+void setproctitle(const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+void statcmd(void);
+void statfilecmd(char *);
+void do_store(char *, char *, int);
+void upper(char *);
+void user(char *);
+void yyerror(char *);
+
+void list_file(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 *);
+
+void builtin_ls(FILE*, const char*);
+
+int do_login(int code, char *passwd);
+int klogin(char *name, char *password);
+
+const char *ftp_rooted(const char *path);
+
+extern struct sockaddr *ctrl_addr, *his_addr;
+extern char hostname[];
+
+extern struct sockaddr *data_dest;
+extern int logged_in;
+extern struct passwd *pw;
+extern int guest;
+extern int logging;
+extern int type;
+extern int oobflag;
+extern off_t file_size;
+extern off_t byte_count;
+extern jmp_buf urgcatch;
+
+extern int form;
+extern int debug;
+extern int ftpd_timeout;
+extern int maxtimeout;
+extern int pdata;
+extern char hostname[], remotehost[];
+extern char proctitle[];
+extern int usedefault;
+extern int transflag;
+extern char tmpline[];
+
+#endif /* _EXTERN_H_ */
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y
new file mode 100644
index 0000000..c482029
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y
@@ -0,0 +1,1457 @@
+/* $NetBSD: ftpcmd.y,v 1.6 1995/06/03 22:46:45 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1985, 1988, 1993, 1994
+ * 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.
+ *
+ * @(#)ftpcmd.y 8.3 (Berkeley) 4/6/94
+ */
+
+/*
+ * Grammar for FTP commands.
+ * See RFC 959.
+ */
+
+%{
+
+#include "ftpd_locl.h"
+RCSID("$Id: ftpcmd.y,v 1.56.2.2 2000/06/23 02:48:19 assar Exp $");
+
+off_t restart_point;
+
+static int cmd_type;
+static int cmd_form;
+static int cmd_bytesz;
+char cbuf[2048];
+char *fromname;
+
+struct tab {
+ char *name;
+ short token;
+ short state;
+ short implemented; /* 1 if command is implemented */
+ char *help;
+};
+
+extern struct tab cmdtab[];
+extern struct tab sitetab[];
+
+static char *copy (char *);
+static void help (struct tab *, char *);
+static struct tab *
+ lookup (struct tab *, char *);
+static void sizecmd (char *);
+static RETSIGTYPE toolong (int);
+static int yylex (void);
+
+/* This is for bison */
+
+#if !defined(alloca) && !defined(HAVE_ALLOCA)
+#define alloca(x) malloc(x)
+#endif
+
+%}
+
+%union {
+ int i;
+ char *s;
+}
+
+%token
+ A B C E F I
+ L N P R S T
+
+ SP CRLF COMMA
+
+ USER PASS ACCT REIN QUIT PORT
+ PASV TYPE STRU MODE RETR STOR
+ APPE MLFL MAIL MSND MSOM MSAM
+ MRSQ MRCP ALLO REST RNFR RNTO
+ ABOR DELE CWD LIST NLST SITE
+ sTAT HELP NOOP MKD RMD PWD
+ CDUP STOU SMNT SYST SIZE MDTM
+ EPRT EPSV
+
+ UMASK IDLE CHMOD
+
+ AUTH ADAT PROT PBSZ CCC MIC
+ CONF ENC
+
+ KAUTH KLIST KDESTROY KRBTKFILE AFSLOG
+ LOCATE URL
+
+ FEAT OPTS
+
+ LEXERR
+
+%token <s> STRING
+%token <i> NUMBER
+
+%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
+
+%start cmd_list
+
+%%
+
+cmd_list
+ : /* empty */
+ | cmd_list cmd
+ {
+ fromname = (char *) 0;
+ restart_point = (off_t) 0;
+ }
+ | cmd_list rcmd
+ ;
+
+cmd
+ : USER SP username CRLF
+ {
+ user($3);
+ free($3);
+ }
+ | PASS SP password CRLF
+ {
+ pass($3);
+ memset ($3, 0, strlen($3));
+ free($3);
+ }
+ | PORT SP host_port CRLF
+ {
+ usedefault = 0;
+ if (pdata >= 0) {
+ close(pdata);
+ pdata = -1;
+ }
+ reply(200, "PORT command successful.");
+ }
+ | EPRT SP STRING CRLF
+ {
+ eprt ($3);
+ free ($3);
+ }
+ | PASV CRLF
+ {
+ pasv ();
+ }
+ | EPSV CRLF
+ {
+ epsv (NULL);
+ }
+ | EPSV SP STRING CRLF
+ {
+ epsv ($3);
+ free ($3);
+ }
+ | TYPE SP type_code CRLF
+ {
+ switch (cmd_type) {
+
+ case TYPE_A:
+ if (cmd_form == FORM_N) {
+ reply(200, "Type set to A.");
+ type = cmd_type;
+ form = cmd_form;
+ } else
+ reply(504, "Form must be N.");
+ break;
+
+ case TYPE_E:
+ reply(504, "Type E not implemented.");
+ break;
+
+ case TYPE_I:
+ reply(200, "Type set to I.");
+ type = cmd_type;
+ break;
+
+ case TYPE_L:
+#if NBBY == 8
+ if (cmd_bytesz == 8) {
+ reply(200,
+ "Type set to L (byte size 8).");
+ type = cmd_type;
+ } else
+ reply(504, "Byte size must be 8.");
+#else /* NBBY == 8 */
+ UNIMPLEMENTED for NBBY != 8
+#endif /* NBBY == 8 */
+ }
+ }
+ | STRU SP struct_code CRLF
+ {
+ switch ($3) {
+
+ case STRU_F:
+ reply(200, "STRU F ok.");
+ break;
+
+ default:
+ reply(504, "Unimplemented STRU type.");
+ }
+ }
+ | MODE SP mode_code CRLF
+ {
+ switch ($3) {
+
+ case MODE_S:
+ reply(200, "MODE S ok.");
+ break;
+
+ default:
+ reply(502, "Unimplemented MODE type.");
+ }
+ }
+ | ALLO SP NUMBER CRLF
+ {
+ reply(202, "ALLO command ignored.");
+ }
+ | ALLO SP NUMBER SP R SP NUMBER CRLF
+ {
+ reply(202, "ALLO command ignored.");
+ }
+ | RETR SP pathname CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ retrieve(0, name);
+ if (name != NULL)
+ free(name);
+ }
+ | STOR SP pathname CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ do_store(name, "w", 0);
+ if (name != NULL)
+ free(name);
+ }
+ | APPE SP pathname CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ do_store(name, "a", 0);
+ if (name != NULL)
+ free(name);
+ }
+ | NLST CRLF check_login
+ {
+ if ($3)
+ send_file_list(".");
+ }
+ | NLST SP STRING CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ send_file_list(name);
+ if (name != NULL)
+ free(name);
+ }
+ | LIST CRLF check_login
+ {
+ if($3)
+ list_file(".");
+ }
+ | LIST SP pathname CRLF check_login
+ {
+ if($5)
+ list_file($3);
+ 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 SP pathname CRLF check_login_no_guest
+ {
+ if ($5 && $3 != NULL)
+ do_delete($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | RNTO SP pathname CRLF check_login_no_guest
+ {
+ if($5){
+ if (fromname) {
+ renamecmd(fromname, $3);
+ free(fromname);
+ fromname = (char *) 0;
+ } else {
+ reply(503, "Bad sequence of commands.");
+ }
+ }
+ if ($3 != NULL)
+ free($3);
+ }
+ | ABOR CRLF
+ {
+ if(oobflag){
+ reply(426, "Transfer aborted. Data connection closed.");
+ reply(226, "Abort successful");
+ oobflag = 0;
+ longjmp(urgcatch, 1);
+ }else
+ reply(225, "ABOR command successful.");
+ }
+ | CWD CRLF check_login
+ {
+ if ($3)
+ cwd(pw->pw_dir);
+ }
+ | CWD SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ cwd($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | HELP CRLF
+ {
+ help(cmdtab, (char *) 0);
+ }
+ | HELP SP STRING CRLF
+ {
+ char *cp = $3;
+
+ if (strncasecmp(cp, "SITE", 4) == 0) {
+ cp = $3 + 4;
+ if (*cp == ' ')
+ cp++;
+ if (*cp)
+ help(sitetab, cp);
+ else
+ help(sitetab, (char *) 0);
+ } else
+ help(cmdtab, $3);
+ }
+ | NOOP CRLF
+ {
+ reply(200, "NOOP command successful.");
+ }
+ | MKD SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ makedir($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | RMD SP pathname CRLF check_login_no_guest
+ {
+ if ($5 && $3 != NULL)
+ removedir($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | PWD CRLF check_login
+ {
+ if ($3)
+ pwd();
+ }
+ | CDUP CRLF check_login
+ {
+ if ($3)
+ cwd("..");
+ }
+ | FEAT CRLF
+ {
+ lreply(211, "Supported features:");
+ lreply(0, " MDTM");
+ lreply(0, " REST STREAM");
+ lreply(0, " SIZE");
+ reply(211, "End");
+ }
+ | OPTS SP STRING CRLF
+ {
+ free ($3);
+ reply(501, "Bad options");
+ }
+
+ | SITE SP HELP CRLF
+ {
+ help(sitetab, (char *) 0);
+ }
+ | SITE SP HELP SP STRING CRLF
+ {
+ help(sitetab, $5);
+ }
+ | SITE SP UMASK CRLF check_login
+ {
+ if ($5) {
+ int oldmask = umask(0);
+ umask(oldmask);
+ reply(200, "Current UMASK is %03o", oldmask);
+ }
+ }
+ | SITE SP UMASK SP octal_number CRLF check_login_no_guest
+ {
+ if ($7) {
+ if (($5 == -1) || ($5 > 0777)) {
+ reply(501, "Bad UMASK value");
+ } else {
+ int oldmask = umask($5);
+ reply(200,
+ "UMASK set to %03o (was %03o)",
+ $5, oldmask);
+ }
+ }
+ }
+ | SITE SP CHMOD SP octal_number SP pathname CRLF check_login_no_guest
+ {
+ if ($9 && $7 != NULL) {
+ if ($5 > 0777)
+ reply(501,
+ "CHMOD: Mode value must be between 0 and 0777");
+ else if (chmod($7, $5) < 0)
+ perror_reply(550, $7);
+ else
+ reply(200, "CHMOD command successful.");
+ }
+ if ($7 != NULL)
+ free($7);
+ }
+ | SITE SP IDLE CRLF
+ {
+ reply(200,
+ "Current IDLE time limit is %d seconds; max %d",
+ ftpd_timeout, maxtimeout);
+ }
+ | SITE SP IDLE SP NUMBER CRLF
+ {
+ if ($5 < 30 || $5 > maxtimeout) {
+ reply(501,
+ "Maximum IDLE time must be between 30 and %d seconds",
+ maxtimeout);
+ } else {
+ ftpd_timeout = $5;
+ alarm((unsigned) ftpd_timeout);
+ reply(200,
+ "Maximum IDLE time set to %d seconds",
+ ftpd_timeout);
+ }
+ }
+
+ | SITE SP KAUTH SP STRING CRLF check_login
+ {
+#ifdef KRB4
+ char *p;
+
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else{
+ if($7 && $5 != NULL){
+ p = strpbrk($5, " \t");
+ if(p){
+ *p++ = 0;
+ kauth($5, p + strspn(p, " \t"));
+ }else
+ kauth($5, NULL);
+ }
+ }
+ if($5 != NULL)
+ free($5);
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP KLIST CRLF check_login
+ {
+#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 LOCATE SP STRING CRLF check_login
+ {
+ 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 SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ do_store($3, "w", 1);
+ if ($3 != NULL)
+ free($3);
+ }
+ | SYST CRLF
+ {
+#if !defined(WIN32) && !defined(__EMX__) && !defined(__OS2__) && !defined(__CYGWIN32__)
+ reply(215, "UNIX Type: L%d", NBBY);
+#else
+ reply(215, "UNKNOWN Type: L%d", NBBY);
+#endif
+ }
+
+ /*
+ * SIZE is not in RFC959, but Postel has blessed it and
+ * it will be in the updated RFC.
+ *
+ * Return size of file in a format suitable for
+ * using with RESTART (we just count bytes).
+ */
+ | SIZE SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ sizecmd($3);
+ if ($3 != NULL)
+ free($3);
+ }
+
+ /*
+ * MDTM is not in RFC959, but Postel has blessed it and
+ * it will be in the updated RFC.
+ *
+ * Return modification time of file as an ISO 3307
+ * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx
+ * where xxx is the fractional second (of any precision,
+ * not necessarily 3 digits)
+ */
+ | MDTM SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL) {
+ struct stat stbuf;
+ if (stat($3, &stbuf) < 0)
+ reply(550, "%s: %s",
+ $3, strerror(errno));
+ else if (!S_ISREG(stbuf.st_mode)) {
+ reply(550,
+ "%s: not a plain file.", $3);
+ } else {
+ struct tm *t;
+ time_t mtime = stbuf.st_mtime;
+
+ t = gmtime(&mtime);
+ reply(213,
+ "%04d%02d%02d%02d%02d%02d",
+ t->tm_year + 1900,
+ t->tm_mon + 1,
+ t->tm_mday,
+ t->tm_hour,
+ t->tm_min,
+ t->tm_sec);
+ }
+ }
+ if ($3 != NULL)
+ free($3);
+ }
+ | QUIT CRLF
+ {
+ reply(221, "Goodbye.");
+ dologout(0);
+ }
+ | error CRLF
+ {
+ yyerrok;
+ }
+ ;
+rcmd
+ : RNFR SP pathname CRLF check_login_no_guest
+ {
+ restart_point = (off_t) 0;
+ if ($5 && $3) {
+ fromname = renamefrom($3);
+ if (fromname == (char *) 0 && $3) {
+ free($3);
+ }
+ }
+ }
+ | REST SP byte_size CRLF
+ {
+ fromname = (char *) 0;
+ restart_point = $3; /* XXX $3 is only "int" */
+ reply(350, "Restarting at %ld. %s",
+ (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
+ {
+ mec($3, prot_private);
+ free($3);
+ }
+ ;
+
+username
+ : STRING
+ ;
+
+password
+ : /* empty */
+ {
+ $$ = (char *)calloc(1, sizeof(char));
+ }
+ | STRING
+ ;
+
+byte_size
+ : NUMBER
+ ;
+
+host_port
+ : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA
+ NUMBER COMMA NUMBER
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)data_dest;
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons($9 * 256 + $11);
+ sin->sin_addr.s_addr =
+ htonl(($1 << 24) | ($3 << 16) | ($5 << 8) | $7);
+ }
+ ;
+
+form_code
+ : N
+ {
+ $$ = FORM_N;
+ }
+ | T
+ {
+ $$ = FORM_T;
+ }
+ | C
+ {
+ $$ = FORM_C;
+ }
+ ;
+
+type_code
+ : A
+ {
+ cmd_type = TYPE_A;
+ cmd_form = FORM_N;
+ }
+ | A SP form_code
+ {
+ cmd_type = TYPE_A;
+ cmd_form = $3;
+ }
+ | E
+ {
+ cmd_type = TYPE_E;
+ cmd_form = FORM_N;
+ }
+ | E SP form_code
+ {
+ cmd_type = TYPE_E;
+ cmd_form = $3;
+ }
+ | I
+ {
+ cmd_type = TYPE_I;
+ }
+ | L
+ {
+ cmd_type = TYPE_L;
+ cmd_bytesz = NBBY;
+ }
+ | L SP byte_size
+ {
+ cmd_type = TYPE_L;
+ cmd_bytesz = $3;
+ }
+ /* this is for a bug in the BBN ftp */
+ | L byte_size
+ {
+ cmd_type = TYPE_L;
+ cmd_bytesz = $2;
+ }
+ ;
+
+struct_code
+ : F
+ {
+ $$ = STRU_F;
+ }
+ | R
+ {
+ $$ = STRU_R;
+ }
+ | P
+ {
+ $$ = STRU_P;
+ }
+ ;
+
+mode_code
+ : S
+ {
+ $$ = MODE_S;
+ }
+ | B
+ {
+ $$ = MODE_B;
+ }
+ | C
+ {
+ $$ = MODE_C;
+ }
+ ;
+
+pathname
+ : pathstring
+ {
+ /*
+ * Problem: this production is used for all pathname
+ * processing, but only gives a 550 error reply.
+ * This is a valid reply in some cases but not in others.
+ */
+ if (logged_in && $1 && *$1 == '~') {
+ glob_t gl;
+ int flags =
+ GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+ memset(&gl, 0, sizeof(gl));
+ if (glob($1, flags, NULL, &gl) ||
+ gl.gl_pathc == 0) {
+ reply(550, "not found");
+ $$ = NULL;
+ } else {
+ $$ = strdup(gl.gl_pathv[0]);
+ }
+ globfree(&gl);
+ free($1);
+ } else
+ $$ = $1;
+ }
+ ;
+
+pathstring
+ : STRING
+ ;
+
+octal_number
+ : NUMBER
+ {
+ int ret, dec, multby, digit;
+
+ /*
+ * Convert a number that was read as decimal number
+ * to what it would be if it had been read as octal.
+ */
+ dec = $1;
+ multby = 1;
+ ret = 0;
+ while (dec) {
+ digit = dec%10;
+ if (digit > 7) {
+ ret = -1;
+ break;
+ }
+ ret += digit * multby;
+ multby *= 8;
+ dec /= 10;
+ }
+ $$ = ret;
+ }
+ ;
+
+
+check_login_no_guest : check_login
+ {
+ $$ = $1 && !guest;
+ if($1 && !$$)
+ reply(550, "Permission denied");
+ }
+ ;
+
+check_login : check_secure
+ {
+ if($1) {
+ if(($$ = logged_in) == 0)
+ reply(530, "Please login with USER and PASS.");
+ } else
+ $$ = 0;
+ }
+ ;
+
+check_secure : /* empty */
+ {
+ $$ = 1;
+ if(sec_complete && !secure_command()) {
+ $$ = 0;
+ reply(533, "Command protection level denied "
+ "for paranoid reasons.");
+ }
+ }
+ ;
+
+%%
+
+extern jmp_buf errcatch;
+
+#define CMD 0 /* beginning of command */
+#define ARGS 1 /* expect miscellaneous arguments */
+#define STR1 2 /* expect SP followed by STRING */
+#define STR2 3 /* expect STRING */
+#define OSTR 4 /* optional SP then STRING */
+#define ZSTR1 5 /* SP then optional STRING */
+#define ZSTR2 6 /* optional STRING after SP */
+#define SITECMD 7 /* SITE command */
+#define NSTR 8 /* Number followed by a string */
+
+struct tab cmdtab[] = { /* In order defined in RFC 765 */
+ { "USER", USER, STR1, 1, "<sp> username" },
+ { "PASS", PASS, ZSTR1, 1, "<sp> password" },
+ { "ACCT", ACCT, STR1, 0, "(specify account)" },
+ { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
+ { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
+ { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
+ { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
+ { "EPRT", EPRT, STR1, 1, "<sp> string" },
+ { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
+ { "EPSV", EPSV, OSTR, 1, "[<sp> foo]" },
+ { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
+ { "STRU", STRU, ARGS, 1, "(specify file structure)" },
+ { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
+ { "RETR", RETR, STR1, 1, "<sp> file-name" },
+ { "STOR", STOR, STR1, 1, "<sp> file-name" },
+ { "APPE", APPE, STR1, 1, "<sp> file-name" },
+ { "MLFL", MLFL, OSTR, 0, "(mail file)" },
+ { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
+ { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
+ { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
+ { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
+ { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
+ { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
+ { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
+ { "REST", REST, ARGS, 1, "<sp> offset (restart command)" },
+ { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
+ { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
+ { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
+ { "DELE", DELE, STR1, 1, "<sp> file-name" },
+ { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
+ { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
+ { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
+ { "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 ]" },
+ { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
+ { "NOOP", NOOP, ARGS, 1, "" },
+ { "MKD", MKD, STR1, 1, "<sp> path-name" },
+ { "XMKD", MKD, STR1, 1, "<sp> path-name" },
+ { "RMD", RMD, STR1, 1, "<sp> path-name" },
+ { "XRMD", RMD, STR1, 1, "<sp> path-name" },
+ { "PWD", PWD, ARGS, 1, "(return current directory)" },
+ { "XPWD", PWD, ARGS, 1, "(return current directory)" },
+ { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
+ { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
+ { "STOU", STOU, STR1, 1, "<sp> file-name" },
+ { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
+ { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
+
+ /* extensions from RFC2228 */
+ { "AUTH", AUTH, STR1, 1, "<sp> auth-type" },
+ { "ADAT", ADAT, STR1, 1, "<sp> auth-data" },
+ { "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" },
+ { "PROT", PROT, STR1, 1, "<sp> prot-level" },
+ { "CCC", CCC, ARGS, 1, "" },
+ { "MIC", MIC, STR1, 1, "<sp> integrity command" },
+ { "CONF", CONF, STR1, 1, "<sp> confidentiality command" },
+ { "ENC", ENC, STR1, 1, "<sp> privacy command" },
+
+ /* RFC2389 */
+ { "FEAT", FEAT, ARGS, 1, "" },
+ { "OPTS", OPTS, ARGS, 1, "<sp> command [<sp> options]" },
+
+ { NULL, 0, 0, 0, 0 }
+};
+
+struct tab sitetab[] = {
+ { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
+ { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
+ { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
+ { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
+
+ { "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]" },
+
+ { "LOCATE", LOCATE, STR1, 1, "<sp> globexpr" },
+ { "FIND", LOCATE, STR1, 1, "<sp> globexpr" },
+
+ { "URL", URL, ARGS, 1, "?" },
+
+ { NULL, 0, 0, 0, 0 }
+};
+
+static struct tab *
+lookup(struct tab *p, char *cmd)
+{
+
+ for (; p->name != NULL; p++)
+ if (strcmp(cmd, p->name) == 0)
+ return (p);
+ return (0);
+}
+
+/*
+ * ftpd_getline - a hacked up version of fgets to ignore TELNET escape codes.
+ */
+char *
+ftpd_getline(char *s, int n)
+{
+ int c;
+ char *cs;
+
+ cs = s;
+/* tmpline may contain saved command from urgent mode interruption */
+ if(ftp_command){
+ strlcpy(s, ftp_command, n);
+ if (debug)
+ syslog(LOG_DEBUG, "command: %s", s);
+#ifdef XXX
+ fprintf(stderr, "%s\n", s);
+#endif
+ return s;
+ }
+ while ((c = getc(stdin)) != EOF) {
+ c &= 0377;
+ if (c == IAC) {
+ if ((c = getc(stdin)) != EOF) {
+ c &= 0377;
+ switch (c) {
+ case WILL:
+ case WONT:
+ c = getc(stdin);
+ printf("%c%c%c", IAC, DONT, 0377&c);
+ fflush(stdout);
+ continue;
+ case DO:
+ case DONT:
+ c = getc(stdin);
+ printf("%c%c%c", IAC, WONT, 0377&c);
+ fflush(stdout);
+ continue;
+ case IAC:
+ break;
+ default:
+ continue; /* ignore command */
+ }
+ }
+ }
+ *cs++ = c;
+ if (--n <= 0 || c == '\n')
+ break;
+ }
+ if (c == EOF && cs == s)
+ return (NULL);
+ *cs++ = '\0';
+ if (debug) {
+ if (!guest && strncasecmp("pass ", s, 5) == 0) {
+ /* Don't syslog passwords */
+ syslog(LOG_DEBUG, "command: %.5s ???", s);
+ } else {
+ char *cp;
+ int len;
+
+ /* Don't syslog trailing CR-LF */
+ len = strlen(s);
+ cp = s + len - 1;
+ while (cp >= s && (*cp == '\n' || *cp == '\r')) {
+ --cp;
+ --len;
+ }
+ syslog(LOG_DEBUG, "command: %.*s", len, s);
+ }
+ }
+#ifdef XXX
+ fprintf(stderr, "%s\n", s);
+#endif
+ return (s);
+}
+
+static RETSIGTYPE
+toolong(int signo)
+{
+
+ reply(421,
+ "Timeout (%d seconds): closing control connection.",
+ ftpd_timeout);
+ if (logging)
+ syslog(LOG_INFO, "User %s timed out after %d seconds",
+ (pw ? pw -> pw_name : "unknown"), ftpd_timeout);
+ dologout(1);
+ SIGRETURN(0);
+}
+
+static int
+yylex(void)
+{
+ static int cpos, state;
+ char *cp, *cp2;
+ struct tab *p;
+ int n;
+ char c;
+
+ for (;;) {
+ switch (state) {
+
+ case CMD:
+ signal(SIGALRM, toolong);
+ alarm((unsigned) ftpd_timeout);
+ if (ftpd_getline(cbuf, sizeof(cbuf)-1) == NULL) {
+ reply(221, "You could at least say goodbye.");
+ dologout(0);
+ }
+ alarm(0);
+#ifdef HAVE_SETPROCTITLE
+ if (strncasecmp(cbuf, "PASS", 4) != NULL)
+ setproctitle("%s: %s", proctitle, cbuf);
+#endif /* HAVE_SETPROCTITLE */
+ if ((cp = strchr(cbuf, '\r'))) {
+ *cp++ = '\n';
+ *cp = '\0';
+ }
+ if ((cp = strpbrk(cbuf, " \n")))
+ cpos = cp - cbuf;
+ if (cpos == 0)
+ cpos = 4;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ strupr(cbuf);
+ p = lookup(cmdtab, cbuf);
+ cbuf[cpos] = c;
+ if (p != 0) {
+ if (p->implemented == 0) {
+ nack(p->name);
+ longjmp(errcatch,0);
+ /* NOTREACHED */
+ }
+ state = p->state;
+ yylval.s = p->name;
+ return (p->token);
+ }
+ break;
+
+ case SITECMD:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ return (SP);
+ }
+ cp = &cbuf[cpos];
+ if ((cp2 = strpbrk(cp, " \n")))
+ cpos = cp2 - cbuf;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ strupr(cp);
+ p = lookup(sitetab, cp);
+ cbuf[cpos] = c;
+ if (p != 0) {
+ if (p->implemented == 0) {
+ state = CMD;
+ nack(p->name);
+ longjmp(errcatch,0);
+ /* NOTREACHED */
+ }
+ state = p->state;
+ yylval.s = p->name;
+ return (p->token);
+ }
+ state = CMD;
+ break;
+
+ case OSTR:
+ if (cbuf[cpos] == '\n') {
+ state = CMD;
+ return (CRLF);
+ }
+ /* FALLTHROUGH */
+
+ case STR1:
+ case ZSTR1:
+ dostr1:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ if(state == OSTR)
+ state = STR2;
+ else
+ state++;
+ return (SP);
+ }
+ break;
+
+ case ZSTR2:
+ if (cbuf[cpos] == '\n') {
+ state = CMD;
+ return (CRLF);
+ }
+ /* FALLTHROUGH */
+
+ case STR2:
+ cp = &cbuf[cpos];
+ n = strlen(cp);
+ cpos += n - 1;
+ /*
+ * Make sure the string is nonempty and \n terminated.
+ */
+ if (n > 1 && cbuf[cpos] == '\n') {
+ cbuf[cpos] = '\0';
+ yylval.s = copy(cp);
+ cbuf[cpos] = '\n';
+ state = ARGS;
+ return (STRING);
+ }
+ break;
+
+ case NSTR:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ return (SP);
+ }
+ if (isdigit(cbuf[cpos])) {
+ cp = &cbuf[cpos];
+ while (isdigit(cbuf[++cpos]))
+ ;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ yylval.i = atoi(cp);
+ cbuf[cpos] = c;
+ state = STR1;
+ return (NUMBER);
+ }
+ state = STR1;
+ goto dostr1;
+
+ case ARGS:
+ if (isdigit(cbuf[cpos])) {
+ cp = &cbuf[cpos];
+ while (isdigit(cbuf[++cpos]))
+ ;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ yylval.i = atoi(cp);
+ cbuf[cpos] = c;
+ return (NUMBER);
+ }
+ switch (cbuf[cpos++]) {
+
+ case '\n':
+ state = CMD;
+ return (CRLF);
+
+ case ' ':
+ return (SP);
+
+ case ',':
+ return (COMMA);
+
+ case 'A':
+ case 'a':
+ return (A);
+
+ case 'B':
+ case 'b':
+ return (B);
+
+ case 'C':
+ case 'c':
+ return (C);
+
+ case 'E':
+ case 'e':
+ return (E);
+
+ case 'F':
+ case 'f':
+ return (F);
+
+ case 'I':
+ case 'i':
+ return (I);
+
+ case 'L':
+ case 'l':
+ return (L);
+
+ case 'N':
+ case 'n':
+ return (N);
+
+ case 'P':
+ case 'p':
+ return (P);
+
+ case 'R':
+ case 'r':
+ return (R);
+
+ case 'S':
+ case 's':
+ return (S);
+
+ case 'T':
+ case 't':
+ return (T);
+
+ }
+ break;
+
+ default:
+ fatal("Unknown state in scanner.");
+ }
+ yyerror((char *) 0);
+ state = CMD;
+ longjmp(errcatch,0);
+ }
+}
+
+static char *
+copy(char *s)
+{
+ char *p;
+
+ p = strdup(s);
+ if (p == NULL)
+ fatal("Ran out of memory.");
+ return p;
+}
+
+static void
+help(struct tab *ctab, char *s)
+{
+ struct tab *c;
+ int width, NCMDS;
+ char *type;
+ char buf[1024];
+
+ if (ctab == sitetab)
+ type = "SITE ";
+ else
+ type = "";
+ width = 0, NCMDS = 0;
+ for (c = ctab; c->name != NULL; c++) {
+ int len = strlen(c->name);
+
+ if (len > width)
+ width = len;
+ NCMDS++;
+ }
+ width = (width + 8) &~ 7;
+ if (s == 0) {
+ int i, j, w;
+ int columns, lines;
+
+ lreply(214, "The following %scommands are recognized %s.",
+ type, "(* =>'s unimplemented)");
+ columns = 76 / width;
+ if (columns == 0)
+ columns = 1;
+ lines = (NCMDS + columns - 1) / columns;
+ for (i = 0; i < lines; i++) {
+ strlcpy (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 ? ' ' : '*');
+ if (c + lines >= &ctab[NCMDS])
+ break;
+ w = strlen(c->name) + 1;
+ while (w < width) {
+ strlcat (buf,
+ " ",
+ sizeof(buf));
+ w++;
+ }
+ }
+ lreply(214, "%s", buf);
+ }
+ reply(214, "Direct comments to kth-krb-bugs@pdc.kth.se");
+ return;
+ }
+ strupr(s);
+ c = lookup(ctab, s);
+ if (c == (struct tab *)0) {
+ reply(502, "Unknown command %s.", s);
+ return;
+ }
+ if (c->implemented)
+ reply(214, "Syntax: %s%s %s", type, c->name, c->help);
+ else
+ reply(214, "%s%-*s\t%s; unimplemented.", type, width,
+ c->name, c->help);
+}
+
+static void
+sizecmd(char *filename)
+{
+ switch (type) {
+ case TYPE_L:
+ case TYPE_I: {
+ struct stat stbuf;
+ if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode))
+ reply(550, "%s: not a plain file.", filename);
+ else
+ reply(213, "%lu", (unsigned long)stbuf.st_size);
+ break;
+ }
+ case TYPE_A: {
+ FILE *fin;
+ int c;
+ size_t count;
+ struct stat stbuf;
+ fin = fopen(filename, "r");
+ if (fin == NULL) {
+ perror_reply(550, filename);
+ return;
+ }
+ if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {
+ reply(550, "%s: not a plain file.", filename);
+ fclose(fin);
+ return;
+ }
+
+ count = 0;
+ while((c=getc(fin)) != EOF) {
+ if (c == '\n') /* will get expanded to \r\n */
+ count++;
+ count++;
+ }
+ fclose(fin);
+
+ 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
new file mode 100644
index 0000000..6d8a392
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c
@@ -0,0 +1,2250 @@
+/*
+ * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#define FTP_NAMES
+#include "ftpd_locl.h"
+#ifdef KRB5
+#include <krb5.h>
+#endif
+#include "getarg.h"
+
+RCSID("$Id: ftpd.c,v 1.131.2.4 2000/09/26 09:30:26 assar Exp $");
+
+static char version[] = "Version 6.00";
+
+extern off_t restart_point;
+extern char cbuf[];
+
+struct sockaddr_storage ctrl_addr_ss;
+struct sockaddr *ctrl_addr = (struct sockaddr *)&ctrl_addr_ss;
+
+struct sockaddr_storage data_source_ss;
+struct sockaddr *data_source = (struct sockaddr *)&data_source_ss;
+
+struct sockaddr_storage data_dest_ss;
+struct sockaddr *data_dest = (struct sockaddr *)&data_dest_ss;
+
+struct sockaddr_storage his_addr_ss;
+struct sockaddr *his_addr = (struct sockaddr *)&his_addr_ss;
+
+struct sockaddr_storage pasv_addr_ss;
+struct sockaddr *pasv_addr = (struct sockaddr *)&pasv_addr_ss;
+
+int data;
+jmp_buf errcatch, urgcatch;
+int oobflag;
+int logged_in;
+struct passwd *pw;
+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;
+int guest;
+int dochroot;
+int type;
+int form;
+int stru; /* avoid C keyword */
+int mode;
+int usedefault = 1; /* for data transfers */
+int pdata = -1; /* for passive mode */
+int transflag;
+off_t file_size;
+off_t byte_count;
+#if !defined(CMASK) || CMASK == 0
+#undef CMASK
+#define CMASK 027
+#endif
+int defumask = CMASK; /* default umask value */
+int guest_umask = 0777; /* Paranoia for anonymous users */
+char tmpline[10240];
+char hostname[MaxHostNameLen];
+char remotehost[MaxHostNameLen];
+static char ttyline[20];
+
+#define AUTH_PLAIN (1 << 0) /* allow sending passwords */
+#define AUTH_OTP (1 << 1) /* passwords are one-time */
+#define AUTH_FTP (1 << 2) /* allow anonymous login */
+
+static int auth_level = 0; /* Only allow kerberos login by default */
+
+/*
+ * Timeout intervals for retrying connections
+ * to hosts that don't accept PORT cmds. This
+ * is a kludge, but given the problems with TCP...
+ */
+#define SWAITMAX 90 /* wait at most 90 seconds */
+#define SWAITINT 5 /* interval between retries */
+
+int swaitmax = SWAITMAX;
+int swaitint = SWAITINT;
+
+#ifdef HAVE_SETPROCTITLE
+char proctitle[BUFSIZ]; /* initial part of title */
+#endif /* HAVE_SETPROCTITLE */
+
+#define LOGCMD(cmd, file) \
+ if (logging > 1) \
+ syslog(LOG_INFO,"%s %s%s", cmd, \
+ *(file) == '/' ? "" : curdir(), file);
+#define LOGCMD2(cmd, file1, file2) \
+ if (logging > 1) \
+ syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
+ *(file1) == '/' ? "" : curdir(), file1, \
+ *(file2) == '/' ? "" : curdir(), file2);
+#define LOGBYTES(cmd, file, cnt) \
+ if (logging > 1) { \
+ if (cnt == (off_t)-1) \
+ syslog(LOG_INFO,"%s %s%s", cmd, \
+ *(file) == '/' ? "" : curdir(), file); \
+ else \
+ syslog(LOG_INFO, "%s %s%s = %ld bytes", \
+ cmd, (*(file) == '/') ? "" : curdir(), file, (long)cnt); \
+ }
+
+static void ack (char *);
+static void myoob (int);
+static int checkuser (char *, char *);
+static int checkaccess (char *);
+static FILE *dataconn (const char *, off_t, const char *);
+static void dolog (struct sockaddr *);
+static void end_login (void);
+static FILE *getdatasock (const char *);
+static char *gunique (char *);
+static RETSIGTYPE lostconn (int);
+static int receive_data (FILE *, FILE *);
+static void send_data (FILE *, FILE *);
+static struct passwd * sgetpwnam (char *);
+
+static char *
+curdir(void)
+{
+ static char path[MaxPathLen+1]; /* path + '/' + '\0' */
+
+ if (getcwd(path, sizeof(path)-1) == NULL)
+ return ("");
+ if (path[1] != '\0') /* special case for root dir. */
+ strlcat(path, "/", sizeof(path));
+ /* For guest account, skip / since it's chrooted */
+ return (guest ? path+1 : path);
+}
+
+#ifndef LINE_MAX
+#define LINE_MAX 1024
+#endif
+
+static int
+parse_auth_level(char *str)
+{
+ char *p;
+ int ret = 0;
+ char *foo = NULL;
+
+ for(p = strtok_r(str, ",", &foo);
+ p;
+ 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;
+ else if(strcmp(p, "plain") == 0)
+ ret |= AUTH_PLAIN;
+ else if(strcmp(p, "none") == 0)
+ ret |= AUTH_PLAIN|AUTH_FTP;
+ else
+ warnx("bad value for -a: `%s'", p);
+ }
+ return ret;
+}
+
+/*
+ * Print usage and die.
+ */
+
+static int interactive_flag;
+static char *guest_umask_string;
+static char *port_string;
+static char *umask_string;
+static char *auth_string;
+
+int use_builtin_ls = -1;
+
+static int help_flag;
+static int version_flag;
+
+struct getargs args[] = {
+ { NULL, 'a', arg_string, &auth_string, "required authentication" },
+ { NULL, 'i', arg_flag, &interactive_flag, "don't assume stdin is a socket" },
+ { NULL, 'p', arg_string, &port_string, "what port to listen to" },
+ { NULL, 'g', arg_string, &guest_umask_string, "umask for guest logins" },
+ { NULL, 'l', arg_counter, &logging, "log more stuff", "" },
+ { NULL, 't', arg_integer, &ftpd_timeout, "initial timeout" },
+ { NULL, 'T', arg_integer, &maxtimeout, "max timeout" },
+ { NULL, 'u', arg_string, &umask_string, "umask for user logins" },
+ { NULL, 'd', arg_flag, &debug, "enable debugging" },
+ { NULL, 'v', arg_flag, &debug, "enable debugging" },
+ { "builtin-ls", 'B', arg_flag, &use_builtin_ls, "use built-in ls to list files" },
+ { "version", 0, arg_flag, &version_flag },
+ { "help", 'h', arg_flag, &help_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage (int code)
+{
+ arg_printusage(args, num_args, NULL, "");
+ exit (code);
+}
+
+/* output contents of a file */
+static int
+show_file(const char *file, int code)
+{
+ FILE *f;
+ char buf[128];
+
+ f = fopen(file, "r");
+ if(f == NULL)
+ return -1;
+ while(fgets(buf, sizeof(buf), f)){
+ buf[strcspn(buf, "\r\n")] = '\0';
+ lreply(code, "%s", buf);
+ }
+ fclose(f);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int addrlen, on = 1, tos;
+ char *cp, line[LINE_MAX];
+ FILE *fd;
+ int port;
+ struct servent *sp;
+
+ int optind = 0;
+
+#ifdef KRB4
+ /* detach from any tickets and tokens */
+ {
+ char tkfile[1024];
+ snprintf(tkfile, sizeof(tkfile),
+ "/tmp/ftp_%u", (unsigned)getpid());
+ krb_set_tkt_string(tkfile);
+ if(k_hasafs())
+ k_setpag();
+ }
+#endif
+ if(getarg(args, num_args, argc, argv, &optind))
+ usage(1);
+
+ if(help_flag)
+ usage(0);
+
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+
+ if(auth_string)
+ auth_level = parse_auth_level(auth_string);
+ {
+ char *p;
+ long val = 0;
+
+ if(guest_umask_string) {
+ val = strtol(guest_umask_string, &p, 8);
+ if (*p != '\0' || val < 0)
+ warnx("bad value for -g");
+ else
+ guest_umask = val;
+ }
+ if(umask_string) {
+ val = strtol(umask_string, &p, 8);
+ if (*p != '\0' || val < 0)
+ warnx("bad value for -u");
+ else
+ defumask = val;
+ }
+ }
+ if(port_string) {
+ sp = getservbyname(port_string, "tcp");
+ if(sp)
+ port = sp->s_port;
+ else
+ if(isdigit(port_string[0]))
+ port = htons(atoi(port_string));
+ else
+ warnx("bad value for -p");
+ } else {
+ sp = getservbyname("ftp", "tcp");
+ if(sp)
+ port = sp->s_port;
+ else
+ port = htons(21);
+ }
+
+ if (maxtimeout < ftpd_timeout)
+ maxtimeout = ftpd_timeout;
+
+#if 0
+ if (ftpd_timeout > maxtimeout)
+ ftpd_timeout = maxtimeout;
+#endif
+
+
+ if(interactive_flag)
+ mini_inetd (port);
+
+ /*
+ * LOG_NDELAY sets up the logging connection immediately,
+ * necessary for anonymous ftp's that chroot and can't do it later.
+ */
+ openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
+ addrlen = sizeof(his_addr_ss);
+ if (getpeername(STDIN_FILENO, his_addr, &addrlen) < 0) {
+ syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
+ exit(1);
+ }
+ addrlen = sizeof(ctrl_addr_ss);
+ if (getsockname(STDIN_FILENO, ctrl_addr, &addrlen) < 0) {
+ syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
+ exit(1);
+ }
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ tos = IPTOS_LOWDELAY;
+ if (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS,
+ (void *)&tos, sizeof(int)) < 0)
+ syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+ data_source->sa_family = ctrl_addr->sa_family;
+ socket_set_port (data_source,
+ htons(ntohs(socket_get_port(ctrl_addr)) - 1));
+
+ /* set this here so it can be put in wtmp */
+ snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid());
+
+
+ /* freopen(_PATH_DEVNULL, "w", stderr); */
+ signal(SIGPIPE, lostconn);
+ signal(SIGCHLD, SIG_IGN);
+#ifdef SIGURG
+ if (signal(SIGURG, myoob) == SIG_ERR)
+ syslog(LOG_ERR, "signal: %m");
+#endif
+
+ /* Try to handle urgent data inline */
+#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
+ if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on,
+ sizeof(on)) < 0)
+ syslog(LOG_ERR, "setsockopt: %m");
+#endif
+
+#ifdef F_SETOWN
+ if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
+ syslog(LOG_ERR, "fcntl F_SETOWN: %m");
+#endif
+ dolog(his_addr);
+ /*
+ * Set up default state
+ */
+ data = -1;
+ type = TYPE_A;
+ form = FORM_N;
+ stru = STRU_F;
+ mode = MODE_S;
+ tmpline[0] = '\0';
+
+ /* If logins are disabled, print out the message. */
+ if(show_file(_PATH_NOLOGIN, 530) == 0) {
+ reply(530, "System not available.");
+ exit(0);
+ }
+ show_file(_PATH_FTPWELCOME, 220);
+ /* reply(220,) must follow */
+ 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();
+ /* NOTREACHED */
+}
+
+static RETSIGTYPE
+lostconn(int signo)
+{
+
+ if (debug)
+ syslog(LOG_DEBUG, "lost connection");
+ dologout(-1);
+}
+
+/*
+ * Helper function for sgetpwnam().
+ */
+static char *
+sgetsave(char *s)
+{
+ char *new = strdup(s);
+
+ if (new == NULL) {
+ perror_reply(421, "Local resource failure: malloc");
+ dologout(1);
+ /* NOTREACHED */
+ }
+ return new;
+}
+
+/*
+ * Save the result of a getpwnam. Used for USER command, since
+ * the data returned must not be clobbered by any other command
+ * (e.g., globbing).
+ */
+static struct passwd *
+sgetpwnam(char *name)
+{
+ static struct passwd save;
+ struct passwd *p;
+
+ if ((p = k_getpwnam(name)) == NULL)
+ return (p);
+ if (save.pw_name) {
+ free(save.pw_name);
+ free(save.pw_passwd);
+ free(save.pw_gecos);
+ free(save.pw_dir);
+ free(save.pw_shell);
+ }
+ save = *p;
+ save.pw_name = sgetsave(p->pw_name);
+ save.pw_passwd = sgetsave(p->pw_passwd);
+ save.pw_gecos = sgetsave(p->pw_gecos);
+ save.pw_dir = sgetsave(p->pw_dir);
+ save.pw_shell = sgetsave(p->pw_shell);
+ return (&save);
+}
+
+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.
+ * Sets global passwd pointer pw if named account exists and is acceptable;
+ * sets askpasswd if a PASS command is expected. If logged in previously,
+ * need to reset state. If name is "ftp" or "anonymous", the name is not in
+ * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
+ * If account doesn't exist, ask for passwd anyway. Otherwise, check user
+ * requesting login privileges. Disallow anyone who does not have a standard
+ * shell as returned by getusershell(). Disallow anyone mentioned in the file
+ * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
+ */
+void
+user(char *name)
+{
+ char *cp, *shell;
+
+ if(auth_level == 0 && !sec_complete){
+ reply(530, "No login allowed without authorization.");
+ return;
+ }
+
+ if (logged_in) {
+ if (guest) {
+ reply(530, "Can't change user from guest login.");
+ return;
+ } else if (dochroot) {
+ reply(530, "Can't change user from chroot user.");
+ return;
+ }
+ end_login();
+ }
+
+ guest = 0;
+ if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
+ if ((auth_level & AUTH_FTP) == 0 ||
+ checkaccess("ftp") ||
+ checkaccess("anonymous"))
+ reply(530, "User %s access denied.", name);
+ else if ((pw = sgetpwnam("ftp")) != NULL) {
+ guest = 1;
+ defumask = guest_umask; /* paranoia for incoming */
+ askpasswd = 1;
+ reply(331, "Guest login ok, type your name as password.");
+ } else
+ reply(530, "User %s unknown.", name);
+ if (!askpasswd && logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_NOTICE,
+ "ANONYMOUS FTP LOGIN REFUSED FROM %s(%s)",
+ remotehost, data_addr);
+ }
+ return;
+ }
+ if((auth_level & AUTH_PLAIN) == 0 && !sec_complete){
+ reply(530, "Only authorized and anonymous login allowed.");
+ return;
+ }
+ if ((pw = sgetpwnam(name))) {
+ if ((shell = pw->pw_shell) == NULL || *shell == 0)
+ shell = _PATH_BSHELL;
+ while ((cp = getusershell()) != NULL)
+ if (strcmp(cp, shell) == 0)
+ break;
+ endusershell();
+
+ if (cp == NULL || checkaccess(name)) {
+ reply(530, "User %s access denied.", name);
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr,
+ sizeof(data_addr)) == NULL)
+ strlcpy (data_addr,
+ "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_NOTICE,
+ "FTP LOGIN REFUSED FROM %s(%s), %s",
+ remotehost,
+ data_addr,
+ name);
+ }
+ pw = (struct passwd *) NULL;
+ return;
+ }
+ }
+ if (logging)
+ strlcpy(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
+#endif
+ if ((auth_level & AUTH_OTP) == 0) {
+ reply(331, "Password required for %s.", name);
+ askpasswd = 1;
+ } else {
+ char *s;
+
+#ifdef OTP
+ if ((s = otp_error (&otp_ctx)) != NULL)
+ lreply(530, "OTP: %s", s);
+#endif
+ reply(530,
+ "Only authorized, anonymous"
+#ifdef OTP
+ " and OTP "
+#endif
+ "login allowed.");
+ }
+
+ }
+ /*
+ * Delay before reading passwd after first failed
+ * attempt to slow down passwd-guessing programs.
+ */
+ if (login_attempts)
+ sleep(login_attempts);
+}
+
+/*
+ * Check if a user is in the file "fname"
+ */
+static int
+checkuser(char *fname, char *name)
+{
+ FILE *fd;
+ int found = 0;
+ char *p, line[BUFSIZ];
+
+ if ((fd = fopen(fname, "r")) != NULL) {
+ while (fgets(line, sizeof(line), fd) != NULL)
+ if ((p = strchr(line, '\n')) != NULL) {
+ *p = '\0';
+ if (line[0] == '#')
+ continue;
+ if (strcmp(line, name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ fclose(fd);
+ }
+ return (found);
+}
+
+
+/*
+ * Determine whether a user has access, based on information in
+ * _PATH_FTPUSERS. The users are listed one per line, with `allow'
+ * or `deny' after the username. If anything other than `allow', or
+ * just nothing, is given after the username, `deny' is assumed.
+ *
+ * If the user is not found in the file, but the pseudo-user `*' is,
+ * the permission is taken from that line.
+ *
+ * This preserves the old semantics where if a user was listed in the
+ * file he was denied, otherwise he was allowed.
+ *
+ * Return 1 if the user is denied, or 0 if he is allowed. */
+
+static int
+match(const char *pattern, const char *string)
+{
+ return fnmatch(pattern, string, FNM_NOESCAPE);
+}
+
+static int
+checkaccess(char *name)
+{
+#define ALLOWED 0
+#define NOT_ALLOWED 1
+ FILE *fd;
+ int allowed = ALLOWED;
+ char *user, *perm, line[BUFSIZ];
+ char *foo;
+
+ fd = fopen(_PATH_FTPUSERS, "r");
+
+ if(fd == NULL)
+ return allowed;
+
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ foo = NULL;
+ user = strtok_r(line, " \t\n", &foo);
+ if (user == NULL || user[0] == '#')
+ continue;
+ perm = strtok_r(NULL, " \t\n", &foo);
+ if (match(user, name) == 0){
+ if(perm && strcmp(perm, "allow") == 0)
+ allowed = ALLOWED;
+ else
+ allowed = NOT_ALLOWED;
+ break;
+ }
+ }
+ fclose(fd);
+ return allowed;
+}
+#undef ALLOWED
+#undef NOT_ALLOWED
+
+
+int do_login(int code, char *passwd)
+{
+ FILE *fd;
+ login_attempts = 0; /* this time successful */
+ if (setegid((gid_t)pw->pw_gid) < 0) {
+ reply(550, "Can't set gid.");
+ return -1;
+ }
+ initgroups(pw->pw_name, pw->pw_gid);
+
+ /* open wtmp before chroot */
+ ftpd_logwtmp(ttyline, pw->pw_name, remotehost);
+ logged_in = 1;
+
+ dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name);
+ if (guest) {
+ /*
+ * We MUST do a chdir() after the chroot. Otherwise
+ * the old current directory will be accessible as "."
+ * outside the new root!
+ */
+ if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
+ reply(550, "Can't set guest privileges.");
+ return -1;
+ }
+ } else if (dochroot) {
+ if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
+ reply(550, "Can't change root.");
+ return -1;
+ }
+ } else if (chdir(pw->pw_dir) < 0) {
+ if (chdir("/") < 0) {
+ reply(530, "User %s: can't change directory to %s.",
+ pw->pw_name, pw->pw_dir);
+ return -1;
+ } else
+ lreply(code, "No directory! Logging in with home=/");
+ }
+ if (seteuid((uid_t)pw->pw_uid) < 0) {
+ reply(550, "Can't set uid.");
+ return -1;
+ }
+
+ if(use_builtin_ls == -1) {
+ struct stat st;
+ /* if /bin/ls exist and is a regular file, use it, otherwise
+ use built-in ls */
+ if(stat("/bin/ls", &st) == 0 &&
+ S_ISREG(st.st_mode))
+ use_builtin_ls = 0;
+ else
+ use_builtin_ls = 1;
+ }
+
+ /*
+ * Display a login message, if it exists.
+ * N.B. reply(code,) must follow the message.
+ */
+ show_file(_PATH_FTPLOGINMESG, code);
+ if(show_file(_PATH_ISSUE_NET, code) != 0)
+ show_file(_PATH_ISSUE, code);
+ if (guest) {
+ reply(code, "Guest login ok, access restrictions apply.");
+#ifdef HAVE_SETPROCTITLE
+ snprintf (proctitle, sizeof(proctitle),
+ "%s: anonymous/%s",
+ remotehost,
+ passwd);
+ setproctitle("%s", proctitle);
+#endif /* HAVE_SETPROCTITLE */
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s(%s), %s",
+ remotehost,
+ data_addr,
+ passwd);
+ }
+ } else {
+ reply(code, "User %s logged in.", pw->pw_name);
+#ifdef HAVE_SETPROCTITLE
+ snprintf(proctitle, sizeof(proctitle), "%s: %s", remotehost, pw->pw_name);
+ setproctitle("%s", proctitle);
+#endif /* HAVE_SETPROCTITLE */
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_INFO, "FTP LOGIN FROM %s(%s) as %s",
+ remotehost,
+ data_addr,
+ pw->pw_name);
+ }
+ }
+ umask(defumask);
+ return 0;
+}
+
+/*
+ * Terminate login as previous user, if any, resetting state;
+ * used when USER command is given or login fails.
+ */
+static void
+end_login(void)
+{
+
+ seteuid((uid_t)0);
+ if (logged_in)
+ ftpd_logwtmp(ttyline, "", "");
+ pw = NULL;
+ logged_in = 0;
+ guest = 0;
+ dochroot = 0;
+}
+
+void
+pass(char *passwd)
+{
+ int rval;
+
+ /* some clients insists on sending a password */
+ if (logged_in && askpasswd == 0){
+ reply(230, "Dumpucko!");
+ return;
+ }
+
+ if (logged_in || askpasswd == 0) {
+ reply(503, "Login with USER first.");
+ return;
+ }
+ askpasswd = 0;
+ rval = 1;
+ 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;
+ }
+#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,
+ KRB_VERIFY_SECURE, NULL);
+ if (rval == KSUCCESS ) {
+ chown (tkt_string(), pw->pw_uid, pw->pw_gid);
+ if(k_hasafs())
+ krb_afslog(0, 0);
+ } else
+#endif
+ rval = unix_verify_user(pw->pw_name, passwd);
+ } else {
+ char *s;
+
+#ifdef OTP
+ if ((s = otp_error(&otp_ctx)) != NULL)
+ lreply(530, "OTP: %s", s);
+#endif
+ }
+ memset (passwd, 0, strlen(passwd));
+
+ /*
+ * If rval == 1, the user failed the authentication
+ * check above. If rval == 0, either Kerberos or
+ * local authentication succeeded.
+ */
+ if (rval) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ reply(530, "Login incorrect.");
+ if (logging)
+ syslog(LOG_NOTICE,
+ "FTP LOGIN FAILED FROM %s(%s), %s",
+ remotehost,
+ data_addr,
+ curname);
+ pw = NULL;
+ if (login_attempts++ >= 5) {
+ syslog(LOG_NOTICE,
+ "repeated login failures from %s(%s)",
+ remotehost,
+ data_addr);
+ exit(0);
+ }
+ return;
+ }
+ }
+ if(!do_login(230, passwd))
+ return;
+
+ /* Forget all about it... */
+ end_login();
+}
+
+void
+retrieve(const char *cmd, char *name)
+{
+ FILE *fin = NULL, *dout;
+ struct stat st;
+ int (*closefunc) (FILE *);
+ char line[BUFSIZ];
+
+
+ if (cmd == 0) {
+ fin = fopen(name, "r");
+ closefunc = fclose;
+ st.st_size = 0;
+ if(fin == NULL){
+ int save_errno = errno;
+ struct cmds {
+ const char *ext;
+ const char *cmd;
+ const char *rev_cmd;
+ } cmds[] = {
+ {".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 -- %s"},
+ {NULL, NULL}
+ };
+ struct cmds *p;
+ for(p = cmds; p->ext; p++){
+ char *tail = name + strlen(name) - strlen(p->ext);
+ char c = *tail;
+
+ if(strcmp(tail, p->ext) == 0 &&
+ (*tail = 0) == 0 &&
+ access(name, R_OK) == 0){
+ snprintf (line, sizeof(line), p->cmd, name);
+ *tail = c;
+ 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);
+ closefunc = ftpd_pclose;
+ st.st_size = -1;
+ cmd = line;
+ } else
+ errno = save_errno;
+ }
+ } else {
+ snprintf(line, sizeof(line), cmd, name);
+ name = line;
+ fin = ftpd_popen(line, "r", 1, 0);
+ closefunc = ftpd_pclose;
+ st.st_size = -1;
+ }
+ if (fin == NULL) {
+ if (errno != 0) {
+ perror_reply(550, name);
+ if (cmd == 0) {
+ LOGCMD("get", name);
+ }
+ }
+ return;
+ }
+ byte_count = -1;
+ if (cmd == 0){
+ if(fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
+ reply(550, "%s: not a plain file.", name);
+ goto done;
+ }
+ }
+ if (restart_point) {
+ if (type == TYPE_A) {
+ off_t i, n;
+ int c;
+
+ n = restart_point;
+ i = 0;
+ while (i++ < n) {
+ if ((c=getc(fin)) == EOF) {
+ perror_reply(550, name);
+ goto done;
+ }
+ if (c == '\n')
+ i++;
+ }
+ } else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ }
+ dout = dataconn(name, st.st_size, "w");
+ if (dout == NULL)
+ goto done;
+ set_buffer_size(fileno(dout), 0);
+ send_data(fin, dout);
+ fclose(dout);
+ data = -1;
+ pdata = -1;
+done:
+ if (cmd == 0)
+ LOGBYTES("get", name, byte_count);
+ (*closefunc)(fin);
+}
+
+/* filename sanity check */
+
+int
+filename_check(char *filename)
+{
+ static const char good_chars[] = "+-=_,.";
+ char *p;
+
+ p = strrchr(filename, '/');
+ if(p)
+ filename = p + 1;
+
+ p = filename;
+
+ if(isalnum(*p)){
+ p++;
+ while(*p && (isalnum(*p) || strchr(good_chars, *p)))
+ p++;
+ if(*p == '\0')
+ return 0;
+ }
+ lreply(553, "\"%s\" is an illegal filename.", filename);
+ lreply(553, "The filename must start with an alphanumeric "
+ "character and must only");
+ reply(553, "consist of alphanumeric characters or any of the following: %s",
+ good_chars);
+ return 1;
+}
+
+void
+do_store(char *name, char *mode, int unique)
+{
+ FILE *fout, *din;
+ struct stat st;
+ int (*closefunc) (FILE *);
+
+ if(guest && filename_check(name))
+ return;
+ if (unique && stat(name, &st) == 0 &&
+ (name = gunique(name)) == NULL) {
+ LOGCMD(*mode == 'w' ? "put" : "append", name);
+ return;
+ }
+
+ if (restart_point)
+ mode = "r+";
+ fout = fopen(name, mode);
+ closefunc = fclose;
+ if (fout == NULL) {
+ perror_reply(553, name);
+ LOGCMD(*mode == 'w' ? "put" : "append", name);
+ return;
+ }
+ byte_count = -1;
+ if (restart_point) {
+ if (type == TYPE_A) {
+ off_t i, n;
+ int c;
+
+ n = restart_point;
+ i = 0;
+ while (i++ < n) {
+ if ((c=getc(fout)) == EOF) {
+ perror_reply(550, name);
+ goto done;
+ }
+ if (c == '\n')
+ i++;
+ }
+ /*
+ * We must do this seek to "current" position
+ * because we are changing from reading to
+ * writing.
+ */
+ if (fseek(fout, 0L, SEEK_CUR) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ } else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ }
+ din = dataconn(name, (off_t)-1, "r");
+ if (din == NULL)
+ goto done;
+ set_buffer_size(fileno(din), 1);
+ if (receive_data(din, fout) == 0) {
+ if (unique)
+ reply(226, "Transfer complete (unique file name:%s).",
+ name);
+ else
+ reply(226, "Transfer complete.");
+ }
+ fclose(din);
+ data = -1;
+ pdata = -1;
+done:
+ LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
+ (*closefunc)(fout);
+}
+
+static FILE *
+getdatasock(const char *mode)
+{
+ int s, t, tries;
+
+ if (data >= 0)
+ return (fdopen(data, mode));
+ seteuid(0);
+ s = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
+ if (s < 0)
+ goto bad;
+ socket_set_reuseaddr (s, 1);
+ /* anchor socket to avoid multi-homing problems */
+ socket_set_address_and_port (data_source,
+ socket_get_address (ctrl_addr),
+ socket_get_port (data_source));
+
+ for (tries = 1; ; tries++) {
+ if (bind(s, data_source,
+ socket_sockaddr_size (data_source)) >= 0)
+ break;
+ if (errno != EADDRINUSE || tries > 10)
+ goto bad;
+ sleep(tries);
+ }
+ seteuid(pw->pw_uid);
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (s, IPTOS_THROUGHPUT);
+#endif
+ return (fdopen(s, mode));
+bad:
+ /* Return the real value of errno (close may change it) */
+ t = errno;
+ seteuid((uid_t)pw->pw_uid);
+ close(s);
+ errno = t;
+ return (NULL);
+}
+
+static FILE *
+dataconn(const char *name, off_t size, const char *mode)
+{
+ char sizebuf[32];
+ FILE *file;
+ int retry = 0;
+
+ file_size = size;
+ byte_count = 0;
+ if (size >= 0)
+ snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", (long)size);
+ else
+ *sizebuf = '\0';
+ if (pdata >= 0) {
+ struct sockaddr_storage from_ss;
+ struct sockaddr *from = (struct sockaddr *)&from_ss;
+ int s;
+ int fromlen = sizeof(from_ss);
+
+ s = accept(pdata, from, &fromlen);
+ if (s < 0) {
+ reply(425, "Can't open data connection.");
+ close(pdata);
+ pdata = -1;
+ return (NULL);
+ }
+ close(pdata);
+ pdata = s;
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ {
+ 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);
+ return (fdopen(pdata, mode));
+ }
+ if (data >= 0) {
+ reply(125, "Using existing data connection for '%s'%s.",
+ name, sizebuf);
+ usedefault = 1;
+ return (fdopen(data, mode));
+ }
+ if (usedefault)
+ data_dest = his_addr;
+ usedefault = 1;
+ file = getdatasock(mode);
+ if (file == NULL) {
+ char data_addr[256];
+
+ if (inet_ntop (data_source->sa_family,
+ socket_get_address(data_source),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ reply(425, "Can't create data socket (%s,%d): %s.",
+ data_addr,
+ socket_get_port (data_source),
+ strerror(errno));
+ return (NULL);
+ }
+ data = fileno(file);
+ while (connect(data, data_dest,
+ socket_sockaddr_size(data_dest)) < 0) {
+ if (errno == EADDRINUSE && retry < swaitmax) {
+ sleep(swaitint);
+ retry += swaitint;
+ continue;
+ }
+ perror_reply(425, "Can't build data connection");
+ fclose(file);
+ data = -1;
+ return (NULL);
+ }
+ reply(150, "Opening %s mode data connection for '%s'%s.",
+ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+ return (file);
+}
+
+/*
+ * Tranfer the contents of "instr" to "outstr" peer using the appropriate
+ * encapsulation of the data subject * to Mode, Structure, and Type.
+ *
+ * NB: Form isn't handled.
+ */
+static void
+send_data(FILE *instr, FILE *outstr)
+{
+ int c, cnt, filefd, netfd;
+ static char *buf;
+ static size_t bufsize;
+
+ transflag++;
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ return;
+ }
+ switch (type) {
+
+ case TYPE_A:
+ 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:
+#if defined(HAVE_MMAP) && !defined(NO_MMAP)
+#ifndef MAP_FAILED
+#define MAP_FAILED (-1)
+#endif
+ {
+ struct stat st;
+ char *chunk;
+ int in = fileno(instr);
+ if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)
+ && st.st_size > 0) {
+ /*
+ * mmap zero bytes has potential of loosing, don't do it.
+ */
+ chunk = mmap(0, st.st_size, PROT_READ,
+ MAP_SHARED, in, 0);
+ if((void *)chunk != (void *)MAP_FAILED) {
+ cnt = st.st_size - restart_point;
+ sec_write(fileno(outstr), chunk + restart_point, cnt);
+ if (munmap(chunk, st.st_size) < 0)
+ warn ("munmap");
+ sec_fflush(outstr);
+ byte_count = cnt;
+ transflag = 0;
+ }
+ }
+ }
+#endif
+ if(transflag) {
+ struct stat st;
+
+ netfd = fileno(outstr);
+ filefd = fileno(instr);
+ buf = alloc_buffer (buf, &bufsize,
+ fstat(filefd, &st) >= 0 ? &st : NULL);
+ if (buf == NULL) {
+ transflag = 0;
+ perror_reply(451, "Local resource failure: malloc");
+ return;
+ }
+ while ((cnt = read(filefd, buf, bufsize)) > 0 &&
+ sec_write(netfd, buf, cnt) == cnt)
+ byte_count += cnt;
+ sec_fflush(outstr); /* to end an encrypted stream */
+ transflag = 0;
+ if (cnt != 0) {
+ if (cnt < 0)
+ goto file_err;
+ goto data_err;
+ }
+ }
+ reply(226, "Transfer complete.");
+ return;
+ default:
+ transflag = 0;
+ reply(550, "Unimplemented TYPE %d in send_data", type);
+ return;
+ }
+
+data_err:
+ transflag = 0;
+ perror_reply(426, "Data connection");
+ return;
+
+file_err:
+ transflag = 0;
+ perror_reply(551, "Error on input file");
+}
+
+/*
+ * Transfer data from peer to "outstr" using the appropriate encapulation of
+ * the data subject to Mode, Structure, and Type.
+ *
+ * N.B.: Form isn't handled.
+ */
+static int
+receive_data(FILE *instr, FILE *outstr)
+{
+ int cnt, bare_lfs = 0;
+ static char *buf;
+ static size_t bufsize;
+ struct stat st;
+
+ transflag++;
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ return (-1);
+ }
+
+ buf = alloc_buffer (buf, &bufsize,
+ fstat(fileno(outstr), &st) >= 0 ? &st : NULL);
+ if (buf == NULL) {
+ transflag = 0;
+ perror_reply(451, "Local resource failure: malloc");
+ return -1;
+ }
+
+ switch (type) {
+
+ case TYPE_I:
+ case TYPE_L:
+ while ((cnt = sec_read(fileno(instr), buf, bufsize)) > 0) {
+ if (write(fileno(outstr), buf, cnt) != cnt)
+ goto file_err;
+ byte_count += cnt;
+ }
+ if (cnt < 0)
+ goto data_err;
+ transflag = 0;
+ return (0);
+
+ case TYPE_E:
+ reply(553, "TYPE E not implemented.");
+ transflag = 0;
+ return (-1);
+
+ case TYPE_A:
+ {
+ char *p, *q;
+ int cr_flag = 0;
+ while ((cnt = sec_read(fileno(instr),
+ buf + cr_flag,
+ bufsize - cr_flag)) > 0){
+ byte_count += cnt;
+ cnt += cr_flag;
+ cr_flag = 0;
+ for(p = buf, q = buf; p < buf + cnt;) {
+ if(*p == '\n')
+ bare_lfs++;
+ if(*p == '\r') {
+ if(p == buf + cnt - 1){
+ cr_flag = 1;
+ p++;
+ continue;
+ }else if(p[1] == '\n'){
+ *q++ = '\n';
+ p += 2;
+ continue;
+ }
+ }
+ *q++ = *p++;
+ }
+ fwrite(buf, q - buf, 1, outstr);
+ if(cr_flag)
+ buf[0] = '\r';
+ }
+ if(cr_flag)
+ putc('\r', outstr);
+ fflush(outstr);
+ if (ferror(instr))
+ goto data_err;
+ if (ferror(outstr))
+ goto file_err;
+ transflag = 0;
+ if (bare_lfs) {
+ lreply(226, "WARNING! %d bare linefeeds received in ASCII mode\r\n"
+ " File may not have transferred correctly.\r\n",
+ bare_lfs);
+ }
+ return (0);
+ }
+ default:
+ reply(550, "Unimplemented TYPE %d in receive_data", type);
+ transflag = 0;
+ return (-1);
+ }
+
+data_err:
+ transflag = 0;
+ perror_reply(426, "Data Connection");
+ return (-1);
+
+file_err:
+ transflag = 0;
+ perror_reply(452, "Error writing file");
+ return (-1);
+}
+
+void
+statfilecmd(char *filename)
+{
+ FILE *fin;
+ int c;
+ char line[LINE_MAX];
+
+ snprintf(line, sizeof(line), "/bin/ls -la -- %s", filename);
+ fin = ftpd_popen(line, "r", 1, 0);
+ lreply(211, "status of %s:", filename);
+ while ((c = getc(fin)) != EOF) {
+ if (c == '\n') {
+ if (ferror(stdout)){
+ perror_reply(421, "control connection");
+ ftpd_pclose(fin);
+ dologout(1);
+ /* NOTREACHED */
+ }
+ if (ferror(fin)) {
+ perror_reply(551, filename);
+ ftpd_pclose(fin);
+ return;
+ }
+ putc('\r', stdout);
+ }
+ putc(c, stdout);
+ }
+ ftpd_pclose(fin);
+ reply(211, "End of Status");
+}
+
+void
+statcmd(void)
+{
+#if 0
+ struct sockaddr_in *sin;
+ u_char *a, *p;
+
+ lreply(211, "%s FTP server (%s) status:", hostname, version);
+ printf(" %s\r\n", version);
+ printf(" Connected to %s", remotehost);
+ if (!isdigit(remotehost[0]))
+ printf(" (%s)", inet_ntoa(his_addr.sin_addr));
+ printf("\r\n");
+ if (logged_in) {
+ if (guest)
+ printf(" Logged in anonymously\r\n");
+ else
+ printf(" Logged in as %s\r\n", pw->pw_name);
+ } else if (askpasswd)
+ printf(" Waiting for password\r\n");
+ else
+ printf(" Waiting for user name\r\n");
+ printf(" TYPE: %s", typenames[type]);
+ if (type == TYPE_A || type == TYPE_E)
+ printf(", FORM: %s", formnames[form]);
+ if (type == TYPE_L)
+#if NBBY == 8
+ printf(" %d", NBBY);
+#else
+ printf(" %d", bytesize); /* need definition! */
+#endif
+ printf("; STRUcture: %s; transfer MODE: %s\r\n",
+ strunames[stru], modenames[mode]);
+ if (data != -1)
+ printf(" Data connection open\r\n");
+ else if (pdata != -1) {
+ printf(" in Passive mode");
+ sin = &pasv_addr;
+ goto printaddr;
+ } else if (usedefault == 0) {
+ printf(" PORT");
+ sin = &data_dest;
+printaddr:
+ a = (u_char *) &sin->sin_addr;
+ p = (u_char *) &sin->sin_port;
+#define UC(b) (((int) b) & 0xff)
+ printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
+ UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+#undef UC
+ } else
+ printf(" No data connection\r\n");
+#endif
+ reply(211, "End of status");
+}
+
+void
+fatal(char *s)
+{
+
+ reply(451, "Error in server: %s\n", s);
+ reply(221, "Closing connection due to server error.");
+ dologout(0);
+ /* NOTREACHED */
+}
+
+static void
+int_reply(int, char *, const char *, va_list)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 3, 0)))
+#endif
+;
+
+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);
+ sec_fprintf(stdout, "%s", buf);
+ fflush(stdout);
+ if (debug)
+ syslog(LOG_DEBUG, "<--- %s- ", buf);
+}
+
+void
+reply(int n, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int_reply(n, " ", fmt, ap);
+ delete_ftp_command();
+ va_end(ap);
+}
+
+void
+lreply(int n, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int_reply(n, "-", fmt, ap);
+ va_end(ap);
+}
+
+void
+nreply(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int_reply(0, NULL, fmt, ap);
+ va_end(ap);
+}
+
+static void
+ack(char *s)
+{
+
+ reply(250, "%s command successful.", s);
+}
+
+void
+nack(char *s)
+{
+
+ reply(502, "%s command not implemented.", s);
+}
+
+/* ARGSUSED */
+void
+yyerror(char *s)
+{
+ char *cp;
+
+ if ((cp = strchr(cbuf,'\n')))
+ *cp = '\0';
+ reply(500, "'%s': command not understood.", cbuf);
+}
+
+void
+do_delete(char *name)
+{
+ struct stat st;
+
+ LOGCMD("delete", name);
+ if (stat(name, &st) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+ if ((st.st_mode&S_IFMT) == S_IFDIR) {
+ if (rmdir(name) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+ goto done;
+ }
+ if (unlink(name) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+done:
+ ack("DELE");
+}
+
+void
+cwd(char *path)
+{
+
+ if (chdir(path) < 0)
+ perror_reply(550, path);
+ else
+ ack("CWD");
+}
+
+void
+makedir(char *name)
+{
+
+ LOGCMD("mkdir", name);
+ if(guest && filename_check(name))
+ return;
+ if (mkdir(name, 0777) < 0)
+ perror_reply(550, name);
+ else{
+ if(guest)
+ chmod(name, 0700); /* guest has umask 777 */
+ reply(257, "MKD command successful.");
+ }
+}
+
+void
+removedir(char *name)
+{
+
+ LOGCMD("rmdir", name);
+ if (rmdir(name) < 0)
+ perror_reply(550, name);
+ else
+ ack("RMD");
+}
+
+void
+pwd(void)
+{
+ char path[MaxPathLen];
+ char *ret;
+
+ /* SunOS has a broken getcwd that does popen(pwd) (!!!), this
+ * failes miserably when running chroot
+ */
+ ret = getcwd(path, sizeof(path));
+ if (ret == NULL)
+ reply(550, "%s.", strerror(errno));
+ else
+ reply(257, "\"%s\" is current directory.", path);
+}
+
+char *
+renamefrom(char *name)
+{
+ struct stat st;
+
+ if (stat(name, &st) < 0) {
+ perror_reply(550, name);
+ return NULL;
+ }
+ reply(350, "File exists, ready for destination name");
+ return (name);
+}
+
+void
+renamecmd(char *from, char *to)
+{
+
+ LOGCMD2("rename", from, to);
+ if(guest && filename_check(to))
+ return;
+ if (rename(from, to) < 0)
+ perror_reply(550, "rename");
+ else
+ ack("RNTO");
+}
+
+static void
+dolog(struct sockaddr *sa)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+ inaddr2str (sin->sin_addr, remotehost, sizeof(remotehost));
+#ifdef HAVE_SETPROCTITLE
+ snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
+ setproctitle("%s", proctitle);
+#endif /* HAVE_SETPROCTITLE */
+
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+
+ syslog(LOG_INFO, "connection from %s(%s)",
+ remotehost,
+ data_addr);
+ }
+}
+
+/*
+ * Record logout in wtmp file
+ * and exit with supplied status.
+ */
+void
+dologout(int status)
+{
+ transflag = 0;
+ if (logged_in) {
+ seteuid((uid_t)0);
+ ftpd_logwtmp(ttyline, "", "");
+#ifdef KRB4
+ cond_kdestroy();
+#endif
+ }
+ /* beware of flushing buffers after a SIGPIPE */
+#ifdef XXX
+ exit(status);
+#else
+ _exit(status);
+#endif
+}
+
+void abor(void)
+{
+}
+
+static void
+myoob(int signo)
+{
+#if 0
+ char *cp;
+#endif
+
+ /* only process if transfer occurring */
+ if (!transflag)
+ return;
+
+ /* This is all XXX */
+ oobflag = 1;
+ /* if the command resulted in a new command,
+ parse that as well */
+ do{
+ yyparse();
+ } while(ftp_command);
+ oobflag = 0;
+
+#if 0
+ cp = tmpline;
+ if (ftpd_getline(cp, 7) == NULL) {
+ reply(221, "You could at least say goodbye.");
+ dologout(0);
+ }
+ upper(cp);
+ if (strcmp(cp, "ABOR\r\n") == 0) {
+ tmpline[0] = '\0';
+ reply(426, "Transfer aborted. Data connection closed.");
+ reply(226, "Abort successful");
+ longjmp(urgcatch, 1);
+ }
+ if (strcmp(cp, "STAT\r\n") == 0) {
+ if (file_size != (off_t) -1)
+ reply(213, "Status: %ld of %ld bytes transferred",
+ (long)byte_count,
+ (long)file_size);
+ else
+ reply(213, "Status: %ld bytes transferred"
+ (long)byte_count);
+ }
+#endif
+}
+
+/*
+ * Note: a response of 425 is not mentioned as a possible response to
+ * the PASV command in RFC959. However, it has been blessed as
+ * a legitimate response by Jon Postel in a telephone conversation
+ * with Rick Adams on 25 Jan 89.
+ */
+void
+pasv(void)
+{
+ int len;
+ char *p, *a;
+ struct sockaddr_in *sin;
+
+ if (ctrl_addr->sa_family != AF_INET) {
+ reply(425,
+ "You cannot do PASV with something that's not IPv4");
+ return;
+ }
+
+ pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
+ if (pdata < 0) {
+ perror_reply(425, "Can't open passive connection");
+ return;
+ }
+ pasv_addr->sa_family = ctrl_addr->sa_family;
+ socket_set_address_and_port (pasv_addr,
+ socket_get_address (ctrl_addr),
+ 0);
+ seteuid(0);
+ if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
+ seteuid(pw->pw_uid);
+ goto pasv_error;
+ }
+ seteuid(pw->pw_uid);
+ len = sizeof(pasv_addr_ss);
+ if (getsockname(pdata, pasv_addr, &len) < 0)
+ goto pasv_error;
+ if (listen(pdata, 1) < 0)
+ goto pasv_error;
+ sin = (struct sockaddr_in *)pasv_addr;
+ a = (char *) &sin->sin_addr;
+ p = (char *) &sin->sin_port;
+
+#define UC(b) (((int) b) & 0xff)
+
+ reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
+ UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+ return;
+
+pasv_error:
+ close(pdata);
+ pdata = -1;
+ perror_reply(425, "Can't open passive connection");
+ return;
+}
+
+void
+epsv(char *proto)
+{
+ int len;
+
+ pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
+ if (pdata < 0) {
+ perror_reply(425, "Can't open passive connection");
+ return;
+ }
+ pasv_addr->sa_family = ctrl_addr->sa_family;
+ socket_set_address_and_port (pasv_addr,
+ socket_get_address (ctrl_addr),
+ 0);
+ seteuid(0);
+ if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
+ seteuid(pw->pw_uid);
+ goto pasv_error;
+ }
+ seteuid(pw->pw_uid);
+ len = sizeof(pasv_addr_ss);
+ if (getsockname(pdata, pasv_addr, &len) < 0)
+ goto pasv_error;
+ if (listen(pdata, 1) < 0)
+ goto pasv_error;
+
+ reply(229, "Entering Extended Passive Mode (|||%d|)",
+ ntohs(socket_get_port (pasv_addr)));
+ return;
+
+pasv_error:
+ close(pdata);
+ pdata = -1;
+ perror_reply(425, "Can't open passive connection");
+ return;
+}
+
+void
+eprt(char *str)
+{
+ char *end;
+ char sep;
+ int af;
+ int ret;
+ int port;
+
+ usedefault = 0;
+ if (pdata >= 0) {
+ close(pdata);
+ pdata = -1;
+ }
+
+ sep = *str++;
+ if (sep == '\0') {
+ reply(500, "Bad syntax in EPRT");
+ return;
+ }
+ af = strtol (str, &end, 0);
+ if (af == 0 || *end != sep) {
+ reply(500, "Bad syntax in EPRT");
+ return;
+ }
+ str = end + 1;
+ switch (af) {
+#ifdef HAVE_IPV6
+ case 2 :
+ data_dest->sa_family = AF_INET6;
+ break;
+#endif
+ case 1 :
+ data_dest->sa_family = AF_INET;
+ break;
+ default :
+ reply(522, "Network protocol %d not supported, use (1"
+#ifdef HAVE_IPV6
+ ",2"
+#endif
+ ")", af);
+ return;
+ }
+ end = strchr (str, sep);
+ if (end == NULL) {
+ reply(500, "Bad syntax in EPRT");
+ return;
+ }
+ *end = '\0';
+ ret = inet_pton (data_dest->sa_family, str,
+ socket_get_address (data_dest));
+
+ if (ret != 1) {
+ reply(500, "Bad address syntax in EPRT");
+ return;
+ }
+ str = end + 1;
+ port = strtol (str, &end, 0);
+ if (port == 0 || *end != sep) {
+ reply(500, "Bad port syntax in EPRT");
+ return;
+ }
+ socket_set_port (data_dest, htons(port));
+ reply(200, "EPRT command successful.");
+}
+
+/*
+ * Generate unique name for file with basename "local".
+ * The file named "local" is already known to exist.
+ * Generates failure reply on error.
+ */
+static char *
+gunique(char *local)
+{
+ static char new[MaxPathLen];
+ struct stat st;
+ int count;
+ char *cp;
+
+ cp = strrchr(local, '/');
+ if (cp)
+ *cp = '\0';
+ if (stat(cp ? local : ".", &st) < 0) {
+ perror_reply(553, cp ? local : ".");
+ return NULL;
+ }
+ if (cp)
+ *cp = '/';
+ for (count = 1; count < 100; count++) {
+ snprintf (new, sizeof(new), "%s.%d", local, count);
+ if (stat(new, &st) < 0)
+ return (new);
+ }
+ reply(452, "Unique file name cannot be created.");
+ return (NULL);
+}
+
+/*
+ * Format and send reply containing system error number.
+ */
+void
+perror_reply(int code, const char *string)
+{
+ reply(code, "%s: %s.", string, strerror(errno));
+}
+
+static char *onefile[] = {
+ "",
+ 0
+};
+
+void
+list_file(char *file)
+{
+ if(use_builtin_ls) {
+ FILE *dout;
+ dout = dataconn(file, -1, "w");
+ if (dout == NULL)
+ return;
+ set_buffer_size(fileno(dout), 0);
+ builtin_ls(dout, file);
+ reply(226, "Transfer complete.");
+ fclose(dout);
+ data = -1;
+ pdata = -1;
+ } else {
+#ifdef HAVE_LS_A
+ const char *cmd = "/bin/ls -lA -- %s";
+#else
+ const char *cmd = "/bin/ls -la -- %s";
+#endif
+ retrieve(cmd, file);
+ }
+}
+
+void
+send_file_list(char *whichf)
+{
+ struct stat st;
+ DIR *dirp = NULL;
+ struct dirent *dir;
+ FILE *dout = NULL;
+ char **dirlist, *dirname;
+ int simple = 0;
+ int freeglob = 0;
+ glob_t gl;
+ char buf[MaxPathLen];
+
+ if (strpbrk(whichf, "~{[*?") != NULL) {
+ int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+ memset(&gl, 0, sizeof(gl));
+ freeglob = 1;
+ if (glob(whichf, flags, 0, &gl)) {
+ reply(550, "not found");
+ goto out;
+ } else if (gl.gl_pathc == 0) {
+ errno = ENOENT;
+ perror_reply(550, whichf);
+ goto out;
+ }
+ dirlist = gl.gl_pathv;
+ } else {
+ onefile[0] = whichf;
+ dirlist = onefile;
+ simple = 1;
+ }
+
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ goto out;
+ }
+ while ((dirname = *dirlist++)) {
+ if (stat(dirname, &st) < 0) {
+ /*
+ * If user typed "ls -l", etc, and the client
+ * used NLST, do what the user meant.
+ */
+ if (dirname[0] == '-' && *dirlist == NULL &&
+ transflag == 0) {
+ list_file(dirname);
+ goto out;
+ }
+ perror_reply(550, whichf);
+ if (dout != NULL) {
+ fclose(dout);
+ transflag = 0;
+ data = -1;
+ pdata = -1;
+ }
+ goto out;
+ }
+
+ if (S_ISREG(st.st_mode)) {
+ if (dout == NULL) {
+ dout = dataconn("file list", (off_t)-1, "w");
+ if (dout == NULL)
+ goto out;
+ transflag++;
+ }
+ snprintf(buf, sizeof(buf), "%s%s\n", dirname,
+ type == TYPE_A ? "\r" : "");
+ sec_write(fileno(dout), buf, strlen(buf));
+ byte_count += strlen(dirname) + 1;
+ continue;
+ } else if (!S_ISDIR(st.st_mode))
+ continue;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ continue;
+
+ while ((dir = readdir(dirp)) != NULL) {
+ char nbuf[MaxPathLen];
+
+ if (!strcmp(dir->d_name, "."))
+ continue;
+ if (!strcmp(dir->d_name, ".."))
+ continue;
+
+ snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname, dir->d_name);
+
+ /*
+ * We have to do a stat to insure it's
+ * not a directory or special file.
+ */
+ if (simple || (stat(nbuf, &st) == 0 &&
+ S_ISREG(st.st_mode))) {
+ if (dout == NULL) {
+ dout = dataconn("file list", (off_t)-1, "w");
+ if (dout == NULL)
+ goto out;
+ transflag++;
+ }
+ if(strncmp(nbuf, "./", 2) == 0)
+ snprintf(buf, sizeof(buf), "%s%s\n", nbuf +2,
+ type == TYPE_A ? "\r" : "");
+ else
+ snprintf(buf, sizeof(buf), "%s%s\n", nbuf,
+ type == TYPE_A ? "\r" : "");
+ sec_write(fileno(dout), buf, strlen(buf));
+ byte_count += strlen(nbuf) + 1;
+ }
+ }
+ closedir(dirp);
+ }
+ if (dout == NULL)
+ reply(550, "No files found.");
+ else if (ferror(dout) != 0)
+ perror_reply(550, "Data connection");
+ else
+ reply(226, "Transfer complete.");
+
+ transflag = 0;
+ if (dout != NULL){
+ sec_write(fileno(dout), buf, 0); /* XXX flush */
+
+ fclose(dout);
+ }
+ data = -1;
+ pdata = -1;
+out:
+ if (freeglob) {
+ freeglob = 0;
+ globfree(&gl);
+ }
+}
+
+
+int
+find(char *pattern)
+{
+ char line[1024];
+ FILE *f;
+
+ snprintf(line, sizeof(line),
+ "/bin/locate -d %s -- %s",
+ ftp_rooted("/etc/locatedb"),
+ pattern);
+ f = ftpd_popen(line, "r", 1, 1);
+ if(f == NULL){
+ perror_reply(550, "/bin/locate");
+ return 1;
+ }
+ lreply(200, "Output from find.");
+ while(fgets(line, sizeof(line), f)){
+ if(line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = 0;
+ nreply("%s", line);
+ }
+ reply(200, "Done");
+ ftpd_pclose(f);
+ return 0;
+}
+
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..5cb4904
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h
@@ -0,0 +1,170 @@
+/*
+ * 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. 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.9 1999/12/02 16:58:30 joda 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 HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.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
+
+/* SunOS doesn't have any declaration of fclose */
+
+int fclose(FILE *stream);
+
+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..28e3596
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ftpd_locl.h"
+#include <gssapi.h>
+#include <krb5.h>
+
+RCSID("$Id: gss_userok.c,v 1.2 1999/12/02 16:58:31 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
new file mode 100644
index 0000000..dad4de5
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c
@@ -0,0 +1,365 @@
+/*
+ * 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. 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"
+
+RCSID("$Id: kauth.c,v 1.25 1999/12/02 16:58:31 joda Exp $");
+
+static KTEXT_ST cip;
+static unsigned int lifetime;
+static time_t local_time;
+
+static krb_principal pr;
+
+static int do_destroy_tickets = 1;
+
+static int
+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));
+ return -1;
+}
+
+static int
+store_ticket(KTEXT cip)
+{
+ char *ptr;
+ des_cblock session;
+ krb_principal sp;
+ unsigned char kvno;
+ KTEXT_ST tkt;
+ int left = cip->length;
+ int len;
+ int kerror;
+
+ ptr = (char *) cip->dat;
+
+ /* extract session key */
+ memmove(session, ptr, 8);
+ ptr += 8;
+ left -= 8;
+
+ len = strnlen(ptr, left);
+ if (len == left)
+ return(INTK_BADPW);
+
+ /* extract server's name */
+ strlcpy(sp.name, ptr, sizeof(sp.name));
+ ptr += len + 1;
+ left -= len + 1;
+
+ len = strnlen(ptr, left);
+ if (len == left)
+ return(INTK_BADPW);
+
+ /* extract server's instance */
+ strlcpy(sp.instance, ptr, sizeof(sp.instance));
+ ptr += len + 1;
+ left -= len + 1;
+
+ len = strnlen(ptr, left);
+ if (len == left)
+ return(INTK_BADPW);
+
+ /* extract server's realm */
+ strlcpy(sp.realm, ptr, sizeof(sp.realm));
+ ptr += len + 1;
+ left -= len + 1;
+
+ if(left < 3)
+ return INTK_BADPW;
+ /* extract ticket lifetime, server key version, ticket length */
+ /* be sure to avoid sign extension on lifetime! */
+ lifetime = (unsigned char) ptr[0];
+ kvno = (unsigned char) ptr[1];
+ tkt.length = (unsigned char) ptr[2];
+ ptr += 3;
+ left -= 3;
+
+ if (tkt.length > left)
+ return(INTK_BADPW);
+
+ /* extract ticket itself */
+ memmove(tkt.dat, ptr, tkt.length);
+ ptr += tkt.length;
+ left -= tkt.length;
+
+ /* Here is where the time should be verified against the KDC.
+ * Unfortunately everything is sent in host byte order (receiver
+ * makes wrong) , and at this stage there is no way for us to know
+ * which byteorder the KDC has. So we simply ignore the time,
+ * there are no security risks with this, the only thing that can
+ * happen is that we might receive a replayed ticket, which could
+ * at most be useless.
+ */
+
+#if 0
+ /* check KDC time stamp */
+ {
+ time_t kdc_time;
+
+ 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
+ code */
+ }
+ }
+#endif
+
+ /* initialize ticket cache */
+
+ if (tf_create(TKT_FILE) != KSUCCESS)
+ return(INTK_ERR);
+
+ if (tf_put_pname(pr.name) != KSUCCESS ||
+ tf_put_pinst(pr.instance) != KSUCCESS) {
+ tf_close();
+ return(INTK_ERR);
+ }
+
+
+ kerror = tf_save_cred(sp.name, sp.instance, sp.realm, session,
+ lifetime, kvno, &tkt, local_time);
+ tf_close();
+
+ return(kerror);
+}
+
+void
+kauth(char *principal, char *ticket)
+{
+ char *p;
+ int ret;
+
+ if(get_command_prot() != prot_private) {
+ reply(500, "Request denied (bad protection level)");
+ return;
+ }
+ ret = krb_parse_name(principal, &pr);
+ if(ret){
+ reply(500, "Bad principal: %s.", krb_get_err_text(ret));
+ return;
+ }
+ if(pr.realm[0] == 0)
+ krb_get_lrealm(pr.realm, 1);
+
+ if(ticket){
+ cip.length = base64_decode(ticket, &cip.dat);
+ if(cip.length == -1){
+ reply(500, "Failed to decode data.");
+ return;
+ }
+ ret = store_ticket(&cip);
+ if(ret){
+ reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
+ memset(&cip, 0, sizeof(cip));
+ return;
+ }
+ do_destroy_tickets = 1;
+
+ if(k_hasafs())
+ krb_afslog(0, 0);
+ reply(200, "Tickets will be destroyed on exit.");
+ return;
+ }
+
+ ret = krb_get_in_tkt (pr.name,
+ pr.instance,
+ pr.realm,
+ KRB_TICKET_GRANTING_TICKET,
+ pr.realm,
+ DEFAULT_TKT_LIFE,
+ NULL, save_tkt, NULL);
+ if(ret != INTK_BADPW){
+ reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
+ return;
+ }
+ 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));
+}
+
+
+static char *
+short_date(int32_t dp)
+{
+ char *cp;
+ time_t t = (time_t)dp;
+
+ if (t == (time_t)(-1L)) return "*** Never *** ";
+ cp = ctime(&t) + 4;
+ cp[15] = '\0';
+ return (cp);
+}
+
+void
+klist(void)
+{
+ int err;
+
+ char *file = tkt_string();
+
+ krb_principal pr;
+
+ char buf1[128], buf2[128];
+ int header = 1;
+ CREDENTIALS c;
+
+
+
+ err = tf_init(file, R_TKT_FIL);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+ tf_close();
+
+ /*
+ * We must find the realm of the ticket file here before calling
+ * tf_init because since the realm of the ticket file is not
+ * really stored in the principal section of the file, the
+ * routine we use must itself call tf_init and tf_close.
+ */
+ err = krb_get_tf_realm(file, pr.realm);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+
+ err = tf_init(file, R_TKT_FIL);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+
+ err = tf_get_pname(pr.name);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+ err = tf_get_pinst(pr.instance);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+
+ /*
+ * You may think that this is the obvious place to get the
+ * realm of the ticket file, but it can't be done here as the
+ * routine to do this must open the ticket file. This is why
+ * 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) {
+ lreply(200, "%-15s %-15s %s",
+ " Issued", " Expires", " Principal (kvno)");
+ header = 0;
+ }
+ strlcpy(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)
+ strlcpy(buf2, short_date(c.issue_date), sizeof(buf2));
+ else
+ strlcpy(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, " ");
+}
+
+/*
+ * 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/krb4.c b/crypto/kerberosIV/appl/ftp/ftpd/krb4.c
new file mode 100644
index 0000000..2457c61
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/krb4.c
@@ -0,0 +1,372 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: krb4.c,v 1.19 1997/05/11 09:00:07 assar Exp $");
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_NETINET_IN_h
+#include <netinet/in.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <krb.h>
+
+#include "base64.h"
+#include "extern.h"
+#include "auth.h"
+#include "krb4.h"
+
+#include <roken.h>
+
+static AUTH_DAT auth_dat;
+static des_key_schedule schedule;
+
+int krb4_auth(char *auth)
+{
+ auth_complete = 0;
+ reply(334, "Using authentication type %s; ADAT must follow", auth);
+ return 0;
+}
+
+int krb4_adat(char *auth)
+{
+ KTEXT_ST tkt;
+ char *p;
+ int kerror;
+ u_int32_t cs;
+ char msg[35]; /* size of encrypted block */
+ int len;
+
+ char inst[INST_SZ];
+
+ memset(&tkt, 0, sizeof(tkt));
+ len = base64_decode(auth, tkt.dat);
+
+ if(len < 0){
+ reply(501, "Failed to decode base64 data.");
+ return -1;
+ }
+ tkt.length = len;
+
+ k_getsockinst(0, inst, sizeof(inst));
+ kerror = krb_rd_req(&tkt, "ftp", inst, 0, &auth_dat, "");
+ if(kerror == RD_AP_UNDEC){
+ k_getsockinst(0, inst, sizeof(inst));
+ kerror = krb_rd_req(&tkt, "rcmd", inst, 0, &auth_dat, "");
+ }
+
+ if(kerror){
+ reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
+ return -1;
+ }
+
+ des_set_key(&auth_dat.session, schedule);
+
+ cs = auth_dat.checksum + 1;
+ {
+ unsigned char tmp[4];
+ tmp[0] = (cs >> 24) & 0xff;
+ tmp[1] = (cs >> 16) & 0xff;
+ tmp[2] = (cs >> 8) & 0xff;
+ tmp[3] = cs & 0xff;
+ len = krb_mk_safe(tmp, msg, 4, &auth_dat.session,
+ &ctrl_addr, &his_addr);
+ }
+ if(len < 0){
+ reply(535, "Error creating reply: %s.", strerror(errno));
+ return -1;
+ }
+ base64_encode(msg, len, &p);
+ reply(235, "ADAT=%s", p);
+ auth_complete = 1;
+ free(p);
+ return 0;
+}
+
+int krb4_pbsz(int size)
+{
+ if(size > 1048576) /* XXX arbitrary number */
+ size = 1048576;
+ buffer_size = size;
+ reply(200, "OK PBSZ=%d", buffer_size);
+ return 0;
+}
+
+int krb4_prot(int level)
+{
+ if(level == prot_confidential)
+ return -1;
+ return 0;
+}
+
+int krb4_ccc(void)
+{
+ reply(534, "Don't event think about it.");
+ return -1;
+}
+
+int krb4_mic(char *msg)
+{
+ int len;
+ int kerror;
+ MSG_DAT m_data;
+ char *tmp, *cmd;
+
+ cmd = strdup(msg);
+
+ len = base64_decode(msg, cmd);
+ if(len < 0){
+ reply(501, "Failed to decode base 64 data.");
+ free(cmd);
+ return -1;
+ }
+ kerror = krb_rd_safe(cmd, len, &auth_dat.session,
+ &his_addr, &ctrl_addr, &m_data);
+
+ if(kerror){
+ reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
+ free(cmd);
+ return -1;
+ }
+
+ tmp = malloc(strlen(msg) + 1);
+ snprintf(tmp, strlen(msg) + 1, "%.*s", (int)m_data.app_length, m_data.app_data);
+ if(!strstr(tmp, "\r\n"))
+ strcat(tmp, "\r\n");
+ new_ftp_command(tmp);
+ free(cmd);
+ return 0;
+}
+
+int krb4_conf(char *msg)
+{
+ prot_level = prot_safe;
+
+ reply(537, "Protection level not supported.");
+ return -1;
+}
+
+int krb4_enc(char *msg)
+{
+ int len;
+ int kerror;
+ MSG_DAT m_data;
+ char *tmp, *cmd;
+
+ cmd = strdup(msg);
+
+ len = base64_decode(msg, cmd);
+ if(len < 0){
+ reply(501, "Failed to decode base 64 data.");
+ free(cmd);
+ return -1;
+ }
+ kerror = krb_rd_priv(cmd, len, schedule, &auth_dat.session,
+ &his_addr, &ctrl_addr, &m_data);
+
+ if(kerror){
+ reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
+ free(cmd);
+ return -1;
+ }
+
+ tmp = strdup(msg);
+ snprintf(tmp, strlen(msg) + 1, "%.*s", (int)m_data.app_length, m_data.app_data);
+ if(!strstr(tmp, "\r\n"))
+ strcat(tmp, "\r\n");
+ new_ftp_command(tmp);
+ free(cmd);
+ return 0;
+}
+
+int krb4_read(int fd, void *data, int length)
+{
+ static int left;
+ static char *extra;
+ static int eof;
+ int len, bytes, tx = 0;
+
+ MSG_DAT m_data;
+ int kerror;
+
+ if(eof){ /* if we haven't reported an end-of-file, do so */
+ eof = 0;
+ return 0;
+ }
+
+ if(left){
+ if(length > left)
+ bytes = left;
+ else
+ bytes = length;
+ memmove(data, extra, bytes);
+ left -= bytes;
+ if(left)
+ memmove(extra, extra + bytes, left);
+ else
+ free(extra);
+ length -= bytes;
+ tx += bytes;
+ }
+
+ while(length){
+ unsigned char tmp[4];
+ if(krb_net_read(fd, tmp, 4) < 4){
+ reply(400, "Unexpected end of file.\n");
+ return -1;
+ }
+ len = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3];
+ krb_net_read(fd, data_buffer, len);
+ if(data_protection == prot_safe)
+ kerror = krb_rd_safe(data_buffer, len, &auth_dat.session,
+ &his_addr, &ctrl_addr, &m_data);
+ else
+ kerror = krb_rd_priv(data_buffer, len, schedule, &auth_dat.session,
+ &his_addr, &ctrl_addr, &m_data);
+
+ if(kerror){
+ reply(400, "Failed to read data: %s.", krb_get_err_text(kerror));
+ return -1;
+ }
+
+ bytes = m_data.app_length;
+ if(bytes == 0){
+ if(tx) eof = 1;
+ return tx;
+ }
+ if(bytes > length){
+ left = bytes - length;
+ bytes = length;
+ extra = malloc(left);
+ memmove(extra, m_data.app_data + bytes, left);
+ }
+ memmove((unsigned char*)data + tx, m_data.app_data, bytes);
+ tx += bytes;
+ length -= bytes;
+ }
+ return tx;
+}
+
+int krb4_write(int fd, void *data, int length)
+{
+ int len, bytes, tx = 0;
+
+ len = buffer_size;
+ if(data_protection == prot_safe)
+ len -= 31; /* always 31 bytes overhead */
+ else
+ len -= 26; /* at most 26 bytes */
+
+ do{
+ if(length < len)
+ len = length;
+ if(data_protection == prot_safe)
+ bytes = krb_mk_safe(data, data_buffer+4, len, &auth_dat.session,
+ &ctrl_addr, &his_addr);
+ else
+ bytes = krb_mk_priv(data, data_buffer+4, len, schedule,
+ &auth_dat.session,
+ &ctrl_addr, &his_addr);
+ if(bytes == -1){
+ reply(535, "Failed to make packet: %s.", strerror(errno));
+ return -1;
+ }
+ data_buffer[0] = (bytes >> 24) & 0xff;
+ data_buffer[1] = (bytes >> 16) & 0xff;
+ data_buffer[2] = (bytes >> 8) & 0xff;
+ data_buffer[3] = bytes & 0xff;
+ if(krb_net_write(fd, data_buffer, bytes+4) < 0)
+ return -1;
+ length -= len;
+ data = (unsigned char*)data + len;
+ tx += len;
+ }while(length);
+ return tx;
+}
+
+int krb4_userok(char *name)
+{
+ if(!kuserok(&auth_dat, name)){
+ do_login(232, name);
+ }else{
+ reply(530, "User %s access denied.", name);
+ }
+ return 0;
+}
+
+
+int
+krb4_vprintf(const char *fmt, va_list ap)
+{
+ char buf[10240];
+ char *p;
+ char *enc;
+ int code;
+ int len;
+
+ vsnprintf (buf, sizeof(buf), fmt, ap);
+ enc = malloc(strlen(buf) + 31);
+ if(prot_level == prot_safe){
+ len = krb_mk_safe((u_char*)buf, (u_char*)enc, strlen(buf), &auth_dat.session,
+ &ctrl_addr, &his_addr);
+ code = 631;
+ }else if(prot_level == prot_private){
+ len = krb_mk_priv((u_char*)buf, (u_char*)enc, strlen(buf), schedule,
+ &auth_dat.session, &ctrl_addr, &his_addr);
+ code = 632;
+ }else{
+ len = 0; /* XXX */
+ code = 631;
+ }
+ base64_encode(enc, len, &p);
+ fprintf(stdout, "%d %s\r\n", code, p);
+ free(enc);
+ free(p);
+ return 0;
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/krb4.h b/crypto/kerberosIV/appl/ftp/ftpd/krb4.h
new file mode 100644
index 0000000..f777dbd
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/krb4.h
@@ -0,0 +1,61 @@
+/*
+ * 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: krb4.h,v 1.6 1997/04/01 08:17:29 joda Exp $ */
+
+#ifndef __KRB4_H__
+#define __KRB4_H__
+
+#include <stdarg.h>
+
+int krb4_auth(char *auth);
+int krb4_adat(char *auth);
+int krb4_pbsz(int size);
+int krb4_prot(int level);
+int krb4_ccc(void);
+int krb4_mic(char *msg);
+int krb4_conf(char *msg);
+int krb4_enc(char *msg);
+
+int krb4_read(int fd, void *data, int length);
+int krb4_write(int fd, void *data, int length);
+
+int krb4_userok(char *name);
+int krb4_vprintf(const char *fmt, va_list ap);
+
+#endif /* __KRB4_H__ */
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c
new file mode 100644
index 0000000..019cc2d
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: logwtmp.c,v 1.14 1999/12/02 16:58:31 joda Exp $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#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_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#include "extern.h"
+
+#ifndef WTMP_FILE
+#ifdef _PATH_WTMP
+#define WTMP_FILE _PATH_WTMP
+#else
+#define WTMP_FILE "/var/adm/wtmp"
+#endif
+#endif
+
+void
+ftpd_logwtmp(char *line, char *name, char *host)
+{
+ static int init = 0;
+ 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_STRUCT_UTMP_UT_TYPE
+ if(name[0])
+ ut.ut_type = USER_PROCESS;
+ else
+ ut.ut_type = DEAD_PROCESS;
+#endif
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+ ut.ut_pid = getpid();
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+#endif
+ ut.ut_time = time(NULL);
+
+#ifdef WTMPX_FILE
+ 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_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
+ {
+ 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;
+ else
+ utx.ut_type = DEAD_PROCESS;
+#endif
+
+ if(!init){
+ fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0);
+#ifdef WTMPX_FILE
+ fdx = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0);
+#endif
+ init = 1;
+ }
+ if(fd >= 0) {
+ write(fd, &ut, sizeof(struct utmp)); /* XXX */
+#ifdef WTMPX_FILE
+ write(fdx, &utx, sizeof(struct utmpx));
+#endif
+ }
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ls.c b/crypto/kerberosIV/appl/ftp/ftpd/ls.c
new file mode 100644
index 0000000..6e2c9a1
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/ls.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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"
+
+RCSID("$Id: ls.c,v 1.13.2.2 2000/06/23 02:51:09 assar Exp $");
+
+struct fileinfo {
+ struct stat st;
+ int inode;
+ int bsize;
+ char mode[11];
+ int n_link;
+ char *user;
+ char *group;
+ char *size;
+ char *major;
+ char *minor;
+ char *date;
+ char *filename;
+ char *link;
+};
+
+#define LS_DIRS 1
+#define LS_IGNORE_DOT 2
+#define LS_SORT_MODE 12
+#define SORT_MODE(f) ((f) & LS_SORT_MODE)
+#define LS_SORT_NAME 4
+#define LS_SORT_MTIME 8
+#define LS_SORT_SIZE 12
+#define LS_SORT_REVERSE 16
+
+#define LS_SIZE 32
+#define LS_INODE 64
+
+#ifndef S_ISTXT
+#define S_ISTXT S_ISVTX
+#endif
+
+#ifndef S_ISSOCK
+#define S_ISSOCK(mode) (((mode) & _S_IFMT) == S_IFSOCK)
+#endif
+
+#ifndef S_ISLNK
+#define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK)
+#endif
+
+static void
+make_fileinfo(const char *filename, struct fileinfo *file, int flags)
+{
+ char buf[128];
+ struct stat *st = &file->st;
+
+ file->inode = st->st_ino;
+#ifdef S_BLKSIZE
+ file->bsize = st->st_blocks * S_BLKSIZE / 1024;
+#else
+ file->bsize = st->st_blocks * 512 / 1024;
+#endif
+
+ if(S_ISDIR(st->st_mode))
+ file->mode[0] = 'd';
+ else if(S_ISCHR(st->st_mode))
+ file->mode[0] = 'c';
+ else if(S_ISBLK(st->st_mode))
+ file->mode[0] = 'b';
+ else if(S_ISREG(st->st_mode))
+ file->mode[0] = '-';
+ else if(S_ISFIFO(st->st_mode))
+ file->mode[0] = 'p';
+ else if(S_ISLNK(st->st_mode))
+ file->mode[0] = 'l';
+ else if(S_ISSOCK(st->st_mode))
+ file->mode[0] = 's';
+#ifdef S_ISWHT
+ else if(S_ISWHT(st->st_mode))
+ file->mode[0] = 'w';
+#endif
+ else
+ file->mode[0] = '?';
+ {
+ char *x[] = { "---", "--x", "-w-", "-wx",
+ "r--", "r-x", "rw-", "rwx" };
+ strcpy(file->mode + 1, x[(st->st_mode & S_IRWXU) >> 6]);
+ strcpy(file->mode + 4, x[(st->st_mode & S_IRWXG) >> 3]);
+ strcpy(file->mode + 7, x[(st->st_mode & S_IRWXO) >> 0]);
+ if((st->st_mode & S_ISUID)) {
+ if((st->st_mode & S_IXUSR))
+ file->mode[3] = 's';
+ else
+ file->mode[3] = 'S';
+ }
+ if((st->st_mode & S_ISGID)) {
+ if((st->st_mode & S_IXGRP))
+ file->mode[6] = 's';
+ else
+ file->mode[6] = 'S';
+ }
+ if((st->st_mode & S_ISTXT)) {
+ if((st->st_mode & S_IXOTH))
+ file->mode[9] = 't';
+ else
+ file->mode[9] = 'T';
+ }
+ }
+ file->n_link = st->st_nlink;
+ {
+ struct passwd *pwd;
+ pwd = getpwuid(st->st_uid);
+ if(pwd == NULL)
+ asprintf(&file->user, "%u", (unsigned)st->st_uid);
+ else
+ file->user = strdup(pwd->pw_name);
+ }
+ {
+ struct group *grp;
+ grp = getgrgid(st->st_gid);
+ if(grp == NULL)
+ asprintf(&file->group, "%u", (unsigned)st->st_gid);
+ else
+ file->group = strdup(grp->gr_name);
+ }
+
+ if(S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+#if defined(major) && defined(minor)
+ asprintf(&file->major, "%u", (unsigned)major(st->st_rdev));
+ asprintf(&file->minor, "%u", (unsigned)minor(st->st_rdev));
+#else
+ /* Don't want to use the DDI/DKI crap. */
+ asprintf(&file->major, "%u", (unsigned)st->st_rdev);
+ asprintf(&file->minor, "%u", 0);
+#endif
+ } else
+ asprintf(&file->size, "%lu", (unsigned long)st->st_size);
+
+ {
+ time_t t = time(NULL);
+ time_t mtime = st->st_mtime;
+ struct tm *tm = localtime(&mtime);
+ if((t - mtime > 6*30*24*60*60) ||
+ (mtime - t > 6*30*24*60*60))
+ strftime(buf, sizeof(buf), "%b %e %Y", tm);
+ else
+ strftime(buf, sizeof(buf), "%b %e %H:%M", tm);
+ file->date = strdup(buf);
+ }
+ {
+ const char *p = strrchr(filename, '/');
+ if(p)
+ p++;
+ else
+ p = filename;
+ file->filename = strdup(p);
+ }
+ if(S_ISLNK(st->st_mode)) {
+ int n;
+ n = readlink((char *)filename, buf, sizeof(buf));
+ if(n >= 0) {
+ buf[n] = '\0';
+ file->link = strdup(buf);
+ } else
+ warn("%s: readlink", filename);
+ }
+}
+
+static void
+print_file(FILE *out,
+ int flags,
+ struct fileinfo *f,
+ int max_inode,
+ int max_bsize,
+ int max_n_link,
+ int max_user,
+ int max_group,
+ int max_size,
+ int max_major,
+ int max_minor,
+ int max_date)
+{
+ if(f->filename == NULL)
+ return;
+
+ if(flags & LS_INODE) {
+ sec_fprintf2(out, "%*d", max_inode, f->inode);
+ sec_fprintf2(out, " ");
+ }
+ if(flags & LS_SIZE) {
+ sec_fprintf2(out, "%*d", max_bsize, f->bsize);
+ sec_fprintf2(out, " ");
+ }
+ sec_fprintf2(out, "%s", f->mode);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%*d", max_n_link, f->n_link);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%-*s", max_user, f->user);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%-*s", max_group, f->group);
+ sec_fprintf2(out, " ");
+ if(f->major != NULL && f->minor != NULL)
+ sec_fprintf2(out, "%*s, %*s", max_major, f->major, max_minor, f->minor);
+ else
+ sec_fprintf2(out, "%*s", max_size, f->size);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%*s", max_date, f->date);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%s", f->filename);
+ if(f->link)
+ sec_fprintf2(out, " -> %s", f->link);
+ sec_fprintf2(out, "\r\n");
+}
+
+static int
+compare_filename(struct fileinfo *a, struct fileinfo *b)
+{
+ if(a->filename == NULL)
+ return 1;
+ if(b->filename == NULL)
+ return -1;
+ return strcmp(a->filename, b->filename);
+}
+
+static int
+compare_mtime(struct fileinfo *a, struct fileinfo *b)
+{
+ if(a->filename == NULL)
+ return 1;
+ if(b->filename == NULL)
+ return -1;
+ return a->st.st_mtime - b->st.st_mtime;
+}
+
+static int
+compare_size(struct fileinfo *a, struct fileinfo *b)
+{
+ if(a->filename == NULL)
+ return 1;
+ if(b->filename == NULL)
+ return -1;
+ return a->st.st_size - b->st.st_size;
+}
+
+static void
+list_dir(FILE *out, const char *directory, int flags);
+
+static int
+log10(int num)
+{
+ int i = 1;
+ while(num > 10) {
+ i++;
+ num /= 10;
+ }
+ return i;
+}
+
+/*
+ * Operate as lstat but fake up entries for AFS mount points so we don't
+ * have to fetch them.
+ */
+
+static int
+lstat_file (const char *file, struct stat *sb)
+{
+#ifdef KRB4
+ if (k_hasafs()
+ && strcmp(file, ".")
+ && strcmp(file, ".."))
+ {
+ struct ViceIoctl a_params;
+ char *last;
+ char *path_bkp;
+ static ino_t ino_counter = 0, ino_last = 0;
+ int ret;
+ const int maxsize = 2048;
+
+ path_bkp = strdup (file);
+ if (path_bkp == NULL)
+ return -1;
+
+ a_params.out = malloc (maxsize);
+ if (a_params.out == NULL) {
+ free (path_bkp);
+ return -1;
+ }
+
+ /* If path contains more than the filename alone - split it */
+
+ last = strrchr (path_bkp, '/');
+ if (last != NULL) {
+ *last = '\0';
+ a_params.in = last + 1;
+ } else
+ a_params.in = (char *)file;
+
+ a_params.in_size = strlen (a_params.in) + 1;
+ a_params.out_size = maxsize;
+
+ ret = k_pioctl (last ? path_bkp : "." ,
+ VIOC_AFS_STAT_MT_PT, &a_params, 0);
+ free (a_params.out);
+ if (ret < 0) {
+ free (path_bkp);
+
+ if (errno != EINVAL)
+ return ret;
+ else
+ /* if we get EINVAL this is probably not a mountpoint */
+ return lstat (file, sb);
+ }
+
+ /*
+ * wow this was a mountpoint, lets cook the struct stat
+ * use . as a prototype
+ */
+
+ ret = lstat (path_bkp, sb);
+ free (path_bkp);
+ if (ret < 0)
+ return ret;
+
+ if (ino_last == sb->st_ino)
+ ino_counter++;
+ else {
+ ino_last = sb->st_ino;
+ ino_counter = 0;
+ }
+ sb->st_ino += ino_counter;
+ sb->st_nlink = 3;
+
+ return 0;
+ }
+#endif /* KRB4 */
+ return lstat (file, sb);
+}
+
+static void
+list_files(FILE *out, char **files, int n_files, int flags)
+{
+ struct fileinfo *fi;
+ int i;
+
+ fi = calloc(n_files, sizeof(*fi));
+ if (fi == NULL) {
+ sec_fprintf2(out, "ouf of memory\r\n");
+ return;
+ }
+ for(i = 0; i < n_files; i++) {
+ if(lstat_file(files[i], &fi[i].st) < 0) {
+ sec_fprintf2(out, "%s: %s\r\n", files[i], strerror(errno));
+ fi[i].filename = NULL;
+ } else {
+ if((flags & LS_DIRS) == 0 && S_ISDIR(fi[i].st.st_mode)) {
+ if(n_files > 1)
+ sec_fprintf2(out, "%s:\r\n", files[i]);
+ list_dir(out, files[i], flags);
+ } else {
+ make_fileinfo(files[i], &fi[i], flags);
+ }
+ }
+ }
+ switch(SORT_MODE(flags)) {
+ case LS_SORT_NAME:
+ qsort(fi, n_files, sizeof(*fi),
+ (int (*)(const void*, const void*))compare_filename);
+ break;
+ case LS_SORT_MTIME:
+ qsort(fi, n_files, sizeof(*fi),
+ (int (*)(const void*, const void*))compare_mtime);
+ break;
+ case LS_SORT_SIZE:
+ qsort(fi, n_files, sizeof(*fi),
+ (int (*)(const void*, const void*))compare_size);
+ break;
+ }
+ {
+ int max_inode = 0;
+ int max_bsize = 0;
+ int max_n_link = 0;
+ int max_user = 0;
+ int max_group = 0;
+ int max_size = 0;
+ int max_major = 0;
+ int max_minor = 0;
+ int max_date = 0;
+ for(i = 0; i < n_files; i++) {
+ if(fi[i].filename == NULL)
+ continue;
+ if(fi[i].inode > max_inode)
+ max_inode = fi[i].inode;
+ if(fi[i].bsize > max_bsize)
+ max_bsize = fi[i].bsize;
+ if(fi[i].n_link > max_n_link)
+ max_n_link = fi[i].n_link;
+ if(strlen(fi[i].user) > max_user)
+ max_user = strlen(fi[i].user);
+ if(strlen(fi[i].group) > max_group)
+ max_group = strlen(fi[i].group);
+ if(fi[i].major != NULL && strlen(fi[i].major) > max_major)
+ max_major = strlen(fi[i].major);
+ if(fi[i].minor != NULL && strlen(fi[i].minor) > max_minor)
+ max_minor = strlen(fi[i].minor);
+ if(fi[i].size != NULL && strlen(fi[i].size) > max_size)
+ max_size = strlen(fi[i].size);
+ if(strlen(fi[i].date) > max_date)
+ max_date = strlen(fi[i].date);
+ }
+ if(max_size < max_major + max_minor + 2)
+ max_size = max_major + max_minor + 2;
+ else if(max_size - max_minor - 2 > max_major)
+ max_major = max_size - max_minor - 2;
+ max_inode = log10(max_inode);
+ max_bsize = log10(max_bsize);
+ max_n_link = log10(max_n_link);
+
+ if(flags & LS_SORT_REVERSE)
+ for(i = n_files - 1; i >= 0; i--)
+ print_file(out,
+ flags,
+ &fi[i],
+ max_inode,
+ max_bsize,
+ max_n_link,
+ max_user,
+ max_group,
+ max_size,
+ max_major,
+ max_minor,
+ max_date);
+ else
+ for(i = 0; i < n_files; i++)
+ print_file(out,
+ flags,
+ &fi[i],
+ max_inode,
+ max_bsize,
+ max_n_link,
+ max_user,
+ max_group,
+ max_size,
+ max_major,
+ max_minor,
+ max_date);
+ }
+}
+
+static void
+free_files (char **files, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ free (files[i]);
+ free (files);
+}
+
+static void
+list_dir(FILE *out, const char *directory, int flags)
+{
+ DIR *d = opendir(directory);
+ struct dirent *ent;
+ char **files = NULL;
+ int n_files = 0;
+
+ if(d == NULL) {
+ sec_fprintf2(out, "%s: %s\r\n", directory, strerror(errno));
+ return;
+ }
+ while((ent = readdir(d)) != NULL) {
+ void *tmp;
+
+ if(ent->d_name[0] == '.') {
+ if (flags & LS_IGNORE_DOT)
+ continue;
+ if (ent->d_name[1] == 0) /* Ignore . */
+ continue;
+ if (ent->d_name[1] == '.' && ent->d_name[2] == 0) /* Ignore .. */
+ continue;
+ }
+ tmp = realloc(files, (n_files + 1) * sizeof(*files));
+ if (tmp == NULL) {
+ sec_fprintf2(out, "%s: out of memory\r\n", directory);
+ free_files (files, n_files);
+ closedir (d);
+ return;
+ }
+ files = tmp;
+ asprintf(&files[n_files], "%s/%s", directory, ent->d_name);
+ if (files[n_files] == NULL) {
+ sec_fprintf2(out, "%s: out of memory\r\n", directory);
+ free_files (files, n_files);
+ closedir (d);
+ return;
+ }
+ ++n_files;
+ }
+ closedir(d);
+ list_files(out, files, n_files, flags | LS_DIRS);
+}
+
+void
+builtin_ls(FILE *out, const char *file)
+{
+ int flags = LS_SORT_NAME;
+
+ if(*file == '-') {
+ const char *p;
+ for(p = file + 1; *p; p++) {
+ switch(*p) {
+ case 'a':
+ case 'A':
+ flags &= ~LS_IGNORE_DOT;
+ break;
+ case 'C':
+ break;
+ case 'd':
+ flags |= LS_DIRS;
+ break;
+ case 'f':
+ flags = (flags & ~LS_SORT_MODE);
+ break;
+ case 'i':
+ flags |= flags | LS_INODE;
+ break;
+ case 'l':
+ break;
+ case 't':
+ flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME;
+ break;
+ case 's':
+ flags |= LS_SIZE;
+ break;
+ case 'S':
+ flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE;
+ break;
+ case 'r':
+ flags |= LS_SORT_REVERSE;
+ break;
+ }
+ }
+ file = ".";
+ }
+ list_files(out, &file, 1, flags);
+ sec_fflush(out);
+}
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/pathnames.h b/crypto/kerberosIV/appl/ftp/ftpd/pathnames.h
new file mode 100644
index 0000000..ff2041b
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/pathnames.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#ifndef _PATH_NOLOGIN
+#define _PATH_NOLOGIN "/etc/nologin"
+#endif
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#define _PATH_FTPUSERS "/etc/ftpusers"
+#define _PATH_FTPCHROOT "/etc/ftpchroot"
+#define _PATH_FTPWELCOME "/etc/ftpwelcome"
+#define _PATH_FTPLOGINMESG "/etc/motd"
+
+#define _PATH_ISSUE "/etc/issue"
+#define _PATH_ISSUE_NET "/etc/issue.net"
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/popen.c b/crypto/kerberosIV/appl/ftp/ftpd/popen.c
new file mode 100644
index 0000000..5f36813
--- /dev/null
+++ b/crypto/kerberosIV/appl/ftp/ftpd/popen.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: popen.c,v 1.19 1999/09/16 20:38:45 assar Exp $");
+#endif
+
+#include <sys/types.h>
+#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
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <glob.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#include <roken.h>
+
+/*
+ * Special version of popen which avoids call to shell. This ensures
+ * no one may create a pipe to a hidden program as a side effect of a
+ * list or dir command.
+ */
+static int *pids;
+static int fds;
+
+extern int dochroot;
+
+/* return path prepended with ~ftp if that file exists, otherwise
+ * return path unchanged
+ */
+
+const char *
+ftp_rooted(const char *path)
+{
+ static char home[MaxPathLen] = "";
+ static char newpath[MaxPathLen];
+ struct passwd *pwd;
+
+ if(!home[0])
+ if((pwd = k_getpwnam("ftp")))
+ strlcpy(home, pwd->pw_dir, sizeof(home));
+ snprintf(newpath, sizeof(newpath), "%s/%s", home, path);
+ if(access(newpath, X_OK))
+ strlcpy(newpath, path, sizeof(newpath));
+ return newpath;
+}
+
+
+FILE *
+ftpd_popen(char *program, char *type, int do_stderr, int no_glob)
+{
+ char *cp;
+ FILE *iop;
+ int argc, gargc, pdes[2], pid;
+ char **pop, *argv[100], *gargv[1000];
+ char *foo;
+
+ if (strcmp(type, "r") && strcmp(type, "w"))
+ return (NULL);
+
+ if (!pids) {
+
+ /* This function is ugly and should be rewritten, in
+ * modern unices there is no such thing as a maximum
+ * filedescriptor.
+ */
+
+ fds = getdtablesize();
+ pids = (int*)calloc(fds, sizeof(int));
+ if(!pids)
+ return NULL;
+ }
+ if (pipe(pdes) < 0)
+ return (NULL);
+
+ /* break up string into pieces */
+ foo = NULL;
+ for (argc = 0, cp = program;; cp = NULL) {
+ if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo)))
+ break;
+ }
+
+ gargv[0] = (char*)ftp_rooted(argv[0]);
+ /* glob each piece */
+ for (gargc = argc = 1; argv[argc]; argc++) {
+ glob_t gl;
+ int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+ memset(&gl, 0, sizeof(gl));
+ if (no_glob || glob(argv[argc], flags, NULL, &gl))
+ gargv[gargc++] = strdup(argv[argc]);
+ else
+ for (pop = gl.gl_pathv; *pop; pop++)
+ gargv[gargc++] = strdup(*pop);
+ globfree(&gl);
+ }
+ gargv[gargc] = NULL;
+
+ iop = NULL;
+ switch(pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ goto pfree;
+ /* NOTREACHED */
+ case 0: /* child */
+ if (*type == 'r') {
+ if (pdes[1] != STDOUT_FILENO) {
+ dup2(pdes[1], STDOUT_FILENO);
+ close(pdes[1]);
+ }
+ if(do_stderr)
+ dup2(STDOUT_FILENO, STDERR_FILENO);
+ close(pdes[0]);
+ } else {
+ if (pdes[0] != STDIN_FILENO) {
+ dup2(pdes[0], STDIN_FILENO);
+ close(pdes[0]);
+ }
+ close(pdes[1]);
+ }
+ execv(gargv[0], gargv);
+ gargv[0] = argv[0];
+ execv(gargv[0], gargv);
+ _exit(1);
+ }
+ /* parent; assume fdopen can't fail... */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ close(pdes[0]);
+ }
+ pids[fileno(iop)] = pid;
+
+pfree:
+ for (argc = 1; gargv[argc] != NULL; argc++)
+ free(gargv[argc]);
+
+
+ return (iop);
+}
+
+int
+ftpd_pclose(FILE *iop)
+{
+ int fdes, status;
+ pid_t pid;
+ sigset_t sigset, osigset;
+
+ /*
+ * pclose returns -1 if stream is not associated with a
+ * `popened' command, or, if already `pclosed'.
+ */
+ if (pids == 0 || pids[fdes = fileno(iop)] == 0)
+ return (-1);
+ fclose(iop);
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
+ sigaddset(&sigset, SIGQUIT);
+ sigaddset(&sigset, SIGHUP);
+ sigprocmask(SIG_BLOCK, &sigset, &osigset);
+ while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
+ continue;
+ sigprocmask(SIG_SETMASK, &osigset, NULL);
+ pids[fdes] = 0;
+ if (pid < 0)
+ return (pid);
+ if (WIFEXITED(status))
+ return (WEXITSTATUS(status));
+ return (1);
+}
diff --git a/crypto/kerberosIV/appl/kauth/ChangeLog b/crypto/kerberosIV/appl/kauth/ChangeLog
new file mode 100644
index 0000000..7ce281c
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/ChangeLog
@@ -0,0 +1,41 @@
+2000-02-28 Assar Westerlund <assar@sics.se>
+
+ * kauth.c (main): don't enable aflag with `-d'. this breaks with
+ kaservers that don't let you get a ticket for a user and besides,
+ adding debugging should not change the functionality
+
+1999-12-06 Assar Westerlund <assar@sics.se>
+
+ * rkinit.c (doit_host): NAT work-around
+ * kauthd.c (doit): type correctness
+
+1999-08-31 Johan Danielsson <joda@pdc.kth.se>
+
+ * kauth.c: cleanup usage string; handle `kauth -h' gracefully
+ (print usage); add `-a' flag to get the ticket address (useful for
+ firewall configurations)
+
+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
new file mode 100644
index 0000000..1e8a4c1
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/Makefile.in
@@ -0,0 +1,115 @@
+# $Id: Makefile.in,v 1.40.16.1 2000/06/23 02:52:31 assar Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+top_builddir = ../..
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@ -DBINDIR='"$(bindir)"'
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS = @LD_FLAGS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+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 = kauth$(EXECSUFFIX)
+SCRIPT_BIN = ksrvtgt
+PROG_LIBEXEC = kauthd$(EXECSUFFIX)
+PROGS = $(PROG_BIN) $(SCRIPT_BIN) $(PROG_LIBEXEC)
+
+SOURCES_KAUTH = kauth.c rkinit.c
+SOURCES_KAUTHD = kauthd.c
+SOURCES_COMMON = encdata.c marshall.c
+
+OBJECTS_KAUTH = kauth.o rkinit.o
+OBJECTS_KAUTHD = kauthd.o
+OBJECTS_COMMON = marshall.o encdata.o
+
+OBJECTS = $(OBJECTS_KAUTH) $(OBJECTS_KAUTHD)
+SOURCES = $(SOURCES_KAUTH) $(SOURCES_KAUTHD) $(SOURCES_COMMON)
+
+KRB_KAFS_LIB = @KRB_KAFS_LIB@
+
+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) $(DESTDIR)$(libexecdir)
+ for x in $(PROG_BIN); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+ for x in $(SCRIPT_BIN); do \
+ $(INSTALL_SCRIPT) $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+ if test -f $(DESTDIR)$(bindir)/zrefresh -o -r $(DESTDIR)$(bindir)/zrefresh; then \
+ true; \
+ else \
+ $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(DESTDIR)$(bindir)/`echo zrefresh | sed '$(transform)'`; \
+ fi
+ for x in $(PROG_LIBEXEC); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(PROG_BIN) $(SCRIPT_BIN); do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+ for x in $(PROG_LIBEXEC); do \
+ rm -f $(DESTDIR)$(libexecdir)/`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
+
+KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
+LIBROKEN=-L../../lib/roken -lroken
+
+kauth$(EXECSUFFIX): $(OBJECTS_KAUTH) $(OBJECTS_COMMON)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTH) $(OBJECTS_COMMON) $(KRB_KAFS_LIB) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+kauthd$(EXECSUFFIX): $(OBJECTS_KAUTHD) $(OBJECTS_COMMON)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+ksrvtgt: ksrvtgt.in
+ sed -e "s!%bindir%!$(bindir)!" $(srcdir)/ksrvtgt.in > $@
+ chmod +x $@
+
+
+$(OBJECTS): ../../include/config.h
+
+.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/kauth/encdata.c b/crypto/kerberosIV/appl/kauth/encdata.c
new file mode 100644
index 0000000..886f549
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/encdata.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kauth.h"
+
+RCSID("$Id: encdata.c,v 1.10 1999/12/02 16:58:31 joda Exp $");
+
+int
+write_encrypted (int fd, void *buf, size_t len, des_key_schedule schedule,
+ des_cblock *session, struct sockaddr_in *me,
+ struct sockaddr_in *him)
+{
+ void *outbuf;
+ int32_t outlen, l;
+ int i;
+ unsigned char tmp[4];
+
+ outbuf = malloc(len + 30);
+ if (outbuf == NULL)
+ return -1;
+ outlen = krb_mk_priv (buf, outbuf, len, schedule, session, me, him);
+ if (outlen < 0) {
+ free(outbuf);
+ return -1;
+ }
+ l = outlen;
+ for(i = 3; i >= 0; i--, l = l >> 8)
+ tmp[i] = l & 0xff;
+ if (krb_net_write (fd, tmp, 4) != 4 ||
+ krb_net_write (fd, outbuf, outlen) != outlen) {
+ free(outbuf);
+ return -1;
+ }
+
+ free(outbuf);
+ return 0;
+}
+
+
+int
+read_encrypted (int fd, void *buf, size_t len, void **ret,
+ des_key_schedule schedule, des_cblock *session,
+ struct sockaddr_in *him, struct sockaddr_in *me)
+{
+ int status;
+ int32_t l;
+ MSG_DAT msg;
+ unsigned char tmp[4];
+
+ l = krb_net_read (fd, tmp, 4);
+ if (l != 4)
+ return l;
+ l = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3];
+ if (l > len)
+ return -1;
+ if (krb_net_read (fd, buf, l) != l)
+ return -1;
+ status = krb_rd_priv (buf, l, schedule, session, him, me, &msg);
+ if (status != RD_AP_OK) {
+ fprintf (stderr, "read_encrypted: %s\n",
+ krb_get_err_text(status));
+ return -1;
+ }
+ *ret = msg.app_data;
+ return msg.app_length;
+}
diff --git a/crypto/kerberosIV/appl/kauth/kauth.c b/crypto/kerberosIV/appl/kauth/kauth.c
new file mode 100644
index 0000000..3f6f0bc
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/kauth.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Little program that reads an srvtab or password and
+ * creates a suitable ticketfile and associated AFS tokens.
+ *
+ * If an optional command is given the command is executed in a
+ * new PAG and when the command exits the tickets are destroyed.
+ */
+
+#include "kauth.h"
+
+RCSID("$Id: kauth.c,v 1.97.2.1 2000/02/28 03:42:51 assar Exp $");
+
+krb_principal princ;
+static char srvtab[MaxPathLen];
+static int lifetime = DEFAULT_TKT_LIFE;
+static char remote_tktfile[MaxPathLen];
+static char remoteuser[100];
+static char *cell = 0;
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "Usage:\n"
+ " %s [name]\n"
+ "or\n"
+ " %s [-ad] [-n name] [-r remoteuser] [-t remote ticketfile]\n"
+ " [-l lifetime (in minutes) ] [-f srvtab ] [-c AFS cell name ]\n"
+ " [-h hosts... [--]] [command ... ]\n\n",
+ __progname, __progname);
+ fprintf(stderr,
+ "A fully qualified name can be given: user[.instance][@realm]\n"
+ "Realm is converted to uppercase!\n");
+ exit(1);
+}
+
+#define EX_NOEXEC 126
+#define EX_NOTFOUND 127
+
+static int
+doexec(int argc, char **argv)
+{
+ 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
+renew(int sig)
+{
+ int code;
+
+ signal(SIGALRM, renew);
+
+ code = krb_get_svc_in_tkt(princ.name, princ.instance, princ.realm,
+ KRB_TICKET_GRANTING_TICKET,
+ princ.realm, lifetime, srvtab);
+ if (code)
+ warnx ("%s", krb_get_err_text(code));
+ else if (k_hasafs())
+ {
+ if ((code = krb_afslog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) {
+ warnx ("%s", krb_get_err_text(code));
+ }
+ }
+
+ alarm(krb_life_to_time(0, lifetime)/2 - 60);
+ SIGRETURN(0);
+}
+
+static int
+zrefresh(void)
+{
+ switch (fork()) {
+ case -1:
+ err (1, "Warning: Failed to fork zrefresh");
+ return -1;
+ case 0:
+ /* Child */
+ execlp("zrefresh", "zrefresh", 0);
+ execl(BINDIR "/zrefresh", "zrefresh", 0);
+ exit(1);
+ default:
+ /* Parent */
+ break;
+ }
+ return 0;
+}
+
+static int
+key_to_key(const char *user,
+ char *instance,
+ const char *realm,
+ const void *arg,
+ des_cblock *key)
+{
+ memcpy(key, arg, sizeof(des_cblock));
+ return 0;
+}
+
+static int
+get_ticket_address(krb_principal *princ, des_cblock *key)
+{
+ int code;
+ unsigned char flags;
+ krb_principal service;
+ u_int32_t addr;
+ struct in_addr addr2;
+ des_cblock session;
+ int life;
+ u_int32_t time_sec;
+ des_key_schedule schedule;
+ CREDENTIALS c;
+
+ code = get_ad_tkt(princ->name, princ->instance, princ->realm, 0);
+ if(code) {
+ warnx("get_ad_tkt: %s\n", krb_get_err_text(code));
+ return code;
+ }
+ code = krb_get_cred(princ->name, princ->instance, princ->realm, &c);
+ if(code) {
+ warnx("krb_get_cred: %s\n", krb_get_err_text(code));
+ return code;
+ }
+
+ des_set_key(key, schedule);
+ code = decomp_ticket(&c.ticket_st,
+ &flags,
+ princ->name,
+ princ->instance,
+ princ->realm,
+ &addr,
+ session,
+ &life,
+ &time_sec,
+ service.name,
+ service.instance,
+ key,
+ schedule);
+ if(code) {
+ warnx("decomp_ticket: %s\n", krb_get_err_text(code));
+ return code;
+ }
+ memset(&session, 0, sizeof(session));
+ memset(schedule, 0, sizeof(schedule));
+ addr2.s_addr = addr;
+ fprintf(stdout, "ticket address = %s\n", inet_ntoa(addr2));
+}
+
+
+int
+main(int argc, char **argv)
+{
+ int code, more_args;
+ int ret;
+ int c;
+ char *file;
+ int pflag = 0;
+ int aflag = 0;
+ int version_flag = 0;
+ char passwd[100];
+ des_cblock key;
+ char **host;
+ int nhost;
+ char tf[MaxPathLen];
+
+ set_progname (argv[0]);
+
+ if ((file = getenv("KRBTKFILE")) == 0)
+ file = TKT_FILE;
+
+ memset(&princ, 0, sizeof(princ));
+ memset(srvtab, 0, sizeof(srvtab));
+ *remoteuser = '\0';
+ nhost = 0;
+ host = NULL;
+
+ /* 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, "ar:t:f:hdl:n:c:v")) != -1)
+ switch (c) {
+ case 'a':
+ aflag++;
+ break;
+ case 'd':
+ krb_enable_debug();
+ _kafs_debug = 1;
+ break;
+ case 'f':
+ strlcpy(srvtab, optarg, sizeof(srvtab));
+ break;
+ case 't':
+ strlcpy(remote_tktfile, optarg, sizeof(remote_tktfile));
+ break;
+ case 'r':
+ strlcpy(remoteuser, optarg, sizeof(remoteuser));
+ break;
+ case 'l':
+ lifetime = atoi(optarg);
+ if (lifetime == -1)
+ lifetime = 255;
+ else if (lifetime < 5)
+ lifetime = 1;
+ else
+ lifetime = krb_time_to_life(0, lifetime*60);
+ if (lifetime > 255)
+ lifetime = 255;
+ break;
+ case 'n':
+ if ((code = krb_parse_name(optarg, &princ)) != 0) {
+ warnx ("%s", krb_get_err_text(code));
+ usage();
+ }
+ strupr(princ.realm);
+ pflag = 1;
+ break;
+ case 'c':
+ cell = optarg;
+ break;
+ case 'h':
+ host = argv + optind;
+ for(nhost = 0; optind < argc && *argv[optind] != '-'; ++optind)
+ ++nhost;
+ if(nhost == 0)
+ usage();
+ break;
+ case 'v':
+ version_flag++;
+ print_version(NULL);
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+
+ 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");
+
+ /* With root tickets assume remote user is root */
+ if (*remoteuser == '\0') {
+ if (strcmp(princ.instance, "root") == 0)
+ strlcpy(remoteuser, princ.instance, sizeof(remoteuser));
+ else
+ strlcpy(remoteuser, princ.name, sizeof(remoteuser));
+ }
+
+ more_args = argc - optind;
+
+ if (princ.realm[0] == '\0')
+ if (krb_get_lrealm(princ.realm, 1) != KSUCCESS)
+ strlcpy(princ.realm, KRB_REALM, REALM_SZ);
+
+ if (more_args) {
+ int f;
+
+ do{
+ snprintf(tf, sizeof(tf), "%s%u_%u", TKT_ROOT, (unsigned)getuid(),
+ (unsigned)(getpid()*time(0)));
+ f = open(tf, O_CREAT|O_EXCL|O_RDWR);
+ }while(f < 0);
+ close(f);
+ unlink(tf);
+ setenv("KRBTKFILE", tf, 1);
+ krb_set_tkt_string (tf);
+ }
+
+ if (srvtab[0])
+ {
+ signal(SIGALRM, renew);
+
+ code = read_service_key (princ.name, princ.instance, princ.realm, 0,
+ srvtab, (char *)&key);
+ if (code == KSUCCESS)
+ code = krb_get_in_tkt(princ.name, princ.instance, princ.realm,
+ KRB_TICKET_GRANTING_TICKET,
+ princ.realm, lifetime,
+ key_to_key, NULL, key);
+ alarm(krb_life_to_time(0, lifetime)/2 - 60);
+ }
+ else {
+ char prompt[128];
+
+ snprintf(prompt, sizeof(prompt), "%s's Password: ", krb_unparse_name(&princ));
+ if (des_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
+ memset(passwd, 0, sizeof(passwd));
+ exit(1);
+ }
+ 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) {
+ memset (key, 0, sizeof(key));
+ errx (1, "%s", krb_get_err_text(code));
+ }
+
+ if(aflag)
+ get_ticket_address(&princ, &key);
+
+ if (k_hasafs()) {
+ if (more_args)
+ k_setpag();
+ 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++)
+ ret += rkinit(&princ, lifetime, remoteuser, remote_tktfile, &key, *host);
+
+ if (ret)
+ return ret;
+
+ if (more_args) {
+ ret = doexec(more_args, &argv[optind]);
+ dest_tkt();
+ if (k_hasafs())
+ k_unlog();
+ }
+ else
+ zrefresh();
+
+ return ret;
+}
diff --git a/crypto/kerberosIV/appl/kauth/kauth.h b/crypto/kerberosIV/appl/kauth/kauth.h
new file mode 100644
index 0000000..32243c7
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/kauth.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: kauth.h,v 1.21 1999/12/02 16:58:31 joda Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <signal.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.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_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
+#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 <kafs.h>
+
+#include <roken.h>
+
+#define KAUTH_PORT 2120
+
+#define KAUTH_VERSION "RKINIT.0"
+
+int rkinit (krb_principal*, int, char*, char*, des_cblock*, char*);
+
+int write_encrypted (int, void*, size_t, des_key_schedule,
+ des_cblock*, struct sockaddr_in*, struct sockaddr_in*);
+
+int read_encrypted (int, void*, size_t, void **, des_key_schedule,
+ des_cblock*, struct sockaddr_in*, struct sockaddr_in*);
+
+int pack_args (char *, size_t, krb_principal*, int, const char*, const 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
new file mode 100644
index 0000000..d0b61ec
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/kauthd.c
@@ -0,0 +1,202 @@
+/* $FreeBSD$ */
+
+/*
+ * 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. 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 "kauth.h"
+
+RCSID("$Id: kauthd.c,v 1.25.2.1 2000/06/28 19:07:58 assar Exp $");
+
+krb_principal princ;
+static char locuser[SNAME_SZ];
+static int lifetime;
+static char tktfile[MaxPathLen];
+
+struct remote_args {
+ int sock;
+ des_key_schedule *schedule;
+ des_cblock *session;
+ struct sockaddr_in *me, *her;
+};
+
+static int
+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;
+ int len;
+ KTEXT cip = *cipp;
+ struct remote_args *args = (struct remote_args *)varg;
+
+ write_encrypted (args->sock, cip->dat, cip->length,
+ *args->schedule, args->session, args->me,
+ args->her);
+ len = read_encrypted (args->sock, buf, sizeof(buf), &ptr, *args->schedule,
+ args->session, args->her, args->me);
+ memcpy(cip->dat, ptr, cip->length);
+
+ return 0;
+}
+
+static int
+doit(int sock)
+{
+ int status;
+ KTEXT_ST ticket;
+ AUTH_DAT auth;
+ char instance[INST_SZ];
+ des_key_schedule schedule;
+ struct sockaddr_in thisaddr, thataddr;
+ int addrlen;
+ int len;
+ char buf[BUFSIZ];
+ void *data;
+ struct passwd *passwd;
+ char version[KRB_SENDAUTH_VLEN + 1];
+ char remotehost[MaxHostNameLen];
+
+ addrlen = sizeof(thisaddr);
+ if (getsockname (sock, (struct sockaddr *)&thisaddr, &addrlen) < 0 ||
+ addrlen != sizeof(thisaddr)) {
+ return 1;
+ }
+ addrlen = sizeof(thataddr);
+ if (getpeername (sock, (struct sockaddr *)&thataddr, &addrlen) < 0 ||
+ addrlen != sizeof(thataddr)) {
+ return 1;
+ }
+
+ inaddr2str (thataddr.sin_addr, remotehost, sizeof(remotehost));
+
+ k_getsockinst (sock, instance, sizeof(instance));
+ status = krb_recvauth (KOPT_DO_MUTUAL, sock, &ticket, "rcmd", instance,
+ &thataddr, &thisaddr, &auth, "", schedule,
+ version);
+ if (status != KSUCCESS ||
+ strncmp(version, KAUTH_VERSION, KRB_SENDAUTH_VLEN) != 0) {
+ return 1;
+ }
+ len = read_encrypted (sock, buf, sizeof(buf), &data, schedule,
+ &auth.session, &thataddr, &thisaddr);
+ if (len < 0) {
+ write_encrypted (sock, "read_enc failed",
+ sizeof("read_enc failed") - 1, schedule,
+ &auth.session, &thisaddr, &thataddr);
+ return 1;
+ }
+ if (unpack_args(data, &princ, &lifetime, locuser,
+ tktfile)) {
+ write_encrypted (sock, "unpack_args failed",
+ sizeof("unpack_args failed") - 1, schedule,
+ &auth.session, &thisaddr, &thataddr);
+ return 1;
+ }
+
+ if( kuserok(&auth, locuser) != 0) {
+ snprintf(buf, sizeof(buf), "%s cannot get tickets for %s",
+ locuser, krb_unparse_name(&princ));
+ syslog (LOG_ERR, "%s", buf);
+ write_encrypted (sock, buf, strlen(buf), schedule,
+ &auth.session, &thisaddr, &thataddr);
+ return 1;
+ }
+ passwd = k_getpwnam (locuser);
+ if (passwd == NULL) {
+ snprintf (buf, sizeof(buf), "No user '%s'", locuser);
+ syslog (LOG_ERR, "%s", buf);
+ write_encrypted (sock, buf, strlen(buf), schedule,
+ &auth.session, &thisaddr, &thataddr);
+ return 1;
+ }
+ if (setgid (passwd->pw_gid) ||
+ initgroups(passwd->pw_name, passwd->pw_gid) ||
+ setuid(passwd->pw_uid)) {
+ snprintf (buf, sizeof(buf), "Could not change user");
+ syslog (LOG_ERR, "%s", buf);
+ write_encrypted (sock, buf, strlen(buf), schedule,
+ &auth.session, &thisaddr, &thataddr);
+ return 1;
+ }
+ write_encrypted (sock, "ok", sizeof("ok") - 1, schedule,
+ &auth.session, &thisaddr, &thataddr);
+
+ if (*tktfile == 0)
+ snprintf(tktfile, sizeof(tktfile), "%s%u", TKT_ROOT, (unsigned)getuid());
+ krb_set_tkt_string (tktfile);
+
+ {
+ struct remote_args arg;
+
+ arg.sock = sock;
+ arg.schedule = &schedule;
+ arg.session = &auth.session;
+ arg.me = &thisaddr;
+ arg.her = &thataddr;
+
+ status = krb_get_in_tkt (princ.name, princ.instance, princ.realm,
+ KRB_TICKET_GRANTING_TICKET,
+ princ.realm,
+ lifetime, NULL, decrypt_remote_tkt, &arg);
+ }
+ if (status == KSUCCESS) {
+ syslog (LOG_INFO, "from %s(%s): %s -> %s",
+ remotehost,
+ inet_ntoa(thataddr.sin_addr),
+ locuser,
+ krb_unparse_name (&princ));
+ write_encrypted (sock, "ok", sizeof("ok") - 1, schedule,
+ &auth.session, &thisaddr, &thataddr);
+ return 0;
+ } else {
+ snprintf (buf, sizeof(buf), "TGT failed: %s", krb_get_err_text(status));
+ syslog (LOG_NOTICE, "%s", buf);
+ write_encrypted (sock, buf, strlen(buf), schedule,
+ &auth.session, &thisaddr, &thataddr);
+ return 1;
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ openlog ("kauthd", LOG_ODELAY, LOG_AUTH);
+
+ if(argc > 1 && strcmp(argv[1], "-i") == 0)
+ mini_inetd (k_getportbyname("kauth", "tcp", htons(KAUTH_PORT)));
+ return doit(STDIN_FILENO);
+}
diff --git a/crypto/kerberosIV/appl/kauth/ksrvtgt.in b/crypto/kerberosIV/appl/kauth/ksrvtgt.in
new file mode 100644
index 0000000..7a520fd
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/ksrvtgt.in
@@ -0,0 +1,15 @@
+#! /bin/sh
+# $Id: ksrvtgt.in,v 1.3 1997/09/13 03:39:03 joda Exp $
+# $FreeBSD$
+
+usage="Usage: `basename $0` name instance [[realm] srvtab]"
+
+if [ $# -lt 2 -o $# -gt 4 ]; then
+ echo "$usage"
+ exit 1
+fi
+
+srvtab="${4-${3-/etc/kerberosIV/srvtab}}"
+realm="${4+@$3}"
+
+%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
new file mode 100644
index 0000000..e37b8c9
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/marshall.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kauth.h"
+
+RCSID("$Id: marshall.c,v 1.10 1999/12/02 16:58:31 joda Exp $");
+
+int
+pack_args (char *buf,
+ size_t sz,
+ krb_principal *pr,
+ int lifetime,
+ const char *locuser,
+ const char *tktfile)
+{
+ char *p = buf;
+ int len;
+
+ p = buf;
+
+ 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;
+
+ 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 (const char *buf, krb_principal *pr, int *lifetime,
+ char *locuser, char *tktfile)
+{
+ int len;
+
+ len = strlen(buf);
+ if (len >= SNAME_SZ)
+ return -1;
+ strlcpy (pr->name, buf, ANAME_SZ);
+ buf += len + 1;
+ len = strlen (buf);
+ if (len >= INST_SZ)
+ return -1;
+ strlcpy (pr->instance, buf, INST_SZ);
+ buf += len + 1;
+ len = strlen (buf);
+ if (len >= REALM_SZ)
+ return -1;
+ strlcpy (pr->realm, buf, REALM_SZ);
+ buf += len + 1;
+ *lifetime = (unsigned char)*buf++;
+ len = strlen(buf);
+ if (len >= SNAME_SZ)
+ return -1;
+ strlcpy (locuser, buf, SNAME_SZ);
+ buf += len + 1;
+ len = strlen(buf);
+ if (len >= MaxPathLen)
+ return -1;
+ strlcpy (tktfile, buf, MaxPathLen);
+ buf += len + 1;
+ return 0;
+}
diff --git a/crypto/kerberosIV/appl/kauth/rkinit.c b/crypto/kerberosIV/appl/kauth/rkinit.c
new file mode 100644
index 0000000..cac62c9
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/rkinit.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kauth.h"
+
+RCSID("$Id: rkinit.c,v 1.22.2.1 1999/12/06 17:27:56 assar Exp $");
+
+static struct in_addr *
+getalladdrs (char *hostname, unsigned *count)
+{
+ struct hostent *hostent;
+ struct in_addr **h;
+ struct in_addr *addr;
+ unsigned naddr;
+ unsigned maxaddr;
+
+ hostent = gethostbyname (hostname);
+ if (hostent == NULL) {
+ warnx ("gethostbyname '%s' failed: %s\n",
+ hostname,
+ hstrerror(h_errno));
+ return NULL;
+ }
+ maxaddr = 1;
+ naddr = 0;
+ addr = malloc(sizeof(*addr) * maxaddr);
+ if (addr == NULL) {
+ warnx ("out of memory");
+ return NULL;
+ }
+ for (h = (struct in_addr **)(hostent->h_addr_list);
+ *h != NULL;
+ h++) {
+ if (naddr >= maxaddr) {
+ maxaddr *= 2;
+ addr = realloc (addr, sizeof(*addr) * maxaddr);
+ if (addr == NULL) {
+ warnx ("out of memory");
+ return NULL;
+ }
+ }
+ addr[naddr++] = **h;
+ }
+ addr = realloc (addr, sizeof(*addr) * naddr);
+ if (addr == NULL) {
+ warnx ("out of memory");
+ return NULL;
+ }
+ *count = naddr;
+ return addr;
+}
+
+static int
+doit_host (krb_principal *princ, int lifetime, char *locuser,
+ char *tktfile, des_cblock *key, int s, char *hostname)
+{
+ char buf[BUFSIZ];
+ int inlen;
+ KTEXT_ST text;
+ CREDENTIALS cred;
+ MSG_DAT msg;
+ int status;
+ des_key_schedule schedule;
+ struct sockaddr_in thisaddr, thataddr;
+ int addrlen;
+ void *ret;
+
+ addrlen = sizeof(thisaddr);
+ if (getsockname (s, (struct sockaddr *)&thisaddr, &addrlen) < 0 ||
+ addrlen != sizeof(thisaddr)) {
+ warn ("getsockname(%s)", hostname);
+ return 1;
+ }
+ addrlen = sizeof(thataddr);
+ if (getpeername (s, (struct sockaddr *)&thataddr, &addrlen) < 0 ||
+ addrlen != sizeof(thataddr)) {
+ warn ("getpeername(%s)", hostname);
+ return 1;
+ }
+
+ if (krb_get_config_bool("nat_in_use")) {
+ struct in_addr natAddr;
+
+ if (krb_get_our_ip_for_realm(krb_realmofhost(hostname),
+ &natAddr) == KSUCCESS
+ || krb_get_our_ip_for_realm (NULL, &natAddr) == KSUCCESS)
+ thisaddr.sin_addr = natAddr;
+ }
+
+ status = krb_sendauth (KOPT_DO_MUTUAL, s, &text, "rcmd",
+ hostname, krb_realmofhost (hostname),
+ getpid(), &msg, &cred, schedule,
+ &thisaddr, &thataddr, KAUTH_VERSION);
+ if (status != KSUCCESS) {
+ warnx ("%s: %s\n", hostname, krb_get_err_text(status));
+ return 1;
+ }
+ 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) {
+ warn ("write to %s", hostname);
+ return 1;
+ }
+
+ inlen = read_encrypted (s, buf, sizeof(buf), &ret, schedule,
+ &cred.session, &thataddr, &thisaddr);
+ if (inlen < 0) {
+ warn ("read from %s failed", hostname);
+ return 1;
+ }
+
+ if (strncmp(ret, "ok", inlen) != 0) {
+ warnx ("error from %s: %.*s\n",
+ hostname, inlen, (char *)ret);
+ return 1;
+ }
+
+ inlen = read_encrypted (s, buf, sizeof(buf), &ret, schedule,
+ &cred.session, &thataddr, &thisaddr);
+ if (inlen < 0) {
+ warn ("read from %s", hostname);
+ return 1;
+ }
+
+ {
+ des_key_schedule key_s;
+
+ des_key_sched(key, key_s);
+ des_pcbc_encrypt(ret, ret, inlen, key_s, key, DES_DECRYPT);
+ memset(key_s, 0, sizeof(key_s));
+ }
+ write_encrypted (s, ret, inlen, schedule, &cred.session,
+ &thisaddr, &thataddr);
+
+ inlen = read_encrypted (s, buf, sizeof(buf), &ret, schedule,
+ &cred.session, &thataddr, &thisaddr);
+ if (inlen < 0) {
+ warn ("read from %s", hostname);
+ return 1;
+ }
+
+ if (strncmp(ret, "ok", inlen) != 0) {
+ warnx ("error from %s: %.*s\n",
+ hostname, inlen, (char *)ret);
+ return 1;
+ }
+ return 0;
+}
+
+int
+rkinit (krb_principal *princ, int lifetime, char *locuser,
+ char *tktfile, des_cblock *key, char *hostname)
+{
+ struct in_addr *addr;
+ unsigned naddr;
+ unsigned i;
+ int port;
+ int success;
+
+ addr = getalladdrs (hostname, &naddr);
+ if (addr == NULL)
+ return 1;
+ port = k_getportbyname ("kauth", "tcp", htons(KAUTH_PORT));
+ success = 0;
+ for (i = 0; !success && i < naddr; ++i) {
+ struct sockaddr_in a;
+ int s;
+
+ memset(&a, 0, sizeof(a));
+ a.sin_family = AF_INET;
+ a.sin_port = port;
+ a.sin_addr = addr[i];
+
+ s = socket (AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ warn("socket");
+ return 1;
+ }
+ if (connect(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
+ warn("connect(%s)", hostname);
+ continue;
+ }
+
+ success = success || !doit_host (princ, lifetime,
+ locuser, tktfile, key,
+ s, hostname);
+ close (s);
+ }
+ return !success;
+}
diff --git a/crypto/kerberosIV/appl/kauth/zrefresh b/crypto/kerberosIV/appl/kauth/zrefresh
new file mode 100644
index 0000000..8347a1b
--- /dev/null
+++ b/crypto/kerberosIV/appl/kauth/zrefresh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# @(#) $Id: zrefresh,v 1.3 1996/06/09 19:21:59 joda Exp $
+#
+# Substitute this script with a real zrefresh if running Zephyr. For
+# instance:
+#
+# if [ -f "$WGFILE" ] ; then
+# zctl load
+# fi
+
+exit 0
diff --git a/crypto/kerberosIV/appl/kip/Makefile.in b/crypto/kerberosIV/appl/kip/Makefile.in
new file mode 100644
index 0000000..16ed049
--- /dev/null
+++ b/crypto/kerberosIV/appl/kip/Makefile.in
@@ -0,0 +1,110 @@
+# $Id: Makefile.in,v 1.18.4.1 2000/06/23 02:54:59 assar Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+LINK = @LINK@
+AR = ar
+DEFS = @DEFS@ -DLIBEXECDIR="\"$(libexecdir)\""
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS = @LD_FLAGS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+LIBS = @LIBS@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libexecdir = @libexecdir@
+libdir = @libdir@
+bindir = @bindir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+PROG_BIN = kip$(EXECSUFFIX)
+PROG_LIBEXEC = kipd$(EXECSUFFIX)
+SCRIPT_LIBEXEC = kip-join-network kipd-control
+PROGS = $(PROG_BIN) $(PROG_LIBEXEC) $(SCRIPT_LIBEXEC)
+
+SOURCES_KIP = kip.c
+SOURCES_KIPD = kipd.c
+SOURCES_COMMON = common.c
+
+OBJECTS_KIP = kip.o common.o
+OBJECTS_KIPD = kipd.o common.o
+
+OBJECTS = $(OBJECTS_KIP) $(OBJECTS_KIPD)
+SOURCES = $(SOURCES_KIP) $(SOURCES_KIPD) $(SOURCES_COMMON)
+
+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) $(DESTDIR)$(libexecdir)
+ for x in $(PROG_BIN); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+ for x in $(PROG_LIBEXEC); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ done
+ for x in $(SCRIPT_LIBEXEC); do \
+ $(INSTALL_SCRIPT) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(PROG_BIN); do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+ for x in $(PROG_LIBEXEC); do \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ done
+ for x in $(SCRIPT_LIBEXEC); do \
+ rm -f $(DESTDIR)$(libexecdir)/`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
+
+KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
+LIBROKEN=-L../../lib/roken -lroken
+
+kip$(EXECSUFFIX): $(OBJECTS_KIP)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIP) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+kipd$(EXECSUFFIX): $(OBJECTS_KIPD)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIPD) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+$(OBJECTS): ../../include/config.h
+
+kip-join-network: kip-join-network.in
+ sed -e "s!%bindir%!$(bindir)!" $(srcdir)/kip-join-network.in > $@
+ chmod +x $@
+
+kipd-control: kipd-control.in
+ sed -e "s!%bindir%!$(bindir)!" $(srcdir)/kipd-control.in > $@
+ chmod +x $@
+
+.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/kip/common.c b/crypto/kerberosIV/appl/kip/common.c
new file mode 100644
index 0000000..4feb9c8
--- /dev/null
+++ b/crypto/kerberosIV/appl/kip/common.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kip.h"
+
+RCSID("$Id: common.c,v 1.13.2.4 2000/10/18 23:31:51 assar Exp $");
+
+sig_atomic_t disconnect = 0;
+int isserver = 0;
+
+/*
+ * Copy packets from `tundev' to `netdev' or vice versa.
+ * Mode is used when reading from `tundev'
+ */
+
+int
+copy_packets (int tundev, int netdev, int mtu, des_cblock *iv,
+ des_key_schedule schedule)
+{
+ des_cblock iv1, iv2;
+ int num1 = 0, num2 = 0;
+ u_char *buf;
+
+ buf = malloc (mtu + 2);
+ if (buf == NULL) {
+ warnx("malloc(%d) failed", mtu);
+ return 1;
+ }
+
+ memcpy (&iv1, iv, sizeof(iv1));
+ memcpy (&iv2, iv, sizeof(iv2));
+ while(!disconnect) {
+ fd_set fdset;
+ int ret, len;
+
+ if (tundev >= FD_SETSIZE || netdev >= FD_SETSIZE) {
+ warnx ("fd too large");
+ return 1;
+ }
+
+ FD_ZERO(&fdset);
+ FD_SET(tundev, &fdset);
+ FD_SET(netdev, &fdset);
+
+ ret = select (max(tundev, netdev)+1, &fdset, NULL, NULL, NULL);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ warn ("select");
+ return 1;
+ }
+ if (FD_ISSET(tundev, &fdset)) {
+ ret = read (tundev, buf + 2, mtu);
+ if (ret == 0)
+ return 0;
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ warn("read");
+ return ret;
+ }
+ }
+ buf[0] = ret >> 8;
+ buf[1] = ret & 0xFF;
+ ret += 2;
+ des_cfb64_encrypt (buf, buf, ret, schedule,
+ &iv1, &num1, DES_ENCRYPT);
+ ret = krb_net_write (netdev, buf, ret);
+ if (ret < 0) {
+ warn("write");
+ return ret;
+ }
+ }
+ if (FD_ISSET(netdev, &fdset)) {
+ ret = read (netdev, buf, 2);
+ if (ret == 0)
+ return 0;
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ warn("read");
+ return ret;
+ }
+ }
+ des_cfb64_encrypt (buf, buf, 2, schedule,
+ &iv2, &num2, DES_DECRYPT);
+ len = (buf[0] << 8 ) | buf[1];
+ if (len > mtu) {
+ fatal (-1, "buffer too large", schedule, &iv2);
+ return -1;
+ }
+
+ if (len == 0) {
+ len = read (netdev, buf, mtu);
+ if (len < 1)
+ len = 1;
+ buf[len-1] = '\0';
+
+ fatal (-1, buf, schedule, &iv2);
+ return -1;
+ }
+
+ ret = krb_net_read (netdev, buf + 2, len);
+ if (ret == 0)
+ return 0;
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ warn("read");
+ return ret;
+ }
+ }
+ des_cfb64_encrypt (buf + 2, buf + 2, len, schedule,
+ &iv2, &num2, DES_DECRYPT);
+ ret = krb_net_write (tundev, buf + 2, len);
+ if (ret < 0) {
+ warn("write");
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Signal handler that justs waits for the children when they die.
+ */
+
+RETSIGTYPE
+childhandler (int sig)
+{
+ pid_t pid;
+ int status;
+
+ do {
+ pid = waitpid (-1, &status, WNOHANG|WUNTRACED);
+ } while(pid > 0);
+ signal (SIGCHLD, childhandler);
+ SIGRETURN(0);
+}
+
+/*
+ * Find a free tunnel device and open it.
+ * Return the interface name in `name, len'.
+ */
+
+int
+tunnel_open (char *name, size_t len)
+{
+ int fd;
+ int i;
+ char devname[256];
+
+ for (i = 0; i < 256; ++i) {
+ snprintf (devname, len, "%s%s%d", _PATH_DEV, TUNDEV, i);
+ fd = open (devname, O_RDWR, 0);
+ if (fd >= 0)
+ break;
+ if (errno == ENOENT || errno == ENODEV) {
+ warn("open %s", name);
+ return fd;
+ }
+ }
+ if (fd < 0)
+ warn("open %s" ,name);
+ else
+ snprintf (name, len, "%s%d", TUNDEV, i);
+ return fd;
+}
+
+/*
+ * run the command `cmd' with (...). return 0 if succesful or error
+ * otherwise (and copy an error messages into `msg, len')
+ */
+
+int
+kip_exec (const char *cmd, char *msg, size_t len, ...)
+{
+ pid_t pid;
+ char **argv;
+ va_list ap;
+
+ va_start(ap, len);
+ argv = vstrcollect(&ap);
+ va_end(ap);
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ snprintf (msg, len, "fork: %s", strerror(errno));
+ return errno;
+ case 0: {
+ int fd = open (_PATH_DEVNULL, O_RDWR, 0600);
+ if (fd < 0) {
+ snprintf (msg, len, "open " _PATH_DEVNULL ": %s", strerror(errno));
+ return errno;
+ }
+
+ close (STDIN_FILENO);
+ close (STDOUT_FILENO);
+ close (STDERR_FILENO);
+
+ dup2 (fd, STDIN_FILENO);
+ dup2 (fd, STDOUT_FILENO);
+ dup2 (fd, STDERR_FILENO);
+
+ execvp (cmd, argv);
+ snprintf (msg, len, "execvp %s: %s", cmd, strerror(errno));
+ return errno;
+ }
+ default: {
+ int status;
+
+ while (waitpid(pid, &status, 0) < 0)
+ if (errno != EINTR) {
+ snprintf (msg, len, "waitpid: %s", strerror(errno));
+ return errno;
+ }
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0) {
+ return 0;
+ } else {
+ snprintf (msg, len, "child returned with %d",
+ WEXITSTATUS(status));
+ return 1;
+ }
+ } else if (WIFSIGNALED(status)) {
+#ifndef WCOREDUMP
+#define WCOREDUMP(X) 0
+#endif
+ snprintf (msg, len, "terminated by signal num %d %s",
+ WTERMSIG(status),
+ WCOREDUMP(status) ? " coredumped" : "");
+ return 1;
+ } else if (WIFSTOPPED(status)) {
+ snprintf (msg, len, "process stoped by signal %d",
+ WSTOPSIG(status));
+ return 1;
+ } else {
+ snprintf (msg, len, "child died in mysterious circumstances");
+ return 1;
+ }
+ }
+ }
+}
+
+/*
+ * fatal error `s' occured.
+ */
+
+void
+fatal (int fd, const char *s, des_key_schedule schedule, des_cblock *iv)
+{
+ int16_t err = 0;
+ int num = 0;
+
+ if (fd != -1) {
+ des_cfb64_encrypt ((unsigned char*) &err, (unsigned char*) &err,
+ sizeof(err), schedule, iv, &num, DES_ENCRYPT);
+
+ write (fd, &err, sizeof(err));
+ write (fd, s, strlen(s)+1);
+ }
+ if (isserver)
+ syslog(LOG_ERR, "%s", s);
+ else
+ warnx ("fatal error: %s", s);
+}
diff --git a/crypto/kerberosIV/appl/kip/kip-join-network.in b/crypto/kerberosIV/appl/kip/kip-join-network.in
new file mode 100644
index 0000000..c105fe6
--- /dev/null
+++ b/crypto/kerberosIV/appl/kip/kip-join-network.in
@@ -0,0 +1,53 @@
+#!/bin/sh
+# $Id$
+#
+# Join a network, see kipd-control from more comments.
+#
+
+PATH=/usr/sbin:/sbin:/usr/bin:/bin:%bindir%
+
+endpointhost=130.237.43.201
+thispointhost=130.237.43.17
+fakepoint=10.0.0.1
+dev=tun0
+
+case $# in
+ 0)
+ modprobe tun
+ def=$(route -n | awk '$1 ~ /0.0.0.0/ && $3 ~ /0.0.0.0/ { print $2 }')
+
+ if test "X$def" = "X" ; then
+ echo "missing default route"
+ exit 1
+ fi
+
+ exec kip -c $0 -a $def $endpointhost
+ ;;
+ *)
+ state=$1
+ dev=$2
+ host=$3
+ arg=$4
+ case $state in
+ up)
+ ifconfig $dev $thispointhost pointopoint $fakepoint
+ route delete default
+
+ route add -host $endpointhost gw $arg
+ route add default gw $fakepoint
+ ;;
+ down)
+
+ echo $dev $arg > /tmp/kip-down
+
+ ifconfig $dev down
+
+ route delete default
+ route delete $endpointhost
+ route add default gw $arg
+ ;;
+ *)
+ exit 17
+ ;;
+ esac
+esac
diff --git a/crypto/kerberosIV/appl/kip/kip.c b/crypto/kerberosIV/appl/kip/kip.c
new file mode 100644
index 0000000..55b6032
--- /dev/null
+++ b/crypto/kerberosIV/appl/kip/kip.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kip.h"
+
+RCSID("$Id: kip.c,v 1.18.2.1 2000/06/23 02:55:01 assar Exp $");
+
+static char *cmd_str = NULL;
+static char *arg_str = NULL;
+static char *port_str = NULL;
+static int version_flag = 0;
+static int help_flag = 0;
+
+struct getargs args[] = {
+ { "port", 'p', arg_string, &port_str, "Use this port",
+ "port" },
+ { "cmd", 'c', arg_string, &cmd_str,
+ "command to run when starting", "cmd"},
+ { "arg", 'a', arg_string, &arg_str,
+ "argument to above command", "arg"},
+ { "version", 0, arg_flag, &version_flag },
+ { "help", 0, arg_flag, &help_flag }
+};
+
+
+static RETSIGTYPE
+disconnecthandler (int sig)
+{
+ disconnect = 1;
+ SIGRETURN(0);
+}
+
+/*
+ * Establish authenticated connection
+ */
+
+static int
+connect_host (char *host, int port,
+ des_cblock *key, des_key_schedule schedule)
+{
+ CREDENTIALS cred;
+ KTEXT_ST text;
+ MSG_DAT msg;
+ int status;
+ struct sockaddr_in thisaddr, thataddr;
+ int addrlen;
+ struct hostent *hostent;
+ int s;
+ u_char b;
+ char **p;
+
+ hostent = gethostbyname (host);
+ if (hostent == NULL) {
+ warnx ("gethostbyname '%s': %s", host,
+ hstrerror(h_errno));
+ return -1;
+ }
+
+ memset (&thataddr, 0, sizeof(thataddr));
+ thataddr.sin_family = AF_INET;
+ thataddr.sin_port = port;
+
+ for(p = hostent->h_addr_list; *p; ++p) {
+ memcpy (&thataddr.sin_addr, *p, sizeof(thataddr.sin_addr));
+
+ s = socket (AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ warn ("socket");
+ return -1;
+ }
+
+#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
+ {
+ int one = 1;
+
+ setsockopt (s, IPPROTO_TCP, TCP_NODELAY,
+ (void *)&one, sizeof(one));
+ }
+#endif
+
+ if (connect (s, (struct sockaddr *)&thataddr, sizeof(thataddr)) < 0) {
+ warn ("connect(%s)", host);
+ close (s);
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (*p == NULL)
+ return -1;
+
+ addrlen = sizeof(thisaddr);
+ if (getsockname (s, (struct sockaddr *)&thisaddr, &addrlen) < 0 ||
+ addrlen != sizeof(thisaddr)) {
+ warn ("getsockname(%s)", host);
+ return -1;
+ }
+ status = krb_sendauth (KOPT_DO_MUTUAL, s, &text, "rcmd",
+ host, krb_realmofhost (host),
+ getpid(), &msg, &cred, schedule,
+ &thisaddr, &thataddr, KIP_VERSION);
+ if (status != KSUCCESS) {
+ warnx("%s: %s", host,
+ krb_get_err_text(status));
+ return -1;
+ }
+ if (read (s, &b, sizeof(b)) != sizeof(b)) {
+ warn ("read");
+ return -1;
+ }
+ if (b) {
+ char buf[BUFSIZ];
+
+ read (s, buf, sizeof(buf));
+ buf[BUFSIZ - 1] = '\0';
+
+ warnx ("%s: %s", host, buf);
+ return -1;
+ }
+
+ memcpy(key, &cred.session, sizeof(des_cblock));
+ return s;
+}
+
+/*
+ * Connect to the given host.
+ */
+
+static int
+doit (char *host, int port)
+{
+ char tun_if_name[64];
+ des_key_schedule schedule;
+ des_cblock iv;
+ int other, this, ret;
+
+ other = connect_host (host, port, &iv, schedule);
+ if (other < 0)
+ return 1;
+ this = tunnel_open (tun_if_name, sizeof(tun_if_name));
+ if (this < 0)
+ return 1;
+
+ if (cmd_str) {
+ char buf[1024];
+ ret = kip_exec (cmd_str, buf, sizeof(buf),
+ "kip-control", "up", tun_if_name, host, arg_str,
+ NULL);
+ if (ret)
+ errx (1, "%s (up) failed: %s", cmd_str, buf);
+ }
+
+ ret = copy_packets (this, other, TUNMTU, &iv, schedule);
+
+ if (cmd_str) {
+ char buf[1024];
+ ret = kip_exec (cmd_str, buf, sizeof(buf),
+ "kip-control", "down", tun_if_name, host, arg_str,
+ NULL);
+ if (ret)
+ errx (1, "%s (down) failed: %s", cmd_str, buf);
+ }
+ return 0;
+}
+
+static void
+usage(int ret)
+{
+ arg_printusage (args,
+ sizeof(args) / sizeof(args[0]),
+ NULL,
+ "hostname");
+ exit (ret);
+}
+
+/*
+ * kip - forward IP packets over a kerberos-encrypted channel.
+ *
+ */
+
+int
+main(int argc, char **argv)
+{
+ int port;
+ int optind = 0;
+ char *hostname;
+
+ set_progname (argv[0]);
+ if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
+ &optind))
+ usage (1);
+
+ if (help_flag)
+ usage (0);
+
+ if (version_flag) {
+ print_version (NULL);
+ return 0;
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc != 1)
+ usage (1);
+
+ hostname = argv[0];
+
+ if(port_str) {
+ struct servent *s = roken_getservbyname (port_str, "tcp");
+
+ if (s)
+ port = s->s_port;
+ else {
+ char *ptr;
+
+ port = strtol (port_str, &ptr, 10);
+ if (port == 0 && ptr == port_str)
+ errx (1, "bad port `%s'", port_str);
+ port = htons(port);
+ }
+ } else {
+ port = k_getportbyname ("kip", "tcp", htons(KIPPORT));
+ }
+
+ signal (SIGCHLD, childhandler);
+ signal (SIGHUP, disconnecthandler);
+ signal (SIGTERM, disconnecthandler);
+
+ return doit (hostname, port);
+}
diff --git a/crypto/kerberosIV/appl/kip/kip.h b/crypto/kerberosIV/appl/kip/kip.h
new file mode 100644
index 0000000..7bfc5f1
--- /dev/null
+++ b/crypto/kerberosIV/appl/kip/kip.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: kip.h,v 1.18.2.1 2000/06/23 02:55:01 assar Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <fcntl.h>
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#include <sys/types.h>
+#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_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/wait.h>
+#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>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <net/if.h>
+#ifdef HAVE_NET_IF_VAR_H
+#include <net/if_var.h>
+#endif
+#ifdef HAVE_NET_IF_TUN_H
+#include <net/if_tun.h>
+#endif
+#include <err.h>
+
+#include <getarg.h>
+
+#ifdef SOCKS
+#include <socks.h>
+#endif
+
+#include <krb.h>
+
+#include <roken.h>
+
+#define TUNDEV "tun"
+
+#ifndef TUNMTU
+#define TUNMTU 1500 /* everything is ethernet :) */
+#endif
+
+#define KIPPORT 2112
+
+#define KIP_VERSION "KIPSRV.0"
+
+int
+copy_packets (int tundev, int netdev, int mtu, des_cblock *iv,
+ des_key_schedule schedule);
+
+RETSIGTYPE childhandler (int);
+
+extern sig_atomic_t disconnect;
+extern int isserver;
+
+int
+tunnel_open (char *, size_t);
+
+void
+fatal (int fd, const char *s, des_key_schedule schedule, des_cblock *iv);
+
+int
+kip_exec (const char *cmd, char *msg, size_t len, ...);
diff --git a/crypto/kerberosIV/appl/kip/kipd-control.in b/crypto/kerberosIV/appl/kip/kipd-control.in
new file mode 100644
index 0000000..8fb0e9b
--- /dev/null
+++ b/crypto/kerberosIV/appl/kip/kipd-control.in
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# $Id$
+#
+# Simple example how you can missuse kip to provide "mobile-ip".
+# This is since there is no way to tunnel ip over udp or any other
+# protocol. There is also problems to get thru firewalls and NATs
+# with mobile-ip since (today) they usully doesn't support IPIP or
+# GRE.
+#
+# All commands are for linux (redhat6.1) but it should be quite
+# simple to fix it to support other OS.
+#
+
+PATH=/sbin:/usr/sbin:/usr/bin:/bin
+
+# arguments are: [up|down] dev remote-peer-addr user
+
+state=$1
+dev=$2
+remote=$3
+user=$4
+
+outdevice=eth0
+
+case "$state" in
+ up)
+ case "$user" in
+ lha.root@E.KTH.SE)
+ ifconfig $dev 10.0.0.1 pointopoint 130.237.43.17
+ route add -host 130.237.43.17 gw 10.0.0.1
+ arp -H ether -i $outdevice \
+ -s 130.237.43.17 00:80:c8:82:83:61 pub
+ ;;
+ esac
+ ;;
+ down)
+ case "$user" in
+ lha.root@E.KTH.SE)
+ ifconfig $dev 0.0.0.0
+ ifconfig $dev down
+ arp -i $outdevice -d 130.237.43.17
+ arp -d 130.237.43.17
+ true
+ ;;
+ *)
+ ifconfig $dev down
+ ;;
+ esac
+ ;;
+ *)
+ exit 17
+ ;;
+esac
diff --git a/crypto/kerberosIV/appl/kip/kipd.c b/crypto/kerberosIV/appl/kip/kipd.c
new file mode 100644
index 0000000..0bbf06b
--- /dev/null
+++ b/crypto/kerberosIV/appl/kip/kipd.c
@@ -0,0 +1,204 @@
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kip.h"
+
+RCSID("$Id: kipd.c,v 1.16.2.3 2000/10/18 20:46:45 assar Exp $");
+
+static int
+recv_conn (int sock, des_cblock *key, des_key_schedule schedule,
+ struct sockaddr_in *retaddr, char *user, size_t len)
+{
+ int status;
+ KTEXT_ST ticket;
+ AUTH_DAT auth;
+ char instance[INST_SZ];
+ struct sockaddr_in thisaddr, thataddr;
+ int addrlen;
+ char version[KRB_SENDAUTH_VLEN + 1];
+ u_char ok = 0;
+ struct passwd *passwd;
+
+ addrlen = sizeof(thisaddr);
+ if (getsockname (sock, (struct sockaddr *)&thisaddr, &addrlen) < 0 ||
+ addrlen != sizeof(thisaddr)) {
+ return 1;
+ }
+ addrlen = sizeof(thataddr);
+ if (getpeername (sock, (struct sockaddr *)&thataddr, &addrlen) < 0 ||
+ addrlen != sizeof(thataddr)) {
+ return 1;
+ }
+
+ k_getsockinst (sock, instance, sizeof(instance));
+ status = krb_recvauth (KOPT_DO_MUTUAL, sock, &ticket, "rcmd", instance,
+ &thataddr, &thisaddr, &auth, "", schedule,
+ version);
+ if (status != KSUCCESS ||
+ strncmp(version, KIP_VERSION, KRB_SENDAUTH_VLEN) != 0) {
+ return 1;
+ }
+ passwd = k_getpwnam ("root");
+ if (passwd == NULL) {
+ fatal (sock, "Cannot find root", schedule, &auth.session);
+ return 1;
+ }
+ if (kuserok(&auth, "root") != 0) {
+ fatal (sock, "Permission denied", schedule, &auth.session);
+ return 1;
+ }
+ if (write (sock, &ok, sizeof(ok)) != sizeof(ok))
+ return 1;
+
+ snprintf (user, len, "%s%s%s@%s", auth.pname,
+ auth.pinst[0] != '\0' ? "." : "",
+ auth.pinst, auth.prealm);
+
+ memcpy(key, &auth.session, sizeof(des_cblock));
+ *retaddr = thataddr;
+ return 0;
+}
+
+static int
+doit(int sock)
+{
+ char msg[1024];
+ char cmd[MAXPATHLEN];
+ char tun_if_name[64];
+ char user[MAX_K_NAME_SZ];
+ struct sockaddr_in thataddr;
+ des_key_schedule schedule;
+ des_cblock key;
+ int this, ret, ret2;
+
+ isserver = 1;
+
+ if (recv_conn (sock, &key, schedule, &thataddr, user, sizeof(user)))
+ return 1;
+ this = tunnel_open (tun_if_name, sizeof(tun_if_name));
+ if (this < 0)
+ fatal (sock, "Cannot open " _PATH_DEV TUNDEV, schedule, &key);
+
+ strlcpy(cmd, LIBEXECDIR "/kipd-control", sizeof(cmd));
+
+ ret = kip_exec (cmd, msg, sizeof(msg), "kipd-control",
+ "up", tun_if_name, inet_ntoa(thataddr.sin_addr), user,
+ NULL);
+ if (ret) {
+ fatal (sock, msg, schedule, &key);
+ return -1;
+ }
+
+ ret = copy_packets (this, sock, TUNMTU, &key, schedule);
+
+ ret2 = kip_exec (cmd, msg, sizeof(msg), "kipd-control",
+ "down", tun_if_name, user, NULL);
+ if (ret2)
+ syslog(LOG_ERR, "%s", msg);
+ return ret;
+}
+
+static char *port_str = NULL;
+static int inetd_flag = 1;
+static int version_flag = 0;
+static int help_flag = 0;
+
+struct getargs args[] = {
+ { "inetd", 'i', arg_negative_flag, &inetd_flag,
+ "Not started from inetd" },
+ { "port", 'p', arg_string, &port_str, "Use this port",
+ "port" },
+ { "version", 0, arg_flag, &version_flag },
+ { "help", 0, arg_flag, &help_flag }
+};
+
+static void
+usage(int ret)
+{
+ arg_printusage (args,
+ sizeof(args) / sizeof(args[0]),
+ NULL,
+ "");
+ exit (ret);
+}
+
+/*
+ * kipd - receive forwarded IP
+ */
+
+int
+main (int argc, char **argv)
+{
+ int port;
+ int optind = 0;
+
+ set_progname (argv[0]);
+ roken_openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON);
+
+ if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
+ &optind))
+ usage (1);
+
+ if (help_flag)
+ usage (0);
+
+ if (version_flag) {
+ print_version (NULL);
+ return 0;
+ }
+
+ if(port_str) {
+ struct servent *s = roken_getservbyname (port_str, "tcp");
+
+ if (s)
+ port = s->s_port;
+ else {
+ char *ptr;
+
+ port = strtol (port_str, &ptr, 10);
+ if (port == 0 && ptr == port_str)
+ errx (1, "bad port `%s'", port_str);
+ port = htons(port);
+ }
+ } else {
+ port = k_getportbyname ("kip", "tcp", htons(KIPPORT));
+ }
+
+ if (!inetd_flag)
+ mini_inetd (port);
+
+ signal (SIGCHLD, childhandler);
+ return doit(STDIN_FILENO);
+}
diff --git a/crypto/kerberosIV/appl/push/ChangeLog b/crypto/kerberosIV/appl/push/ChangeLog
new file mode 100644
index 0000000..a55954d
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/ChangeLog
@@ -0,0 +1,135 @@
+1999-11-13 Assar Westerlund <assar@sics.se>
+
+ * push.c: make `-v' a arg_counter
+
+1999-11-02 Assar Westerlund <assar@sics.se>
+
+ * push.c (main): redo the v4/v5 selection for consistency. -4 ->
+ try only v4 -5 -> try only v5 none, -45 -> try v5, v4
+
+1999-08-19 Assar Westerlund <assar@sics.se>
+
+ * push.c (doit): remember to step over the error message when we
+ discover that XDELE is not supported
+
+1999-08-12 Johan Danielsson <joda@pdc.kth.se>
+
+ * push.c: use XDELE
+
+1999-08-05 Assar Westerlund <assar@sics.se>
+
+ * push.c (do_connect): v6-ify
+
+1999-06-15 Assar Westerlund <assar@sics.se>
+
+ * push.c: get_default_username and the resulting const propagation
+
+1999-05-21 Assar Westerlund <assar@sics.se>
+
+ * push.c (parse_pobox): try $USERNAME
+
+1999-05-11 Assar Westerlund <assar@sics.se>
+
+ * push.c (do_v5): remove unused and non-working code
+
+1999-05-10 Assar Westerlund <assar@sics.se>
+
+ * push.c (do_v5): call krb5_sendauth with ccache == NULL
+
+Wed Apr 7 23:40:00 1999 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in: fix names of hesiod variables
+
+Wed Mar 24 04:37:04 1999 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (pfrom): fix typo
+
+ * push.c (get_pobox): try to handle old and new hesiod APIs
+
+Mon Mar 22 22:19:40 1999 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: hesoid -> hesiod
+
+Sun Mar 21 18:02:10 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: bindir -> libexecdir
+
+Sat Mar 20 00:12:26 1999 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: LDADD: add missing backslash
+
+Thu Mar 18 15:28:35 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: clean pfrom
+
+ * Makefile.am: include Makefile.am.common
+
+Mon Mar 15 18:26:16 1999 Johan Danielsson <joda@blubb.pdc.kth.se>
+
+ * push.c: strncasecmp headers
+
+Mon Feb 15 22:22:09 1999 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (pfrom): use libexecdir
+
+ * Makefile.am: build and install pfrom
+
+ * push.c (do_connect): init `s'
+ (pop_state): spell-check enums
+
+Tue Nov 24 23:20:54 1998 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in: build and install pfrom
+
+ * pfrom.in: bindir -> libexecdir
+
+Sun Nov 22 15:33:52 1998 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * push.c: eliminate some warnings
+
+Sun Nov 22 10:34:54 1998 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (WFLAGS): set
+
+Thu Nov 19 01:17:33 1998 Assar Westerlund <assar@sics.se>
+
+ * push_locl.h: add <hesiod.h>
+
+ * Makefile.am, Makefile.in: link and include hesiod
+
+ * push.c (get_pobox): new function. add hesiod support.
+
+1998-11-07 Assar Westerlund <assar@sics.se>
+
+ * push.8: updated
+
+ * push.c: --from implementation from <lha@stacken.kth.se>
+
+Fri Jul 10 01:14:45 1998 Assar Westerlund <assar@sics.se>
+
+ * push.c (net_{read,write}): remove
+
+Wed Jun 24 14:41:41 1998 Johan Danielsson <joda@blubb.pdc.kth.se>
+
+ * push.c: allow `po:user@host' mailbox syntax
+
+Tue Jun 2 17:35:06 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * push.c: quote '^From ' properly
+
+Mon May 25 05:22:47 1998 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (clean): PROGS -> PROGRAMS
+
+Sun Apr 26 11:42:13 1998 Assar Westerlund <assar@sics.se>
+
+ * push.c (main): better default for v4 and v5
+
+ * push.c (main): init context correctly
+
+ * push.c: should work with krb4
+
+ * push_locl.h: krb4 compat
+
+ * Makefile.in: new file
+
diff --git a/crypto/kerberosIV/appl/push/Makefile.am b/crypto/kerberosIV/appl/push/Makefile.am
new file mode 100644
index 0000000..07ecd0a
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/Makefile.am
@@ -0,0 +1,27 @@
+# $Id: Makefile.am,v 1.15 1999/04/09 18:29:48 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += $(INCLUDE_krb4) $(INCLUDE_hesiod)
+
+bin_SCRIPTS = pfrom
+
+libexec_PROGRAMS = push
+
+push_SOURCES = push.c push_locl.h
+
+pfrom: pfrom.in
+ sed -e "s!%libexecdir%!$(libexecdir)!" $(srcdir)/pfrom.in > $@
+ chmod +x $@
+
+man_MANS = push.8
+
+CLEANFILES = pfrom
+
+EXTRA_DIST = pfrom.in $(man_MANS)
+
+LDADD = $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_roken) \
+ $(LIB_hesiod)
diff --git a/crypto/kerberosIV/appl/push/Makefile.in b/crypto/kerberosIV/appl/push/Makefile.in
new file mode 100644
index 0000000..87da6cf
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/Makefile.in
@@ -0,0 +1,95 @@
+# $Id: Makefile.in,v 1.10 1999/04/07 18:39:56 assar Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+LINK = @LINK@
+RANLIB = @RANLIB@
+DEFS = @DEFS@ @INCLUDE_hesiod@
+CFLAGS = @CFLAGS@ $(WFLAGS)
+WFLAGS = @WFLAGS@
+LD_FLAGS = @LD_FLAGS@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LIBS = @LIB_hesiod@ @LIBS@
+LIB_DBM = @LIB_DBM@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+libexecdir = @libexecdir@
+bindir = @bindir@
+transform=@program_transform_name@
+EXECSUFFIX=@EXECSUFFIX@
+
+bin_PROGRAMS = pfrom
+
+libexec_PROGRAMS = push$(EXECSUFFIX)
+
+PROGRAMS = $(libexec_PROGRAMS) $(bin_PROGRAMS)
+
+push_SOURCES = push.c
+
+push_OBJECTS = push.o
+
+SOURCES = $(push_SOURCES)
+
+OBJECTS = $(push_OBJECTS)
+
+all: $(PROGRAMS)
+
+.c.o:
+ $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $<
+
+install: all
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
+ for x in $(bin_PROGRAMS); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+ $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir)
+ for x in $(libexec_PROGRAMS); do \
+ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(bin_PROGRAMS); do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \
+ done
+ for x in $(libexec_PROGRAMS); do \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \
+ done
+
+TAGS: $(SOURCES)
+ etags $(SOURCES)
+
+check:
+
+clean:
+ rm -f *.a *.o $(PROGRAMS)
+
+mostlyclean: clean
+
+distclean: clean
+ rm -f Makefile *~
+
+realclean: distclean
+ rm -f TAGS
+
+KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
+LIBROKEN=-L../../lib/roken -lroken
+
+push$(EXECSUFFIX): $(push_OBJECTS)
+ $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(push_OBJECTS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+pfrom: pfrom.in
+ sed -e "s!%libexecdir%!$(libexecdir)!" $(srcdir)/pfrom.in > $@
+ chmod +x $@
+
+$(OBJECTS): ../../include/config.h
+
+.PHONY: all install uninstall check clean mostlyclean distclean realclean
diff --git a/crypto/kerberosIV/appl/push/pfrom.in b/crypto/kerberosIV/appl/push/pfrom.in
new file mode 100644
index 0000000..6adf4f0
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/pfrom.in
@@ -0,0 +1,6 @@
+#!/bin/sh
+# $Id: pfrom.in,v 1.2 1998/11/24 13:25:47 assar Exp $
+libexecdir=%libexecdir%
+PATH=$libexecdir:$PATH
+export PATH
+push --from $*
diff --git a/crypto/kerberosIV/appl/push/push.8 b/crypto/kerberosIV/appl/push/push.8
new file mode 100644
index 0000000..0cf4a6c
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/push.8
@@ -0,0 +1,139 @@
+.\" $Id: push.8,v 1.3.16.2 2000/06/23 03:06:11 assar Exp $
+.\"
+.Dd May 31, 1998
+.Dt PUSH 8
+.Os HEIMDAL
+.Sh NAME
+.Nm push
+.Nd
+fetch mail via POP
+.Sh SYNOPSIS
+.Nm
+.Op Fl 4 | Fl -krb4
+.Op Fl 5 | Fl -krb5
+.Op Fl v | Fl -verbose
+.Op Fl f | Fl -fork
+.Op Fl l | -leave
+.Op Fl -from
+.Op Fl c | -count
+.Op Fl -header
+.Oo Fl p Ar port-spec \*(Ba Xo
+.Fl -port= Ns Ar port-spec Oc
+.Xc
+.Ar po-box
+.Pa filename
+.Sh DESCRIPTION
+.Nm
+retrieves mail from the post office box
+.Ar po-box ,
+and stores the mail in mbox format in
+.Pa filename .
+The
+.Ar po-box
+can have any of the following formats:
+.Bl -hang -compact -offset indent
+.It Ql hostname:username
+.It Ql po:hostname:username
+.It Ql username@hostname
+.It Ql po:username@hostname
+.It Ql hostname
+.It Ql po:username
+.El
+
+If no username is specified,
+.Nm
+assumes that it's the same as on the local machine;
+.Ar hostname
+defaults to the value of the
+.Ev MAILHOST
+environment variable.
+
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl 4 Ns ,
+.Fl -krb4
+.Xc
+use Kerberos 4 (if compiled with support for Kerberos 4)
+.It Xo
+.Fl 5 Ns ,
+.Fl -krb5
+.Xc
+use Kerberos 5 (if compiled with support for Kerberos 5)
+.It Xo
+.Fl f Ns ,
+.Fl -fork
+.Xc
+fork before starting to delete messages
+.It Xo
+.Fl l Ns ,
+.Fl -leave
+.Xc
+don't delete fetched mail
+.It Xo
+.Fl -from
+.Xc
+behave like from.
+.It Xo
+.Fl c Ns ,
+.Fl -count
+.Xc
+first print how many messages and bytes there are.
+.It Xo
+.Fl -header
+.Xc
+which header from should print.
+.It Xo
+.Fl p Ar port-spec Ns ,
+.Fl -port= Ns Ar port-spec
+.Xc
+use this port instead of the default
+.Ql kpop
+or
+.Ql 1109 .
+.El
+
+The default is to first try Kerberos 5 authentication and then, if
+that fails, Kerberos 4.
+.Sh ENVIRONMENT
+
+.Bl -tag -width Ds
+.It Ev MAILHOST
+points to the post office, if no other hostname is specified.
+.El
+.\".Sh FILES
+.Sh EXAMPLES
+.Bd -literal -offset indent
+$ push cornfield:roosta ~/.gnus-crash-box
+.Ed
+
+tries to fetch mail for the user
+.Ar roosta
+from the post office at
+.Dq cornfield ,
+and stores the mail in
+.Pa ~/.gnus-crash-box
+(you are using Gnus, aren't you?)
+.Bd -literal -offset indent
+$ push --from -5 havregryn
+.Ed
+
+tries to fetch
+.Nm From:
+lines for current user at post office
+.Dq havregryn
+using Kerberos 5.
+.\".Sh DIAGNOSTICS
+.Sh SEE ALSO
+.Xr movemail 8 ,
+.Xr popper 8 ,
+.Xr from 1 ,
+.Xr pfrom 1
+.\".Sh STANDARDS
+.Sh HISTORY
+.Nm
+was written while waiting for
+.Nm movemail
+to finish getting the mail.
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/crypto/kerberosIV/appl/push/push.c b/crypto/kerberosIV/appl/push/push.c
new file mode 100644
index 0000000..bc7574f
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/push.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright (c) 1997-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. 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 "push_locl.h"
+RCSID("$Id: push.c,v 1.34.2.1 1999/12/06 17:25:28 assar Exp $");
+
+#ifdef KRB4
+static int use_v4 = -1;
+#endif
+
+#ifdef KRB5
+static int use_v5 = -1;
+static krb5_context context;
+#endif
+
+static char *port_str;
+static int verbose_level;
+static int do_fork;
+static int do_leave;
+static int do_version;
+static int do_help;
+static int do_from;
+static int do_count;
+static char *header_str;
+
+struct getargs args[] = {
+#ifdef KRB4
+ { "krb4", '4', arg_flag, &use_v4, "Use Kerberos V4",
+ NULL },
+#endif
+#ifdef KRB5
+ { "krb5", '5', arg_flag, &use_v5, "Use Kerberos V5",
+ NULL },
+#endif
+ { "verbose",'v', arg_counter, &verbose_level, "Verbose",
+ NULL },
+ { "fork", 'f', arg_flag, &do_fork, "Fork deleting proc",
+ NULL },
+ { "leave", 'l', arg_flag, &do_leave, "Leave mail on server",
+ NULL },
+ { "port", 'p', arg_string, &port_str, "Use this port",
+ "number-or-service" },
+ { "from", 0, arg_flag, &do_from, "Behave like from",
+ NULL },
+ { "header", 0, arg_string, &header_str, "Header string to print", NULL },
+ { "count", 'c', arg_flag, &do_count, "Print number of messages", NULL},
+ { "version", 0, arg_flag, &do_version, "Print version",
+ NULL },
+ { "help", 0, arg_flag, &do_help, NULL,
+ NULL }
+
+};
+
+static void
+usage (int ret)
+{
+ arg_printusage (args,
+ sizeof(args) / sizeof(args[0]),
+ NULL,
+ "[[{po:username[@hostname] | hostname[:username]}] ...]"
+ "filename");
+ exit (ret);
+}
+
+static int
+do_connect (const char *hostname, int port, int nodelay)
+{
+ struct hostent *hostent = NULL;
+ char **h;
+ int error;
+ int af;
+ int s;
+
+#ifdef HAVE_IPV6
+ if (hostent == NULL)
+ hostent = getipnodebyname (hostname, AF_INET6, 0, &error);
+#endif
+ if (hostent == NULL)
+ hostent = getipnodebyname (hostname, AF_INET, 0, &error);
+
+ if (hostent == NULL)
+ errx(1, "gethostbyname '%s' failed: %s", hostname, hstrerror(error));
+
+ af = hostent->h_addrtype;
+
+ for (h = hostent->h_addr_list; *h != NULL; ++h) {
+ struct sockaddr_storage sa_ss;
+ struct sockaddr *sa = (struct sockaddr *)&sa_ss;
+
+ sa->sa_family = af;
+ socket_set_address_and_port (sa, *h, port);
+
+ s = socket (af, SOCK_STREAM, 0);
+ if (s < 0)
+ err (1, "socket");
+ if (connect(s, sa, socket_sockaddr_size(sa)) < 0) {
+ warn ("connect(%s)", hostname);
+ close (s);
+ continue;
+ } else {
+ break;
+ }
+ }
+ freehostent (hostent);
+ if (*h == NULL)
+ return -1;
+ if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
+ (void *)&nodelay, sizeof(nodelay)) < 0)
+ err (1, "setsockopt TCP_NODELAY");
+ return s;
+}
+
+typedef enum { INIT = 0, GREET, USER, PASS, STAT, RETR, TOP,
+ DELE, XDELE, QUIT} pop_state;
+
+#define PUSH_BUFSIZ 65536
+
+#define STEP 16
+
+struct write_state {
+ struct iovec *iovecs;
+ size_t niovecs, maxiovecs, allociovecs;
+ int fd;
+};
+
+static void
+write_state_init (struct write_state *w, int fd)
+{
+#ifdef UIO_MAXIOV
+ w->maxiovecs = UIO_MAXIOV;
+#else
+ w->maxiovecs = 16;
+#endif
+ w->allociovecs = min(STEP, w->maxiovecs);
+ w->niovecs = 0;
+ w->iovecs = malloc(w->allociovecs * sizeof(*w->iovecs));
+ if (w->iovecs == NULL)
+ err (1, "malloc");
+ w->fd = fd;
+}
+
+static void
+write_state_add (struct write_state *w, void *v, size_t len)
+{
+ if(w->niovecs == w->allociovecs) {
+ if(w->niovecs == w->maxiovecs) {
+ if(writev (w->fd, w->iovecs, w->niovecs) < 0)
+ err(1, "writev");
+ w->niovecs = 0;
+ } else {
+ w->allociovecs = min(w->allociovecs + STEP, w->maxiovecs);
+ w->iovecs = realloc (w->iovecs,
+ w->allociovecs * sizeof(*w->iovecs));
+ if (w->iovecs == NULL)
+ errx (1, "realloc");
+ }
+ }
+ w->iovecs[w->niovecs].iov_base = v;
+ w->iovecs[w->niovecs].iov_len = len;
+ ++w->niovecs;
+}
+
+static void
+write_state_flush (struct write_state *w)
+{
+ if (w->niovecs) {
+ if (writev (w->fd, w->iovecs, w->niovecs) < 0)
+ err (1, "writev");
+ w->niovecs = 0;
+ }
+}
+
+static void
+write_state_destroy (struct write_state *w)
+{
+ free (w->iovecs);
+}
+
+static int
+doit(int s,
+ const char *host,
+ const char *user,
+ const char *outfilename,
+ const char *header_str,
+ int leavep,
+ int verbose,
+ int forkp)
+{
+ int ret;
+ char out_buf[PUSH_BUFSIZ];
+ size_t out_len = 0;
+ char in_buf[PUSH_BUFSIZ + 1]; /* sentinel */
+ size_t in_len = 0;
+ char *in_ptr = in_buf;
+ pop_state state = INIT;
+ unsigned count, bytes;
+ unsigned asked_for = 0, retrieved = 0, asked_deleted = 0, deleted = 0;
+ unsigned sent_xdele = 0;
+ int out_fd;
+ char from_line[128];
+ size_t from_line_length;
+ time_t now;
+ struct write_state write_state;
+
+ if (do_from) {
+ out_fd = -1;
+ if (verbose)
+ fprintf (stderr, "%s@%s\n", user, host);
+ } else {
+ out_fd = open(outfilename, O_WRONLY | O_APPEND | O_CREAT, 0666);
+ if (out_fd < 0)
+ err (1, "open %s", outfilename);
+ if (verbose)
+ fprintf (stderr, "%s@%s -> %s\n", user, host, outfilename);
+ }
+
+ now = time(NULL);
+ from_line_length = snprintf (from_line, sizeof(from_line),
+ "From %s %s", "push", ctime(&now));
+
+ out_len = snprintf (out_buf, sizeof(out_buf),
+ "USER %s\r\nPASS hej\r\nSTAT\r\n",
+ user);
+ if (net_write (s, out_buf, out_len) != out_len)
+ err (1, "write");
+ if (verbose > 1)
+ write (STDERR_FILENO, out_buf, out_len);
+
+ if (!do_from)
+ write_state_init (&write_state, out_fd);
+
+ while(state != QUIT) {
+ fd_set readset, writeset;
+
+ FD_ZERO(&readset);
+ FD_ZERO(&writeset);
+ FD_SET(s,&readset);
+ if (((state == STAT || state == RETR || state == TOP)
+ && asked_for < count)
+ || (state == XDELE && !sent_xdele)
+ || (state == DELE && asked_deleted < count))
+ FD_SET(s,&writeset);
+ ret = select (s + 1, &readset, &writeset, NULL, NULL);
+ if (ret < 0) {
+ if (errno == EAGAIN)
+ continue;
+ else
+ err (1, "select");
+ }
+
+ if (FD_ISSET(s, &readset)) {
+ char *beg, *p;
+ size_t rem;
+ int blank_line = 0;
+
+ ret = read (s, in_ptr, sizeof(in_buf) - in_len - 1);
+ if (ret < 0)
+ err (1, "read");
+ else if (ret == 0)
+ errx (1, "EOF during read");
+
+ in_len += ret;
+ in_ptr += ret;
+ *in_ptr = '\0';
+
+ beg = in_buf;
+ rem = in_len;
+ while(rem > 1
+ && (p = strstr(beg, "\r\n")) != NULL) {
+ if (state == TOP) {
+ char *copy = beg;
+
+ if (strncasecmp(copy,
+ header_str,
+ min(p - copy + 1, strlen(header_str))) == 0) {
+ fprintf (stdout, "%.*s\n", (int)(p - copy), copy);
+ }
+ if (beg[0] == '.' && beg[1] == '\r' && beg[2] == '\n') {
+ state = STAT;
+ if (++retrieved == count) {
+ state = QUIT;
+ net_write (s, "QUIT\r\n", 6);
+ if (verbose > 1)
+ net_write (STDERR_FILENO, "QUIT\r\n", 6);
+ }
+ }
+ rem -= p - beg + 2;
+ beg = p + 2;
+ } else if (state == RETR) {
+ char *copy = beg;
+ if (beg[0] == '.') {
+ if (beg[1] == '\r' && beg[2] == '\n') {
+ if(!blank_line)
+ write_state_add(&write_state, "\n", 1);
+ state = STAT;
+ rem -= p - beg + 2;
+ beg = p + 2;
+ if (++retrieved == count) {
+ write_state_flush (&write_state);
+ if (fsync (out_fd) < 0)
+ err (1, "fsync");
+ close(out_fd);
+ if (leavep) {
+ state = QUIT;
+ net_write (s, "QUIT\r\n", 6);
+ if (verbose > 1)
+ net_write (STDERR_FILENO, "QUIT\r\n", 6);
+ } else {
+ if (forkp) {
+ pid_t pid;
+
+ pid = fork();
+ if (pid < 0)
+ warn ("fork");
+ else if(pid != 0) {
+ if(verbose)
+ fprintf (stderr,
+ "(exiting)");
+ return 0;
+ }
+ }
+
+ state = XDELE;
+ if (verbose)
+ fprintf (stderr, "deleting... ");
+ }
+ }
+ continue;
+ } else
+ ++copy;
+ }
+ *p = '\n';
+ if(blank_line &&
+ strncmp(copy, "From ", min(p - copy + 1, 5)) == 0)
+ write_state_add(&write_state, ">", 1);
+ write_state_add(&write_state, copy, p - copy + 1);
+ blank_line = (*copy == '\n');
+ rem -= p - beg + 2;
+ beg = p + 2;
+ } else if (rem >= 3 && strncmp (beg, "+OK", 3) == 0) {
+ if (state == STAT) {
+ if (!do_from)
+ write_state_add(&write_state,
+ from_line, from_line_length);
+ blank_line = 0;
+ if (do_from)
+ state = TOP;
+ else
+ state = RETR;
+ } else if (state == XDELE) {
+ state = QUIT;
+ net_write (s, "QUIT\r\n", 6);
+ if (verbose > 1)
+ net_write (STDERR_FILENO, "QUIT\r\n", 6);
+ break;
+ } else if (state == DELE) {
+ if (++deleted == count) {
+ state = QUIT;
+ net_write (s, "QUIT\r\n", 6);
+ if (verbose > 1)
+ net_write (STDERR_FILENO, "QUIT\r\n", 6);
+ break;
+ }
+ } else if (++state == STAT) {
+ if(sscanf (beg + 4, "%u %u", &count, &bytes) != 2)
+ errx(1, "Bad STAT-line: %.*s", (int)(p - beg), beg);
+ if (verbose) {
+ fprintf (stderr, "%u message(s) (%u bytes). "
+ "fetching... ",
+ count, bytes);
+ if (do_from)
+ fprintf (stderr, "\n");
+ } else if (do_count) {
+ fprintf (stderr, "%u message(s) (%u bytes).\n",
+ count, bytes);
+ }
+ if (count == 0) {
+ state = QUIT;
+ net_write (s, "QUIT\r\n", 6);
+ if (verbose > 1)
+ net_write (STDERR_FILENO, "QUIT\r\n", 6);
+ break;
+ }
+ }
+
+ rem -= p - beg + 2;
+ beg = p + 2;
+ } else {
+ if(state == XDELE) {
+ state = DELE;
+ rem -= p - beg + 2;
+ beg = p + 2;
+ } else
+ errx (1, "Bad response: %.*s", (int)(p - beg), beg);
+ }
+ }
+ if (!do_from)
+ write_state_flush (&write_state);
+
+ memmove (in_buf, beg, rem);
+ in_len = rem;
+ in_ptr = in_buf + rem;
+ }
+ if (FD_ISSET(s, &writeset)) {
+ if ((state == STAT && !do_from) || state == RETR)
+ out_len = snprintf (out_buf, sizeof(out_buf),
+ "RETR %u\r\n", ++asked_for);
+ else if ((state == STAT && do_from) || state == TOP)
+ out_len = snprintf (out_buf, sizeof(out_buf),
+ "TOP %u 0\r\n", ++asked_for);
+ else if(state == XDELE) {
+ out_len = snprintf(out_buf, sizeof(out_buf),
+ "XDELE %u %u\r\n", 1, count);
+ sent_xdele++;
+ }
+ else if(state == DELE)
+ out_len = snprintf (out_buf, sizeof(out_buf),
+ "DELE %u\r\n", ++asked_deleted);
+ if (net_write (s, out_buf, out_len) != out_len)
+ err (1, "write");
+ if (verbose > 1)
+ write (STDERR_FILENO, out_buf, out_len);
+ }
+ }
+ if (verbose)
+ fprintf (stderr, "Done\n");
+ if (!do_from)
+ write_state_destroy (&write_state);
+ return 0;
+}
+
+#ifdef KRB5
+static int
+do_v5 (const char *host,
+ int port,
+ const char *user,
+ const char *filename,
+ const char *header_str,
+ int leavep,
+ int verbose,
+ int forkp)
+{
+ krb5_error_code ret;
+ krb5_auth_context auth_context = NULL;
+ krb5_principal server;
+ int s;
+
+ s = do_connect (host, port, 1);
+ if (s < 0)
+ return 1;
+
+ ret = krb5_sname_to_principal (context,
+ host,
+ "pop",
+ KRB5_NT_SRV_HST,
+ &server);
+ if (ret) {
+ warnx ("krb5_sname_to_principal: %s",
+ krb5_get_err_text (context, ret));
+ return 1;
+ }
+
+ ret = krb5_sendauth (context,
+ &auth_context,
+ &s,
+ "KPOPV1.0",
+ NULL,
+ server,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ krb5_free_principal (context, server);
+ if (ret) {
+ warnx ("krb5_sendauth: %s",
+ krb5_get_err_text (context, ret));
+ return 1;
+ }
+ return doit (s, host, user, filename, header_str, leavep, verbose, forkp);
+}
+#endif
+
+#ifdef KRB4
+static int
+do_v4 (const char *host,
+ int port,
+ const char *user,
+ const char *filename,
+ const char *header_str,
+ int leavep,
+ int verbose,
+ int forkp)
+{
+ KTEXT_ST ticket;
+ MSG_DAT msg_data;
+ CREDENTIALS cred;
+ des_key_schedule sched;
+ int s;
+ int ret;
+
+ s = do_connect (host, port, 1);
+ if (s < 0)
+ return 1;
+ ret = krb_sendauth(0,
+ s,
+ &ticket,
+ "pop",
+ (char *)host,
+ krb_realmofhost(host),
+ getpid(),
+ &msg_data,
+ &cred,
+ sched,
+ NULL,
+ NULL,
+ "KPOPV0.1");
+ if(ret) {
+ warnx("krb_sendauth: %s", krb_get_err_text(ret));
+ return 1;
+ }
+ return doit (s, host, user, filename, header_str, leavep, verbose, forkp);
+}
+#endif /* KRB4 */
+
+#ifdef HESIOD
+
+#ifdef HESIOD_INTERFACES
+
+static char *
+hesiod_get_pobox (const char **user)
+{
+ void *context;
+ struct hesiod_postoffice *hpo;
+ char *ret = NULL;
+
+ if(hesiod_init (&context) != 0)
+ err (1, "hesiod_init");
+
+ hpo = hesiod_getmailhost (context, *user);
+ if (hpo == NULL) {
+ warn ("hesiod_getmailhost %s", *user);
+ } else {
+ if (strcasecmp(hpo->hesiod_po_type, "pop") != 0)
+ errx (1, "Unsupported po type %s", hpo->hesiod_po_type);
+
+ ret = strdup(hpo->hesiod_po_host);
+ if(ret == NULL)
+ errx (1, "strdup: out of memory");
+ *user = strdup(hpo->hesiod_po_name);
+ if (*user == NULL)
+ errx (1, "strdup: out of memory");
+ hesiod_free_postoffice (context, hpo);
+ }
+ hesiod_end (context);
+ return ret;
+}
+
+#else /* !HESIOD_INTERFACES */
+
+static char *
+hesiod_get_pobox (const char **user)
+{
+ char *ret = NULL;
+ struct hes_postoffice *hpo;
+
+ hpo = hes_getmailhost (*user);
+ if (hpo == NULL) {
+ warn ("hes_getmailhost %s", *user);
+ } else {
+ if (strcasecmp(hpo->po_type, "pop") != 0)
+ errx (1, "Unsupported po type %s", hpo->po_type);
+
+ ret = strdup(hpo->po_host);
+ if(ret == NULL)
+ errx (1, "strdup: out of memory");
+ *user = strdup(hpo->po_name);
+ if (*user == NULL)
+ errx (1, "strdup: out of memory");
+ }
+ return ret;
+}
+
+#endif /* HESIOD_INTERFACES */
+
+#endif /* HESIOD */
+
+static char *
+get_pobox (const char **user)
+{
+ char *ret = NULL;
+
+#ifdef HESIOD
+ ret = hesiod_get_pobox (user);
+#endif
+
+ if (ret == NULL)
+ ret = getenv("MAILHOST");
+ if (ret == NULL)
+ errx (1, "MAILHOST not set");
+ return ret;
+}
+
+static void
+parse_pobox (char *a0, const char **host, const char **user)
+{
+ const char *h, *u;
+ char *p;
+ int po = 0;
+
+ if (a0 == NULL) {
+
+ *user = getenv ("USERNAME");
+ if (*user == NULL) {
+ struct passwd *pwd = getpwuid (getuid ());
+
+ if (pwd == NULL)
+ errx (1, "Who are you?");
+ *user = strdup (pwd->pw_name);
+ if (*user == NULL)
+ errx (1, "strdup: out of memory");
+ }
+ *host = get_pobox (user);
+ return;
+ }
+
+ /* if the specification starts with po:, remember this information */
+ if(strncmp(a0, "po:", 3) == 0) {
+ a0 += 3;
+ po++;
+ }
+ /* if there is an `@', the hostname is after it, otherwise at the
+ beginning of the string */
+ p = strchr(a0, '@');
+ if(p != NULL) {
+ *p++ = '\0';
+ h = p;
+ } else {
+ h = a0;
+ }
+ /* if there is a `:', the username comes before it, otherwise at
+ the beginning of the string */
+ p = strchr(a0, ':');
+ if(p != NULL) {
+ *p++ = '\0';
+ u = p;
+ } else {
+ u = a0;
+ }
+ if(h == u) {
+ /* some inconsistent compatibility with various mailers */
+ if(po) {
+ h = get_pobox (&u);
+ } else {
+ u = get_default_username ();
+ if (u == NULL)
+ errx (1, "Who are you?");
+ }
+ }
+ *host = h;
+ *user = u;
+}
+
+int
+main(int argc, char **argv)
+{
+ int port = 0;
+ int optind = 0;
+ int ret = 1;
+ const char *host, *user, *filename = NULL;
+ char *pobox = NULL;
+
+ set_progname (argv[0]);
+
+#ifdef KRB5
+ krb5_init_context (&context);
+#endif
+
+ if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
+ &optind))
+ usage (1);
+
+ argc -= optind;
+ argv += optind;
+
+#if defined(KRB4) && defined(KRB5)
+ if(use_v4 == -1 && use_v5 == 1)
+ use_v4 = 0;
+ if(use_v5 == -1 && use_v4 == 1)
+ use_v5 = 0;
+#endif
+
+ if (do_help)
+ usage (0);
+
+ if (do_version) {
+ print_version(NULL);
+ return 0;
+ }
+
+ if (do_from && header_str == NULL)
+ header_str = "From:";
+ else if (header_str != NULL)
+ do_from = 1;
+
+ if (do_from) {
+ if (argc == 0)
+ pobox = NULL;
+ else if (argc == 1)
+ pobox = argv[0];
+ else
+ usage (1);
+ } else {
+ if (argc == 1) {
+ filename = argv[0];
+ pobox = NULL;
+ } else if (argc == 2) {
+ filename = argv[1];
+ pobox = argv[0];
+ } else
+ usage (1);
+ }
+
+ if (port_str) {
+ struct servent *s = roken_getservbyname (port_str, "tcp");
+
+ if (s)
+ port = s->s_port;
+ else {
+ char *ptr;
+
+ port = strtol (port_str, &ptr, 10);
+ if (port == 0 && ptr == port_str)
+ errx (1, "Bad port `%s'", port_str);
+ port = htons(port);
+ }
+ }
+ if (port == 0)
+#ifdef KRB5
+ port = krb5_getportbyname (context, "kpop", "tcp", 1109);
+#elif defined(KRB4)
+ port = k_getportbyname ("kpop", "tcp", 1109);
+#else
+#error must define KRB4 or KRB5
+#endif
+
+ parse_pobox (pobox, &host, &user);
+
+#ifdef KRB5
+ if (ret && use_v5) {
+ ret = do_v5 (host, port, user, filename, header_str,
+ do_leave, verbose_level, do_fork);
+ }
+#endif
+
+#ifdef KRB4
+ if (ret && use_v4) {
+ ret = do_v4 (host, port, user, filename, header_str,
+ do_leave, verbose_level, do_fork);
+ }
+#endif /* KRB4 */
+ return ret;
+}
diff --git a/crypto/kerberosIV/appl/push/push.cat8 b/crypto/kerberosIV/appl/push/push.cat8
new file mode 100644
index 0000000..1c0b7a4
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/push.cat8
@@ -0,0 +1,77 @@
+
+PUSH(8) System Manager's Manual PUSH(8)
+
+NNAAMMEE
+ ppuusshh - fetch mail via POP
+
+SSYYNNOOPPSSIISS
+ ppuusshh [--44 | ----kkrrbb44] [--55 | ----kkrrbb55] [--vv | ----vveerrbboossee] [--ff | ----ffoorrkk] [--ll |
+ ----lleeaavvee] [----ffrroomm] [--cc | ----ccoouunntt] [----hheeaaddeerr] [--pp _p_o_r_t_-_s_p_e_c | ----ppoorrtt==_p_o_r_t_-
+ _s_p_e_c] _p_o_-_b_o_x _f_i_l_e_n_a_m_e
+
+DDEESSCCRRIIPPTTIIOONN
+ ppuusshh retrieves mail from the post office box _p_o_-_b_o_x, and stores the mail
+ in mbox format in _f_i_l_e_n_a_m_e. The _p_o_-_b_o_x can have any of the following for-
+ mats:
+ `hostname:username'
+ `po:hostname:username'
+ `username@hostname'
+ `po:username@hostname'
+ `hostname'
+ `po:username'
+
+ If no username is specified, ppuusshh assumes that it's the same as on the
+ local machine; _h_o_s_t_n_a_m_e defaults to the value of the MAILHOST environment
+ variable.
+
+ Supported options:
+
+ --44, ----kkrrbb44
+ use Kerberos 4 (if compiled with support for Kerberos 4)
+
+ --55, ----kkrrbb55
+ use Kerberos 5 (if compiled with support for Kerberos 5)
+
+ --ff, ----ffoorrkk
+ fork before starting to delete messages
+
+ --ll, ----lleeaavvee
+ don't delete fetched mail
+
+ ----ffrroomm behave like from.
+
+ --cc, ----ccoouunntt
+ first print how many messages and bytes there are.
+
+ ----hheeaaddeerr
+ which header from should print.
+
+ --pp _p_o_r_t_-_s_p_e_c, ----ppoorrtt==_p_o_r_t_-_s_p_e_c
+ use this port instead of the default `kpop' or `1109'.
+
+ The default is to first try Kerberos 5 authentication and then, if that
+ fails, Kerberos 4.
+
+EENNVVIIRROONNMMEENNTT
+ MAILHOST
+ points to the post office, if no other hostname is specified.
+
+EEXXAAMMPPLLEESS
+ $ push cornfield:roosta ~/.gnus-crash-box
+
+ tries to fetch mail for the user _r_o_o_s_t_a from the post office at
+ ``cornfield'', and stores the mail in _~_/_._g_n_u_s_-_c_r_a_s_h_-_b_o_x (you are using
+ Gnus, aren't you?)
+
+ $ push --from -5 havregryn
+
+ tries to fetch FFrroomm:: lines for current user at post office ``havregryn''
+ using Kerberos 5.
+
+SSEEEE AALLSSOO
+ movemail(8), popper(8), from(1), pfrom(1)
+
+HHIISSTTOORRYY
+ ppuusshh was written while waiting for mmoovveemmaaiill to finish getting the mail.
+
+ HEIMDAL May 31, 1998 2
diff --git a/crypto/kerberosIV/appl/push/push_locl.h b/crypto/kerberosIV/appl/push/push_locl.h
new file mode 100644
index 0000000..1e5ca78
--- /dev/null
+++ b/crypto/kerberosIV/appl/push/push_locl.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 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. 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: push_locl.h,v 1.6 1999/12/02 16:58:33 joda Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <ctype.h>
+#include <limits.h>
+#include <time.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.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_TCP_H
+#include <netinet/tcp.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+
+#include <roken.h>
+#include <err.h>
+#include <getarg.h>
+#ifdef KRB5
+#include <krb5.h>
+#endif
+
+#ifdef KRB4
+#include <krb.h>
+#endif
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..d79d574
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/sample.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: sample.h,v 1.11 1999/12/02 16:58:33 joda 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..d0ec1c5
--- /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.21 1999/11/13 06:27:01 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]);
+ strlcpy (service, SAMPLE_SERVICE, sizeof(service));
+ port = 0;
+
+ while ((c = getopt(argc, argv, "s:p:")) != -1)
+ switch(c) {
+ case 's' :
+ strlcpy (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..65b61ae
--- /dev/null
+++ b/crypto/kerberosIV/appl/sample/sample_server.c
@@ -0,0 +1,155 @@
+/* $FreeBSD$ */
+
+/*
+ *
+ * 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.14.2.1 2000/06/28 19:08:00 assar 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);
+
+ strlcpy (service, SAMPLE_SERVICE, sizeof(service));
+ *srvtab = '\0';
+
+ while ((c = getopt (argc, argv, "s:t:i")) != -1)
+ switch (c) {
+ case 's' :
+ strlcpy (service, optarg, sizeof(service));
+ break;
+ case 't' :
+ strlcpy (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, "%s", 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)
+ strlcpy(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..434150d
--- /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.15 1999/11/13 06:29:01 assar 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]);
+
+ strlcpy (service, SAMPLE_SERVICE, sizeof(service));
+
+ while ((c = getopt(argc, argv, "s:p:")) != -1)
+ switch(c) {
+ case 's' :
+ strlcpy (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..05baa4e
--- /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.11 1999/11/13 06:29:24 assar 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]);
+ strlcpy (service, SAMPLE_SERVICE, sizeof(service));
+ strlcpy (instance, "*", sizeof(instance));
+ *srvtab = '\0';
+ port = 0;
+
+ while ((c = getopt (argc, argv, "p:s:t:")) != -1)
+ 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' :
+ strlcpy (service, optarg, sizeof(service));
+ break;
+ case 't' :
+ strlcpy (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..b2c27bc
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/ChangeLog
@@ -0,0 +1,286 @@
+2000-03-26 Assar Westerlund <assar@sics.se>
+
+ * telnetd/sys_term.c (*): make sure to always call time, ctime,
+ and gmtime with `time_t's. there were some types (like in
+ lastlog) that we believed to always be time_t. this has proven
+ wrong on Solaris 8 in 64-bit mode, where they are stored as 32-bit
+ quantities but time_t has gone up to 64 bits
+
+1999-09-16 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c: revert 1.54, get_default_username should DTRT
+ now
+
+1999-09-05 Assar Westerlund <assar@sics.se>
+
+ * telnetd/utility.c (ttloop): make it return 1 if interrupted by a
+ signal, which must have been what was meant from the beginning
+
+ * telnetd/ext.h (ttloop): update prototype
+
+ * telnetd/authenc.c (telnet_spin): actually return the value from
+ ttloop (otherwise it's kind of bogus)
+
+1999-08-05 Assar Westerlund <assar@sics.se>
+
+ * telnetd/sys_term.c (rmut): free utxp
+
+1999-08-04 Assar Westerlund <assar@sics.se>
+
+ * telnet/main.c: add -G and config file support. From Miroslav
+ Ruda <ruda@ics.muni.cz>
+
+ * telnetd/sys_term.c (rmut): work around utmpx strangness. From
+ Miroslav Ruda <ruda@ics.muni.cz>
+
+1999-08-02 Assar Westerlund <assar@sics.se>
+
+ * telnetd/telnetd.c (doit): only free hp if != NULL. From: Jonas
+ Oberg <jonas@coyote.org>
+
+1999-07-29 Assar Westerlund <assar@sics.se>
+
+ * telnetd/telnetd.c (doit): remove unused variable mapped_sin
+
+1999-07-26 Assar Westerlund <assar@sics.se>
+
+ * telnetd/ext.h: update prototypes
+
+ * telnetd/telnetd.c: make it handle v4 and v6 sockets. (it
+ doesn't handle being given a v6 socket that's really talking to an
+ v4 adress (mapped) because the rest of the code in telnetd is not
+ able to handle it anyway). please run two telnetd from your
+ inetd, one for v4 and one for v6.
+
+1999-07-07 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c (tn): extra bogus const-cast
+
+1999-07-06 Assar Westerlund <assar@sics.se>
+
+ * telnetd/sys_term.c (start_login): print a different warning with
+ `-a otp'
+
+1999-06-24 Assar Westerlund <assar@sics.se>
+
+ * libtelnet/kerberos5.c (kerberos5_send): set the addresses in the
+ auth_context
+
+1999-06-23 Assar Westerlund <assar@sics.se>
+
+ * telnet/Makefile.am (INCLUDES): add $(INCLUDE_krb4)
+
+ * telnet/commands.c (togkrbdebug): conditionalize on
+ krb_disable_debug
+
+1999-06-16 Johan Danielsson <joda@pdc.kth.se>
+
+ * telnet/commands.c: add kerberos debugging option
+
+1999-06-15 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c (tn): use get_default_username
+
+1999-05-14 Assar Westerlund <assar@sics.se>
+
+ * telnetd/state.c (telrcv): magic patch to make it work against
+ DOS Clarkson Telnet. From Miroslav Ruda <ruda@ics.muni.cz>
+
+1999-04-25 Assar Westerlund <assar@sics.se>
+
+ * libtelnet/kerberos5.c (kerberos5_send): use
+ `krb5_auth_setkeytype' instead of `krb5_auth_setenctype' to make
+ sure we get a DES session key.
+
+Thu Apr 1 16:59:27 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * telnetd/Makefile.am: don't run check-local
+
+ * telnet/Makefile.am: don't run check-local
+
+Mon Mar 29 16:11:33 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * telnetd/sys_term.c: _CRAY -> HAVE_STRUCT_UTMP_UT_ID
+
+Sat Mar 20 00:12:54 1999 Assar Westerlund <assar@sics.se>
+
+ * telnet/authenc.c (telnet_gets): remove old extern declarations
+
+Thu Mar 18 11:20:16 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * telnetd/Makefile.am: include Makefile.am.common
+
+ * telnet/Makefile.am: include Makefile.am.common
+
+ * libtelnet/Makefile.am: include Makefile.am.common
+
+ * Makefile.am: include Makefile.am.common
+
+Mon Mar 15 17:40:53 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * telnetd/telnetd.c: replace perror/exit with fatalperror
+
+Sat Mar 13 22:18:57 1999 Assar Westerlund <assar@sics.se>
+
+ * telnetd/telnetd.c (main): 0 -> STDIN_FILENO. remove abs
+
+ * libtelnet/kerberos.c (kerberos4_is): syslog root logins
+
+Thu Mar 11 14:48:54 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * telnetd/Makefile.in: add WFLAGS
+
+ * telnet/Makefile.in: add WFLAGS
+
+ * libtelnet/Makefile.in: add WFLAGS
+
+ * telnetd/sys_term.c: remove unused variables
+
+ * telnet/telnet.c: fix some warnings
+
+ * telnet/main.c: fix some warnings
+
+ * telnet/commands.c: fix types in format string
+
+ * libtelnet/auth.c: fix types in format string
+
+Mon Mar 1 10:50:30 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * telnetd/sys_term.c: HAVE_UT_* -> HAVE_STRUCT_UTMP*_UT_*
+
+Mon Feb 1 04:08:36 1999 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c (tn): only call gethostbyname2 with AF_INET6
+ if we actually have IPv6. From "Brandon S. Allbery KF8NH"
+ <allbery@kf8nh.apk.net>
+
+Sat Nov 21 16:51:00 1998 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * telnetd/sys_term.c (cleanup): don't call vhangup() on sgi:s
+
+Fri Aug 14 16:29:18 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * libtelnet/kerberos.c: krb_put_int -> KRB_PUT_INT
+
+Thu Jul 23 20:29:05 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * libtelnet/kerberos5.c: use krb5_verify_authenticator_checksum
+
+Mon Jul 13 22:00:09 1998 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c (tn): don't advance hostent->h_addr_list, use
+ a copy instead
+
+Wed May 27 04:19:17 1998 Assar Westerlund <assar@sics.se>
+
+ * telnet/sys_bsd.c (process_rings): correct call to `stilloob'
+
+Fri May 15 19:38:19 1998 Johan Danielsson <joda@blubb.pdc.kth.se>
+
+ * libtelnet/kerberos5.c: Always print errors from mk_req.
+
+Fri May 1 07:16:59 1998 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c: unifdef -DHAVE_H_ERRNO
+
+Sat Apr 4 15:00:29 1998 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c (tn): moved the printing of `trying...' to the
+ loop
+
+Thu Mar 12 02:33:48 1998 Assar Westerlund <assar@sics.se>
+
+ * telnet/telnet_locl.h: include <term.h>. From Gregory S. Stark
+ <gsstark@mit.edu>
+
+Sat Feb 21 15:12:38 1998 Assar Westerlund <assar@sics.se>
+
+ * telnetd/ext.h: add prototype for login_tty
+
+ * telnet/utilities.c (printsub): `direction' is now an int.
+
+ * libtelnet/misc-proto.h: add prototype for `printsub'
+
+Tue Feb 17 02:45:01 1998 Assar Westerlund <assar@sics.se>
+
+ * libtelnet/kerberos.c (kerberos4_is): cred.pname should be
+ cred.pinst. From <art@stacken.kth.se>
+
+Sun Feb 15 02:46:39 1998 Assar Westerlund <assar@sics.se>
+
+ * telnet/*/*.c: renamed `telnet' to `my_telnet' to avoid
+ conflicts with system header files on mklinux.
+
+Tue Feb 10 02:09:03 1998 Assar Westerlund <assar@sics.se>
+
+ * telnetd/telnetd.c: new signature for `getterminaltype' and
+ `auth_wait'
+
+ * libtelnet: changed the signature of the authentication method
+ `status'
+
+Sat Feb 7 07:21:29 1998 Assar Westerlund <assar@sics.se>
+
+ * */*.c: replace HAS_GETTOS by HAVE_PARSETOS and HAVE_GETTOSBYNAME
+
+Fri Dec 26 16:17:10 1997 Assar Westerlund <assar@sics.se>
+
+ * telnet/commands.c (tn): repair support for numeric addresses
+
+Sun Dec 21 09:40:31 1997 Assar Westerlund <assar@sics.se>
+
+ * libtelnet/kerberos.c: fix up lots of stuff related to the
+ forwarding of v4 tickets.
+
+ * libtelnet/kerberos5.c (kerberos5_forward): zero out `creds'.
+
+Mon Dec 15 20:53:13 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * telnet/sys_bsd.c: Don't turn off OPOST in 8bit-mode.
+
+Tue Dec 9 19:26:50 1997 Assar Westerlund <assar@sics.se>
+
+ * telnet/main.c (main): add 'b' to getopt
+
+Sat Nov 29 03:28:54 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * telnet/telnet.c: Change binary mode to do just that, and add a
+ eight-bit mode for just passing all characters.
+
+Sun Nov 16 04:37:02 1997 Assar Westerlund <assar@sics.se>
+
+ * libtelnet/kerberos5.c (kerberos5_send): always ask for a session
+ key of type DES
+
+ * libtelnet/kerberos5.c: remove old garbage and fix call to
+ krb5_auth_con_setaddrs_from_fd
+
+Fri Nov 14 20:35:18 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * telnetd/telnetd.c: Output contents of /etc/issue.
+
+Mon Nov 3 07:09:16 1997 Assar Westerlund <assar@sics.se>
+
+ * telnet/telnet_locl.h: only include <sys/termio.h> iff
+ !defined(HAVE_TERMIOS_H)
+
+ * libtelnet/kerberos.c (kerberos4_is): send the peer address to
+ krb_rd_req
+
+ * telnetd/telnetd.c (terminaltypeok): always return OK. It used
+ to call `tgetent' to figure if it was a defined terminal type.
+ It's possible to overflow tgetent so that's a bad idea. The worst
+ that could happen by saying yes to all terminals is that the user
+ ends up with a terminal that has no definition on the local
+ system. And besides, most telnet client has no support for
+ falling back to a different terminal type.
+
+Mon Oct 20 05:47:19 1997 Assar Westerlund <assar@sics.se>
+
+ * libtelnet/kerberos5.c: remove lots of old junk. clean-up.
+ better error checking and reporting. tell the user permission
+ denied much earlier.
+
+ * libtelnet/kerberos.c (kerberos4_is): only print
+ UserNameRequested if != NULL
+
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..ec13b3f
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c
@@ -0,0 +1,672 @@
+/*-
+ * 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.
+ */
+/* $FreeBSD$ */
+
+#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 <openssl/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..9037ac6
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c
@@ -0,0 +1,718 @@
+/*-
+ * 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.
+ */
+/* $FreeBSD$ */
+
+/*
+ * 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.46 1999/09/16 20:41:33 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 <openssl/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));
+
+ strlcpy (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)) {
+ strlcpy(name, UserNameRequested, name_sz);
+ return(AUTH_VALID);
+ } else
+ return(AUTH_USER);
+}
+
+#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
+#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+void
+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) */
+ strlcpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB_ACCEPT: /* Accepted (name might follow) */
+ strlcpy((char *)buf, " ACCEPT ", buflen);
+ common:
+ BUMP(buf, buflen);
+ if (cnt <= 4)
+ break;
+ ADDC(buf, buflen, '"');
+ for (i = 4; i < cnt; i++)
+ ADDC(buf, buflen, data[i]);
+ ADDC(buf, buflen, '"');
+ ADDC(buf, buflen, '\0');
+ break;
+
+ case KRB_AUTH: /* Authentication data follows */
+ strlcpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB_CHALLENGE:
+ strlcpy((char *)buf, " CHALLENGE", buflen);
+ goto common2;
+
+ case KRB_RESPONSE:
+ strlcpy((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..3e6abbb
--- /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.38 1999/09/16 20:41:33 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))
+ {
+ strlcpy(name, UserNameRequested, name_sz);
+ return(AUTH_VALID);
+ } else
+ return(AUTH_USER);
+}
+
+#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
+#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+void
+kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
+{
+ int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case KRB_REJECT: /* Rejected (reason might follow) */
+ strlcpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB_ACCEPT: /* Accepted (name might follow) */
+ strlcpy((char *)buf, " ACCEPT ", buflen);
+ common:
+ BUMP(buf, buflen);
+ if (cnt <= 4)
+ break;
+ ADDC(buf, buflen, '"');
+ for (i = 4; i < cnt; i++)
+ ADDC(buf, buflen, data[i]);
+ ADDC(buf, buflen, '"');
+ ADDC(buf, buflen, '\0');
+ break;
+
+
+ case KRB_AUTH: /* Authentication data follows */
+ strlcpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB_RESPONSE:
+ strlcpy((char *)buf, " RESPONSE", buflen);
+ goto common2;
+
+ case KRB_FORWARD: /* Forwarded credentials follow */
+ strlcpy((char *)buf, " FORWARD", buflen);
+ goto common2;
+
+ case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
+ strlcpy((char *)buf, " FORWARD_ACCEPT", buflen);
+ goto common2;
+
+ case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
+ /* (reason might follow) */
+ strlcpy((char *)buf, " FORWARD_REJECT", buflen);
+ goto common2;
+
+ default:
+ snprintf(buf, buflen, " %d (unknown)", data[3]);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ snprintf(buf, buflen, " %d", data[i]);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+void
+kerberos5_forward(Authenticator *ap)
+{
+ krb5_error_code ret;
+ krb5_ccache ccache;
+ krb5_creds creds;
+ krb5_kdc_flags flags;
+ krb5_data out_data;
+ krb5_principal principal;
+
+ ret = krb5_cc_default (context, &ccache);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("KerberosV5: could not get default ccache: %s\r\n",
+ krb5_get_err_text (context, ret));
+ return;
+ }
+
+ ret = krb5_cc_get_principal (context, ccache, &principal);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("KerberosV5: could not get principal: %s\r\n",
+ krb5_get_err_text (context, ret));
+ return;
+ }
+
+ memset (&creds, 0, sizeof(creds));
+
+ creds.client = principal;
+
+ ret = krb5_build_principal (context,
+ &creds.server,
+ strlen(principal->realm),
+ principal->realm,
+ "krbtgt",
+ principal->realm,
+ NULL);
+
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("KerberosV5: could not get principal: %s\r\n",
+ krb5_get_err_text (context, ret));
+ return;
+ }
+
+ creds.times.endtime = 0;
+
+ flags.i = 0;
+ flags.b.forwarded = 1;
+ if (forward_flags & OPTS_FORWARDABLE_CREDS)
+ flags.b.forwardable = 1;
+
+ ret = krb5_get_forwarded_creds (context,
+ auth_context,
+ ccache,
+ flags.i,
+ RemoteHostName,
+ &creds,
+ &out_data);
+ if (ret) {
+ if (auth_debug_mode)
+ printf ("Kerberos V5: error 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..a4f8a2c
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c
@@ -0,0 +1,438 @@
+/*-
+ * 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.
+ */
+/* $FreeBSD$ */
+
+#include <config.h>
+
+RCSID("$Id: krb4encpwd.c,v 1.18 1999/09/16 20:41:34 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 <openssl/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;
+ strlcpy(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)) {
+ strlcpy(name, UserNameRequested, name_sz);
+ return(AUTH_VALID);
+ } else {
+ return(AUTH_USER);
+ }
+}
+
+#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
+#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+ void
+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) */
+ strlcpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */
+ strlcpy((char *)buf, " ACCEPT ", buflen);
+ common:
+ BUMP(buf, buflen);
+ if (cnt <= 4)
+ break;
+ ADDC(buf, buflen, '"');
+ for (i = 4; i < cnt; i++)
+ ADDC(buf, buflen, data[i]);
+ ADDC(buf, buflen, '"');
+ ADDC(buf, buflen, '\0');
+ break;
+
+ case KRB4_ENCPWD_AUTH: /* Authentication data follows */
+ strlcpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB4_ENCPWD_CHALLENGE:
+ strlcpy((char *)buf, " CHALLENGE", buflen);
+ goto common2;
+
+ case KRB4_ENCPWD_ACK:
+ strlcpy((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..dafb448
--- /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.18 1999/09/16 20:41:34 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 {
+ strlcpy(challenge, "randchal", sizeof(challenge));
+ challenge_len = 8;
+ }
+
+ if ((fp=fopen(key_file, "r"))==NULL) {
+ Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ /*
+ * skip privkey
+ */
+ fscanf(fp, "%x;", &len);
+ for (i=0;i<len;i++) {
+ j = getc(fp);
+ }
+ /*
+ * get pubkey
+ */
+ fscanf(fp, "%x;", &len);
+ for (i=0;i<len;i++) {
+ j = getc(fp); key[i]=j;
+ }
+ fclose(fp);
+ chalkey[0] = 0x30;
+ ptr = (char *) &chalkey[1];
+ chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len;
+ EncodeLength(ptr, chalkey_len);
+ ptr +=NumEncodeLengthOctets(chalkey_len);
+ *ptr++ = 0x04; /* OCTET STRING */
+ *ptr++ = challenge_len;
+ memmove(ptr, challenge, challenge_len);
+ ptr += challenge_len;
+ *ptr++ = 0x04; /* OCTET STRING */
+ EncodeLength(ptr, i);
+ ptr += NumEncodeLengthOctets(i);
+ memmove(ptr, key, i);
+ chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len;
+ Data(ap, RSA_ENCPWD_CHALLENGEKEY, chalkey, chalkey_len);
+ }
+ break;
+
+ default:
+ Data(ap, RSA_ENCPWD_REJECT, 0, 0);
+ break;
+ }
+}
+
+
+ void
+rsaencpwd_reply(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ Session_Key skey;
+ KTEXT_ST token;
+ des_cblock enckey;
+ int r, pubkey_len;
+ char randchal[CHAL_SZ], *cp;
+ char chalkey[160], pubkey[128], *ptr;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case RSA_ENCPWD_REJECT:
+ if (cnt > 0) {
+ printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n",
+ cnt, data);
+ } else
+ printf("[ RSA_ENCPWD refuses authentication ]\r\n");
+ auth_send_retry();
+ return;
+ case RSA_ENCPWD_ACCEPT:
+ printf("[ RSA_ENCPWD accepts you ]\r\n");
+ auth_finished(ap, AUTH_USER);
+ return;
+ case RSA_ENCPWD_CHALLENGEKEY:
+ /*
+ * Verify that the response to the challenge is correct.
+ */
+
+ memmove(chalkey, data, cnt);
+ ptr = (char *) &chalkey[0];
+ ptr += DecodeHeaderLength(chalkey);
+ if (*ptr != 0x04) {
+ return;
+ }
+ *ptr++;
+ challenge_len = DecodeValueLength(ptr);
+ ptr += NumEncodeLengthOctets(challenge_len);
+ memmove(challenge, ptr, challenge_len);
+ ptr += challenge_len;
+ if (*ptr != 0x04) {
+ return;
+ }
+ *ptr++;
+ pubkey_len = DecodeValueLength(ptr);
+ ptr += NumEncodeLengthOctets(pubkey_len);
+ memmove(pubkey, ptr, pubkey_len);
+ memset(user_passwd, 0, sizeof(user_passwd));
+ des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
+ UserPassword = user_passwd;
+ Challenge = challenge;
+ r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey);
+ if (r < 0) {
+ token.length = 1;
+ }
+
+ if (!Data(ap, RSA_ENCPWD_AUTH, token.dat, token.length)) {
+ return;
+ }
+
+ break;
+
+ default:
+ return;
+ }
+}
+
+ int
+rsaencpwd_status(ap, name, name_sz, level)
+ Authenticator *ap;
+ char *name;
+ size_t name_sz;
+ int level;
+{
+
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) {
+ strlcpy(name, UserNameRequested, name_sz);
+ return(AUTH_VALID);
+ } else {
+ return(AUTH_USER);
+ }
+}
+
+#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
+#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+ void
+rsaencpwd_printsub(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) */
+ strlcpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */
+ strlcpy((char *)buf, " ACCEPT ", buflen);
+ common:
+ BUMP(buf, buflen);
+ if (cnt <= 4)
+ break;
+ ADDC(buf, buflen, '"');
+ for (i = 4; i < cnt; i++)
+ ADDC(buf, buflen, data[i]);
+ ADDC(buf, buflen, '"');
+ ADDC(buf, buflen, '\0');
+ break;
+
+ case RSA_ENCPWD_AUTH: /* Authentication data follows */
+ strlcpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case RSA_ENCPWD_CHALLENGEKEY:
+ strlcpy((char *)buf, " CHALLENGEKEY", buflen);
+ goto common2;
+
+ default:
+ snprintf(buf, buflen, " %d (unknown)", data[3]);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ snprintf(buf, buflen, " %d", data[i]);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+int rsaencpwd_passwdok(name, passwd)
+char *name, *passwd;
+{
+ char *crypt();
+ char *salt, *p;
+ struct passwd *pwd;
+ int passwdok_status = 0;
+
+ if (pwd = k_getpwnam(name))
+ salt = pwd->pw_passwd;
+ else salt = "xx";
+
+ p = crypt(passwd, salt);
+
+ if (pwd && !strcmp(p, pwd->pw_passwd)) {
+ passwdok_status = 1;
+ } else passwdok_status = 0;
+ return(passwdok_status);
+}
+
+#endif
+
+#ifdef notdef
+
+prkey(msg, key)
+ char *msg;
+ unsigned char *key;
+{
+ int i;
+ printf("%s:", msg);
+ for (i = 0; i < 8; i++)
+ printf(" %3d", key[i]);
+ printf("\r\n");
+}
+#endif
diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/spx.c b/crypto/kerberosIV/appl/telnet/libtelnet/spx.c
new file mode 100644
index 0000000..9155ef2
--- /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.17 1999/09/16 20:41:34 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) {
+ strlcpy(name, UserNameRequested, name_sz);
+ return(AUTH_VALID);
+ } else {
+ return(AUTH_USER);
+ }
+
+}
+
+#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
+#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
+
+ void
+spx_printsub(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) */
+ strlcpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case SPX_ACCEPT: /* Accepted (name might follow) */
+ strlcpy((char *)buf, " ACCEPT ", buflen);
+ common:
+ BUMP(buf, buflen);
+ if (cnt <= 4)
+ break;
+ ADDC(buf, buflen, '"');
+ for (i = 4; i < cnt; i++)
+ ADDC(buf, buflen, data[i]);
+ ADDC(buf, buflen, '"');
+ ADDC(buf, buflen, '\0');
+ break;
+
+ case SPX_AUTH: /* Authentication data follows */
+ strlcpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ default:
+ snprintf(buf, buflen, " %d (unknown)", data[3]);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ snprintf(buf, buflen, " %d", data[i]);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+#endif
+
+#ifdef notdef
+
+prkey(msg, key)
+ char *msg;
+ unsigned char *key;
+{
+ int i;
+ printf("%s:", msg);
+ for (i = 0; i < 8; i++)
+ printf(" %3d", key[i]);
+ printf("\r\n");
+}
+#endif
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..6150fc7
--- /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.10 1999/09/16 20:41:35 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))) {
+ strlcpy(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..fe77b56
--- /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.56 1999/09/16 20:41:35 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 */
+ strlcpy(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)
+ strlcpy(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;
+
+ strlcpy(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) {
+ strlcpy(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);
+ strlcpy(_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);
+ strlcpy(_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) {
+ strlcpy(_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..ea60ae9
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/main.c
@@ -0,0 +1,358 @@
+/*
+ * 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.30 1999/11/13 06:30:11 assar 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] [-G] [-S tos] [-X atype] [-a] [-c] [-d] [-e char]",
+ "\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] ",
+#else
+ "[-8] [-E] [-L] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
+ "\n\t[-n tracefile]",
+#endif
+ "[-r] ",
+#ifdef ENCRYPTION
+ "[-x] [host-name [port]]"
+#else
+ "[host-name [port]]"
+#endif
+ );
+ exit(1);
+}
+
+/*
+ * main. Parse arguments, invoke the protocol or command parser.
+ */
+
+
+#ifdef FORWARD
+extern int forward_flags;
+static int default_forward=0;
+#endif /* FORWARD */
+
+#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);
+
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+ if (krb5_config_get_bool (context, NULL,
+ "libdefaults", "forward", NULL)) {
+ forward_flags |= OPTS_FORWARD_CREDS;
+ default_forward=1;
+ }
+ if (krb5_config_get_bool (context, NULL,
+ "libdefaults", "forwardable", NULL)) {
+ forward_flags |= OPTS_FORWARDABLE_CREDS;
+ default_forward=1;
+ }
+#endif
+#ifdef ENCRYPTION
+ if (krb5_config_get_bool (context, NULL,
+ "libdefaults", "encrypt", NULL)) {
+ encrypt_auto(1);
+ decrypt_auto(1);
+ EncryptVerbose(1);
+ }
+#endif
+
+ krb5_free_context(context);
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ char *user;
+
+#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:rxG")) != -1) {
+ switch(ch) {
+ case '8':
+ eight = 3; /* binary output and input */
+ break;
+ case '7':
+ eight = 0;
+ break;
+ case 'b':
+ binary = 3;
+ break;
+ case 'D': {
+ /* sometimes we don't want a mangled display */
+ char *p;
+ if((p = getenv("DISPLAY")))
+ env_define("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) &&
+ !default_forward) {
+ 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) &&
+ !default_forward) {
+ 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;
+ strlcpy(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 'G':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+ forward_flags ^= OPTS_FORWARD_CREDS;
+ forward_flags ^= OPTS_FORWARDABLE_CREDS;
+#else
+ fprintf(stderr,
+ "%s: Warning: -G ignored, no Kerberos V5 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..42ca388
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/network.c
@@ -0,0 +1,165 @@
+/*
+ * 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.28.1 2000/10/10 13:08:27 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);
+ if (net >= FD_SETSIZE)
+ errx (1, "fd too large");
+ FD_SET(net, &excepts);
+ value = select(net+1, 0, 0, &excepts, &timeout);
+ } while ((value == -1) && (errno == EINTR));
+
+ if (value < 0) {
+ perror("select");
+ quit();
+ /* NOTREACHED */
+ }
+ if (FD_ISSET(net, &excepts)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * setneturg()
+ *
+ * Sets "neturg" to the current location.
+ */
+
+void
+setneturg(void)
+{
+ ring_mark(&netoring);
+}
+
+
+/*
+ * netflush
+ * Send as much data as possible to the network,
+ * handling requests for urgent data.
+ *
+ * The return value indicates whether we did any
+ * useful work.
+ */
+
+
+int
+netflush(void)
+{
+ int n, n1;
+
+#if defined(ENCRYPTION)
+ if (encrypt_output)
+ ring_encrypt(&netoring, encrypt_output);
+#endif
+ if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
+ if (!ring_at_mark(&netoring)) {
+ n = send(net, (char *)netoring.consume, n, 0); /* normal write */
+ } else {
+ /*
+ * In 4.2 (and 4.3) systems, there is some question about
+ * what byte in a sendOOB operation is the "OOB" data.
+ * To make ourselves compatible, we only send ONE byte
+ * out of band, the one WE THINK should be OOB (though
+ * we really have more the TCP philosophy of urgent data
+ * rather than the Unix philosophy of OOB data).
+ */
+ n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
+ }
+ }
+ if (n < 0) {
+ if (errno != ENOBUFS && errno != EWOULDBLOCK) {
+ setcommandmode();
+ perror(hostname);
+ NetClose(net);
+ ring_clear_mark(&netoring);
+ longjmp(peerdied, -1);
+ /*NOTREACHED*/
+ }
+ n = 0;
+ }
+ if (netdata && n) {
+ Dump('>', netoring.consume, n);
+ }
+ if (n) {
+ ring_consumed(&netoring, n);
+ /*
+ * If we sent all, and more to send, then recurse to pick
+ * up the other half.
+ */
+ if ((n1 == n) && ring_full_consecutive(&netoring)) {
+ netflush();
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
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..6bff638
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c
@@ -0,0 +1,977 @@
+/*
+ * 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.18.2 2000/10/19 21:21:21 assar 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 (net >= FD_SETSIZE
+ || tout >= FD_SETSIZE
+ || tin >= FD_SETSIZE)
+ errx (1, "fd too large");
+
+ if (netout) {
+ FD_SET(net, &obits);
+ }
+ if (ttyout) {
+ FD_SET(tout, &obits);
+ }
+ if (ttyin) {
+ FD_SET(tin, &ibits);
+ }
+ if (netin) {
+ FD_SET(net, &ibits);
+ }
+#if !defined(SO_OOBINLINE)
+ if (netex) {
+ FD_SET(net, &xbits);
+ }
+#endif
+ if ((c = select(FD_SETSIZE, &ibits, &obits, &xbits,
+ (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
+ if (c == -1) {
+ /*
+ * we can get EINTR if we are in line mode,
+ * and the user does an escape (TSTP), or
+ * some other signal generator.
+ */
+ if (errno == EINTR) {
+ return 0;
+ }
+ /* I don't like this, does it ever happen? */
+ printf("sleep(5) from telnet, after select\r\n");
+ sleep(5);
+ }
+ return 0;
+ }
+
+ /*
+ * Any urgent data?
+ */
+ if (FD_ISSET(net, &xbits)) {
+ FD_CLR(net, &xbits);
+ SYNCHing = 1;
+ ttyflush(1); /* flush already enqueued data */
+ }
+
+ /*
+ * Something to read from the network...
+ */
+ if (FD_ISSET(net, &ibits)) {
+ int canread;
+
+ FD_CLR(net, &ibits);
+ canread = ring_empty_consecutive(&netiring);
+#if !defined(SO_OOBINLINE)
+ /*
+ * In 4.2 (and some early 4.3) systems, the
+ * OOB indication and data handling in the kernel
+ * is such that if two separate TCP Urgent requests
+ * come in, one byte of TCP data will be overlaid.
+ * This is fatal for Telnet, but we try to live
+ * with it.
+ *
+ * In addition, in 4.2 (and...), a special protocol
+ * is needed to pick up the TCP Urgent data in
+ * the correct sequence.
+ *
+ * What we do is: if we think we are in urgent
+ * mode, we look to see if we are "at the mark".
+ * If we are, we do an OOB receive. If we run
+ * this twice, we will do the OOB receive twice,
+ * but the second will fail, since the second
+ * time we were "at the mark", but there wasn't
+ * any data there (the kernel doesn't reset
+ * "at the mark" until we do a normal read).
+ * Once we've read the OOB data, we go ahead
+ * and do normal reads.
+ *
+ * There is also another problem, which is that
+ * since the OOB byte we read doesn't put us
+ * out of OOB state, and since that byte is most
+ * likely the TELNET DM (data mark), we would
+ * stay in the TELNET SYNCH (SYNCHing) state.
+ * So, clocks to the rescue. If we've "just"
+ * received a DM, then we test for the
+ * presence of OOB data when the receive OOB
+ * fails (and AFTER we did the normal mode read
+ * to clear "at the mark").
+ */
+ if (SYNCHing) {
+ int atmark;
+ static int bogus_oob = 0, first = 1;
+
+ ioctl(net, SIOCATMARK, (char *)&atmark);
+ if (atmark) {
+ c = recv(net, netiring.supply, canread, MSG_OOB);
+ if ((c == -1) && (errno == EINVAL)) {
+ c = recv(net, netiring.supply, canread, 0);
+ if (clocks.didnetreceive < clocks.gotDM) {
+ SYNCHing = stilloob();
+ }
+ } else if (first && c > 0) {
+ /*
+ * Bogosity check. Systems based on 4.2BSD
+ * do not return an error if you do a second
+ * recv(MSG_OOB). So, we do one. If it
+ * succeeds and returns exactly the same
+ * data, then assume that we are running
+ * on a broken system and set the bogus_oob
+ * flag. (If the data was different, then
+ * we probably got some valid new data, so
+ * increment the count...)
+ */
+ int i;
+ i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
+ if (i == c &&
+ memcmp(netiring.supply, netiring.supply + c, i) == 0) {
+ bogus_oob = 1;
+ first = 0;
+ } else if (i < 0) {
+ bogus_oob = 0;
+ first = 0;
+ } else
+ c += i;
+ }
+ if (bogus_oob && c > 0) {
+ int i;
+ /*
+ * Bogosity. We have to do the read
+ * to clear the atmark to get out of
+ * an infinate loop.
+ */
+ i = read(net, netiring.supply + c, canread - c);
+ if (i > 0)
+ c += i;
+ }
+ } else {
+ c = recv(net, netiring.supply, canread, 0);
+ }
+ } else {
+ c = recv(net, netiring.supply, canread, 0);
+ }
+ settimer(didnetreceive);
+#else /* !defined(SO_OOBINLINE) */
+ c = recv(net, (char *)netiring.supply, canread, 0);
+#endif /* !defined(SO_OOBINLINE) */
+ if (c < 0 && errno == EWOULDBLOCK) {
+ c = 0;
+ } else if (c <= 0) {
+ return -1;
+ }
+ if (netdata) {
+ Dump('<', netiring.supply, c);
+ }
+ if (c)
+ ring_supplied(&netiring, c);
+ returnValue = 1;
+ }
+
+ /*
+ * Something to read from the tty...
+ */
+ if (FD_ISSET(tin, &ibits)) {
+ FD_CLR(tin, &ibits);
+ c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
+ if (c < 0 && errno == EIO)
+ c = 0;
+ if (c < 0 && errno == EWOULDBLOCK) {
+ c = 0;
+ } else {
+ /* EOF detection for line mode!!!! */
+ if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
+ /* must be an EOF... */
+ *ttyiring.supply = termEofChar;
+ c = 1;
+ }
+ if (c <= 0) {
+ return -1;
+ }
+ if (termdata) {
+ Dump('<', ttyiring.supply, c);
+ }
+ ring_supplied(&ttyiring, c);
+ }
+ returnValue = 1; /* did something useful */
+ }
+
+ if (FD_ISSET(net, &obits)) {
+ FD_CLR(net, &obits);
+ returnValue |= netflush();
+ }
+ if (FD_ISSET(tout, &obits)) {
+ FD_CLR(tout, &obits);
+ returnValue |= (ttyflush(SYNCHing|flushout) > 0);
+ }
+
+ return returnValue;
+}
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..0c883d6
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: telnet_locl.h,v 1.18 1999/12/02 16:58:34 joda 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..ab281a5
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnet/utilities.c
@@ -0,0 +1,866 @@
+/*
+ * 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.22.2.1 2000/10/10 13:10:27 assar 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) {
+ strlcpy(NetTraceFile, file, sizeof(NetTraceFile));
+ return;
+ }
+ fprintf(stderr, "Cannot open %s.\n", file);
+ }
+ NetTrace = stdout;
+ strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile));
+}
+
+void
+Dump(char direction, unsigned char *buffer, int length)
+{
+# define BYTES_PER_LINE 32
+ unsigned char *pThis;
+ int offset;
+
+ offset = 0;
+
+ while (length) {
+ /* print one line */
+ fprintf(NetTrace, "%c 0x%x\t", direction, offset);
+ pThis = buffer;
+ if (prettydump) {
+ buffer = buffer + min(length, BYTES_PER_LINE/2);
+ while (pThis < buffer) {
+ fprintf(NetTrace, "%c%.2x",
+ (((*pThis)&0xff) == 0xff) ? '*' : ' ',
+ (*pThis)&0xff);
+ pThis++;
+ }
+ length -= BYTES_PER_LINE/2;
+ offset += BYTES_PER_LINE/2;
+ } else {
+ buffer = buffer + min(length, BYTES_PER_LINE);
+ while (pThis < buffer) {
+ fprintf(NetTrace, "%.2x", (*pThis)&0xff);
+ pThis++;
+ }
+ length -= BYTES_PER_LINE;
+ offset += BYTES_PER_LINE;
+ }
+ if (NetTrace == stdout) {
+ fprintf(NetTrace, "\r\n");
+ } else {
+ fprintf(NetTrace, "\n");
+ }
+ if (length < 0) {
+ fflush(NetTrace);
+ return;
+ }
+ /* find next unique line */
+ }
+ fflush(NetTrace);
+}
+
+
+void
+printoption(char *direction, int cmd, int option)
+{
+ if (!showoptions)
+ return;
+ if (cmd == IAC) {
+ if (TELCMD_OK(option))
+ fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
+ else
+ fprintf(NetTrace, "%s IAC %d", direction, option);
+ } else {
+ char *fmt;
+ fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
+ (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
+ if (fmt) {
+ fprintf(NetTrace, "%s %s ", direction, fmt);
+ if (TELOPT_OK(option))
+ fprintf(NetTrace, "%s", TELOPT(option));
+ else if (option == TELOPT_EXOPL)
+ fprintf(NetTrace, "EXOPL");
+ else
+ fprintf(NetTrace, "%d", option);
+ } else
+ fprintf(NetTrace, "%s %d %d", direction, cmd, option);
+ }
+ if (NetTrace == stdout) {
+ fprintf(NetTrace, "\r\n");
+ fflush(NetTrace);
+ } else {
+ fprintf(NetTrace, "\n");
+ }
+ return;
+}
+
+void
+optionstatus(void)
+{
+ int i;
+ 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 (tout >= FD_SETSIZE)
+ ExitString("fd too large", 1);
+
+ if (TTYBYTES() == 0) {
+ FD_SET(tout, &outs);
+ select(tout+1, 0, &outs, 0,
+ (struct timeval *) 0); /* wait for TTLOWAT */
+ } else {
+ while (TTYBYTES()) {
+ ttyflush(0);
+ FD_SET(tout, &outs);
+ select(tout+1, 0, &outs, 0,
+ (struct timeval *) 0); /* wait for TTLOWAT */
+ }
+ }
+}
+
+void
+SetForExit(void)
+{
+ setconnmode(0);
+ do {
+ telrcv(); /* Process any incoming data */
+ EmptyTerminal();
+ } while (ring_full_count(&netiring)); /* While there is any */
+ setcommandmode();
+ fflush(stdout);
+ fflush(stderr);
+ setconnmode(0);
+ EmptyTerminal(); /* Flush the path to the tty */
+ setcommandmode();
+}
+
+void
+Exit(int returnCode)
+{
+ SetForExit();
+ exit(returnCode);
+}
+
+void
+ExitString(char *string, int returnCode)
+{
+ SetForExit();
+ fwrite(string, 1, strlen(string), stderr);
+ exit(returnCode);
+}
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..ec5f2dc
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/authenc.c
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "telnetd.h"
+
+RCSID("$Id: authenc.c,v 1.9 1999/09/05 19:14:50 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)
+{
+ return ttloop();
+}
+
+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..8f5edf1
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/ext.h
@@ -0,0 +1,202 @@
+/*
+ * 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.19 1999/09/05 19:15:21 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);
+int getterminaltype (char *name, size_t);
+void _gettermname (void);
+int terminaltypeok (char *s);
+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);
+int 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..2477c42
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/sys_term.c
@@ -0,0 +1,1893 @@
+/*
+ * 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.89.2.6 2000/12/08 23:34:05 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;
+ strlcpy(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
+ strlcpy(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
+ */
+ wtmp.ut_time = time(NULL);
+ 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()
+ *
+ * We only accept the environment variables listed below.
+ */
+
+static void
+scrub_env(void)
+{
+ static const char *reject[] = {
+ "TERMCAP=/",
+ NULL
+ };
+
+ static const char *accept[] = {
+ "XAUTH=", "XAUTHORITY=", "DISPLAY=",
+ "TERM=",
+ "EDITOR=",
+ "PAGER=",
+ "PRINTER=",
+ "LOGNAME=",
+ "POSIXLY_CORRECT=",
+ "TERMCAP=",
+ NULL
+ };
+
+ char **cpp, **cpp2;
+ const char **p;
+
+ for (cpp2 = cpp = environ; *cpp; cpp++) {
+ int reject_it = 0;
+
+ for(p = reject; *p; p++)
+ if(strncmp(*cpp, *p, strlen(*p)) == 0) {
+ reject_it = 1;
+ break;
+ }
+ if (reject_it)
+ continue;
+
+ for(p = accept; *p; p++)
+ if(strncmp(*cpp, *p, strlen(*p)) == 0)
+ break;
+ if(*p != NULL)
+ *cpp2++ = *cpp;
+ }
+ *cpp2 = NULL;
+}
+
+
+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 utmpx, *non_save_utxp;
+ 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;
+ non_save_utxp = getutxline(&utmpx);
+ if (non_save_utxp) {
+ struct utmpx *utxp;
+ char user0;
+
+ utxp = malloc(sizeof(struct utmpx));
+ *utxp = *non_save_utxp;
+ user0 = utxp->ut_user[0];
+ 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
+ utxp->ut_user[0] = user0;
+ 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
+ wtmp.ut_time = time(NULL);
+ write(f, &wtmp, sizeof(wtmp));
+ close(f);
+ }
+ }
+#endif
+ free (utxp);
+ }
+ 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
+ u->ut_time = time(NULL);
+ 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
+ wtmp.ut_time = time(NULL);
+ 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..0c2750e
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.c
@@ -0,0 +1,1399 @@
+/*
+ * 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.58.2.1 2000/10/10 13:12:08 assar 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;
+
+static 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
+ ;
+
+static void doit(struct sockaddr*, int);
+
+int
+main(int argc, char **argv)
+{
+ struct sockaddr_storage __ss;
+ struct sockaddr *sa = (struct sockaddr *)&__ss;
+ int on = 1, sa_size;
+ 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)) != -1) {
+ 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);
+ sa_size = sizeof (__ss);
+ if (getpeername(STDIN_FILENO, sa, &sa_size) < 0) {
+ fprintf(stderr, "%s: ", progname);
+ perror("getpeername");
+ _exit(1);
+ }
+ if (keepalive &&
+ setsockopt(STDIN_FILENO, 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
+ && sa->sa_family == AF_INET
+ && (setsockopt(STDIN_FILENO, 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 = STDIN_FILENO;
+ doit(sa, sa_size);
+ /* NOTREACHED */
+ return 0;
+} /* end of main */
+
+static void
+usage(void)
+{
+ 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)) {
+ strlcpy(first, terminaltype, sizeof(first));
+ for(;;) {
+ /*
+ * Save the unknown name, and request the next name.
+ */
+ strlcpy(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.
+ */
+static void
+doit(struct sockaddr *who, int who_len)
+{
+ char *host = NULL;
+ struct hostent *hp = NULL;
+ int level;
+ int ptynum;
+ char user_name[256];
+ int error;
+ char host_addr[256];
+ void *addr;
+ int addr_sz;
+ const char *tmp;
+ int af;
+
+ /*
+ * 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 */
+
+ af = who->sa_family;
+ switch (af) {
+ case AF_INET : {
+ struct sockaddr_in *sin = (struct sockaddr_in *)who;
+
+ addr = &sin->sin_addr;
+ addr_sz = sizeof(sin->sin_addr);
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)who;
+
+ addr = &sin6->sin6_addr;
+ addr_sz = sizeof(sin6->sin6_addr);
+ break;
+ }
+#endif
+ default :
+ fatal (net, "Unknown address family\r\n");
+ break;
+ }
+
+ hp = getipnodebyaddr (addr, addr_sz, af, &error);
+
+ 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 != NULL) {
+ host = hp->h_name;
+ }
+
+ tmp = inet_ntop(af, addr, host_addr, sizeof(host_addr));
+ if (tmp == NULL)
+ strlcpy (host_addr, "unknown address", sizeof(host_addr));
+
+ if (host == NULL)
+ host = host_addr;
+
+ /*
+ * We must make a copy because Kerberos is probably going
+ * to also do a gethost* and overwrite the static data...
+ */
+ strlcpy(remote_host_name, host, sizeof(remote_host_name));
+ if (hp != NULL)
+ freehostent (hp);
+ 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))
+ strlcpy(remote_host_name,
+ host_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);
+
+ if (f >= FD_SETSIZE
+ || p >= FD_SETSIZE)
+ fatal(net, "fd too large");
+
+ /*
+ * 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..c89ce0e
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)telnetd.h 8.1 (Berkeley) 6/4/93
+ */
+/* $FreeBSD$ */
+
+
+#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"
+
+#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
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+
+#include "ext.h"
+
+#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 <openssl/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..ff5192e
--- /dev/null
+++ b/crypto/kerberosIV/appl/telnet/telnetd/utility.c
@@ -0,0 +1,1165 @@
+/*
+ * 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.22.2.1 2000/10/10 13:12:34 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.
+ *
+ * return 0 if OK or 1 if interrupted by a signal.
+ */
+
+int
+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) {
+ if (errno == EINTR)
+ return 1;
+ syslog(LOG_INFO, "ttloop: read: %m\n");
+ exit(1);
+ } else if (ncc == 0) {
+ syslog(LOG_INFO, "ttloop: peer died\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();
+ }
+ return 0;
+} /* 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;
+
+ if (s >= FD_SETSIZE)
+ fatal(ourpty, "fd too large");
+
+ 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)
+ strlcpy (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