summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/appl/bsd
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/appl/bsd')
-rw-r--r--crypto/kerberosIV/appl/bsd/Makefile.in135
-rw-r--r--crypto/kerberosIV/appl/bsd/README.login20
-rw-r--r--crypto/kerberosIV/appl/bsd/bsd_locl.h380
-rw-r--r--crypto/kerberosIV/appl/bsd/encrypt.c311
-rw-r--r--crypto/kerberosIV/appl/bsd/forkpty.c461
-rw-r--r--crypto/kerberosIV/appl/bsd/iruserok.c279
-rw-r--r--crypto/kerberosIV/appl/bsd/kcmd.c270
-rw-r--r--crypto/kerberosIV/appl/bsd/klogin.c184
-rw-r--r--crypto/kerberosIV/appl/bsd/krcmd.c117
-rw-r--r--crypto/kerberosIV/appl/bsd/login.c990
-rw-r--r--crypto/kerberosIV/appl/bsd/login_access.c221
-rw-r--r--crypto/kerberosIV/appl/bsd/login_fbtab.c144
-rw-r--r--crypto/kerberosIV/appl/bsd/pathnames.h191
-rw-r--r--crypto/kerberosIV/appl/bsd/rcmd_util.c246
-rw-r--r--crypto/kerberosIV/appl/bsd/rcp.c1019
-rw-r--r--crypto/kerberosIV/appl/bsd/rcp_util.c97
-rw-r--r--crypto/kerberosIV/appl/bsd/rlogin.c707
-rw-r--r--crypto/kerberosIV/appl/bsd/rlogind.c934
-rw-r--r--crypto/kerberosIV/appl/bsd/rsh.c353
-rw-r--r--crypto/kerberosIV/appl/bsd/rshd.c635
-rw-r--r--crypto/kerberosIV/appl/bsd/stty_default.c105
-rw-r--r--crypto/kerberosIV/appl/bsd/su.c452
-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.c192
-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.c75
-rw-r--r--crypto/kerberosIV/appl/bsd/utmp_login.c121
-rw-r--r--crypto/kerberosIV/appl/bsd/utmpx_login.c88
30 files changed, 8890 insertions, 0 deletions
diff --git a/crypto/kerberosIV/appl/bsd/Makefile.in b/crypto/kerberosIV/appl/bsd/Makefile.in
new file mode 100644
index 0000000..57a8108
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/Makefile.in
@@ -0,0 +1,135 @@
+# $Id: Makefile.in,v 1.56 1997/05/20 20:35:04 assar Exp $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+topdir = ../..
+
+CC = @CC@
+AR = ar
+RANLIB = @RANLIB@
+DEFS = @DEFS@ -DBINDIR='"$(bindir)"'
+CFLAGS = @CFLAGS@
+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 iruserok.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
+
+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
+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
+su_OBJS = su.o
+rshd_OBJS = rshd.o iruserok.o encrypt.o rcmd_util.o
+rlogind_OBJS = rlogind.o iruserok.o forkpty.o encrypt.o rcmd_util.o tty.o
+
+
+all: $(PROGS)
+
+Wall:
+ make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__"
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $<
+
+install: all
+ $(MKINSTALLDIRS) $(libexecdir)
+ for x in $(PROG_LIBEXEC); do \
+ $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ done
+ $(MKINSTALLDIRS) $(bindir)
+ for x in $(PROG_BIN); do \
+ $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+ -for x in $(PROG_SUIDBIN); do \
+ $(INSTALL_PROGRAM) -o root -m 04555 $$x $(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+
+uninstall:
+ for x in $(PROG_LIBEXEC); do \
+ rm -f $(libexecdir)/`echo $$x| sed '$(transform)'`; \
+ done
+ for x in $(PROG_BIN); do \
+ rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \
+ done
+ for x in $(PROG_SUIDBIN); do \
+ rm -f $(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
+
+dist: $(DISTFILES)
+ for file in $(DISTFILES); do \
+ ln $$file ../`cat ../.fname`/lib \
+ || cp -p $$file ../`cat ../.fname`/lib; \
+ done
+
+KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes
+KLIB_AFS=@KRB_KAFS_LIB@ $(KLIB)
+OTPLIB=-L../../lib/otp -lotp
+LIBROKEN=-L../../lib/roken -lroken
+
+rcp$(EXECSUFFIX): $(rcp_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rcp_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+rsh$(EXECSUFFIX): $(rsh_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rsh_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+rshd$(EXECSUFFIX): $(rshd_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rshd_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+rlogin$(EXECSUFFIX): $(rlogin_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogin_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+rlogind$(EXECSUFFIX): $(rlogind_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogind_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
+
+login$(EXECSUFFIX): $(login_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(login_OBJS) $(OTPLIB) $(KLIB_AFS) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN)
+
+su$(EXECSUFFIX): $(su_OBJS)
+ $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(su_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN)
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..d0b37aa
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/bsd_locl.h
@@ -0,0 +1,380 @@
+/*
+ * 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: bsd_locl.h,v 1.98 1997/05/25 01:14:17 assar Exp $ */
+
+#define LOGALL
+#define KERBEROS
+#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 == 5) || 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 <stdarg.h>
+
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.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 != 4
+#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>
+#endif
+#ifndef UT_NAMESIZE
+#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name)
+#endif
+
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+
+#ifdef HAVE_USERPW_H
+#include <userpw.h>
+#endif /* HAVE_USERPW_H */
+
+#ifdef HAVE_USERSEC_H
+#include <usersec.h>
+#endif /* HAVE_USERSEC_H */
+
+#ifndef PRIO_PROCESS
+#define PRIO_PROCESS 0
+#endif
+
+#include <err.h>
+
+#include <roken.h>
+
+#ifdef SOCKS
+#include <socks.h>
+#endif
+
+#include <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);
+
+typedef struct {
+ int cnt;
+ char *buf;
+} BUF;
+
+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);
+
+#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(char *user, char *from);
+#ifndef HAVE_IRUSEROK
+int iruserok(u_int32_t raddr, int superuser, const char *ruser,
+ const char *luser);
+#endif
+void fatal(int f, const char *msg, int syserr);
+
+extern int LEFT_JUSTIFIED;
+int des_enc_read(int fd,char *buf,int len,des_key_schedule sched,
+ des_cblock *iv);
+int des_enc_write(int fd,char *buf,int len,des_key_schedule sched,
+ des_cblock *iv);
+
+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 == 4
+#include <sys/ttold.h>
+#endif
+
+#if defined(_AIX)
+#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);
+void prepare_utmp (struct utmp *utmp, char *tty, char *username,
+ char *hostname);
diff --git a/crypto/kerberosIV/appl/bsd/encrypt.c b/crypto/kerberosIV/appl/bsd/encrypt.c
new file mode 100644
index 0000000..b74f329
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/encrypt.c
@@ -0,0 +1,311 @@
+/* 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.3 1996/04/30 13:50:54 bg Exp $");
+
+#undef BSIZE
+
+/* used in des_read and des_write */
+#define MAXWRITE (1024*16)
+#define BSIZE (MAXWRITE+4)
+
+/* 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[BSIZE];
+ /* extra unencrypted data
+ * for when a block of 100 comes in but is des_read one byte at
+ * a time. */
+ static char unnet[BSIZE];
+ static 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 > MAXWRITE) len=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 > 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[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[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 > MAXWRITE)
+ {
+ j=0;
+ for (i=0; i<len; i+=k)
+ {
+ k=des_enc_write(fd,&(buf[i]),
+ ((len-i) > MAXWRITE)?MAXWRITE:(len-i),sched,iv);
+ 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..5c0aaaf
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/forkpty.c
@@ -0,0 +1,461 @@
+/*
+ * 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.
+ */
+
+#include "bsd_locl.h"
+
+#ifndef HAVE_FORKPTY
+
+RCSID("$Id: forkpty.c,v 1.52 1997/05/25 07:37:01 assar 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, 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 */
+ strcpy(pts_name, ptr1); /* Return name of slave */
+ 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, 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 == 4
+ /* 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;
+ strcpy (pts_name, p);
+ return fdm;
+ }
+ }
+#endif
+
+#ifdef STREAMSPTY
+ fdm = ptym_open_streams_flavor(pts_name, streams_pty);
+ if (fdm >= 0)
+ {
+ *streams_pty = 1;
+ return fdm;
+ }
+#endif
+
+ fdm = ptym_open_bsd_flavor(pts_name, streams_pty);
+ if (fdm >= 0)
+ {
+ *streams_pty = 0;
+ return fdm;
+ }
+
+#ifndef STREAMSPTY
+ fdm = ptym_open_streams_flavor(pts_name, 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 */
+ chown(pts_name, getuid(), gid);
+ chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);
+
+ if ( (fds = open(pts_name, O_RDWR)) < 0) {
+ close(fdm);
+ return(-1);
+ }
+ }
+ return(fds);
+}
+
+int
+forkpty(int *ptrfdm,
+ char *slave_name,
+ 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)
+ strcpy(slave_name, pts_name); /* Return name of slave */
+
+ 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 */
+ }
+}
+#endif /* HAVE_FORKPTY */
diff --git a/crypto/kerberosIV/appl/bsd/iruserok.c b/crypto/kerberosIV/appl/bsd/iruserok.c
new file mode 100644
index 0000000..8349d85
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/iruserok.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 1983, 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: iruserok.c,v 1.15 1997/03/23 04:54:00 assar Exp $");
+
+#ifndef HAVE_IRUSEROK
+
+int __check_rhosts_file = 1;
+char *__rcmd_errstr = 0;
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+static
+int
+__icheckhost(u_int32_t raddr, const char *lhost)
+{
+ struct hostent *hp;
+ u_long laddr;
+ char **pp;
+
+ /* Try for raw ip address first. */
+ if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
+ return (raddr == laddr);
+
+ /* Better be a hostname. */
+ if ((hp = gethostbyname(lhost)) == NULL)
+ return (0);
+
+ /* Spin through ip addresses. */
+ for (pp = hp->h_addr_list; *pp; ++pp)
+ if (memcmp(&raddr, *pp, sizeof(u_long)) == 0)
+ return (1);
+
+ /* No match. */
+ return (0);
+}
+
+#ifndef HAVE_INNETGR
+static int
+innetgr(const char *netgroup, const char *machine,
+ const char *user, const char *domain)
+{
+ return 0;
+}
+#endif
+
+/*
+ * Returns 0 if ok, -1 if not ok.
+ */
+static
+int
+__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser,
+ const char *ruser)
+{
+ char *user, *p;
+ int ch;
+ char buf[MaxHostNameLen + 128]; /* host + login */
+ char hname[MaxHostNameLen];
+ struct hostent *hp;
+ /* Presumed guilty until proven innocent. */
+ int userok = 0, hostok = 0;
+#ifdef HAVE_YP_GET_DEFAULT_DOMAIN
+ char *ypdomain;
+
+ if (yp_get_default_domain(&ypdomain))
+ ypdomain = NULL;
+#else
+#define ypdomain NULL
+#endif
+ /* We need to get the damn hostname back for netgroup matching. */
+ if ((hp = gethostbyaddr((char *)&raddr,
+ sizeof(u_long),
+ AF_INET)) == NULL)
+ return (-1);
+ strncpy(hname, hp->h_name, sizeof(hname));
+ hname[sizeof(hname) - 1] = '\0';
+
+ while (fgets(buf, sizeof(buf), hostf)) {
+ p = buf;
+ /* Skip lines that are too long. */
+ if (strchr(p, '\n') == NULL) {
+ while ((ch = getc(hostf)) != '\n' && ch != EOF);
+ continue;
+ }
+ if (*p == '\n' || *p == '#') {
+ /* comment... */
+ continue;
+ }
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ *p = isupper(*p) ? tolower(*p) : *p;
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' &&
+ *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+ /*
+ * Do +/- and +@/-@ checking. This looks really nasty,
+ * but it matches SunOS's behavior so far as I can tell.
+ */
+ switch(buf[0]) {
+ case '+':
+ if (!buf[1]) { /* '+' matches all hosts */
+ hostok = 1;
+ break;
+ }
+ if (buf[1] == '@') /* match a host by netgroup */
+ hostok = innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain);
+ else /* match a host by addr */
+ hostok = __icheckhost(raddr,(char *)&buf[1]);
+ break;
+ case '-': /* reject '-' hosts and all their users */
+ if (buf[1] == '@') {
+ if (innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain))
+ return(-1);
+ } else {
+ if (__icheckhost(raddr,(char *)&buf[1]))
+ return(-1);
+ }
+ break;
+ default: /* if no '+' or '-', do a simple match */
+ hostok = __icheckhost(raddr, buf);
+ break;
+ }
+ switch(*user) {
+ case '+':
+ if (!*(user+1)) { /* '+' matches all users */
+ userok = 1;
+ break;
+ }
+ if (*(user+1) == '@') /* match a user by netgroup */
+ userok = innetgr(user+2, NULL, (char *)ruser,
+ ypdomain);
+ else /* match a user by direct specification */
+ userok = !(strcmp(ruser, user+1));
+ break;
+ case '-': /* if we matched a hostname, */
+ if (hostok) { /* check for user field rejections */
+ if (!*(user+1))
+ return(-1);
+ if (*(user+1) == '@') {
+ if (innetgr(user+2, NULL,
+ (char *)ruser, ypdomain))
+ return(-1);
+ } else {
+ if (!strcmp(ruser, user+1))
+ return(-1);
+ }
+ }
+ break;
+ default: /* no rejections: try to match the user */
+ if (hostok)
+ userok = !(strcmp(ruser,*user ? user : luser));
+ break;
+ }
+ if (hostok && userok)
+ return(0);
+ }
+ return (-1);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver. When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok(u_int32_t raddr, int superuser, const char *ruser, const char *luser)
+{
+ char *cp;
+ struct stat sbuf;
+ struct passwd *pwd;
+ FILE *hostf;
+ uid_t uid;
+ int first;
+ char pbuf[MaxPathLen];
+
+ first = 1;
+ hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
+ fclose(hostf);
+ return (0);
+ }
+ fclose(hostf);
+ }
+ if (first == 1 && (__check_rhosts_file || superuser)) {
+ first = 0;
+ if ((pwd = k_getpwnam((char*)luser)) == NULL)
+ return (-1);
+ strcpy(pbuf, pwd->pw_dir);
+ strcat(pbuf, "/.rhosts");
+
+ /*
+ * Change effective uid while opening .rhosts. If root and
+ * reading an NFS mounted file system, can't read files that
+ * are protected read/write owner only.
+ */
+ uid = geteuid();
+ seteuid(pwd->pw_uid);
+ hostf = fopen(pbuf, "r");
+ seteuid(uid);
+
+ if (hostf == NULL)
+ return (-1);
+ /*
+ * If not a regular file, or is owned by someone other than
+ * user or root or if writeable by anyone but the owner, quit.
+ */
+ cp = NULL;
+ if (lstat(pbuf, &sbuf) < 0)
+ cp = ".rhosts lstat failed";
+ else if (!S_ISREG(sbuf.st_mode))
+ cp = ".rhosts not regular file";
+ else if (fstat(fileno(hostf), &sbuf) < 0)
+ cp = ".rhosts fstat failed";
+ else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+ cp = "bad .rhosts owner";
+ else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+ cp = ".rhosts writeable by other than owner";
+ /* If there were any problems, quit. */
+ if (cp) {
+ __rcmd_errstr = cp;
+ fclose(hostf);
+ return (-1);
+ }
+ goto again;
+ }
+ return (-1);
+}
+
+#endif /* !HAVE_IRUSEROK */
diff --git a/crypto/kerberosIV/appl/bsd/kcmd.c b/crypto/kerberosIV/appl/bsd/kcmd.c
new file mode 100644
index 0000000..9fa7ab2
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/kcmd.c
@@ -0,0 +1,270 @@
+/*
+ * 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.19 1997/05/02 14:27:42 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;
+
+ 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;
+
+ /* 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, hp->h_addr, 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 (hp->h_addr_list[1] != NULL) {
+ warn ("kcmd: connect (%s)",
+ inet_ntoa(sin.sin_addr));
+ hp->h_addr_list++;
+ memcpy(&sin.sin_addr,
+ hp->h_addr_list[0],
+ 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);
+ 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..321da64
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/klogin.c
@@ -0,0 +1,184 @@
+/*-
+ * 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.20 1997/05/02 14:27:42 assar Exp $");
+
+#ifdef KERBEROS
+
+#define VERIFY_SERVICE "rcmd"
+
+extern int notickets;
+extern char *krbtkfile_env;
+
+static char tkt_location[MaxPathLen];
+
+/*
+ * 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, 0) != 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);
+
+ kerror = krb_get_pw_in_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);
+
+ strncpy(savehost, krb_get_phost(localhost), sizeof(savehost));
+ savehost[sizeof(savehost)-1] = '\0';
+
+#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..c436f8d
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/login.c
@@ -0,0 +1,990 @@
+/*-
+ * 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"
+
+RCSID("$Id: login.c,v 1.104 1997/05/20 20:35:06 assar Exp $");
+
+#include <otp.h>
+
+#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;
+ int pid;
+ int wpid;
+
+ switch (pid = fork()) {
+ case -1:
+ warn("fork /bin/passwd");
+ sleepexit(1);
+ case 0:
+ execlp("/bin/passwd", "passwd", who->pw_name, (char *) 0);
+ _exit(1);
+ default:
+ while ((wpid = wait(&status)) != -1 && wpid != pid)
+ /* void */ ;
+ return (status);
+ }
+}
+
+#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;
+ OtpContext otp_ctx;
+ 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 (k_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:")) != EOF)
+ switch (ch) {
+ case 'a':
+ if (strcmp (optarg, "none") == 0)
+ auth_level = AUTH_NONE;
+ else if (strcmp (optarg, "otp") == 0)
+ auth_level = AUTH_OTP;
+ 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;
+ strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
+ 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;
+ strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
+ 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] [-a otp]"
+ "[-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;
+ }
+ strcpy(tbuf, username);
+
+ 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);
+
+ if (otp_challenge (&otp_ctx, username,
+ ss, sizeof(ss)) == 0)
+ snprintf (prompt, sizeof(prompt), "%s's %s Password: ",
+ username, ss);
+ else {
+ if (auth_level == AUTH_NONE)
+ snprintf(prompt, sizeof(prompt), "%s's Password: ",
+ username);
+ else {
+ char *s;
+
+ rval = 1;
+ s = otp_error(&otp_ctx);
+ if(s)
+ printf ("OTP: %s\n", s);
+ continue;
+ }
+ }
+
+ if (des_read_pw_string (passwd, sizeof(passwd) - 1, prompt, 0))
+ continue;
+ passwd[sizeof(passwd) - 1] = '\0';
+
+ /* Verify it somehow */
+
+ if (otp_verify_user (&otp_ctx, passwd) == 0)
+ rval = 0;
+ else 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;
+ if ((s = otp_error(&otp_ctx)))
+ printf ("OTP: %s\n", s);
+ }
+
+ 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 */
+ udb = getudbnam(pwd->pw_name);
+ if(udb == UDB_NULL){
+ warnx("Failed to get UDB entry.");
+ exit(1);
+ }
+ t = udb->ue_pcpulim[UDBRC_INTER];
+ if(t == 0 || t > maxcpu)
+ t = CPUUNLIM;
+ else
+ t *= 100 * CLOCKS_PER_SEC;
+
+ if(limit(C_PROC, 0, L_CPU, t) < 0)
+ warn("limit C_PROC");
+
+ t = udb->ue_jcpulim[UDBRC_INTER];
+ if(t == 0 || t > maxcpu)
+ t = CPUUNLIM;
+ else
+ t *= 100 * CLOCKS_PER_SEC;
+
+ if(limit(C_JOBPROCS, 0, L_CPU, t) < 0)
+ warn("limit C_JOBPROCS");
+
+ 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)
+ 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)
+ printf("Warning: your password expires on %s",
+ ctime(&pwd->pw_change));
+ 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)
+ printf("Warning: your account expires on %s",
+ ctime(&pwd->pw_expire));
+#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);
+
+ chown(ttyn, pwd->pw_uid,
+ (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+ chmod(ttyn, S_IRUSR | S_IWUSR | S_IWGRP);
+ 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')
+ strncpy(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->pw_name, 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);
+ signal(SIGTSTP, SIG_IGN);
+
+ tbuf[0] = '-';
+ strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
+ 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
+ /* 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);
+ }
+ }
+
+
+ /*
+ * 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];
+ k_setpag();
+ if(k_afs_cell_of_file(pwd->pw_dir, cell, sizeof(cell)) == 0)
+ k_afsklog(cell, 0);
+ k_afsklog(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
+rootterm(char *ttyn)
+{
+#ifndef HAVE_TTYENT_H
+ return (default_console == 0 || strcmp(default_console, ttyname(0)) == 0);
+#else
+ struct ttyent *t;
+
+ return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
+#endif
+}
+
+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) || defined(SYSV_SHADOW)
+ struct lastlog ll;
+ int fd;
+
+ 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) {
+ printf("Last login: %.*s ",
+ 24-5, ctime(&ll.ll_time));
+ 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) {
+ printf("Last login: %.*s ",
+ 24-5, ctime(&ll.ll_time));
+ 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));
+ time(&ll.ll_time);
+ 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..0e017b1
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/login_access.c
@@ -0,0 +1,221 @@
+ /*
+ * 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.15 1997/06/01 03:12:28 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
+
+static int list_match(char *list, char *item, int (*match_fn)(char *, char *));
+static int user_match(char *tok, char *string);
+static int from_match(char *tok, char *string);
+static int string_match(char *tok, char *string);
+
+/* login_access - match username/group and host/tty with access control file */
+
+int login_access(char *user, char *from)
+{
+ 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;
+
+ /*
+ * 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(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, from, from_match)
+ && list_match(users, user, 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, char *item, int (*match_fn)(char *, char *))
+{
+ 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);
+}
+
+/* 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, char *string)
+{
+ struct group *group;
+ int i;
+
+ /*
+ * If a token has the magic value "ALL" the match always succeeds.
+ * Otherwise, return YES if the token fully matches the username, or if
+ * the token is a group that contains the username.
+ */
+
+ 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 */
+ 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, char *string)
+{
+ 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..f7f53aa
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/login_fbtab.c
@@ -0,0 +1,144 @@
+/************************************************************************
+* 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.10 1997/06/01 03:12:54 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 {
+ strcpy(buf, path);
+ buf[pathlen - 1] = 0;
+ if ((dir = opendir(buf)) == 0) {
+ syslog(LOG_ERR, "%s: opendir(%s): %m", table, path);
+ } else {
+ while ((ent = readdir(dir)) != 0) {
+ if (strcmp(ent->d_name, ".") != 0
+ && strcmp(ent->d_name, "..") != 0) {
+ strcpy(buf + pathlen - 1, ent->d_name);
+ login_protect(table, buf, mask, uid, gid);
+ }
+ }
+ closedir(dir);
+ }
+ }
+}
diff --git a/crypto/kerberosIV/appl/bsd/pathnames.h b/crypto/kerberosIV/appl/bsd/pathnames.h
new file mode 100644
index 0000000..3c10bff
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/pathnames.h
@@ -0,0 +1,191 @@
+/*
+ * 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.23 1996/11/17 06:36:42 joda Exp $
+ */
+
+/******* 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_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
+
+/*
+ * 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_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..4669009
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rcmd_util.c
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: rcmd_util.c,v 1.15 1997/05/02 14:27:44 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 B38400
+ {B38400, 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);
+ warnx(fmt, args);
+ }
+ va_end(args);
+}
diff --git a/crypto/kerberosIV/appl/bsd/rcp.c b/crypto/kerberosIV/appl/bsd/rcp.c
new file mode 100644
index 0000000..6dfb472
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rcp.c
@@ -0,0 +1,1019 @@
+/*
+ * 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.43 1997/05/13 09:41:26 bg 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:prtx"
+
+static int errs, rem;
+static struct passwd *pwd;
+static u_short port;
+static uid_t userid;
+static int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+
+#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, local;
+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, &lslen) < 0)
+ err(1, "getsockname");
+ fslen = sizeof(struct sockaddr_in);
+ if (getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0)
+ err(1, "getpeername");
+ if ((r == NULL) || (*r == '\0'))
+ r = krb_realmofhost(h);
+ opts = KOPT_DO_MUTUAL;
+ if ((status = krb_sendauth(opts, rem, &ticket, SERVICE_NAME, h, r,
+ (unsigned long)getpid(), &msg_data, &cred,
+ schedule, &local,
+ &foreign, "KCMDV0.1")) != KSUCCESS)
+ 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, &lslen) < 0)
+ err(1, "getsockname");
+ fslen = sizeof(struct sockaddr_in);
+ if(getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0)
+ err(1, "getperrname");
+ k_getsockinst(rem, inst, sizeof(inst));
+ opts = KOPT_DO_MUTUAL;
+ if ((status = krb_recvauth(opts, rem, &ticket, SERVICE_NAME, inst,
+ &foreign, &local,
+ &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: "
+ strcpy (errbuf, RCPERR);
+ vsnprintf (errbuf + strlen(RCPERR), sizeof(errbuf) - strlen(RCPERR),
+ fmt, args);
+ strcat (errbuf, "\n");
+ 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];
+
+ if (!(dirp = opendir(name))) {
+ run_err("%s: %s", name, strerror(errno));
+ return;
+ }
+ last = strrchr(name, '/');
+ if (last == 0)
+ last = name;
+ else
+ last++;
+ if (pflag) {
+ snprintf(path, sizeof(path), "T%ld 0 %ld 0\n",
+ (long)statp->st_mtime, (long)statp->st_atime);
+ 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;
+again:
+ if (use_kerberos) {
+ 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) {
+ use_kerberos = 0;
+ port = get_shell_port(use_kerberos, 0);
+ if (errno == ECONNREFUSED)
+ oldw("remote host doesn't support Kerberos");
+ else if (errno == ENOENT)
+ oldw("can't provide Kerberos authentication data");
+ goto again;
+ }
+ } 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 = NULL;
+ }
+
+ 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], '@');
+ len = strlen(_PATH_RSH) + strlen(argv[i]) +
+ strlen(src) + (tuser ? strlen(tuser) : 0) +
+ strlen(thost) + strlen(targ) + CMDNEEDS + 20;
+ if (!(bp = malloc(len)))
+ err(1, " ");
+ if (host) {
+ *host++ = 0;
+ suser = argv[i];
+ if (*suser == '\0')
+ suser = pwd->pw_name;
+ else if (!okname(suser))
+ continue;
+ snprintf(bp, len,
+ "%s %s -l %s -n %s %s '%s%s%s:%s'",
+ _PATH_RSH, host, suser, cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
+ } else
+ snprintf(bp, len,
+ "exec %s %s -n %s %s '%s%s%s:%s'",
+ _PATH_RSH, argv[i], cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
+ 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);
+ 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) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '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(*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;
+#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;
+
+ set_progname(argv[0]);
+ fflag = tflag = 0;
+ while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
+ switch(ch) { /* User-visible flags. */
+ case 'K':
+ use_kerberos = 0;
+ break;
+ case 'k':
+ dest_realm = dst_realm_buf;
+ strncpy(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 '?':
+ 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);
+
+#ifndef __CYGWIN32__
+ if ((pwd = k_getpwuid(userid = getuid())) == NULL)
+ errx(1, "unknown user %d", (int)userid);
+#endif
+
+ rem = STDIN_FILENO; /* XXX */
+
+ if (fflag) { /* Follow "protocol", send data. */
+ if (doencrypt)
+ answer_auth();
+ response();
+ setuid(userid);
+ if (k_hasafs()) {
+ /* Sometimes we will need cell specific tokens
+ * to be able to read and write files, thus,
+ * the token stuff done in rshd might not
+ * suffice.
+ */
+ char cell[64];
+ if (k_afs_cell_of_file(pwd->pw_dir,
+ cell, sizeof(cell)) == 0)
+ k_afsklog(cell, 0);
+ k_afsklog(0, 0);
+ }
+ source(argc, argv);
+ exit(errs);
+ }
+
+ if (tflag) { /* Receive data. */
+ if (doencrypt)
+ answer_auth();
+ setuid(userid);
+ if (k_hasafs()) {
+ char cell[64];
+ if (k_afs_cell_of_file(pwd->pw_dir,
+ cell, sizeof(cell)) == 0)
+ k_afsklog(cell, 0);
+ k_afsklog(0, 0);
+ }
+ 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..6f0c5f0
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rcp_util.c
@@ -0,0 +1,97 @@
+/*-
+ * 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.7 1996/11/17 20:23:05 assar 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:
+ 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..27aa8f0
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rlogin.c
@@ -0,0 +1,707 @@
+/*
+ * 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.61 1997/05/25 01:14:47 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);
+ 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)) != EOF)
+ 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;
+ strncpy(dest_realm, optarg, REALM_SZ);
+ break;
+ case 'l':
+ user = optarg;
+ break;
+ case 'x':
+ doencrypt = 1;
+ break;
+ case 'p':
+ user_port = htons(atoi(optarg));
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ optind += argoff;
+ argc -= optind;
+ argv += optind;
+
+ /* if haven't gotten a host yet, do so */
+ if (!host && !(host = *argv++))
+ usage();
+
+ if (*argv)
+ 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);
+
+ try_connect:
+ if (use_kerberos) {
+ struct hostent *hp;
+
+ /* Fully qualify hostname (needed for krb_realmofhost). */
+ hp = gethostbyname(host);
+ if (hp != NULL && !(host = strdup(hp->h_name))) {
+ errno = ENOMEM;
+ err(1, NULL);
+ }
+
+ 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) {
+ use_kerberos = 0;
+ if (user_port == 0)
+ sv_port = get_login_port(use_kerberos,
+ doencrypt);
+ if (errno == ECONNREFUSED)
+ warning("remote host doesn't support Kerberos");
+ if (errno == ENOENT)
+ warning("can't provide Kerberos auth data");
+ goto try_connect;
+ }
+ } 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 */
+
+ 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..c5d80774
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rlogind.c
@@ -0,0 +1,934 @@
+/*-
+ * 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.100 1997/05/25 01:15:20 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
+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) {
+ strcpy(utxp->ut_user, "");
+ utxp->ut_type = DEAD_PROCESS;
+#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
+ gettimeofday(&utxp->ut_tv, NULL);
+ pututxline(utxp);
+#ifdef WTMPX_FILE
+ updwtmpx(WTMPX_FILE, utxp);
+#else
+ ret = 0;
+#endif
+ }
+ endutxent();
+ return ret;
+}
+#else
+static int
+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_UT_HOST
+ memset(ut.ut_host, 0, sizeof(ut.ut_host));
+#endif
+ time(&ut.ut_time);
+ 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_UT_HOST
+ strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+#endif
+#ifdef HAVE_UT_PID
+ ut.ut_pid = getpid();
+#endif
+#ifdef HAVE_UT_TYPE
+ if(name[0])
+ ut.ut_type = USER_PROCESS;
+ else
+ ut.ut_type = DEAD_PROCESS;
+#endif
+ time(&ut.ut_time);
+ 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)) != EOF)
+ 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;
+
+ pid = forkpty(&master, line, NULL, NULL);
+ 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
+ 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);
+ signal(SIGTSTP, SIG_IGN);
+ 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 == 5) || 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;
+
+ /*
+ * 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);
+
+ 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 (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..329ebf7
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rsh.c
@@ -0,0 +1,353 @@
+/*-
+ * 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.35 1997/03/30 18:20:22 joda 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] [-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;
+ if (!(args = malloc(cc)))
+ errx(1, "Out of memory.");
+ for (p = args, ap = argv; *ap; ++ap) {
+ strcpy(p, *ap);
+ for (p = strcpy(p, *ap); *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[BUFSIZ];
+
+ 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);
+ FD_SET(rem, &rembits);
+ if (select(16, 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);
+ FD_SET(rem, &readfrom);
+ FD_SET(rfd2, &readfrom);
+ do {
+ ready = readfrom;
+ if (select(16, &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;
+ 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 (!host && argc > 2 && argv[1][0] != '-') {
+ host = argv[1];
+ argoff = 1;
+ }
+
+#define OPTIONS "+8KLde:k:l:nwx"
+ while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
+ 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;
+ strncpy(dest_realm, optarg, REALM_SZ);
+ break;
+ case 'n':
+ nflag = nfork = 1;
+ break;
+ case 'x':
+ doencrypt = 1;
+ 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";
+ setuid(getuid());
+ execv(_PATH_RLOGIN, argv);
+ err(1, "can't exec %s", _PATH_RLOGIN);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+#ifndef __CYGWIN32__
+ if (!(pw = k_getpwuid(uid = getuid())))
+ errx(1, "unknown user id.");
+ 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);
+
+ sv_port=get_shell_port(use_kerberos, doencrypt);
+
+try_connect:
+ if (use_kerberos) {
+ 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) {
+ if (errno == ECONNREFUSED)
+ warning("remote host doesn't support Kerberos");
+ if (errno == ENOENT)
+ warning("can't provide Kerberos auth data");
+ use_kerberos = 0;
+ sv_port=get_shell_port(use_kerberos, doencrypt);
+ goto try_connect;
+ }
+ } 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
+
+ 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);
+
+ 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..75ca1df
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/rshd.c
@@ -0,0 +1,635 @@
+/*-
+ * 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.51 1997/05/13 09:42:39 bg 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)) != EOF)
+ 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[BUFSIZ];
+ char cmdbuf[NCARGS+1], locuser[16], remuser[16];
+ char remotehost[2 * MaxHostNameLen + 1];
+
+ 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("rlogind: 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]);
+
+ FD_ZERO(&readfrom);
+ FD_SET(s, &readfrom);
+ FD_SET(pv[0], &readfrom);
+ if (pv[0] > s)
+ nfd = pv[0];
+ else
+ nfd = s;
+ if (doencrypt) {
+ 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 */
+ setgid((gid_t)pwd->pw_gid);
+ initgroups(pwd->pw_name, pwd->pw_gid);
+ setuid((uid_t)pwd->pw_uid);
+ strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
+
+ /* Need to extend path to find rcp */
+ strncat(path, BINDIR, sizeof(path)-1);
+ strncat(path, ":", sizeof(path)-1);
+ strncat(path, _PATH_DEFPATH, sizeof(path)-1);
+ path[sizeof(path)-1] = '\0';
+
+ strncat(shell, pwd->pw_shell, sizeof(shell)-7);
+ strncat(username, pwd->pw_name, sizeof(username)-6);
+ cp = strrchr(pwd->pw_shell, '/');
+ if (cp)
+ cp++;
+ else
+ cp = pwd->pw_shell;
+ endpwent();
+ if (log_success || pwd->pw_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()) {
+ if (new_pag)
+ k_setpag(); /* Put users process in an new pag */
+ k_afsklog(0, 0);
+ }
+ execle(pwd->pw_shell, cp, "-c", cmdbuf, 0, envinit);
+ err(1, pwd->pw_shell);
+}
+
+/*
+ * 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..b7112c1
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/stty_default.c
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: stty_default.c,v 1.6 1997/04/01 08:17:17 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..8c610e1
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/su.c
@@ -0,0 +1,452 @@
+/*
+ * 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.59 1997/05/26 17:45:54 bg Exp $");
+
+#ifdef SYSV_SHADOW
+#include "sysv_shadow.h"
+#endif
+
+static int kerberos (char *username, char *user, 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 "Kflmi:"
+
+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];
+
+ set_progname (argv[0]);
+
+ asme = asthem = fastlogin = 0;
+ while ((ch = getopt (argc, argv, ARGSTR)) != EOF)
+ switch ((char) ch) {
+ case 'K':
+ use_kerberos = 0;
+ break;
+ case 'f':
+ fastlogin = 1;
+ break;
+ case 'l':
+ asme = 0;
+ asthem = 1;
+ break;
+ case 'm':
+ asme = 1;
+ asthem = 0;
+ break;
+ case 'i':
+ root_inst = optarg;
+ break;
+ case '?':
+ default:
+ fprintf (stderr,
+ "usage: su [-Kflm] [-i root-instance] [-] [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, 0);
+
+ /* 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 (asme)
+ if (pwd->pw_shell && *pwd->pw_shell)
+ shell = strcpy (shellbuf, pwd->pw_shell);
+ 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, 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))
+ errx (1, "initgroups failed.");
+
+ if (setuid (pwd->pw_uid) < 0)
+ err (1, "setuid");
+
+ if (!asme) {
+ if (asthem) {
+ char *k = getenv ("KRBTKFILE");
+ char *t = getenv ("TERM");
+
+ environ = malloc (10 * sizeof (char *));
+ 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) {
+ avshellbuf[0] = '-';
+ strcpy (avshellbuf + 1, avshell);
+ avshell = avshellbuf;
+ } else if (iscsh == YES) {
+ /* csh strips the first character... */
+ avshellbuf[0] = '_';
+ strcpy (avshellbuf + 1, 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 = k_afsklog (0, 0);
+ if (code != KSUCCESS && code != KDC_PR_UNKNOWN)
+ warnx ("afsklog: %s", krb_get_err_text (code));
+ }
+ 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, int uid)
+{
+ KTEXT_ST ticket;
+ AUTH_DAT authdata;
+ struct hostent *hp;
+ int kerno;
+ u_long faddr;
+ char lrealm[REALM_SZ], krbtkfile[MaxPathLen];
+ char hostname[MaxHostNameLen], savehost[MaxHostNameLen];
+
+ if (krb_get_lrealm (lrealm, 1) != KSUCCESS)
+ return (1);
+ if (koktologin (username, lrealm, user) && !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);
+ /*
+ * 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 (k_gethostname (hostname, sizeof (hostname)) == -1) {
+ warn ("gethostname");
+ dest_tkt ();
+ return (1);
+ }
+ strncpy (savehost, krb_get_phost (hostname), sizeof (savehost));
+ savehost[sizeof (savehost) - 1] = '\0';
+
+ kerno = krb_mk_req (&ticket, "rcmd", savehost, lrealm, 33);
+
+ 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);
+ }
+ }
+ 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..cb36b84
--- /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.9 1997/03/31 01:47:59 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 = "60";
+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(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..f5e782d
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/sysv_environ.c
@@ -0,0 +1,192 @@
+/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: sysv_environ.c,v 1.21 1997/05/14 17:34:15 joda 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;
+ long limit_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 = "";
+ k_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) {
+ 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..6839441
--- /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.7 1997/03/23 04:56:05 assar 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);
+
+ 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..4f07b49
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.h
@@ -0,0 +1,5 @@
+/* $Id: sysv_shadow.h,v 1.6 1997/03/23 04:55:51 assar Exp $ */
+
+#include <shadow.h>
+
+extern 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..3192426
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/tty.c
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: tty.c,v 1.2 1997/05/25 01:14:22 assar 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..da3f96a
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/utmp_login.c
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: utmp_login.c,v 1.13 1997/05/20 13:46:21 assar Exp $");
+
+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_UT_USER
+ strncpy(utmp->ut_user, username, sizeof(utmp->ut_user));
+# endif
+
+# ifdef HAVE_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_UT_HOST
+ strncpy(utmp->ut_host, hostname, sizeof(utmp->ut_host));
+# endif
+
+# ifdef HAVE_UT_TYPE
+ utmp->ut_type = USER_PROCESS;
+# endif
+
+# ifdef HAVE_UT_PID
+ utmp->ut_pid = getpid();
+# endif
+
+# ifdef HAVE_UT_ID
+ strncpy(utmp->ut_id, make_id(ttyx), sizeof(utmp->ut_id));
+# 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..005eca5
--- /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.20 1997/06/01 03:13:15 assar 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_UT_ID
+ strncpy(ut->ut_id, make_id(clean_tty), sizeof(ut->ut_id));
+#endif
+ strncpy(ut->ut_user, user, sizeof(ut->ut_user));
+ strncpy(ut->ut_host, host, sizeof(ut->ut_host));
+#ifdef HAVE_UT_SYSLEN
+ 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 */
OpenPOWER on IntegriCloud