diff options
Diffstat (limited to 'crypto/kerberosIV/appl')
134 files changed, 29588 insertions, 2625 deletions
diff --git a/crypto/kerberosIV/appl/Makefile.in b/crypto/kerberosIV/appl/Makefile.in index c951258..2cc8391 100644 --- a/crypto/kerberosIV/appl/Makefile.in +++ b/crypto/kerberosIV/appl/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.27 1997/05/20 18:58:37 bg Exp $ +# $Id: Makefile.in,v 1.31 1998/04/26 09:59:31 assar Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -7,8 +7,8 @@ SHELL = /bin/sh @SET_MAKE@ -SUBDIRS = sample kauth bsd movemail afsutil \ - kpopper xnlock kx otp @APPL_KIP_DIR@ ftp telnet +SUBDIRS = sample kauth bsd movemail push afsutil \ + popper xnlock kx @OTP_dir@ @APPL_KIP_DIR@ ftp telnet all: for i in $(SUBDIRS); \ @@ -40,4 +40,4 @@ realclean: for i in $(SUBDIRS); \ do (cd $$i && $(MAKE) $(MFLAGS) realclean); done -.PHONY: all install uninstall clean distclean realclean mostlyclean +.PHONY: all Wall install uninstall clean mostlyclean distclean realclean diff --git a/crypto/kerberosIV/appl/afsutil/Makefile.in b/crypto/kerberosIV/appl/afsutil/Makefile.in new file mode 100644 index 0000000..86adb88 --- /dev/null +++ b/crypto/kerberosIV/appl/afsutil/Makefile.in @@ -0,0 +1,89 @@ +# $Id: Makefile.in,v 1.27 1999/03/10 19:01:10 joda Exp $ + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +top_builddir = ../.. + +CC = @CC@ +LINK = @LINK@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ +LD_FLAGS= @LD_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LIBROKEN = -L../../lib/roken -lroken +LIBS = @KRB_KAFS_LIB@ -L../../lib/krb -lkrb -L../../lib/des -ldes $(LIBROKEN) @LIBS@ $(LIBROKEN) +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +bindir = @bindir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +PROG_BIN = pagsh$(EXECSUFFIX) \ + afslog$(EXECSUFFIX) \ + kstring2key$(EXECSUFFIX) +PROG_LIBEXEC = +PROGS = $(PROG_BIN) $(PROG_LIBEXEC) + +SOURCES = pagsh.c aklog.c kstring2key.c + +OBJECTS = pagsh.o aklog.o kstring2key.o + +all: $(PROGS) + +Wall: + make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +.c.o: + $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $< + +install: all + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) + for x in $(PROG_BIN); do \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROG_BIN); do \ + rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ + done + +TAGS: $(SOURCES) + etags $(SOURCES) + +check: + +clean: + rm -f *.a *.o $(PROGS) + +mostlyclean: clean + +distclean: clean + rm -f Makefile *.tab.c *~ + +realclean: distclean + rm -f TAGS + +pagsh$(EXECSUFFIX): pagsh.o + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ pagsh.o $(LIBS) + +afslog$(EXECSUFFIX): aklog.o + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ aklog.o $(LIBS) + +kstring2key$(EXECSUFFIX): kstring2key.o + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ kstring2key.o $(LIBS) + + +$(OBJECTS): ../../include/config.h + +.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean diff --git a/crypto/kerberosIV/appl/afsutil/aklog.c b/crypto/kerberosIV/appl/afsutil/aklog.c new file mode 100644 index 0000000..f3bcb8b --- /dev/null +++ b/crypto/kerberosIV/appl/afsutil/aklog.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 +#include <sys/ioctl.h> +#endif +#ifdef HAVE_SYS_IOCCOM_H +#include <sys/ioccom.h> +#endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#include <err.h> +#include <krb.h> +#include <kafs.h> + +#include <roken.h> + +RCSID("$Id: aklog.c,v 1.22.2.1 1999/07/22 03:13:22 assar Exp $"); + +static int debug = 0; + +static void +DEBUG(const char *, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + +static void +DEBUG(const char *fmt, ...) +{ + va_list ap; + if (debug) { + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); + } +} + +static char * +expand_cell_name(char *cell) +{ + FILE *f; + static char buf[128]; + char *p; + + f = fopen(_PATH_CELLSERVDB, "r"); + if(f == NULL) + return cell; + while(fgets(buf, sizeof(buf), f) != NULL) { + if(buf[0] == '>') { + for(p=buf; *p && !isspace(*p) && *p != '#'; p++) + ; + *p = '\0'; + if(strstr(buf, cell)){ + fclose(f); + return buf + 1; + } + } + buf[0] = 0; + } + fclose(f); + return cell; +} + +static int +createuser (char *cell) +{ + char cellbuf[64]; + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + char cmd[1024]; + + if (cell == NULL) { + FILE *f; + int len; + + f = fopen (_PATH_THISCELL, "r"); + if (f == NULL) + err (1, "open(%s)", _PATH_THISCELL); + if (fgets (cellbuf, sizeof(cellbuf), f) == NULL) + err (1, "read cellname from %s", _PATH_THISCELL); + fclose (f); + len = strlen(cellbuf); + if (cellbuf[len-1] == '\n') + cellbuf[len-1] = '\0'; + cell = cellbuf; + } + + if(krb_get_default_principal(name, instance, realm)) + errx (1, "Could not even figure out who you are"); + + snprintf (cmd, sizeof(cmd), + "pts createuser %s%s%s@%s -cell %s", + name, *instance ? "." : "", instance, strlwr(realm), + cell); + DEBUG("Executing %s", cmd); + return system(cmd); +} + +int +main(int argc, char **argv) +{ + int i; + int do_aklog = -1; + int do_createuser = -1; + char *cell = NULL; + char *realm = NULL; + char cellbuf[64]; + + set_progname (argv[0]); + + if(!k_hasafs()) + exit(1); + + for(i = 1; i < argc; i++){ + if(!strncmp(argv[i], "-createuser", 11)){ + do_createuser = do_aklog = 1; + + }else if(!strncmp(argv[i], "-c", 2) && i + 1 < argc){ + cell = expand_cell_name(argv[++i]); + do_aklog = 1; + + }else if(!strncmp(argv[i], "-k", 2) && i + 1 < argc){ + realm = argv[++i]; + + }else if(!strncmp(argv[i], "-p", 2) && i + 1 < argc){ + if(k_afs_cell_of_file(argv[++i], cellbuf, sizeof(cellbuf))) + errx (1, "No cell found for file \"%s\".", argv[i]); + else + cell = cellbuf; + do_aklog = 1; + + }else if(!strncmp(argv[i], "-unlog", 6)){ + exit(k_unlog()); + + }else if(!strncmp(argv[i], "-hosts", 6)){ + warnx ("Argument -hosts is not implemented."); + + }else if(!strncmp(argv[i], "-zsubs", 6)){ + warnx("Argument -zsubs is not implemented."); + + }else if(!strncmp(argv[i], "-noprdb", 6)){ + warnx("Argument -noprdb is not implemented."); + + }else if(!strncmp(argv[i], "-d", 6)){ + debug = 1; + + }else{ + if(!strcmp(argv[i], ".") || + !strcmp(argv[i], "..") || + strchr(argv[i], '/')){ + DEBUG("I guess that \"%s\" is a filename.", argv[i]); + if(k_afs_cell_of_file(argv[i], cellbuf, sizeof(cellbuf))) + errx (1, "No cell found for file \"%s\".", argv[i]); + else { + cell = cellbuf; + DEBUG("The file \"%s\" lives in cell \"%s\".", argv[i], cell); + } + }else{ + cell = expand_cell_name(argv[i]); + DEBUG("I guess that %s is cell %s.", argv[i], cell); + } + do_aklog = 1; + } + if(do_aklog == 1){ + do_aklog = 0; + if(krb_afslog(cell, realm)) + errx (1, "Failed getting tokens for cell %s in realm %s.", + cell?cell:"(local cell)", realm?realm:"(local realm)"); + } + if(do_createuser == 1) { + do_createuser = 0; + if(createuser(cell)) + errx (1, "Failed creating user in cell %s", cell?cell:"(local cell)"); + } + } + if(do_aklog == -1 && do_createuser == -1 && krb_afslog(0, realm)) + errx (1, "Failed getting tokens for cell %s in realm %s.", + cell?cell:"(local cell)", realm?realm:"(local realm)"); + return 0; +} diff --git a/crypto/kerberosIV/appl/afsutil/kstring2key.c b/crypto/kerberosIV/appl/afsutil/kstring2key.c new file mode 100644 index 0000000..30482f0 --- /dev/null +++ b/crypto/kerberosIV/appl/afsutil/kstring2key.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +RCSID("$Id: kstring2key.c,v 1.14 1998/06/09 19:24:14 joda Exp $"); + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <err.h> + +#include <roken.h> + +#include <des.h> +#include <krb.h> + +#define VERIFY 0 + +static void +usage(void) +{ + fprintf(stderr, + "Usage: %s [-c AFS cellname] [ -5 krb5salt ] [ password ]\n", + __progname); + fprintf(stderr, + " krb5salt is realmname APPEND principal APPEND instance\n"); + exit(1); +} + +static +void +krb5_string_to_key(char *str, + char *salt, + des_cblock *key) +{ + char *foo; + + asprintf(&foo, "%s%s", str, salt); + if (foo == NULL) + errx (1, "malloc: out of memory"); + des_string_to_key(foo, key); + free (foo); +} + + +int +main(int argc, char **argv) +{ + des_cblock key; + char buf[1024]; + char *cellname = 0, *salt = 0; + + set_progname (argv[0]); + + if (argc >= 3 && argv[1][0] == '-' && argv[1][1] == 'c') + { + cellname = argv[2]; + argv += 2; + argc -= 2; + } + else if (argc >= 3 && argv[1][0] == '-' && argv[1][1] == '5') + { + salt = argv[2]; + argv += 2; + argc -= 2; + } + if (argc >= 2 && argv[1][0] == '-') + usage(); + + switch (argc) { + case 1: + if (des_read_pw_string(buf, sizeof(buf)-1, "password: ", VERIFY)) + errx (1, "Error reading password."); + break; + case 2: + strcpy_truncate(buf, argv[1], sizeof(buf)); + break; + default: + usage(); + break; + } + + if (cellname != 0) + afs_string_to_key(buf, cellname, &key); + else if (salt != 0) + krb5_string_to_key(buf, salt, &key); + else + des_string_to_key(buf, &key); + + { + int j; + unsigned char *tkey = (unsigned char *) &key; + printf("ascii = "); + for(j = 0; j < 8; j++) + if(tkey[j] != '\\' && isalpha(tkey[j]) != 0) + printf("%c", tkey[j]); + else + printf("\\%03o",(unsigned char)tkey[j]); + printf("\n"); + printf("hex = "); + for(j = 0; j < 8; j++) + printf("%02x",(unsigned char)tkey[j]); + printf("\n"); + } + exit(0); +} diff --git a/crypto/kerberosIV/appl/afsutil/pagsh.c b/crypto/kerberosIV/appl/afsutil/pagsh.c new file mode 100644 index 0000000..1f02ee8 --- /dev/null +++ b/crypto/kerberosIV/appl/afsutil/pagsh.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +RCSID("$Id: pagsh.c,v 1.21 1999/03/11 13:56:55 joda Exp $"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <time.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#include <err.h> +#include <roken.h> + +#include <krb.h> +#include <kafs.h> + +int +main(int argc, char **argv) +{ + int f; + char tf[1024]; + char *p; + + char *path; + char **args; + int i; + + do { + snprintf(tf, sizeof(tf), "%s%u_%u", TKT_ROOT, (unsigned int)getuid(), + (unsigned int)(getpid()*time(0))); + f = open(tf, O_CREAT|O_EXCL|O_RDWR); + } while(f < 0); + close(f); + unlink(tf); + setenv("KRBTKFILE", tf, 1); + + i = 0; + + args = (char **) malloc((argc + 10)*sizeof(char *)); + if (args == NULL) + errx (1, "Out of memory allocating %lu bytes", + (unsigned long)((argc + 10)*sizeof(char *))); + + argv++; + + if(*argv == NULL) { + path = getenv("SHELL"); + if(path == NULL){ + struct passwd *pw = k_getpwuid(geteuid()); + path = strdup(pw->pw_shell); + } + } else { + if(strcmp(*argv, "-c") == 0) argv++; + path = strdup(*argv++); + } + if (path == NULL) + errx (1, "Out of memory copying path"); + + p=strrchr(path, '/'); + if(p) + args[i] = strdup(p+1); + else + args[i] = strdup(path); + + if (args[i++] == NULL) + errx (1, "Out of memory copying arguments"); + + while(*argv) + args[i++] = *argv++; + + args[i++] = NULL; + + if(k_hasafs()) + k_setpag(); + + execvp(path, args); + if (errno == ENOENT) { + char **sh_args = malloc ((i + 2) * sizeof(char *)); + int j; + + if (sh_args == NULL) + errx (1, "Out of memory copying sh arguments"); + for (j = 1; j < i; ++j) + sh_args[j + 2] = args[j]; + sh_args[0] = "sh"; + sh_args[1] = "-c"; + sh_args[2] = path; + execv ("/bin/sh", sh_args); + } + perror("execvp"); + exit(1); +} diff --git a/crypto/kerberosIV/appl/bsd/Makefile.in b/crypto/kerberosIV/appl/bsd/Makefile.in index 57a8108..fdda8c1 100644 --- a/crypto/kerberosIV/appl/bsd/Makefile.in +++ b/crypto/kerberosIV/appl/bsd/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.56 1997/05/20 20:35:04 assar Exp $ +# $Id: Makefile.in,v 1.68 1999/03/27 17:05:34 joda Exp $ SHELL = /bin/sh @@ -6,13 +6,15 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -topdir = ../.. +top_builddir = ../.. CC = @CC@ +LINK = @LINK@ AR = ar RANLIB = @RANLIB@ DEFS = @DEFS@ -DBINDIR='"$(bindir)"' -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ LD_FLAGS = @LD_FLAGS@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -39,19 +41,20 @@ PROG_LIBEXEC = rshd$(EXECSUFFIX) \ PROGS = $(PROG_SUIDBIN) $(PROG_BIN) $(PROG_LIBEXEC) SOURCES = rsh.c kcmd.c krcmd.c rlogin.c rcp.c rcp_util.c rshd.c \ - login.c klogin.c login_access.c su.c rlogind.c iruserok.c \ + login.c klogin.c login_access.c su.c rlogind.c \ login_fbtab.c forkpty.c sysv_default.c sysv_environ.c sysv_shadow.c \ - utmp_login.c utmpx_login.c stty_default.c encrypt.c rcmd_util.c tty.c + utmp_login.c utmpx_login.c stty_default.c encrypt.c rcmd_util.c tty.c \ + osfc2.c rsh_OBJS = rsh.o kcmd.o krcmd.o encrypt.o rcmd_util.o -rcp_OBJS = rcp.o rcp_util.o kcmd.o krcmd.o encrypt.o rcmd_util.o +rcp_OBJS = rcp.o rcp_util.o kcmd.o krcmd.o encrypt.o rcmd_util.o osfc2.o rlogin_OBJS = rlogin.o kcmd.o krcmd.o encrypt.o rcmd_util.o login_OBJS = login.o klogin.o login_fbtab.o login_access.o \ sysv_default.o sysv_environ.o sysv_shadow.o \ - utmp_login.o utmpx_login.o stty_default.o tty.o + utmp_login.o utmpx_login.o stty_default.o tty.o osfc2.o su_OBJS = su.o -rshd_OBJS = rshd.o iruserok.o encrypt.o rcmd_util.o -rlogind_OBJS = rlogind.o iruserok.o forkpty.o encrypt.o rcmd_util.o tty.o +rshd_OBJS = rshd.o encrypt.o rcmd_util.o osfc2.o +rlogind_OBJS = rlogind.o forkpty.o encrypt.o rcmd_util.o tty.o all: $(PROGS) @@ -60,30 +63,30 @@ Wall: make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" .c.o: - $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $< + $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $< install: all - $(MKINSTALLDIRS) $(libexecdir) + $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir) for x in $(PROG_LIBEXEC); do \ - $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \ done - $(MKINSTALLDIRS) $(bindir) + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) for x in $(PROG_BIN); do \ - $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x| sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \ done -for x in $(PROG_SUIDBIN); do \ - $(INSTALL_PROGRAM) -o root -m 04555 $$x $(bindir)/`echo $$x| sed '$(transform)'`; \ + $(INSTALL_PROGRAM) -o root -m 04555 $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \ done uninstall: for x in $(PROG_LIBEXEC); do \ - rm -f $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + rm -f $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \ done for x in $(PROG_BIN); do \ - rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \ + rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \ done for x in $(PROG_SUIDBIN); do \ - rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \ + rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \ done TAGS: $(SOURCES) @@ -102,34 +105,32 @@ distclean: clean realclean: distclean rm -f TAGS -dist: $(DISTFILES) - for file in $(DISTFILES); do \ - ln $$file ../`cat ../.fname`/lib \ - || cp -p $$file ../`cat ../.fname`/lib; \ - done - KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes KLIB_AFS=@KRB_KAFS_LIB@ $(KLIB) -OTPLIB=-L../../lib/otp -lotp +OTPLIB=@LIB_otp@ LIBROKEN=-L../../lib/roken -lroken +LIB_security=@LIB_security@ + rcp$(EXECSUFFIX): $(rcp_OBJS) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rcp_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rcp_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) $(LIB_security) rsh$(EXECSUFFIX): $(rsh_OBJS) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rsh_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rsh_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) rshd$(EXECSUFFIX): $(rshd_OBJS) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rshd_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rshd_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) $(LIB_security) rlogin$(EXECSUFFIX): $(rlogin_OBJS) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogin_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogin_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) rlogind$(EXECSUFFIX): $(rlogind_OBJS) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogind_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogind_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) login$(EXECSUFFIX): $(login_OBJS) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(login_OBJS) $(OTPLIB) $(KLIB_AFS) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(login_OBJS) $(OTPLIB) $(KLIB_AFS) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN) $(LIB_security) su$(EXECSUFFIX): $(su_OBJS) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(su_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(su_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean diff --git a/crypto/kerberosIV/appl/bsd/bsd_locl.h b/crypto/kerberosIV/appl/bsd/bsd_locl.h index d0b37aa..2731f03 100644 --- a/crypto/kerberosIV/appl/bsd/bsd_locl.h +++ b/crypto/kerberosIV/appl/bsd/bsd_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,7 +36,7 @@ * SUCH DAMAGE. */ -/* $Id: bsd_locl.h,v 1.98 1997/05/25 01:14:17 assar Exp $ */ +/* $Id: bsd_locl.h,v 1.109.2.1 1999/07/22 03:13:49 assar Exp $ */ #define LOGALL #define KERBEROS @@ -49,7 +49,7 @@ #endif /* Any better way to test NO_MOTD? */ -#if (SunOS == 5) || defined(__hpux) +#if (SunOS >= 50) || defined(__hpux) #define NO_MOTD #endif @@ -62,13 +62,20 @@ #include <stdlib.h> #include <ctype.h> #include <setjmp.h> +#include <limits.h> #include <stdarg.h> #include <errno.h> +#ifdef HAVE_IO_H +#include <io.h> +#endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif @@ -145,7 +152,7 @@ #include <netdb.h> #endif -#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4 +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 #include <sys/ioctl.h> #endif #ifdef HAVE_SYS_IOCCOM_H @@ -228,10 +235,10 @@ #ifdef HAVE_UTMP_H #include <utmp.h> -#endif #ifndef UT_NAMESIZE #define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name) #endif +#endif #ifdef HAVE_UTMPX_H #include <utmpx.h> @@ -242,9 +249,14 @@ #endif /* HAVE_USERPW_H */ #ifdef HAVE_USERSEC_H +struct aud_rec; #include <usersec.h> #endif /* HAVE_USERSEC_H */ +#ifdef HAVE_OSFC2 +#include "/usr/include/prot.h" +#endif + #ifndef PRIO_PROCESS #define PRIO_PROCESS 0 #endif @@ -255,6 +267,9 @@ #ifdef SOCKS #include <socks.h> +/* This doesn't belong here. */ +struct tm *localtime(const time_t *); +struct hostent *gethostbyname(const char *); #endif #include <des.h> @@ -289,6 +304,9 @@ int susystem(char *s, int userid); int forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp); +int forkpty_truncate(int *amaster, char *name, size_t name_sz, + struct termios *termp, struct winsize *winp); + #ifndef MODEMASK #define MODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) #endif @@ -310,11 +328,7 @@ extern char **environ; void sysv_newenv(int argc, char **argv, struct passwd *pwd, char *term, int pflag); -int login_access(char *user, char *from); -#ifndef HAVE_IRUSEROK -int iruserok(u_int32_t raddr, int superuser, const char *ruser, - const char *luser); -#endif +int login_access(struct passwd *user, char *from); void fatal(int f, const char *msg, int syserr); extern int LEFT_JUSTIFIED; @@ -323,6 +337,10 @@ int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, des_cblock *iv); +/* used in des_read and des_write */ +#define DES_RW_MAXWRITE (1024*16) +#define DES_RW_BSIZE (DES_RW_MAXWRITE+4) + void sysv_defaults(void); void utmp_login(char *tty, char *username, char *hostname); void sleepexit (int); @@ -342,11 +360,11 @@ void sleepexit (int); #ifndef _POSIX_VDISABLE #define _POSIX_VDISABLE 0 #endif /* _POSIX_VDISABLE */ -#if SunOS == 4 +#if SunOS == 40 #include <sys/ttold.h> #endif -#if defined(_AIX) +#if defined(HAVE_SYS_TERMIO_H) && !defined(HAVE_TERMIOS_H) #include <sys/termio.h> #endif @@ -376,5 +394,9 @@ __attribute__ ((format (printf, 1, 2))) char *clean_ttyname (char *tty); char *make_id (char *tty); +#ifdef HAVE_UTMP_H void prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname); +#endif + +int do_osfc2_magic(uid_t); diff --git a/crypto/kerberosIV/appl/bsd/encrypt.c b/crypto/kerberosIV/appl/bsd/encrypt.c index b74f329..9f835c6 100644 --- a/crypto/kerberosIV/appl/bsd/encrypt.c +++ b/crypto/kerberosIV/appl/bsd/encrypt.c @@ -46,13 +46,7 @@ #include "bsd_locl.h" -RCSID("$Id: encrypt.c,v 1.3 1996/04/30 13:50:54 bg Exp $"); - -#undef BSIZE - -/* used in des_read and des_write */ -#define MAXWRITE (1024*16) -#define BSIZE (MAXWRITE+4) +RCSID("$Id: encrypt.c,v 1.4 1999/06/17 18:47:26 assar Exp $"); /* replacements for htonl and ntohl since I have no idea what to do * when faced with machines with 8 byte longs. */ @@ -78,11 +72,11 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock { /* data to be unencrypted */ int net_num=0; - unsigned char net[BSIZE]; + unsigned char net[DES_RW_BSIZE]; /* extra unencrypted data * for when a block of 100 comes in but is des_read one byte at * a time. */ - static char unnet[BSIZE]; + static char unnet[DES_RW_BSIZE]; static int unnet_start=0; static int unnet_left=0; int i; @@ -114,7 +108,7 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock } /* We need to get more data. */ - if (len > MAXWRITE) len=MAXWRITE; + if (len > DES_RW_MAXWRITE) len=DES_RW_MAXWRITE; /* first - get the length */ net_num=0; @@ -133,7 +127,7 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock /* num should be rounded up to the next group of eight * we make sure that we have read a multiple of 8 bytes from the net. */ - if ((num > MAXWRITE) || (num < 0)) /* error */ + if ((num > DES_RW_MAXWRITE) || (num < 0)) /* error */ return(-1); rnum=(num < 8)?8:((num+7)/8*8); @@ -172,7 +166,7 @@ des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock * FIXED - Should be ok now 18-9-90 - eay */ if (len < rnum) { - char tmpbuf[BSIZE]; + char tmpbuf[DES_RW_BSIZE]; if (des_rw_mode & DES_PCBC_MODE) des_pcbc_encrypt((des_cblock *)net, @@ -223,7 +217,7 @@ des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cbloc { long rnum; int i,j,k,outnum; - char outbuf[BSIZE+HDRSIZE]; + char outbuf[DES_RW_BSIZE+HDRSIZE]; char shortbuf[8]; char *p; static int start=1; @@ -237,13 +231,13 @@ des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cbloc } /* lets recurse if we want to send the data in small chunks */ - if (len > MAXWRITE) + if (len > DES_RW_MAXWRITE) { j=0; for (i=0; i<len; i+=k) { k=des_enc_write(fd,&(buf[i]), - ((len-i) > MAXWRITE)?MAXWRITE:(len-i),sched,iv); + ((len-i) > DES_RW_MAXWRITE)?DES_RW_MAXWRITE:(len-i),sched,iv); if (k < 0) return(k); else diff --git a/crypto/kerberosIV/appl/bsd/forkpty.c b/crypto/kerberosIV/appl/bsd/forkpty.c index 5c0aaaf..0ab7ef2 100644 --- a/crypto/kerberosIV/appl/bsd/forkpty.c +++ b/crypto/kerberosIV/appl/bsd/forkpty.c @@ -40,7 +40,7 @@ #ifndef HAVE_FORKPTY -RCSID("$Id: forkpty.c,v 1.52 1997/05/25 07:37:01 assar Exp $"); +RCSID("$Id: forkpty.c,v 1.53.2.2 1999/08/19 13:37:16 assar Exp $"); /* Only CRAY is known to have problems with forkpty(). */ #if defined(CRAY) @@ -150,7 +150,9 @@ pty_scan_tty(char *buf, size_t sz) } static int -ptym_open_streams_flavor(char *pts_name, int *streams_pty) +ptym_open_streams_flavor(char *pts_name, + size_t pts_name_sz, + int *streams_pty) { /* Try clone device master ptys */ const char *const clone[] = { "/dev/ptc", "/dev/ptmx", @@ -166,7 +168,8 @@ ptym_open_streams_flavor(char *pts_name, int *streams_pty) if (fdm >= 0) { char *ptr1; if ((ptr1 = ptsname(fdm)) != NULL) /* Get slave's name */ - strcpy(pts_name, ptr1); /* Return name of slave */ + /* Return name of slave */ + strcpy_truncate(pts_name, ptr1, pts_name_sz); else { close(fdm); return(-4); @@ -185,7 +188,7 @@ ptym_open_streams_flavor(char *pts_name, int *streams_pty) } static int -ptym_open_bsd_flavor(char *pts_name, int *streams_pty) +ptym_open_bsd_flavor(char *pts_name, size_t pts_name_sz, int *streams_pty) { int fdm; char ptm[MaxPathLen]; @@ -196,7 +199,7 @@ ptym_open_bsd_flavor(char *pts_name, int *streams_pty) fdm = open(ptm, O_RDWR); if (fdm < 0) continue; -#if SunOS == 4 +#if SunOS == 40 /* Avoid a bug in SunOS4 ttydriver */ if (fdm > 0) { int pgrp; @@ -265,14 +268,14 @@ ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty) char *p = _getpty(&fdm, O_RDWR, 0600, 1); if (p) { *streams_pty = 1; - strcpy (pts_name, p); + strcpy_truncate (pts_name, p, pts_name_sz); return fdm; } } #endif #ifdef STREAMSPTY - fdm = ptym_open_streams_flavor(pts_name, streams_pty); + fdm = ptym_open_streams_flavor(pts_name, pts_name_sz, streams_pty); if (fdm >= 0) { *streams_pty = 1; @@ -280,7 +283,7 @@ ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty) } #endif - fdm = ptym_open_bsd_flavor(pts_name, streams_pty); + fdm = ptym_open_bsd_flavor(pts_name, pts_name_sz, streams_pty); if (fdm >= 0) { *streams_pty = 0; @@ -288,7 +291,7 @@ ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty) } #ifndef STREAMSPTY - fdm = ptym_open_streams_flavor(pts_name, streams_pty); + fdm = ptym_open_streams_flavor(pts_name, pts_name_sz, streams_pty); if (fdm >= 0) { *streams_pty = 1; @@ -363,8 +366,10 @@ ptys_open(int fdm, char *pts_name, int streams_pty) gid = -1; /* group tty is not in the group file */ /* Grant access to slave */ - chown(pts_name, getuid(), gid); - chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP); + if (chown(pts_name, getuid(), gid) < 0) + fatal(0, "chown slave tty failed", 1); + if (chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP) < 0) + fatal(0, "chmod slave tty failed", 1); if ( (fds = open(pts_name, O_RDWR)) < 0) { close(fdm); @@ -375,10 +380,11 @@ ptys_open(int fdm, char *pts_name, int streams_pty) } int -forkpty(int *ptrfdm, - char *slave_name, - struct termios *slave_termios, - struct winsize *slave_winsize) +forkpty_truncate(int *ptrfdm, + char *slave_name, + size_t slave_name_sz, + struct termios *slave_termios, + struct winsize *slave_winsize) { int fdm, fds, streams_pty; pid_t pid; @@ -391,7 +397,8 @@ forkpty(int *ptrfdm, return -1; if (slave_name != NULL) - strcpy(slave_name, pts_name); /* Return name of slave */ + /* Return name of slave */ + strcpy_truncate(slave_name, pts_name, slave_name_sz); pid = fork(); if (pid < 0) @@ -458,4 +465,18 @@ forkpty(int *ptrfdm, return(pid); /* Parent returns pid of child */ } } + +int +forkpty(int *ptrfdm, + char *slave_name, + struct termios *slave_termios, + struct winsize *slave_winsize) +{ + return forkpty_truncate (ptrfdm, + slave_name, + MaxPathLen, + slave_termios, + slave_winsize); +} + #endif /* HAVE_FORKPTY */ diff --git a/crypto/kerberosIV/appl/bsd/kcmd.c b/crypto/kerberosIV/appl/bsd/kcmd.c index 9fa7ab2..af20357 100644 --- a/crypto/kerberosIV/appl/bsd/kcmd.c +++ b/crypto/kerberosIV/appl/bsd/kcmd.c @@ -33,7 +33,7 @@ #include "bsd_locl.h" -RCSID("$Id: kcmd.c,v 1.19 1997/05/02 14:27:42 assar Exp $"); +RCSID("$Id: kcmd.c,v 1.20 1998/07/13 13:54:07 assar Exp $"); #define START_PORT 5120 /* arbitrary */ @@ -100,6 +100,7 @@ kcmd(int *sock, int rc; char *host_save; int status; + char **h_addr_list; pid = getpid(); hp = gethostbyname(*ahost); @@ -112,6 +113,7 @@ kcmd(int *sock, if (host_save == NULL) return -1; *ahost = host_save; + h_addr_list = hp->h_addr_list; /* If realm is null, look up from table */ if (realm == NULL || realm[0] == '\0') @@ -127,7 +129,7 @@ kcmd(int *sock, return (-1); } sin.sin_family = hp->h_addrtype; - memcpy (&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); + memcpy (&sin.sin_addr, h_addr_list[0], sizeof(sin.sin_addr)); sin.sin_port = rport; if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) break; @@ -144,12 +146,12 @@ kcmd(int *sock, timo *= 2; continue; } - if (hp->h_addr_list[1] != NULL) { + if (h_addr_list[1] != NULL) { warn ("kcmd: connect (%s)", inet_ntoa(sin.sin_addr)); - hp->h_addr_list++; + h_addr_list++; memcpy(&sin.sin_addr, - hp->h_addr_list[0], + *h_addr_list, sizeof(sin.sin_addr)); fprintf(stderr, "Trying %s...\n", inet_ntoa(sin.sin_addr)); diff --git a/crypto/kerberosIV/appl/bsd/klogin.c b/crypto/kerberosIV/appl/bsd/klogin.c index 321da64..41002dc 100644 --- a/crypto/kerberosIV/appl/bsd/klogin.c +++ b/crypto/kerberosIV/appl/bsd/klogin.c @@ -33,7 +33,7 @@ #include "bsd_locl.h" -RCSID("$Id: klogin.c,v 1.20 1997/05/02 14:27:42 assar Exp $"); +RCSID("$Id: klogin.c,v 1.24 1999/03/15 13:34:12 bg Exp $"); #ifdef KERBEROS @@ -44,6 +44,63 @@ extern char *krbtkfile_env; static char tkt_location[MaxPathLen]; +static int +multiple_get_tkt(char *name, + char *instance, + char *realm, + char *service, + char *sinstance, + int life, + char *password) +{ + int n; + char rlm[256]; +#define ERICSSON_COMPAT 1 +#ifdef ERICSSON_COMPAT + FILE *f; + + f = fopen("/etc/krb.localrealms", "r"); + if (f != NULL) { + while (fgets(rlm, sizeof(rlm), f) != NULL) { + if (rlm[strlen(rlm) - 1] == '\n') + rlm[strlen(rlm) - 1] = '\0'; + + if (krb_get_pw_in_tkt(name, + instance, + rlm, + service, + realm, + life, + password) == KSUCCESS) { + fclose(f); + return KSUCCESS; + } + } + return krb_get_pw_in_tkt(name, + instance, + realm, + service, + realm, + life, + password); + } +#endif + /* First try to verify against the supplied realm. */ + if (krb_get_pw_in_tkt(name, instance, realm, service, realm, life, password) + == KSUCCESS) + return KSUCCESS; + + /* Verify all local realms, except the supplied realm. */ + for (n = 1; krb_get_lrealm(rlm, n) == KSUCCESS; n++) + if (strcmp(rlm, realm) != 0) + if (krb_get_pw_in_tkt(name, instance, rlm,service, realm, life, password) + == KSUCCESS) + return KSUCCESS; + + return KFAILURE; + +} + /* * Attempt to log the user in using Kerberos authentication * @@ -73,7 +130,7 @@ klogin(struct passwd *pw, char *instance, char *localhost, char *password) * without issuing any tickets. */ if (strcmp(pw->pw_name, "root") == 0 || - krb_get_lrealm(realm, 0) != KSUCCESS) + krb_get_lrealm(realm, 1) != KSUCCESS) return (1); noticketsdontcomplain = 0; /* enable warning message */ @@ -96,9 +153,25 @@ klogin(struct passwd *pw, char *instance, char *localhost, char *password) krbtkfile_env = tkt_location; krb_set_tkt_string(tkt_location); - kerror = krb_get_pw_in_tkt(pw->pw_name, instance, - realm, KRB_TICKET_GRANTING_TICKET, realm, - DEFAULT_TKT_LIFE, password); + /* + * Set real as well as effective ID to 0 for the moment, + * to make the kerberos library do the right thing. + */ + if (setuid(0) < 0) { + warnx("setuid"); + return (1); + } + + /* + * Get ticket + */ + kerror = multiple_get_tkt(pw->pw_name, + instance, + realm, + KRB_TICKET_GRANTING_TICKET, + realm, + DEFAULT_TKT_LIFE, + password); /* * If we got a TGT, get a local "rcmd" ticket and check it so as to @@ -121,8 +194,7 @@ klogin(struct passwd *pw, char *instance, char *localhost, char *password) if (chown(TKT_FILE, pw->pw_uid, pw->pw_gid) < 0) syslog(LOG_ERR, "chown tkfile (%s): %m", TKT_FILE); - strncpy(savehost, krb_get_phost(localhost), sizeof(savehost)); - savehost[sizeof(savehost)-1] = '\0'; + strcpy_truncate(savehost, krb_get_phost(localhost), sizeof(savehost)); #ifdef KLOGIN_PARANOID /* diff --git a/crypto/kerberosIV/appl/bsd/login.c b/crypto/kerberosIV/appl/bsd/login.c index c436f8d..702c5ff 100644 --- a/crypto/kerberosIV/appl/bsd/login.c +++ b/crypto/kerberosIV/appl/bsd/login.c @@ -38,10 +38,18 @@ */ #include "bsd_locl.h" +#ifdef HAVE_CAPABILITY_H +#include <capability.h> +#endif +#ifdef HAVE_SYS_CAPABILITY_H +#include <sys/capability.h> +#endif -RCSID("$Id: login.c,v 1.104 1997/05/20 20:35:06 assar Exp $"); +RCSID("$Id: login.c,v 1.120.2.2 1999/09/02 08:55:26 joda Exp $"); +#ifdef OTP #include <otp.h> +#endif #include "sysv_default.h" #ifdef SYSV_SHADOW @@ -93,22 +101,20 @@ static char rusername[100], lusername[100]; static int change_passwd(struct passwd *who) { - int status; - int pid; - int wpid; + int status; + pid_t pid; - switch (pid = fork()) { - case -1: - warn("fork /bin/passwd"); - sleepexit(1); - case 0: - execlp("/bin/passwd", "passwd", who->pw_name, (char *) 0); - _exit(1); - default: - while ((wpid = wait(&status)) != -1 && wpid != pid) - /* void */ ; - return (status); - } + switch (pid = fork()) { + case -1: + warn("fork /bin/passwd"); + sleepexit(1); + case 0: + execlp("/bin/passwd", "passwd", who->pw_name, (char *) 0); + _exit(1); + default: + waitpid(pid, &status, 0); + return (status); + } } #ifndef NO_MOTD /* message of the day stuff */ @@ -177,7 +183,9 @@ main(int argc, char **argv) char localhost[MaxHostNameLen]; char full_hostname[MaxHostNameLen]; int auth_level = AUTH_NONE; +#ifdef OTP OtpContext otp_ctx; +#endif int mask = 022; /* Default umask (set below) */ int maxtrys = 5; /* Default number of allowed failed logins */ @@ -210,7 +218,7 @@ main(int argc, char **argv) *full_hostname = '\0'; domain = NULL; - if (k_gethostname(localhost, sizeof(localhost)) < 0) + if (gethostname(localhost, sizeof(localhost)) < 0) syslog(LOG_ERR, "couldn't get local hostname: %m"); else domain = strchr(localhost, '.'); @@ -222,8 +230,10 @@ main(int argc, char **argv) case 'a': if (strcmp (optarg, "none") == 0) auth_level = AUTH_NONE; +#ifdef OTP else if (strcmp (optarg, "otp") == 0) auth_level = AUTH_OTP; +#endif else warnx ("bad value for -a: %s", optarg); break; @@ -240,7 +250,9 @@ main(int argc, char **argv) if (uid) errx(1, "-h option: %s", strerror(EPERM)); hflag = 1; - strncpy(full_hostname, optarg, sizeof(full_hostname)-1); + strcpy_truncate(full_hostname, + optarg, + sizeof(full_hostname)); if (domain && (p = strchr(optarg, '.')) && strcasecmp(p, domain) == 0) *p = 0; @@ -263,7 +275,9 @@ main(int argc, char **argv) exit(1); } rflag = 1; - strncpy(full_hostname, optarg, sizeof(full_hostname)-1); + strcpy_truncate(full_hostname, + optarg, + sizeof(full_hostname)); if (domain && (p = strchr(optarg, '.')) && strcasecmp(p, domain) == 0) *p = 0; @@ -275,8 +289,11 @@ main(int argc, char **argv) if (!uid) syslog(LOG_ERR, "invalid flag %c", ch); fprintf(stderr, - "usage: login [-fp] [-a otp]" - "[-h hostname | -r hostname] [username]\n"); + "usage: login [-fp]" +#ifdef OTP + " [-a otp]" +#endif + " [-h hostname | -r hostname] [username]\n"); exit(1); } argc -= optind; @@ -366,7 +383,7 @@ main(int argc, char **argv) badlogin(tbuf); failures = 0; } - strcpy(tbuf, username); + strcpy_truncate(tbuf, username, sizeof(tbuf)); pwd = paranoid_getpwnam (username); @@ -394,11 +411,14 @@ main(int argc, char **argv) setpriority(PRIO_PROCESS, 0, -4); +#ifdef OTP if (otp_challenge (&otp_ctx, username, ss, sizeof(ss)) == 0) snprintf (prompt, sizeof(prompt), "%s's %s Password: ", username, ss); - else { + else +#endif + { if (auth_level == AUTH_NONE) snprintf(prompt, sizeof(prompt), "%s's Password: ", username); @@ -406,9 +426,11 @@ main(int argc, char **argv) char *s; rval = 1; +#ifdef OTP s = otp_error(&otp_ctx); if(s) printf ("OTP: %s\n", s); +#endif continue; } } @@ -419,9 +441,12 @@ main(int argc, char **argv) /* Verify it somehow */ +#ifdef OTP if (otp_verify_user (&otp_ctx, passwd) == 0) rval = 0; - else if (pwd == NULL) + else +#endif + if (pwd == NULL) ; else if (auth_level == AUTH_NONE) { uid_t pwd_uid = pwd->pw_uid; @@ -445,8 +470,10 @@ main(int argc, char **argv) char *s; rval = 1; +#ifdef OTP if ((s = otp_error(&otp_ctx))) printf ("OTP: %s\n", s); +#endif } memset (passwd, 0, sizeof(passwd)); @@ -507,28 +534,45 @@ main(int argc, char **argv) struct udb *udb; long t; const long maxcpu = 46116860184; /* some random constant */ + + if(setjob(pwd->pw_uid, 0) < 0) + warn("setjob"); + udb = getudbnam(pwd->pw_name); - if(udb == UDB_NULL){ - warnx("Failed to get UDB entry."); - exit(1); - } + if(udb == UDB_NULL) + errx(1, "Failed to get UDB entry."); + + /* per process cpu limit */ t = udb->ue_pcpulim[UDBRC_INTER]; if(t == 0 || t > maxcpu) t = CPUUNLIM; else - t *= 100 * CLOCKS_PER_SEC; + t *= CLK_TCK; if(limit(C_PROC, 0, L_CPU, t) < 0) - warn("limit C_PROC"); + warn("limit process cpu"); + /* per process memory limit */ + if(limit(C_PROC, 0, L_MEM, udb->ue_pmemlim[UDBRC_INTER]) < 0) + warn("limit process memory"); + + /* per job cpu limit */ t = udb->ue_jcpulim[UDBRC_INTER]; if(t == 0 || t > maxcpu) t = CPUUNLIM; else - t *= 100 * CLOCKS_PER_SEC; + t *= CLK_TCK; + + if(limit(C_JOB, 0, L_CPU, t) < 0) + warn("limit job cpu"); + + /* per job processor limit */ + if(limit(C_JOB, 0, L_CPROC, udb->ue_jproclim[UDBRC_INTER]) < 0) + warn("limit job processors"); - if(limit(C_JOBPROCS, 0, L_CPU, t) < 0) - warn("limit C_JOBPROCS"); + /* per job memory limit */ + if(limit(C_JOB, 0, L_MEM, udb->ue_jmemlim[UDBRC_INTER]) < 0) + warn("limit job memory"); nice(udb->ue_nice[UDBRC_INTER]); } @@ -590,9 +634,11 @@ main(int argc, char **argv) */ login_fbtab(tty, pwd->pw_uid, pwd->pw_gid); - chown(ttyn, pwd->pw_uid, - (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); - chmod(ttyn, S_IRUSR | S_IWUSR | S_IWGRP); + if (chown(ttyn, pwd->pw_uid, + (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid) < 0) + err(1, "chown tty failed"); + if (chmod(ttyn, S_IRUSR | S_IWUSR | S_IWGRP) < 0) + err(1, "chmod tty failed"); setgid(pwd->pw_gid); initgroups(username, pwd->pw_gid); @@ -608,7 +654,7 @@ main(int argc, char **argv) * that LD_* and IFS are never preserved. */ if (term[0] == '\0') - strncpy(term, stypeof(tty), sizeof(term)); + strcpy_truncate(term, stypeof(tty), sizeof(term)); /* set up a somewhat censored environment. */ sysv_newenv(argc, argv, pwd, term, pflag); #ifdef KERBEROS @@ -620,12 +666,13 @@ main(int argc, char **argv) syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); /* If fflag is on, assume caller/authenticator has logged root login. */ - if (rootlogin && fflag == 0) + if (rootlogin && fflag == 0) { if (hostname) syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", username, tty, hostname); else syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty); + } #ifdef KERBEROS if (!quietlog && notickets == 1 && !noticketsdontcomplain) @@ -668,7 +715,7 @@ main(int argc, char **argv) #endif /* NO_MOTD */ #ifdef LOGIN_ACCESS - if (login_access(pwd->pw_name, hostname ? full_hostname : tty) == 0) { + if (login_access(pwd, hostname ? full_hostname : tty) == 0) { printf("Permission denied\n"); if (hostname) syslog(LOG_NOTICE, "%s LOGIN REFUSED FROM %s", @@ -683,11 +730,12 @@ main(int argc, char **argv) signal(SIGALRM, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGINT, SIG_DFL); +#ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); +#endif - tbuf[0] = '-'; - strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ? - p + 1 : pwd->pw_shell); + p = strrchr(pwd->pw_shell, '/'); + snprintf (tbuf, sizeof(tbuf), "-%s", p ? p + 1 : pwd->pw_shell); #ifdef HAVE_SETLOGIN if (setlogin(pwd->pw_name) < 0) @@ -703,6 +751,35 @@ main(int argc, char **argv) spwd = getspnam (username); endspent (); #endif + /* perhaps work some magic */ + if(do_osfc2_magic(pwd->pw_uid)) + sleepexit(1); +#if defined(HAVE_SGI_GETCAPABILITYBYNAME) && defined(HAVE_CAP_SET_PROC) + /* XXX SGI capability hack IRIX 6.x (x >= 0?) has something + called capabilities, that allow you to give away + permissions (such as chown) to specific processes. From 6.5 + this is default on, and the default capability set seems to + not always be the empty set. The problem is that the + runtime linker refuses to do just about anything if the + process has *any* capabilities set, so we have to remove + them here (unless otherwise instructed by /etc/capability). + In IRIX < 6.5, these functions was called sgi_cap_setproc, + etc, but we ignore this fact (it works anyway). */ + { + struct user_cap *ucap = sgi_getcapabilitybyname(pwd->pw_name); + cap_t cap; + if(ucap == NULL) + cap = cap_from_text("all="); + else + cap = cap_from_text(ucap->ca_default); + if(cap == NULL) + err(1, "cap_from_text"); + if(cap_set_proc(cap) < 0) + err(1, "cap_set_proc"); + cap_free(cap); + free(ucap); + } +#endif /* Discard permissions last so can't get killed and drop core. */ { int uid = rootlogin ? 0 : pwd->pw_uid; @@ -742,10 +819,18 @@ main(int argc, char **argv) if (k_hasafs()) { char cell[64]; +#ifdef _AIX + /* XXX this is a fix for a bug in AFS for AIX 4.3, w/o + this hack the kernel crashes on the following + pioctl... */ + char *pw_dir = strdup(pwd->pw_dir); +#else + char *pw_dir = pwd->pw_dir; +#endif k_setpag(); - if(k_afs_cell_of_file(pwd->pw_dir, cell, sizeof(cell)) == 0) - k_afsklog(cell, 0); - k_afsklog(0, 0); + if(k_afs_cell_of_file(pw_dir, cell, sizeof(cell)) == 0) + krb_afslog(cell, 0); + krb_afslog(0, 0); } execlp(pwd->pw_shell, tbuf, 0); @@ -768,46 +853,77 @@ main(int argc, char **argv) static void getloginname(int prompt) { - int ch; - char *p; - static char nbuf[NBUFSIZ]; - - for (;;) { - if (prompt) - if (ttyprompt && *ttyprompt) - printf("%s", ttyprompt); - else - printf("login: "); - prompt = 1; - for (p = nbuf; (ch = getchar()) != '\n'; ) { - if (ch == EOF) { - badlogin(username); - exit(0); - } - if (p < nbuf + (NBUFSIZ - 1)) - *p++ = ch; - } - if (p > nbuf) - if (nbuf[0] == '-') - warnx("login names may not start with '-'."); - else { - *p = '\0'; - username = nbuf; - break; - } + int ch; + char *p; + static char nbuf[NBUFSIZ]; + + for (;;) { + if (prompt) { + if (ttyprompt && *ttyprompt) + printf("%s", ttyprompt); + else + printf("login: "); + } + prompt = 1; + for (p = nbuf; (ch = getchar()) != '\n'; ) { + if (ch == EOF) { + badlogin(username); + exit(0); + } + if (p < nbuf + (NBUFSIZ - 1)) + *p++ = ch; + } + if (p > nbuf) { + if (nbuf[0] == '-') + warnx("login names may not start with '-'."); + else { + *p = '\0'; + username = nbuf; + break; + } } + } +} + +static int +find_in_etc_securetty (char *ttyn) +{ + FILE *f; + char buf[128]; + int ret = 0; + + f = fopen (_PATH_ETC_SECURETTY, "r"); + if (f == NULL) + return 0; + while (fgets(buf, sizeof(buf), f) != NULL) { + if(buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + if (strcmp (buf, ttyn) == 0) { + ret = 1; + break; + } + } + fclose(f); + return ret; } static int rootterm(char *ttyn) { -#ifndef HAVE_TTYENT_H - return (default_console == 0 || strcmp(default_console, ttyname(0)) == 0); -#else +#ifdef HAVE_TTYENT_H + { struct ttyent *t; - return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); + t = getttynam (ttyn); + if (t && t->ty_status & TTY_SECURE) + return 1; + } #endif + if (find_in_etc_securetty(ttyn)) + return 1; + if (default_console == 0 || strcmp(default_console, ttyn) == 0) + return 1; + return 0; } static RETSIGTYPE diff --git a/crypto/kerberosIV/appl/bsd/login_access.c b/crypto/kerberosIV/appl/bsd/login_access.c index 0e017b1..7b79dc8 100644 --- a/crypto/kerberosIV/appl/bsd/login_access.c +++ b/crypto/kerberosIV/appl/bsd/login_access.c @@ -9,7 +9,7 @@ #include "bsd_locl.h" -RCSID("$Id: login_access.c,v 1.15 1997/06/01 03:12:28 assar Exp $"); +RCSID("$Id: login_access.c,v 1.19 1999/05/14 22:02:14 assar Exp $"); #ifdef LOGIN_ACCESS @@ -23,15 +23,26 @@ static char sep[] = ", \t"; /* list-element separator */ #define YES 1 #define NO 0 -static int list_match(char *list, char *item, int (*match_fn)(char *, char *)); -static int user_match(char *tok, char *string); -static int from_match(char *tok, char *string); + /* + * A structure to bundle up all login-related information to keep the + * functional interfaces as generic as possible. + */ +struct login_info { + struct passwd *user; + char *from; +}; + +static int list_match(char *list, struct login_info *item, + int (*match_fn)(char *, struct login_info *)); +static int user_match(char *tok, struct login_info *item); +static int from_match(char *tok, struct login_info *item); static int string_match(char *tok, char *string); /* login_access - match username/group and host/tty with access control file */ -int login_access(char *user, char *from) +int login_access(struct passwd *user, char *from) { + struct login_info item; FILE *fp; char line[BUFSIZ]; char *perm; /* becomes permission field */ @@ -43,6 +54,12 @@ int login_access(char *user, char *from) char *foo; /* + * Bundle up the arguments to avoid unnecessary clumsiness lateron. + */ + item.user = user; + item.from = from; + + /* * Process the table one line at a time and stop at the first match. * Blank lines and lines that begin with a '#' character are ignored. * Non-comment lines are broken at the ':' character. All fields are @@ -60,7 +77,7 @@ int login_access(char *user, char *from) } if (line[0] == '#') continue; /* comment line */ - while (end > 0 && isspace(line[end - 1])) + while (end > 0 && isspace((unsigned char)line[end - 1])) end--; line[end] = 0; /* strip trailing whitespace */ if (line[0] == 0) /* skip blank lines */ @@ -81,8 +98,8 @@ int login_access(char *user, char *from) lineno); continue; } - match = (list_match(froms, from, from_match) - && list_match(users, user, user_match)); + match = (list_match(froms, &item, from_match) + && list_match(users, &item, user_match)); } fclose(fp); } else if (errno != ENOENT) { @@ -94,7 +111,9 @@ int login_access(char *user, char *from) /* list_match - match an item against a list of tokens with exceptions */ static int -list_match(char *list, char *item, int (*match_fn)(char *, char *)) +list_match(char *list, + struct login_info *item, + int (*match_fn)(char *, struct login_info *)) { char *tok; int match = NO; @@ -126,6 +145,19 @@ list_match(char *list, char *item, int (*match_fn)(char *, char *)) return (NO); } +/* myhostname - figure out local machine name */ + +static char *myhostname(void) +{ + static char name[MAXHOSTNAMELEN + 1] = ""; + + if (name[0] == 0) { + gethostname(name, sizeof(name)); + name[MAXHOSTNAMELEN] = 0; + } + return (name); +} + /* netgroup_match - match group against machine or user */ static int netgroup_match(char *group, char *machine, char *user) @@ -144,22 +176,32 @@ static int netgroup_match(char *group, char *machine, char *user) /* user_match - match a username against one token */ -static int user_match(char *tok, char *string) +static int user_match(char *tok, struct login_info *item) { + char *string = item->user->pw_name; + struct login_info fake_item; struct group *group; int i; + char *at; /* * If a token has the magic value "ALL" the match always succeeds. - * Otherwise, return YES if the token fully matches the username, or if - * the token is a group that contains the username. + * Otherwise, return YES if the token fully matches the username, if the + * token is a group that contains the username, or if the token is the + * name of the user's primary group. */ - if (tok[0] == '@') { /* netgroup */ + if ((at = strchr(tok + 1, '@')) != 0) { /* split user@host pattern */ + *at = 0; + fake_item.from = myhostname(); + return (user_match(tok, item) && from_match(at + 1, &fake_item)); + } else if (tok[0] == '@') { /* netgroup */ return (netgroup_match(tok + 1, (char *) 0, string)); } else if (string_match(tok, string)) { /* ALL or exact match */ return (YES); } else if ((group = getgrnam(tok)) != 0) { /* try group membership */ + if (item->user->pw_gid == group->gr_gid) + return (YES); for (i = 0; group->gr_mem[i]; i++) if (strcasecmp(string, group->gr_mem[i]) == 0) return (YES); @@ -169,8 +211,9 @@ static int user_match(char *tok, char *string) /* from_match - match a host or tty against a list of tokens */ -static int from_match(char *tok, char *string) +static int from_match(char *tok, struct login_info *item) { + char *string = item->from; int tok_len; int str_len; diff --git a/crypto/kerberosIV/appl/bsd/login_fbtab.c b/crypto/kerberosIV/appl/bsd/login_fbtab.c index f7f53aa..f831909 100644 --- a/crypto/kerberosIV/appl/bsd/login_fbtab.c +++ b/crypto/kerberosIV/appl/bsd/login_fbtab.c @@ -58,7 +58,7 @@ #include "bsd_locl.h" -RCSID("$Id: login_fbtab.c,v 1.10 1997/06/01 03:12:54 assar Exp $"); +RCSID("$Id: login_fbtab.c,v 1.13 1999/01/14 00:37:59 assar Exp $"); void login_protect (char *, char *, int, uid_t, gid_t); void login_fbtab (char *tty, uid_t uid, gid_t gid); @@ -126,15 +126,25 @@ login_protect(char *table, char *path, int mask, uid_t uid, gid_t gid) if (chown(path, uid, gid) && errno != ENOENT) syslog(LOG_ERR, "%s: chown(%s): %m", table, path); } else { - strcpy(buf, path); - buf[pathlen - 1] = 0; + strcpy_truncate (buf, path, sizeof(buf)); + if (sizeof(buf) > pathlen) + buf[pathlen - 2] = '\0'; + /* Solaris evidently operates on the directory as well */ + login_protect(table, buf, mask | ((mask & 0444) >> 2), uid, gid); if ((dir = opendir(buf)) == 0) { syslog(LOG_ERR, "%s: opendir(%s): %m", table, path); } else { + if (sizeof(buf) > pathlen) { + buf[pathlen - 2] = '/'; + buf[pathlen - 1] = '\0'; + } + while ((ent = readdir(dir)) != 0) { if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { - strcpy(buf + pathlen - 1, ent->d_name); + strcpy_truncate (buf + pathlen - 1, + ent->d_name, + sizeof(buf) - (pathlen + 1)); login_protect(table, buf, mask, uid, gid); } } diff --git a/crypto/kerberosIV/appl/bsd/osfc2.c b/crypto/kerberosIV/appl/bsd/osfc2.c new file mode 100644 index 0000000..78f2e6e --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/osfc2.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "bsd_locl.h" +RCSID("$Id: osfc2.c,v 1.1 1998/09/28 11:47:36 joda Exp $"); + +int +do_osfc2_magic(uid_t uid) +{ +#ifdef HAVE_OSFC2 + struct es_passwd *epw; + char *argv[2]; + + /* fake */ + argv[0] = (char*)__progname; + argv[1] = NULL; + set_auth_parameters(1, argv); + + epw = getespwuid(uid); + if(epw == NULL) { + syslog(LOG_AUTHPRIV|LOG_NOTICE, + "getespwuid failed for %d", uid); + printf("Sorry.\n"); + return 1; + } + /* We don't check for auto-retired, foo-retired, + bar-retired, or any other kind of retired accounts + here; neither do we check for time-locked accounts, or + any other kind of serious C2 mumbo-jumbo. We do, + however, call setluid, since failing to do so it not + very good (take my word for it). */ + + if(!epw->uflg->fg_uid) { + syslog(LOG_AUTHPRIV|LOG_NOTICE, + "attempted login by %s (has no uid)", epw->ufld->fd_name); + printf("Sorry.\n"); + return 1; + } + setluid(epw->ufld->fd_uid); + if(getluid() != epw->ufld->fd_uid) { + syslog(LOG_AUTHPRIV|LOG_NOTICE, + "failed to set LUID for %s (%d)", + epw->ufld->fd_name, epw->ufld->fd_uid); + printf("Sorry.\n"); + return 1; + } +#endif /* HAVE_OSFC2 */ + return 0; +} diff --git a/crypto/kerberosIV/appl/bsd/pathnames.h b/crypto/kerberosIV/appl/bsd/pathnames.h index 3c10bff..671f663 100644 --- a/crypto/kerberosIV/appl/bsd/pathnames.h +++ b/crypto/kerberosIV/appl/bsd/pathnames.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)pathnames.h 5.2 (Berkeley) 4/9/90 - * $Id: pathnames.h,v 1.23 1996/11/17 06:36:42 joda Exp $ + * $Id: pathnames.h,v 1.25 1998/02/03 23:29:30 assar Exp $ */ /******* First fix default path, we stick to _PATH_DEFPATH everywhere */ @@ -65,6 +65,9 @@ #undef _PATH_RSH /* Redifine rsh */ #define _PATH_RSH BINDIR "/rsh" +#undef _PATH_RCP /* Redifine rcp */ +#define _PATH_RCP BINDIR "/rcp" + #undef _PATH_LOGIN #define _PATH_LOGIN BINDIR "/login" @@ -175,6 +178,10 @@ #define _PATH_ETC_ENVIRONMENT "/etc/environment" #endif +#ifndef _PATH_ETC_SECURETTY +#define _PATH_ETC_SECURETTY "/etc/securetty" +#endif + /* * NeXT KLUDGE ALERT!!!!!!!!!!!!!!!!!! * Some sort of bug in the NEXTSTEP cpp. @@ -186,6 +193,8 @@ #define _PATH_RLOGIN "/usr/athena/bin/rlogin" #undef _PATH_RSH #define _PATH_RSH "/usr/athena/bin/rsh" +#undef _PATH_RCP +#define _PATH_RCP "/usr/athena/bin/rcp" #undef _PATH_LOGIN #define _PATH_LOGIN "/usr/athena/bin/login" #endif diff --git a/crypto/kerberosIV/appl/bsd/rcmd_util.c b/crypto/kerberosIV/appl/bsd/rcmd_util.c index 4669009..1884133 100644 --- a/crypto/kerberosIV/appl/bsd/rcmd_util.c +++ b/crypto/kerberosIV/appl/bsd/rcmd_util.c @@ -38,7 +38,7 @@ #include "bsd_locl.h" -RCSID("$Id: rcmd_util.c,v 1.15 1997/05/02 14:27:44 assar Exp $"); +RCSID("$Id: rcmd_util.c,v 1.17 1997/09/24 21:14:23 assar Exp $"); int get_login_port(int kerberos, int encryption) @@ -240,7 +240,7 @@ warning(const char *fmt, ...) if (strncmp(rstar_no_warn, "yes", 3) != 0) { /* XXX */ fprintf(stderr, "%s: warning, using standard ", __progname); - warnx(fmt, args); + vwarnx(fmt, args); } va_end(args); } diff --git a/crypto/kerberosIV/appl/bsd/rcp.c b/crypto/kerberosIV/appl/bsd/rcp.c index 6dfb472..39fd36e 100644 --- a/crypto/kerberosIV/appl/bsd/rcp.c +++ b/crypto/kerberosIV/appl/bsd/rcp.c @@ -33,7 +33,7 @@ #include "bsd_locl.h" -RCSID("$Id: rcp.c,v 1.43 1997/05/13 09:41:26 bg Exp $"); +RCSID("$Id: rcp.c,v 1.49 1999/07/06 03:17:58 assar Exp $"); /* Globals */ static char dst_realm_buf[REALM_SZ]; @@ -49,6 +49,9 @@ static u_short port; static uid_t userid; static int pflag, iamremote, iamrecursive, targetshouldbedirectory; +static int argc_copy; +static char **argv_copy; + #define CMDNEEDS 64 static char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ @@ -58,7 +61,7 @@ void rsource(char *name, struct stat *statp); CREDENTIALS cred; MSG_DAT msg_data; -struct sockaddr_in foreign, local; +struct sockaddr_in foreign_addr, local_addr; Key_schedule schedule; KTEXT_ST ticket; @@ -71,18 +74,18 @@ send_auth(char *h, char *r) long opts; lslen = sizeof(struct sockaddr_in); - if (getsockname(rem, (struct sockaddr *)&local, &lslen) < 0) + if (getsockname(rem, (struct sockaddr *)&local_addr, &lslen) < 0) err(1, "getsockname"); fslen = sizeof(struct sockaddr_in); - if (getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0) + if (getpeername(rem, (struct sockaddr *)&foreign_addr, &fslen) < 0) err(1, "getpeername"); if ((r == NULL) || (*r == '\0')) r = krb_realmofhost(h); opts = KOPT_DO_MUTUAL; if ((status = krb_sendauth(opts, rem, &ticket, SERVICE_NAME, h, r, (unsigned long)getpid(), &msg_data, &cred, - schedule, &local, - &foreign, "KCMDV0.1")) != KSUCCESS) + schedule, &local_addr, + &foreign_addr, "KCMDV0.1")) != KSUCCESS) errx(1, "krb_sendauth failure: %s", krb_get_err_text(status)); } @@ -94,15 +97,15 @@ answer_auth(void) char inst[INST_SZ], v[9]; lslen = sizeof(struct sockaddr_in); - if (getsockname(rem, (struct sockaddr *)&local, &lslen) < 0) + if (getsockname(rem, (struct sockaddr *)&local_addr, &lslen) < 0) err(1, "getsockname"); fslen = sizeof(struct sockaddr_in); - if(getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0) + if(getpeername(rem, (struct sockaddr *)&foreign_addr, &fslen) < 0) err(1, "getperrname"); k_getsockinst(rem, inst, sizeof(inst)); opts = KOPT_DO_MUTUAL; if ((status = krb_recvauth(opts, rem, &ticket, SERVICE_NAME, inst, - &foreign, &local, + &foreign_addr, &local_addr, &kdata, "", schedule, v)) != KSUCCESS) errx(1, "krb_recvauth failure: %s", krb_get_err_text(status)); } @@ -143,10 +146,11 @@ run_err(const char *fmt, ...) va_start(args, fmt); ++errs; #define RCPERR "\001rcp: " - strcpy (errbuf, RCPERR); - vsnprintf (errbuf + strlen(RCPERR), sizeof(errbuf) - strlen(RCPERR), + strcpy_truncate (errbuf, RCPERR, sizeof(errbuf)); + vsnprintf (errbuf + strlen(errbuf), + sizeof(errbuf) - strlen(errbuf), fmt, args); - strcat (errbuf, "\n"); + strcat_truncate (errbuf, "\n", sizeof(errbuf)); des_write (rem, errbuf, strlen(errbuf)); if (!iamremote) vwarnx(fmt, args); @@ -351,11 +355,15 @@ rsource(char *name, struct stat *statp) DIR *dirp; struct dirent *dp; char *last, *vect[1], path[MaxPathLen]; + char *p; if (!(dirp = opendir(name))) { run_err("%s: %s", name, strerror(errno)); return; } + for (p = name + strlen(name) - 1; p >= name && *p == '/'; --p) + *p = '\0'; + last = strrchr(name, '/'); if (last == 0) last = name; @@ -403,8 +411,9 @@ static int kerberos(char **host, char *bp, char *locuser, char *user) { int sock = -1, err; -again: + if (use_kerberos) { + setuid(getuid()); rem = KSUCCESS; errno = 0; if (dest_realm == NULL) @@ -439,13 +448,11 @@ again: rem = sock; #endif if (rem < 0) { - use_kerberos = 0; - port = get_shell_port(use_kerberos, 0); if (errno == ECONNREFUSED) oldw("remote host doesn't support Kerberos"); else if (errno == ENOENT) oldw("can't provide Kerberos authentication data"); - goto again; + execv(_PATH_RCP, argv_copy); } } else { if (doencrypt) @@ -493,29 +500,24 @@ toremote(char *targ, int argc, char **argv) if (*src == 0) src = "."; host = strchr(argv[i], '@'); - len = strlen(_PATH_RSH) + strlen(argv[i]) + - strlen(src) + (tuser ? strlen(tuser) : 0) + - strlen(thost) + strlen(targ) + CMDNEEDS + 20; - if (!(bp = malloc(len))) - err(1, " "); if (host) { - *host++ = 0; - suser = argv[i]; - if (*suser == '\0') - suser = pwd->pw_name; - else if (!okname(suser)) - continue; - snprintf(bp, len, - "%s %s -l %s -n %s %s '%s%s%s:%s'", - _PATH_RSH, host, suser, cmd, src, - tuser ? tuser : "", tuser ? "@" : "", - thost, targ); + *host++ = 0; + suser = argv[i]; + if (*suser == '\0') + suser = pwd->pw_name; + else if (!okname(suser)) + continue; + asprintf(&bp, "%s %s -l %s -n %s %s '%s%s%s:%s'", + _PATH_RSH, host, suser, cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); } else - snprintf(bp, len, - "exec %s %s -n %s %s '%s%s%s:%s'", - _PATH_RSH, argv[i], cmd, src, - tuser ? tuser : "", tuser ? "@" : "", - thost, targ); + asprintf(&bp, "exec %s %s -n %s %s '%s%s%s:%s'", + _PATH_RSH, argv[i], cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + if(bp == NULL) + errx(1, "out of memory"); susystem(bp, userid); free(bp); } else { /* local to remote */ @@ -623,7 +625,13 @@ sink(int argc, char **argv) if (ch == '\n') *--cp = 0; -#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); +#define getnum(t) \ + do { \ + (t) = 0; \ + while (isdigit((unsigned char)*cp)) \ + (t) = (t) * 10 + (*cp++ - '0'); \ + } while(0) + cp = buf; if (*cp == 'T') { setimes++; @@ -666,7 +674,7 @@ sink(int argc, char **argv) if (*cp++ != ' ') SCREWUP("mode not delimited"); - for (size = 0; isdigit(*cp);) + for (size = 0; isdigit((unsigned char)*cp);) size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') SCREWUP("size not delimited"); @@ -906,8 +914,28 @@ main(int argc, char **argv) { int ch, fflag, tflag; char *targ; + int i; set_progname(argv[0]); + + /* + * Prepare for execing ourselves. + */ + + argc_copy = argc + 1; + argv_copy = malloc((argc_copy + 1) * sizeof(*argv_copy)); + if (argv_copy == NULL) + err(1, "malloc"); + argv_copy[0] = argv[0]; + argv_copy[1] = "-K"; + for(i = 1; i < argc; ++i) { + argv_copy[i + 1] = strdup(argv[i]); + if (argv_copy[i + 1] == NULL) + errx(1, "strdup: out of memory"); + } + argv_copy[argc + 1] = NULL; + + fflag = tflag = 0; while ((ch = getopt(argc, argv, OPTIONS)) != EOF) switch(ch) { /* User-visible flags. */ @@ -916,7 +944,7 @@ main(int argc, char **argv) break; case 'k': dest_realm = dst_realm_buf; - strncpy(dst_realm_buf, optarg, REALM_SZ); + strcpy_truncate(dst_realm_buf, optarg, REALM_SZ); break; case 'x': doencrypt = 1; @@ -951,47 +979,40 @@ main(int argc, char **argv) * kshell service, pass 0 for no encryption */ port = get_shell_port(use_kerberos, 0); + userid = getuid(); + #ifndef __CYGWIN32__ - if ((pwd = k_getpwuid(userid = getuid())) == NULL) + if ((pwd = k_getpwuid(userid)) == NULL) errx(1, "unknown user %d", (int)userid); #endif rem = STDIN_FILENO; /* XXX */ - if (fflag) { /* Follow "protocol", send data. */ - if (doencrypt) - answer_auth(); + if (fflag || tflag) { + if (doencrypt) + answer_auth(); + if(fflag) response(); - setuid(userid); - if (k_hasafs()) { - /* Sometimes we will need cell specific tokens - * to be able to read and write files, thus, - * the token stuff done in rshd might not - * suffice. - */ - char cell[64]; - if (k_afs_cell_of_file(pwd->pw_dir, - cell, sizeof(cell)) == 0) - k_afsklog(cell, 0); - k_afsklog(0, 0); - } + if(do_osfc2_magic(pwd->pw_uid)) + exit(1); + setuid(userid); + if (k_hasafs()) { + /* Sometimes we will need cell specific tokens + * to be able to read and write files, thus, + * the token stuff done in rshd might not + * suffice. + */ + char cell[64]; + if (k_afs_cell_of_file(pwd->pw_dir, + cell, sizeof(cell)) == 0) + krb_afslog(cell, 0); + krb_afslog(0, 0); + } + if(fflag) source(argc, argv); - exit(errs); - } - - if (tflag) { /* Receive data. */ - if (doencrypt) - answer_auth(); - setuid(userid); - if (k_hasafs()) { - char cell[64]; - if (k_afs_cell_of_file(pwd->pw_dir, - cell, sizeof(cell)) == 0) - k_afsklog(cell, 0); - k_afsklog(0, 0); - } + else sink(argc, argv); - exit(errs); + exit(errs); } if (argc < 2) diff --git a/crypto/kerberosIV/appl/bsd/rcp_util.c b/crypto/kerberosIV/appl/bsd/rcp_util.c index 6f0c5f0..54233af 100644 --- a/crypto/kerberosIV/appl/bsd/rcp_util.c +++ b/crypto/kerberosIV/appl/bsd/rcp_util.c @@ -33,7 +33,7 @@ #include "bsd_locl.h" -RCSID("$Id: rcp_util.c,v 1.7 1996/11/17 20:23:05 assar Exp $"); +RCSID("$Id: rcp_util.c,v 1.8 1998/09/28 11:45:21 joda Exp $"); char * colon(char *cp) @@ -73,25 +73,27 @@ bad: warnx("%s: invalid user name", cp0); int susystem(char *s, int userid) { - RETSIGTYPE (*istat)(), (*qstat)(); - int status; - pid_t pid; + RETSIGTYPE (*istat)(), (*qstat)(); + int status; + pid_t pid; - pid = fork(); - switch (pid) { - case -1: - return (127); + pid = fork(); + switch (pid) { + case -1: + return (127); - case 0: - setuid(userid); - execl(_PATH_BSHELL, "sh", "-c", s, NULL); - _exit(127); - } - istat = signal(SIGINT, SIG_IGN); - qstat = signal(SIGQUIT, SIG_IGN); - if (waitpid(pid, &status, 0) < 0) - status = -1; - signal(SIGINT, istat); - signal(SIGQUIT, qstat); - return (status); + case 0: + if(do_osfc2_magic(userid)) + exit(1); + setuid(userid); + execl(_PATH_BSHELL, "sh", "-c", s, NULL); + _exit(127); + } + istat = signal(SIGINT, SIG_IGN); + qstat = signal(SIGQUIT, SIG_IGN); + if (waitpid(pid, &status, 0) < 0) + status = -1; + signal(SIGINT, istat); + signal(SIGQUIT, qstat); + return (status); } diff --git a/crypto/kerberosIV/appl/bsd/rlogin.c b/crypto/kerberosIV/appl/bsd/rlogin.c index 27aa8f0..5bc6196 100644 --- a/crypto/kerberosIV/appl/bsd/rlogin.c +++ b/crypto/kerberosIV/appl/bsd/rlogin.c @@ -36,7 +36,7 @@ */ #include "bsd_locl.h" -RCSID("$Id: rlogin.c,v 1.61 1997/05/25 01:14:47 assar Exp $"); +RCSID("$Id: rlogin.c,v 1.65 1999/03/13 21:13:54 assar Exp $"); CREDENTIALS cred; Key_schedule schedule; @@ -406,13 +406,14 @@ writer(void) continue; } #endif /* VDSUSP */ - if (c != escapechar) + if (c != escapechar) { #ifndef NOENCRYPTION if (doencrypt) des_enc_write(rem, &escapechar,1, schedule, &cred.session); else #endif write(rem, &escapechar, 1); + } } if (doencrypt) { @@ -578,7 +579,7 @@ main(int argc, char **argv) break; case 'k': dest_realm = dst_realm_buf; - strncpy(dest_realm, optarg, REALM_SZ); + strcpy_truncate(dest_realm, optarg, REALM_SZ); break; case 'l': user = optarg; @@ -586,22 +587,26 @@ main(int argc, char **argv) case 'x': doencrypt = 1; break; - case 'p': - user_port = htons(atoi(optarg)); - break; + case 'p': { + char *endptr; + + user_port = strtol (optarg, &endptr, 0); + if (user_port == 0 && optarg == endptr) + errx (1, "Bad port `%s'", optarg); + user_port = htons(user_port); + break; + } case '?': default: usage(); } optind += argoff; - argc -= optind; - argv += optind; /* if haven't gotten a host yet, do so */ - if (!host && !(host = *argv++)) + if (!host && !(host = argv[optind++])) usage(); - if (*argv) + if (argv[optind]) usage(); if (!(pw = k_getpwuid(uid = getuid()))) @@ -609,7 +614,6 @@ main(int argc, char **argv) if (!user) user = pw->pw_name; - if (user_port) sv_port = user_port; else @@ -636,17 +640,8 @@ main(int argc, char **argv) get_window_size(0, &winsize); - try_connect: if (use_kerberos) { - struct hostent *hp; - - /* Fully qualify hostname (needed for krb_realmofhost). */ - hp = gethostbyname(host); - if (hp != NULL && !(host = strdup(hp->h_name))) { - errno = ENOMEM; - err(1, NULL); - } - + setuid(getuid()); rem = KSUCCESS; errno = 0; if (dest_realm == NULL) @@ -656,18 +651,25 @@ main(int argc, char **argv) rem = krcmd_mutual(&host, sv_port, user, term, 0, dest_realm, &cred, schedule); else - rem = krcmd(&host, sv_port, user, term, 0, - dest_realm); + rem = krcmd(&host, sv_port, user, term, 0, + dest_realm); if (rem < 0) { - use_kerberos = 0; - if (user_port == 0) - sv_port = get_login_port(use_kerberos, - doencrypt); - if (errno == ECONNREFUSED) - warning("remote host doesn't support Kerberos"); - if (errno == ENOENT) - warning("can't provide Kerberos auth data"); - goto try_connect; + int i; + char **newargv; + + if (errno == ECONNREFUSED) + warning("remote host doesn't support Kerberos"); + if (errno == ENOENT) + warning("can't provide Kerberos auth data"); + newargv = malloc((argc + 2) * sizeof(*newargv)); + if (newargv == NULL) + err(1, "malloc"); + newargv[0] = argv[0]; + newargv[1] = "-K"; + for(i = 1; i < argc; ++i) + newargv[i + 1] = argv[i]; + newargv[argc + 1] = NULL; + execv(_PATH_RLOGIN, newargv); } } else { if (doencrypt) diff --git a/crypto/kerberosIV/appl/bsd/rlogind.c b/crypto/kerberosIV/appl/bsd/rlogind.c index c5d80774..d36df92 100644 --- a/crypto/kerberosIV/appl/bsd/rlogind.c +++ b/crypto/kerberosIV/appl/bsd/rlogind.c @@ -42,7 +42,7 @@ #include "bsd_locl.h" -RCSID("$Id: rlogind.c,v 1.100 1997/05/25 01:15:20 assar Exp $"); +RCSID("$Id: rlogind.c,v 1.107.2.1 1999/07/22 03:14:39 assar Exp $"); extern int __check_rhosts_file; @@ -187,7 +187,7 @@ readstream(int p, char *ibuf, int bufsize) #ifdef HAVE_UTMPX_H static int -logout(const char *line) +rlogind_logout(const char *line) { struct utmpx utmpx, *utxp; int ret = 1; @@ -198,8 +198,9 @@ logout(const char *line) strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line)); utxp = getutxline(&utmpx); if (utxp) { - strcpy(utxp->ut_user, ""); + utxp->ut_user[0] = '\0'; utxp->ut_type = DEAD_PROCESS; +#ifdef HAVE_STRUCT_UTMPX_UT_EXIT #ifdef _STRUCT___EXIT_STATUS utxp->ut_exit.__e_termination = 0; utxp->ut_exit.__e_exit = 0; @@ -210,6 +211,7 @@ logout(const char *line) utxp->ut_exit.e_termination = 0; utxp->ut_exit.e_exit = 0; #endif +#endif gettimeofday(&utxp->ut_tv, NULL); pututxline(utxp); #ifdef WTMPX_FILE @@ -223,7 +225,7 @@ logout(const char *line) } #else static int -logout(const char *line) +rlogind_logout(const char *line) { FILE *fp; struct utmp ut; @@ -237,9 +239,24 @@ logout(const char *line) strncmp(ut.ut_line, line, sizeof(ut.ut_line))) continue; memset(ut.ut_name, 0, sizeof(ut.ut_name)); -#ifdef HAVE_UT_HOST +#ifdef HAVE_STRUCT_UTMP_UT_HOST memset(ut.ut_host, 0, sizeof(ut.ut_host)); #endif +#ifdef HAVE_STRUCT_UTMP_UT_TYPE + ut.ut_type = DEAD_PROCESS; +#endif +#ifdef HAVE_STRUCT_UTMP_UT_EXIT +#ifdef _STRUCT___EXIT_STATUS + ut.ut_exit.__e_termination = 0; + ut.ut_exit.__e_exit = 0; +#elif defined(__osf__) /* XXX */ + ut.ut_exit.ut_termination = 0; + ut.ut_exit.ut_exit = 0; +#else + ut.ut_exit.e_termination = 0; + ut.ut_exit.e_exit = 0; +#endif +#endif time(&ut.ut_time); fseek(fp, (long)-sizeof(struct utmp), SEEK_CUR); fwrite(&ut, sizeof(struct utmp), 1, fp); @@ -265,13 +282,16 @@ logwtmp(const char *line, const char *name, const char *host) if (!fstat(fd, &buf)) { strncpy(ut.ut_line, line, sizeof(ut.ut_line)); strncpy(ut.ut_name, name, sizeof(ut.ut_name)); -#ifdef HAVE_UT_HOST +#ifdef HAVE_STRUCT_UTMP_UT_ID + strncpy(ut.ut_id, make_id((char *)line), sizeof(ut.ut_id)); +#endif +#ifdef HAVE_STRUCT_UTMP_UT_HOST strncpy(ut.ut_host, host, sizeof(ut.ut_host)); #endif -#ifdef HAVE_UT_PID +#ifdef HAVE_STRUCT_UTMP_UT_PID ut.ut_pid = getpid(); #endif -#ifdef HAVE_UT_TYPE +#ifdef HAVE_STRUCT_UTMP_UT_TYPE if(name[0]) ut.ut_type = USER_PROCESS; else @@ -440,7 +460,11 @@ doit(int f, struct sockaddr_in *fromp) write(f, INSECURE_MESSAGE, strlen(INSECURE_MESSAGE)); netf = f; +#ifdef HAVE_FORKPTY pid = forkpty(&master, line, NULL, NULL); +#else + pid = forkpty_truncate(&master, line, sizeof(line), NULL, NULL); +#endif if (pid < 0) { if (errno == ENOENT) fatal(f, "Out of ptys", 0); @@ -482,7 +506,9 @@ doit(int f, struct sockaddr_in *fromp) ioctl(f, FIONBIO, &on); ioctl(master, FIONBIO, &on); ioctl(master, TIOCPKT, &on); +#ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); +#endif signal(SIGCHLD, cleanup); setsid(); protocol(f, master); @@ -532,7 +558,7 @@ send_oob(int fd, char c) { static char last_oob = 0xFF; -#if (SunOS == 5) || defined(__hpux) +#if (SunOS >= 50) || defined(__hpux) /* * PSoriasis and HP-UX always send TIOCPKT_DOSTOP at startup so we * can avoid sending OOB data and thus not break on Linux by merging @@ -571,12 +597,14 @@ protocol(int f, int master) char cntl; unsigned char oob_queue = 0; +#ifdef SIGTTOU /* * Must ignore SIGTTOU, otherwise we'll stop * when we try and set slave pty's window shape * (our controlling tty is the master pty). */ signal(SIGTTOU, SIG_IGN); +#endif send_oob(f, TIOCPKT_WINDOW); /* indicate new rlogin */ @@ -600,12 +628,13 @@ protocol(int f, int master) omask = &obits; } else FD_SET(f, &ibits); - if (pcc >= 0) + if (pcc >= 0) { if (pcc) { FD_SET(f, &obits); omask = &obits; } else FD_SET(master, &ibits); + } FD_SET(master, &ebits); if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { if (errno == EINTR) @@ -735,7 +764,7 @@ cleanup(int signo) { char *p = clean_ttyname (line); - if (logout(p) == 0) + if (rlogind_logout(p) == 0) logwtmp(p, "", ""); chmod(line, 0666); chown(line, 0, 0); diff --git a/crypto/kerberosIV/appl/bsd/rsh.c b/crypto/kerberosIV/appl/bsd/rsh.c index 329ebf7..be2dfea 100644 --- a/crypto/kerberosIV/appl/bsd/rsh.c +++ b/crypto/kerberosIV/appl/bsd/rsh.c @@ -33,7 +33,7 @@ #include "bsd_locl.h" -RCSID("$Id: rsh.c,v 1.35 1997/03/30 18:20:22 joda Exp $"); +RCSID("$Id: rsh.c,v 1.41 1999/06/17 18:49:18 assar Exp $"); CREDENTIALS cred; Key_schedule schedule; @@ -49,7 +49,7 @@ static void usage(void) { fprintf(stderr, - "usage: rsh [-ndKx] [-k realm] [-l login] host [command]\n"); + "usage: rsh [-ndKx] [-k realm] [-p port] [-l login] host [command]\n"); exit(1); } @@ -63,11 +63,13 @@ copyargs(char **argv) cc = 0; for (ap = argv; *ap; ++ap) cc += strlen(*ap) + 1; - if (!(args = malloc(cc))) + args = malloc(cc); + if (args == NULL) errx(1, "Out of memory."); for (p = args, ap = argv; *ap; ++ap) { strcpy(p, *ap); - for (p = strcpy(p, *ap); *p; ++p); + while(*p) + ++p; if (ap[1]) *p++ = ' '; } @@ -92,7 +94,7 @@ talk(int nflag, sigset_t omask, int pid, int rem) int cc, wc; char *bp; fd_set readfrom, ready, rembits; - char buf[BUFSIZ]; + char buf[DES_RW_MAXWRITE]; if (pid == 0) { if (nflag) @@ -107,7 +109,7 @@ talk(int nflag, sigset_t omask, int pid, int rem) rewrite: FD_ZERO(&rembits); FD_SET(rem, &rembits); - if (select(16, 0, &rembits, 0, 0) < 0) { + if (select(rem + 1, 0, &rembits, 0, 0) < 0) { if (errno != EINTR) err(1, "select"); goto rewrite; @@ -142,7 +144,7 @@ talk(int nflag, sigset_t omask, int pid, int rem) FD_SET(rfd2, &readfrom); do { ready = readfrom; - if (select(16, &ready, 0, 0, 0) < 0) { + if (select(max(rem,rfd2)+1, &ready, 0, 0, 0) < 0) { if (errno != EINTR) err(1, "select"); continue; @@ -184,7 +186,7 @@ int main(int argc, char **argv) { struct passwd *pw; - int sv_port; + int sv_port, user_port = 0; sigset_t omask; int argoff, ch, dflag, nflag, nfork, one, pid, rem, uid; char *args, *host, *user, *local_user; @@ -197,12 +199,12 @@ main(int argc, char **argv) set_progname(argv[0]); /* handle "rsh host flags" */ - if (!host && argc > 2 && argv[1][0] != '-') { + if (argc > 2 && argv[1][0] != '-') { host = argv[1]; argoff = 1; } -#define OPTIONS "+8KLde:k:l:nwx" +#define OPTIONS "+8KLde:k:l:np:wx" while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) switch(ch) { case 'K': @@ -221,7 +223,7 @@ main(int argc, char **argv) break; case 'k': dest_realm = dst_realm_buf; - strncpy(dest_realm, optarg, REALM_SZ); + strcpy_truncate(dest_realm, optarg, REALM_SZ); break; case 'n': nflag = nfork = 1; @@ -229,6 +231,15 @@ main(int argc, char **argv) case 'x': doencrypt = 1; break; + case 'p': { + char *endptr; + + user_port = strtol (optarg, &endptr, 0); + if (user_port == 0 && optarg == endptr) + errx (1, "Bad port `%s'", optarg); + user_port = htons(user_port); + break; + } case '?': default: usage(); @@ -247,9 +258,6 @@ main(int argc, char **argv) err(1, "can't exec %s", _PATH_RLOGIN); } - argc -= optind; - argv += optind; - #ifndef __CYGWIN32__ if (!(pw = k_getpwuid(uid = getuid()))) errx(1, "unknown user id."); @@ -266,12 +274,15 @@ main(int argc, char **argv) if (doencrypt) nfork = 0; - args = copyargs(argv); + args = copyargs(argv+optind); - sv_port=get_shell_port(use_kerberos, doencrypt); + if (user_port) + sv_port = user_port; + else + sv_port = get_shell_port(use_kerberos, doencrypt); -try_connect: if (use_kerberos) { + setuid(getuid()); rem = KSUCCESS; errno = 0; if (dest_realm == NULL) @@ -284,13 +295,27 @@ try_connect: rem = krcmd(&host, sv_port, user, args, &rfd2, dest_realm); if (rem < 0) { + int i = 0; + char **newargv; + if (errno == ECONNREFUSED) warning("remote host doesn't support Kerberos"); if (errno == ENOENT) warning("can't provide Kerberos auth data"); - use_kerberos = 0; - sv_port=get_shell_port(use_kerberos, doencrypt); - goto try_connect; + newargv = malloc((argc + 2) * sizeof(*newargv)); + if (newargv == NULL) + err(1, "malloc"); + newargv[i] = argv[i]; + ++i; + if (argv[i][0] != '-') { + newargv[i] = argv[i]; + ++i; + } + newargv[i++] = "-K"; + for(; i <= argc; ++i) + newargv[i] = argv[i - 1]; + newargv[argc + 1] = NULL; + execv(_PATH_RSH, newargv); } } else { if (doencrypt) diff --git a/crypto/kerberosIV/appl/bsd/rshd.c b/crypto/kerberosIV/appl/bsd/rshd.c index 75ca1df..1a30793 100644 --- a/crypto/kerberosIV/appl/bsd/rshd.c +++ b/crypto/kerberosIV/appl/bsd/rshd.c @@ -42,7 +42,7 @@ #include "bsd_locl.h" -RCSID("$Id: rshd.c,v 1.51 1997/05/13 09:42:39 bg Exp $"); +RCSID("$Id: rshd.c,v 1.58 1999/06/17 18:49:43 assar Exp $"); extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */ extern int __check_rhosts_file; @@ -197,7 +197,7 @@ doit(struct sockaddr_in *fromp) int one = 1; const char *errorhost = ""; char *errorstr; - char *cp, sig, buf[BUFSIZ]; + char *cp, sig, buf[DES_RW_MAXWRITE]; char cmdbuf[NCARGS+1], locuser[16], remuser[16]; char remotehost[2 * MaxHostNameLen + 1]; @@ -279,7 +279,7 @@ doit(struct sockaddr_in *fromp) } if (vacuous) { - error("rshd: remote host requires Kerberos authentication\n"); + error("rshd: Remote host requires Kerberos authentication.\n"); exit(1); } @@ -298,7 +298,7 @@ doit(struct sockaddr_in *fromp) if (getsockname(0, (struct sockaddr *)&local_addr, &rc) < 0) { syslog(LOG_ERR, "getsockname: %m"); - error("rlogind: getsockname: %m"); + error("rshd: getsockname: %m"); exit(1); } authopts = KOPT_DO_MUTUAL; @@ -369,9 +369,9 @@ doit(struct sockaddr_in *fromp) } else if (errorstr || - pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && + (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0, - remuser, locuser) < 0) { + remuser, locuser) < 0)) { if (__rcmd_errstr) syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: permission denied (%s). cmd='%.80s'", @@ -560,19 +560,18 @@ doit(struct sockaddr_in *fromp) if (setpcred (pwd->pw_name, NULL) == -1) syslog(LOG_ERR, "setpcred() failure: %m"); #endif /* HAVE_SETPCRED */ + if(do_osfc2_magic(pwd->pw_uid)) + exit(1); setgid((gid_t)pwd->pw_gid); initgroups(pwd->pw_name, pwd->pw_gid); setuid((uid_t)pwd->pw_uid); - strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); + strcat_truncate(homedir, pwd->pw_dir, sizeof(homedir)); - /* Need to extend path to find rcp */ - strncat(path, BINDIR, sizeof(path)-1); - strncat(path, ":", sizeof(path)-1); - strncat(path, _PATH_DEFPATH, sizeof(path)-1); - path[sizeof(path)-1] = '\0'; + /* Need to prepend path with BINDIR (/usr/athena/bin) to find rcp */ + snprintf(path, sizeof(path), "PATH=%s:%s", BINDIR, _PATH_DEFPATH); - strncat(shell, pwd->pw_shell, sizeof(shell)-7); - strncat(username, pwd->pw_name, sizeof(username)-6); + strcat_truncate(shell, pwd->pw_shell, sizeof(shell)); + strcat_truncate(username, pwd->pw_name, sizeof(username)); cp = strrchr(pwd->pw_shell, '/'); if (cp) cp++; @@ -594,7 +593,7 @@ doit(struct sockaddr_in *fromp) if (k_hasafs()) { if (new_pag) k_setpag(); /* Put users process in an new pag */ - k_afsklog(0, 0); + krb_afslog(0, 0); } execle(pwd->pw_shell, cp, "-c", cmdbuf, 0, envinit); err(1, pwd->pw_shell); @@ -620,8 +619,8 @@ error(const char *fmt, ...) len = 1; } else len = 0; - len = vsnprintf (bp, sizeof(buf) - len, fmt, ap); - write (STDERR_FILENO, buf, len); + len += vsnprintf(bp, sizeof(buf) - len, fmt, ap); + write(STDERR_FILENO, buf, len); va_end(ap); } diff --git a/crypto/kerberosIV/appl/bsd/su.c b/crypto/kerberosIV/appl/bsd/su.c index 8c610e1..d0da21d 100644 --- a/crypto/kerberosIV/appl/bsd/su.c +++ b/crypto/kerberosIV/appl/bsd/su.c @@ -33,7 +33,7 @@ #include "bsd_locl.h" -RCSID ("$Id: su.c,v 1.59 1997/05/26 17:45:54 bg Exp $"); +RCSID ("$Id: su.c,v 1.66 1999/03/11 13:57:58 joda Exp $"); #ifdef SYSV_SHADOW #include "sysv_shadow.h" @@ -112,7 +112,7 @@ main (int argc, char **argv) if (errno) prio = 0; setpriority (PRIO_PROCESS, 0, -2); - openlog ("su", LOG_CONS, 0); + openlog ("su", LOG_CONS, LOG_AUTH); /* get current login name and shell */ ruid = getuid (); @@ -123,13 +123,17 @@ main (int argc, char **argv) if (pwd == NULL) errx (1, "who are you?"); username = strdup (pwd->pw_name); - if (asme) - if (pwd->pw_shell && *pwd->pw_shell) - shell = strcpy (shellbuf, pwd->pw_shell); - else { + if (username == NULL) + errx (1, "strdup: out of memory"); + if (asme) { + if (pwd->pw_shell && *pwd->pw_shell) { + strcpy_truncate (shellbuf, pwd->pw_shell, sizeof(shellbuf)); + shell = shellbuf; + } else { shell = _PATH_BSHELL; iscsh = NO; } + } /* get target login information, default to root */ user = *argv ? *argv : "root"; @@ -229,6 +233,8 @@ main (int argc, char **argv) char *t = getenv ("TERM"); environ = malloc (10 * sizeof (char *)); + if (environ == NULL) + err (1, "malloc"); environ[0] = NULL; setenv ("PATH", _PATH_DEFPATH, 1); if (t) @@ -250,13 +256,13 @@ main (int argc, char **argv) *np-- = "-m"; } if (asthem) { - avshellbuf[0] = '-'; - strcpy (avshellbuf + 1, avshell); + snprintf (avshellbuf, sizeof(avshellbuf), + "-%s", avshell); avshell = avshellbuf; } else if (iscsh == YES) { /* csh strips the first character... */ - avshellbuf[0] = '_'; - strcpy (avshellbuf + 1, avshell); + snprintf (avshellbuf, sizeof(avshellbuf), + "_%s", avshell); avshell = avshellbuf; } *np = avshell; @@ -272,7 +278,7 @@ main (int argc, char **argv) if (k_setpag () != 0) warn ("setpag"); - code = k_afsklog (0, 0); + code = krb_afslog (0, 0); if (code != KSUCCESS && code != KDC_PR_UNKNOWN) warnx ("afsklog: %s", krb_get_err_text (code)); } @@ -334,6 +340,15 @@ kerberos (char *username, char *user, int uid) setenv ("KRBTKFILE", krbtkfile, 1); krb_set_tkt_string (krbtkfile); /* + * Set real as well as effective ID to 0 for the moment, + * to make the kerberos library do the right thing. + */ + if (setuid(0) < 0) { + warn("setuid"); + return (1); + } + + /* * Little trick here -- if we are su'ing to root, we need to get a ticket * for "xxx.root", where xxx represents the name of the person su'ing. * Otherwise (non-root case), we need to get a ticket for "yyy.", where @@ -388,13 +403,12 @@ kerberos (char *username, char *user, int uid) } setpriority (PRIO_PROCESS, 0, -2); - if (k_gethostname (hostname, sizeof (hostname)) == -1) { + if (gethostname (hostname, sizeof (hostname)) == -1) { warn ("gethostname"); dest_tkt (); return (1); } - strncpy (savehost, krb_get_phost (hostname), sizeof (savehost)); - savehost[sizeof (savehost) - 1] = '\0'; + strcpy_truncate (savehost, krb_get_phost (hostname), sizeof (savehost)); kerno = krb_mk_req (&ticket, "rcmd", savehost, lrealm, 33); diff --git a/crypto/kerberosIV/appl/bsd/sysv_default.c b/crypto/kerberosIV/appl/bsd/sysv_default.c index cb36b84..e6b28a7 100644 --- a/crypto/kerberosIV/appl/bsd/sysv_default.c +++ b/crypto/kerberosIV/appl/bsd/sysv_default.c @@ -2,7 +2,7 @@ #include "bsd_locl.h" -RCSID("$Id: sysv_default.c,v 1.9 1997/03/31 01:47:59 assar Exp $"); +RCSID("$Id: sysv_default.c,v 1.11 1999/03/13 21:15:24 assar Exp $"); #include "sysv_default.h" @@ -21,7 +21,7 @@ char *default_hz = 0; char *default_path = _PATH_DEFPATH; char *default_supath = _PATH_DEFSUPATH; char *default_ulimit = 0; -char *default_timeout = "60"; +char *default_timeout = "180"; char *default_umask = default_umask_value; char *default_sleep = "4"; char *default_maxtrys = "5"; @@ -48,7 +48,7 @@ static struct sysv_default { #define trim(s) { \ char *cp = s + strlen(s); \ - while (cp > s && isspace(cp[-1])) \ + while (cp > s && isspace((unsigned char)cp[-1])) \ cp--; \ *cp = 0; \ } diff --git a/crypto/kerberosIV/appl/bsd/sysv_environ.c b/crypto/kerberosIV/appl/bsd/sysv_environ.c index f5e782d..3df800e 100644 --- a/crypto/kerberosIV/appl/bsd/sysv_environ.c +++ b/crypto/kerberosIV/appl/bsd/sysv_environ.c @@ -2,7 +2,7 @@ #include "bsd_locl.h" -RCSID("$Id: sysv_environ.c,v 1.21 1997/05/14 17:34:15 joda Exp $"); +RCSID("$Id: sysv_environ.c,v 1.23 1997/12/14 23:50:44 assar Exp $"); #ifdef HAVE_ULIMIT_H #include <ulimit.h> @@ -86,7 +86,6 @@ void sysv_newenv(int argc, char **argv, struct passwd *pwd, char *term, int pflag) { unsigned umask_val; - long limit_val; char buf[BUFSIZ]; int count = 0; struct censored *cp; @@ -153,7 +152,7 @@ void sysv_newenv(int argc, char **argv, struct passwd *pwd, char *sep = "/"; if(KRB4_MAILDIR[strlen(KRB4_MAILDIR) - 1] == '/') sep = ""; - k_concat(buf, sizeof(buf), KRB4_MAILDIR, sep, pwd->pw_name, NULL); + roken_concat(buf, sizeof(buf), KRB4_MAILDIR, sep, pwd->pw_name, NULL); } setenv("MAIL", buf, 1); setenv("LOGNAME", pwd->pw_name, 1); @@ -182,6 +181,8 @@ void sysv_newenv(int argc, char **argv, struct passwd *pwd, } #ifdef HAVE_ULIMIT if (default_ulimit) { + long limit_val; + if (sscanf(default_ulimit, "%ld", &limit_val) == 1 && limit_val) if (ulimit(UL_SETFSIZE, limit_val) < 0) warn ("ulimit(UL_SETFSIZE, %ld)", limit_val); diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.c b/crypto/kerberosIV/appl/bsd/sysv_shadow.c index 6839441..99794bd 100644 --- a/crypto/kerberosIV/appl/bsd/sysv_shadow.c +++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.c @@ -2,7 +2,7 @@ #include "bsd_locl.h" -RCSID("$Id: sysv_shadow.c,v 1.7 1997/03/23 04:56:05 assar Exp $"); +RCSID("$Id: sysv_shadow.c,v 1.8 1997/12/29 19:56:07 bg Exp $"); #ifdef SYSV_SHADOW @@ -16,7 +16,7 @@ sysv_expire(struct spwd *spwd) long today; tzset(); - today = time(0); + today = time(0)/(60*60*24); /* In days since Jan. 1, 1970 */ if (spwd->sp_expire > 0) { if (today > spwd->sp_expire) { diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.h b/crypto/kerberosIV/appl/bsd/sysv_shadow.h index 4f07b49..339035b 100644 --- a/crypto/kerberosIV/appl/bsd/sysv_shadow.h +++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.h @@ -1,5 +1,5 @@ -/* $Id: sysv_shadow.h,v 1.6 1997/03/23 04:55:51 assar Exp $ */ +/* $Id: sysv_shadow.h,v 1.7 1999/03/13 21:15:43 assar Exp $ */ #include <shadow.h> -extern sysv_expire(struct spwd *); +int sysv_expire(struct spwd *); diff --git a/crypto/kerberosIV/appl/bsd/utmp_login.c b/crypto/kerberosIV/appl/bsd/utmp_login.c index da3f96a..8c1a2d3 100644 --- a/crypto/kerberosIV/appl/bsd/utmp_login.c +++ b/crypto/kerberosIV/appl/bsd/utmp_login.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -38,8 +38,9 @@ #include "bsd_locl.h" -RCSID("$Id: utmp_login.c,v 1.13 1997/05/20 13:46:21 assar Exp $"); +RCSID("$Id: utmp_login.c,v 1.15 1999/03/29 17:57:16 joda Exp $"); +#ifdef HAVE_UTMP_H void prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname) { @@ -50,11 +51,11 @@ prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname) strncpy(utmp->ut_line, ttyx, sizeof(utmp->ut_line)); strncpy(utmp->ut_name, username, sizeof(utmp->ut_name)); -# ifdef HAVE_UT_USER +# ifdef HAVE_STRUCT_UTMP_UT_USER strncpy(utmp->ut_user, username, sizeof(utmp->ut_user)); # endif -# ifdef HAVE_UT_ADDR +# ifdef HAVE_STRUCT_UTMP_UT_ADDR if (hostname[0]) { struct hostent *he; if ((he = gethostbyname(hostname))) @@ -63,22 +64,23 @@ prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname) } # endif -# ifdef HAVE_UT_HOST +# ifdef HAVE_STRUCT_UTMP_UT_HOST strncpy(utmp->ut_host, hostname, sizeof(utmp->ut_host)); # endif -# ifdef HAVE_UT_TYPE +# ifdef HAVE_STRUCT_UTMP_UT_TYPE utmp->ut_type = USER_PROCESS; # endif -# ifdef HAVE_UT_PID +# ifdef HAVE_STRUCT_UTMP_UT_PID utmp->ut_pid = getpid(); # endif -# ifdef HAVE_UT_ID +# ifdef HAVE_STRUCT_UTMP_UT_ID strncpy(utmp->ut_id, make_id(ttyx), sizeof(utmp->ut_id)); # endif } +#endif #ifdef HAVE_UTMPX_H void utmp_login(char *tty, char *username, char *hostname) { return; } diff --git a/crypto/kerberosIV/appl/bsd/utmpx_login.c b/crypto/kerberosIV/appl/bsd/utmpx_login.c index 005eca5..acc6a154 100644 --- a/crypto/kerberosIV/appl/bsd/utmpx_login.c +++ b/crypto/kerberosIV/appl/bsd/utmpx_login.c @@ -2,7 +2,7 @@ #include "bsd_locl.h" -RCSID("$Id: utmpx_login.c,v 1.20 1997/06/01 03:13:15 assar Exp $"); +RCSID("$Id: utmpx_login.c,v 1.21 1999/03/29 17:57:31 joda Exp $"); /* utmpx_login - update utmp and wtmp after login */ @@ -17,12 +17,12 @@ utmpx_update(struct utmpx *ut, char *line, char *user, char *host) char *clean_tty = clean_ttyname(line); strncpy(ut->ut_line, clean_tty, sizeof(ut->ut_line)); -#ifdef HAVE_UT_ID +#ifdef HAVE_STRUCT_UTMPX_UT_ID strncpy(ut->ut_id, make_id(clean_tty), sizeof(ut->ut_id)); #endif strncpy(ut->ut_user, user, sizeof(ut->ut_user)); strncpy(ut->ut_host, host, sizeof(ut->ut_host)); -#ifdef HAVE_UT_SYSLEN +#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN ut->ut_syslen = strlen(host) + 1; if (ut->ut_syslen > sizeof(ut->ut_host)) ut->ut_syslen = sizeof(ut->ut_host); diff --git a/crypto/kerberosIV/appl/ftp/ChangeLog b/crypto/kerberosIV/appl/ftp/ChangeLog new file mode 100644 index 0000000..422f4a5 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ChangeLog @@ -0,0 +1,196 @@ +1999-08-18 Assar Westerlund <assar@sics.se> + + * ftp/cmds.c (getit): be more suspicious when parsing the result + of MDTM. Do the comparison of timestamps correctly. + +1999-06-15 Assar Westerlund <assar@sics.se> + + * ftp/krb4.c (krb4_auth): type correctness + +1999-06-02 Johan Danielsson <joda@pdc.kth.se> + + * ftp/ftp.c (sendrequest): lmode != rmode + +1999-05-21 Assar Westerlund <assar@sics.se> + + * ftp/extern.h (sendrequest): update prototype + + * ftp/cmds.c: update calls to sendrequest and recvrequest to send + "b" when appropriate + + * ftp/ftp.c (sendrequest): add argument for mode to open file in. + +1999-05-08 Assar Westerlund <assar@sics.se> + + * ftpd/ftpcmd.y: rename getline -> ftpd_getline + + * ftp/main.c (makeargv): fill in unused slots with NULL + +Thu Apr 8 15:06:40 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/ftpd.c: remove definition of KRB_VERIFY_USER (moved to + config.h) + +Wed Apr 7 16:15:21 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftp/gssapi.c (gss_auth): call gss_display_status to get a sane + error message; return AUTH_{CONTINUE,ERROR}, where appropriate + + * ftp/krb4.c: return AUTH_{CONTINUE,ERROR}, where appropriate + + * ftp/security.c (sec_login): if mechanism returns AUTH_CONTINUE, + just continue with the next mechanism, this fixes the case of + having GSSAPI fail because of non-existant of expired tickets + + * ftp/security.h: add AUTH_{OK,CONTINUE,ERROR} + +Thu Apr 1 16:59:04 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/Makefile.am: don't run check-local + + * ftp/Makefile.am: don't run check-local + +Mon Mar 22 22:15:18 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd.c (pass): fall-back for KRB_VERIFY_SECURE + + * ftpd/ftpd.c (pass): 1 -> KRB_VERIFY_SECURE + +Thu Mar 18 12:07:09 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/Makefile.am: clean ftpcmd.c + + * ftpd/ftpd_locl.h: remove krb5.h (breaks in ftpcmd.y) + + * ftpd/ftpd.c: move include of krb5.h here + + * ftpd/Makefile.am: include Makefile.am.common + + * Makefile.am: include Makefile.am.common + + * ftp/Makefile.am: include Makefile.am.common + + * common/Makefile.am: include Makefile.am.common + +Tue Mar 16 22:28:37 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd_locl.h: add krb5.h to get heimdal_version + + * ftpd/ftpd.c: krb_verify_user_multiple -> krb_verify_user + +Thu Mar 11 14:54:59 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftp/Makefile.in: WFLAGS + + * ftp/ruserpass.c: add some if-braces + +Wed Mar 10 20:02:55 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/ftpd_locl.h: remove ifdef HAVE_FNMATCH + +Mon Mar 8 21:29:24 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/ftpd.c: re-add version in greeting message + +Mon Mar 1 10:49:38 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/logwtmp.c: HAVE_UT_* -> HAVE_STRUCT_UTMP*_UT_* + +Mon Feb 22 19:20:51 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * common/Makefile.in: remove glob + +Sat Feb 13 17:19:35 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd.c (match): remove #ifdef HAVE_FNMATCH. We have a + fnmatch implementation in roken and therefore always have it. + + * ftp/ftp.c (copy_stream): initialize `werr' + +Wed Jan 13 23:52:57 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpcmd.y: moved all check_login and check_login_no_guest to + the end of the rules to ensure we don't generate several + (independent) error messages. once again, having a yacc-grammar + for FTP with embedded actions doesn't strike me as the most + optimal way of doing it. + +Tue Dec 1 14:44:29 1998 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/Makefile.am: link with extra libs for aix + +Sun Nov 22 10:28:20 1998 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd.c (retrying): support on-the-fly decompression + + * ftpd/Makefile.in (WFLAGS): set + + * ftp/ruserpass.c (guess_domain): new function + (ruserpass): use it + + * common/Makefile.in (WFLAGS): set + + * Makefile.in (WFLAGS): set + +Sat Nov 21 23:13:03 1998 Assar Westerlund <assar@sics.se> + + * ftp/security.c: some more type correctness. + + * ftp/gssapi.c (gss_adat): more braces to shut up warnings + +Wed Nov 18 21:47:55 1998 Assar Westerlund <assar@sics.se> + + * ftp/main.c (main): new option `-p' for enable passive mode. + +Mon Nov 2 01:57:49 1998 Assar Westerlund <assar@sics.se> + + * ftp/ftp.c (getreply): remove extra `break' + + * ftp/gssapi.c (gss_auth): fixo typo(copyo?) + + * ftp/security.c (sec_login): fix loop and return value + +Tue Sep 1 16:56:42 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/cmds.c (quote1): fix % quoting bug + +Fri Aug 14 17:10:06 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/krb4.c: krb_put_int -> KRB_PUT_INT + +Tue Jun 30 18:07:15 1998 Assar Westerlund <assar@sics.se> + + * ftp/security.c (auth): free `app_data' + (sec_end): only destroy if it was initialized + +Tue Jun 9 21:01:59 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/krb4.c: pass client address to krb_rd_req + +Sat May 16 00:02:07 1998 Assar Westerlund <assar@sics.se> + + * ftpd/Makefile.am: link with DBLIB + +Tue May 12 14:15:32 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/gssapi.c: Save client name for userok(). + + * ftpd/gss_userok.c: Userok for gssapi. + +Fri May 1 07:15:01 1998 Assar Westerlund <assar@sics.se> + + * ftp/ftp.c: unifdef -DHAVE_H_ERRNO + +Fri Mar 27 00:46:07 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * Make compile w/o krb4. + +Thu Mar 26 03:49:12 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/*, ftpd/*: Changes for new framework. + + * ftp/gssapi.c: GSS-API backend for the new security framework. + + * ftp/krb4.c: Updated for new framework. + + * ftp/security.{c,h}: New unified security framework. diff --git a/crypto/kerberosIV/appl/ftp/Makefile.am b/crypto/kerberosIV/appl/ftp/Makefile.am new file mode 100644 index 0000000..f8831a3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/Makefile.am @@ -0,0 +1,5 @@ +# $Id: Makefile.am,v 1.5 1999/03/20 13:58:14 joda Exp $ + +include $(top_srcdir)/Makefile.am.common + +SUBDIRS = common ftp ftpd diff --git a/crypto/kerberosIV/appl/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/Makefile.in index 6d0c420..68546ab 100644 --- a/crypto/kerberosIV/appl/ftp/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.9 1997/03/23 13:03:54 assar Exp $ +# $Id: Makefile.in,v 1.12 1999/03/10 19:01:11 joda Exp $ srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -11,7 +11,8 @@ SHELL = /bin/sh CC = @CC@ RANLIB = @RANLIB@ DEFS = @DEFS@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ INSTALL = @INSTALL@ @@ -39,3 +40,5 @@ distclean: for i in $(SUBDIRS); \ do (cd $$i && $(MAKE) $(MFLAGS) distclean); done rm -f Makefile *~ + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/common/Makefile.am b/crypto/kerberosIV/appl/ftp/common/Makefile.am new file mode 100644 index 0000000..2ab5801 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/Makefile.am @@ -0,0 +1,12 @@ +# $Id: Makefile.am,v 1.7 1999/03/20 13:58:14 joda Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += $(INCLUDE_krb4) + +noinst_LIBRARIES = libcommon.a + +libcommon_a_SOURCES = \ + sockbuf.c \ + buffer.c \ + common.h diff --git a/crypto/kerberosIV/appl/ftp/common/Makefile.in b/crypto/kerberosIV/appl/ftp/common/Makefile.in index 9ce1aa5..b00bd0a 100644 --- a/crypto/kerberosIV/appl/ftp/common/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/common/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.17 1997/05/18 20:00:06 assar Exp $ +# $Id: Makefile.in,v 1.23 1999/03/10 19:01:11 joda Exp $ SHELL = /bin/sh @@ -10,16 +10,17 @@ CC = @CC@ AR = ar RANLIB = @RANLIB@ DEFS = @DEFS@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ INSTALL = @INSTALL@ prefix = @prefix@ -SOURCES = base64.c glob.c sockbuf.c buffer.c +SOURCES = sockbuf.c buffer.c OBJECTS = $(libcommon_OBJS) -libcommon_OBJS = base64.o glob.o sockbuf.o buffer.o +libcommon_OBJS = sockbuf.o buffer.o LIBNAME = $(LIBPREFIX)common LIBEXT = a @@ -29,7 +30,7 @@ LIB = $(LIBNAME).$(LIBEXT) all: $(LIB) .c.o: - $(CC) -c $(CFLAGS) -I$(srcdir) -I../../../include $(DEFS) $< + $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $< $(LIB): $(libcommon_OBJS) rm -f $@ @@ -50,3 +51,5 @@ distclean: rm -f Makefile $(OBJECTS): ../../../include/config.h + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/common/buffer.c b/crypto/kerberosIV/appl/ftp/common/buffer.c index 5b7829a..97e2815 100644 --- a/crypto/kerberosIV/appl/ftp/common/buffer.c +++ b/crypto/kerberosIV/appl/ftp/common/buffer.c @@ -38,9 +38,10 @@ #include "common.h" #include <stdio.h> +#include <err.h> #include "roken.h" -RCSID("$Id: buffer.c,v 1.1 1997/05/18 19:59:24 assar Exp $"); +RCSID("$Id: buffer.c,v 1.2 1997/12/14 23:51:45 assar Exp $"); /* * Allocate a buffer enough to handle st->st_blksize, if diff --git a/crypto/kerberosIV/appl/ftp/ftp/Makefile.am b/crypto/kerberosIV/appl/ftp/ftp/Makefile.am new file mode 100644 index 0000000..081465a --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.am @@ -0,0 +1,44 @@ +# $Id: Makefile.am,v 1.12 1999/04/09 18:22:08 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += -I$(srcdir)/../common $(INCLUDE_readline) $(INCLUDE_krb4) + +bin_PROGRAMS = ftp + +CHECK_LOCAL = + +if KRB4 +krb4_sources = krb4.c kauth.c +endif +if KRB5 +krb5_sources = gssapi.c +endif + +ftp_SOURCES = \ + cmds.c \ + cmdtab.c \ + extern.h \ + ftp.c \ + ftp_locl.h \ + ftp_var.h \ + main.c \ + pathnames.h \ + ruserpass.c \ + domacro.c \ + globals.c \ + security.c \ + security.h \ + $(krb4_sources) \ + $(krb5_sources) + +EXTRA_ftp_SOURCES = krb4.c kauth.c gssapi.c + +LDADD = \ + ../common/libcommon.a \ + $(LIB_gssapi) \ + $(LIB_krb5) \ + $(LIB_krb4) \ + $(top_builddir)/lib/des/libdes.la \ + $(LIB_roken) \ + $(LIB_readline) diff --git a/crypto/kerberosIV/appl/ftp/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in index 62bde3b..637d553 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in @@ -1,5 +1,5 @@ # -# $Id: Makefile.in,v 1.24 1997/03/23 13:03:55 assar Exp $ +# $Id: Makefile.in,v 1.32 1999/03/11 13:58:09 joda Exp $ # SHELL = /bin/sh @@ -8,13 +8,14 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -topdir = ../../.. +top_builddir = ../../.. CC = @CC@ RANLIB = @RANLIB@ DEFS = @DEFS@ -CFLAGS = @CFLAGS@ -CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I$(topdir) -I$(top_srcdir) -I$(topdir)/include -I$(top_srcdir)/include -I$(srcdir)/../common @INCLUDE_readline@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ +CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir)/../common @INCLUDE_readline@ LD_FLAGS = @LD_FLAGS@ LIB_tgetent = @LIB_tgetent@ LIBS = @LIBS@ @LIB_readline@ @@ -30,17 +31,35 @@ libdir = @libdir@ transform=@program_transform_name@ EXECSUFFIX=@EXECSUFFIX@ -INCTOP = $(topdir)/include +INCTOP = $(top_builddir)/include -LIBTOP = $(topdir)/lib +LIBTOP = $(top_builddir)/lib PROGS = ftp$(EXECSUFFIX) -ftp_OBJS = cmds.o cmdtab.o ftp.o krb4.o main.o ruserpass.o domacro.o \ - globals.o kauth.o - -ftp_SOURCES = cmds.c cmdtab.c ftp.c krb4.c main.c ruserpass.c \ - domacro.c globals.c kauth.c +ftp_SOURCES = \ + cmds.c \ + cmdtab.c \ + domacro.c \ + ftp.c \ + globals.c \ + kauth.c \ + krb4.c \ + main.c \ + ruserpass.c \ + security.c + +ftp_OBJS = \ + cmds.o \ + cmdtab.o \ + domacro.o \ + ftp.o \ + globals.o \ + kauth.o \ + krb4.o \ + main.o \ + ruserpass.o \ + security.o OBJECTS = $(ftp_OBJS) SOURCES = $(ftp_SOURCES) @@ -48,29 +67,36 @@ SOURCES = $(ftp_SOURCES) all: $(PROGS) .c.o: - $(CC) -c $(CFLAGS) $(CPPFLAGS) $(DEFS) $< + $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $< install: all - $(MKINSTALLDIRS) $(bindir) + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) for x in $(PROGS); do \ - $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done uninstall: for x in $(PROGS); do \ - rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \ + rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done -ftp$(EXECSUFFIX): $(ftp_OBJS) # ../common/libcommon.a +ftp$(EXECSUFFIX): $(ftp_OBJS) $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(ftp_OBJS) -L../common -lcommon -L$(LIBTOP)/krb -lkrb -L$(LIBTOP)/des -ldes -L$(LIBTOP)/roken -lroken $(LIBS) -L$(LIBTOP)/roken -lroken -TAGS: $(SOURCES) +TAGS: $(SOURCES) etags $(SOURCES) -clean cleandir: - rm -f *~ *.o core ftp \#* +clean: + rm -f *~ *.o core ftp$(EXECSUFFIX) \#* + +mostlyclean: clean -distclean: +distclean: clean rm -f Makefile +realclean: distclean + rm -f TAGS + $(OBJECTS): ../../../include/config.h + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/ftp/cmds.c b/crypto/kerberosIV/appl/ftp/ftp/cmds.c index 5e1980b..1571fc8 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/cmds.c +++ b/crypto/kerberosIV/appl/ftp/ftp/cmds.c @@ -36,7 +36,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: cmds.c,v 1.23 1997/06/01 22:52:37 assar Exp $"); +RCSID("$Id: cmds.c,v 1.34.2.1 1999/08/18 18:19:44 assar Exp $"); typedef void (*sighand)(int); @@ -119,12 +119,17 @@ setpeer(int argc, char **argv) /* * Set up defaults for FTP. */ - strcpy(typename, "ascii"), type = TYPE_A; + strcpy_truncate(typename, "ascii", sizeof(typename)); + type = TYPE_A; curtype = TYPE_A; - strcpy(formname, "non-print"), form = FORM_N; - strcpy(modename, "stream"), mode = MODE_S; - strcpy(structname, "file"), stru = STRU_F; - strcpy(bytename, "8"), bytesize = 8; + strcpy_truncate(formname, "non-print", sizeof(formname)); + form = FORM_N; + strcpy_truncate(modename, "stream", sizeof(modename)); + mode = MODE_S; + strcpy_truncate(structname, "file", sizeof(structname)); + stru = STRU_F; + strcpy_truncate(bytename, "8", sizeof(bytename)); + bytesize = 8; if (autologin) login(argv[1]); @@ -165,7 +170,7 @@ setpeer(int argc, char **argv) * for text files unless changed by the user. */ type = 0; - strcpy(typename, "binary"); + strcpy_truncate(typename, "binary", sizeof(typename)); if (overbose) printf("Using %s mode to transfer files.\n", typename); @@ -238,7 +243,7 @@ settype(int argc, char **argv) else comret = command("TYPE %s", p->t_mode); if (comret == COMPLETE) { - strcpy(typename, p->t_name); + strcpy_truncate(typename, p->t_name, sizeof(typename)); curtype = type = p->t_type; } } @@ -398,7 +403,8 @@ usage: argv[2] = domap(argv[2]); } sendrequest(cmd, argv[1], argv[2], - argv[1] != oldargv1 || argv[2] != oldargv2); + curtype == TYPE_I ? "rb" : "r", + argv[1] != oldargv1 || argv[2] != oldargv2); } /* ARGSUSED */ @@ -428,133 +434,150 @@ mabort(int signo) void mput(int argc, char **argv) { - int i; - RETSIGTYPE (*oldintr)(); - int ointer; - char *tp; + int i; + RETSIGTYPE (*oldintr)(); + int ointer; + char *tp; - if (argc < 2 && !another(&argc, &argv, "local-files")) { - printf("usage: %s local-files\n", argv[0]); - code = -1; - return; - } - mname = argv[0]; - mflag = 1; - oldintr = signal(SIGINT, mabort); - setjmp(jabort); - if (proxy) { - char *cp, *tp2, tmpbuf[MaxPathLen]; + if (argc < 2 && !another(&argc, &argv, "local-files")) { + printf("usage: %s local-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + setjmp(jabort); + if (proxy) { + char *cp, *tp2, tmpbuf[MaxPathLen]; - while ((cp = remglob(argv,0)) != NULL) { - if (*cp == 0) { - mflag = 0; - continue; - } - if (mflag && confirm(argv[0], cp)) { - tp = cp; - if (mcase) { - while (*tp && !islower(*tp)) { - tp++; - } - if (!*tp) { - tp = cp; - tp2 = tmpbuf; - while ((*tp2 = *tp) != '\0') { - if (isupper(*tp2)) { - *tp2 = 'a' + *tp2 - 'A'; - } - tp++; - tp2++; - } - } - tp = tmpbuf; - } - if (ntflag) { - tp = dotrans(tp); - } - if (mapflag) { - tp = domap(tp); - } - sendrequest((sunique) ? "STOU" : "STOR", - cp, tp, cp != tp || !interactive); - if (!mflag && fromatty) { - ointer = interactive; - interactive = 1; - if (confirm("Continue with","mput")) { - mflag++; - } - interactive = ointer; - } - } - } - signal(SIGINT, oldintr); + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == 0) { mflag = 0; - return; - } - for (i = 1; i < argc; i++) { - char **cpp; - glob_t gl; - int flags; - - if (!doglob) { - if (mflag && confirm(argv[0], argv[i])) { - tp = (ntflag) ? dotrans(argv[i]) : argv[i]; - tp = (mapflag) ? domap(tp) : tp; - sendrequest((sunique) ? "STOU" : "STOR", - argv[i], tp, tp != argv[i] || !interactive); - if (!mflag && fromatty) { - ointer = interactive; - interactive = 1; - if (confirm("Continue with","mput")) { - mflag++; - } - interactive = ointer; - } + continue; + } + if (mflag && confirm(argv[0], cp)) { + tp = cp; + if (mcase) { + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = cp; + tp2 = tmpbuf; + while ((*tp2 = *tp) != '\0') { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; } - continue; + } + tp = tmpbuf; } - - memset(&gl, 0, sizeof(gl)); - flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; - if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { - warnx("%s: not found", argv[i]); - globfree(&gl); - continue; + if (ntflag) { + tp = dotrans(tp); } - for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) { - if (mflag && confirm(argv[0], *cpp)) { - tp = (ntflag) ? dotrans(*cpp) : *cpp; - tp = (mapflag) ? domap(tp) : tp; - sendrequest((sunique) ? "STOU" : "STOR", - *cpp, tp, *cpp != tp || !interactive); - if (!mflag && fromatty) { - ointer = interactive; - interactive = 1; - if (confirm("Continue with","mput")) { - mflag++; - } - interactive = ointer; - } - } + if (mapflag) { + tp = domap(tp); } - globfree(&gl); + sendrequest((sunique) ? "STOU" : "STOR", + cp, tp, + curtype == TYPE_I ? "rb" : "r", + cp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } } signal(SIGINT, oldintr); mflag = 0; + return; + } + for (i = 1; i < argc; i++) { + char **cpp; + glob_t gl; + int flags; + + if (!doglob) { + if (mflag && confirm(argv[0], argv[i])) { + tp = (ntflag) ? dotrans(argv[i]) : argv[i]; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + argv[i], + curtype == TYPE_I ? "rb" : "r", + tp, tp != argv[i] || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + continue; + } + + memset(&gl, 0, sizeof(gl)); + flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { + warnx("%s: not found", argv[i]); + globfree(&gl); + continue; + } + for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) { + if (mflag && confirm(argv[0], *cpp)) { + tp = (ntflag) ? dotrans(*cpp) : *cpp; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + *cpp, tp, + curtype == TYPE_I ? "rb" : "r", + *cpp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + } + globfree(&gl); + } + signal(SIGINT, oldintr); + mflag = 0; } void reget(int argc, char **argv) { - - getit(argc, argv, 1, "r+w"); + getit(argc, argv, 1, curtype == TYPE_I ? "r+wb" : "r+w"); } void get(int argc, char **argv) { + char *mode; - getit(argc, argv, 0, restart_point ? "r+w" : "w" ); + if (restart_point) + if (curtype == TYPE_I) + mode = "r+wb"; + else + mode = "r+w"; + else + if (curtype == TYPE_I) + mode = "wb"; + else + mode = "w"; + + getit(argc, argv, 0, mode); } /* @@ -564,17 +587,17 @@ int getit(int argc, char **argv, int restartit, char *mode) { int loc = 0; + int local_given = 1; char *oldargv1, *oldargv2; if (argc == 2) { argc++; + local_given = 0; argv[2] = argv[1]; loc++; } - if (argc < 2 && !another(&argc, &argv, "remote-file")) - goto usage; - if (argc < 3 && !another(&argc, &argv, "local-file")) { -usage: + if ((argc < 2 && !another(&argc, &argv, "remote-file")) || + (argc < 3 && !another(&argc, &argv, "local-file"))) { printf("usage: %s remote-file [ local-file ]\n", argv[0]); code = -1; return (0); @@ -619,50 +642,60 @@ usage: return (0); } restart_point = stbuf.st_size; - } else { - if (ret == 0) { - int overbose; - - overbose = verbose; - if (debug == 0) - verbose = -1; - if (command("MDTM %s", argv[1]) == COMPLETE) { - int yy, mo, day, hour, min, sec; - struct tm *tm; - verbose = overbose; - sscanf(reply_string, - "%*s %04d%02d%02d%02d%02d%02d", - &yy, &mo, &day, &hour, &min, &sec); - tm = gmtime(&stbuf.st_mtime); - tm->tm_mon++; - if (tm->tm_year > yy%100) - return (1); - if ((tm->tm_year == yy%100 && - tm->tm_mon > mo) || - (tm->tm_mon == mo && - tm->tm_mday > day) || - (tm->tm_mday == day && - tm->tm_hour > hour) || - (tm->tm_hour == hour && - tm->tm_min > min) || - (tm->tm_min == min && - tm->tm_sec > sec)) - return (1); - } else { - printf("%s\n", reply_string); - verbose = overbose; - return (0); - } + } else if (ret == 0) { + int overbose; + int cmdret; + int yy, mo, day, hour, min, sec; + struct tm *tm; + + overbose = verbose; + if (debug == 0) + verbose = -1; + cmdret = command("MDTM %s", argv[1]); + verbose = overbose; + if (cmdret != COMPLETE) { + printf("%s\n", reply_string); + return (0); + } + if (sscanf(reply_string, + "%*s %04d%02d%02d%02d%02d%02d", + &yy, &mo, &day, &hour, &min, &sec) + != 6) { + printf ("bad MDTM result\n"); + return (0); } + + tm = gmtime(&stbuf.st_mtime); + tm->tm_mon++; + tm->tm_year += 1900; + + if ((tm->tm_year > yy) || + (tm->tm_year == yy && + tm->tm_mon > mo) || + (tm->tm_mon == mo && + tm->tm_mday > day) || + (tm->tm_mday == day && + tm->tm_hour > hour) || + (tm->tm_hour == hour && + tm->tm_min > min) || + (tm->tm_min == min && + tm->tm_sec > sec)) + return (1); } } recvrequest("RETR", argv[2], argv[1], mode, - argv[1] != oldargv1 || argv[2] != oldargv2); + argv[1] != oldargv1 || argv[2] != oldargv2, local_given); restart_point = 0; return (0); } +static int +suspicious_filename(const char *fn) +{ + return strstr(fn, "../") != NULL || *fn == '/'; +} + /* * Get multiple files. */ @@ -687,6 +720,8 @@ mget(int argc, char **argv) mflag = 0; continue; } + if (mflag && suspicious_filename(cp)) + printf("*** Suspicious filename: %s\n", cp); if (mflag && confirm(argv[0], cp)) { tp = cp; if (mcase) { @@ -701,8 +736,9 @@ mget(int argc, char **argv) if (mapflag) { tp = domap(tp); } - recvrequest("RETR", tp, cp, "w", - tp != cp || !interactive); + recvrequest("RETR", tp, cp, + curtype == TYPE_I ? "wb" : "w", + tp != cp || !interactive, 0); if (!mflag && fromatty) { ointer = interactive; interactive = 1; @@ -720,61 +756,71 @@ mget(int argc, char **argv) char * remglob(char **argv, int doswitch) { - char temp[16]; - static char buf[MaxPathLen]; - static FILE *ftemp = NULL; - static char **args; - int oldverbose, oldhash; - char *cp, *mode; + char temp[16]; + static char buf[MaxPathLen]; + static FILE *ftemp = NULL; + static char **args; + int oldverbose, oldhash; + char *cp, *mode; - if (!mflag) { - if (!doglob) { - args = NULL; - } - else { - if (ftemp) { - fclose(ftemp); - ftemp = NULL; - } - } - return (NULL); - } + if (!mflag) { if (!doglob) { - if (args == NULL) - args = argv; - if ((cp = *++args) == NULL) - args = NULL; - return (cp); + args = NULL; } - if (ftemp == NULL) { - strcpy(temp, _PATH_TMP_XXX); - mktemp(temp); - oldverbose = verbose, verbose = 0; - oldhash = hash, hash = 0; - if (doswitch) { - pswitch(!proxy); - } - for (mode = "w"; *++argv != NULL; mode = "a") - recvrequest ("NLST", temp, *argv, mode, 0); - if (doswitch) { - pswitch(!proxy); - } - verbose = oldverbose; hash = oldhash; - ftemp = fopen(temp, "r"); - unlink(temp); - if (ftemp == NULL) { - printf("can't find list of remote files, oops\n"); - return (NULL); - } - } - if (fgets(buf, sizeof (buf), ftemp) == NULL) { + else { + if (ftemp) { fclose(ftemp); ftemp = NULL; - return (NULL); + } } + return (NULL); + } + if (!doglob) { + if (args == NULL) + args = argv; + if ((cp = *++args) == NULL) + args = NULL; + return (cp); + } + if (ftemp == NULL) { + int fd; + strcpy_truncate(temp, _PATH_TMP_XXX, sizeof(temp)); + fd = mkstemp(temp); + if(fd < 0){ + warn("unable to create temporary file %s", temp); + return NULL; + } + close(fd); + oldverbose = verbose, verbose = 0; + oldhash = hash, hash = 0; + if (doswitch) { + pswitch(!proxy); + } + for (mode = "w"; *++argv != NULL; mode = "a") + recvrequest ("NLST", temp, *argv, mode, 0, 0); + if (doswitch) { + pswitch(!proxy); + } + verbose = oldverbose; hash = oldhash; + ftemp = fopen(temp, "r"); + unlink(temp); + if (ftemp == NULL) { + printf("can't find list of remote files, oops\n"); + return (NULL); + } + } + while(fgets(buf, sizeof (buf), ftemp)) { if ((cp = strchr(buf, '\n')) != NULL) - *cp = '\0'; - return (buf); + *cp = '\0'; + if(!interactive && suspicious_filename(buf)){ + printf("Ignoring remote globbed file `%s'\n", buf); + continue; + } + return buf; + } + fclose(ftemp); + ftemp = NULL; + return (NULL); } char * @@ -1036,38 +1082,38 @@ delete(int argc, char **argv) void mdelete(int argc, char **argv) { - sighand oldintr; - int ointer; - char *cp; + sighand oldintr; + int ointer; + char *cp; - if (argc < 2 && !another(&argc, &argv, "remote-files")) { - printf("usage: %s remote-files\n", argv[0]); - code = -1; - return; - } - mname = argv[0]; - mflag = 1; - oldintr = signal(SIGINT, mabort); - setjmp(jabort); - while ((cp = remglob(argv,0)) != NULL) { - if (*cp == '\0') { - mflag = 0; - continue; - } - if (mflag && confirm(argv[0], cp)) { - command("DELE %s", cp); - if (!mflag && fromatty) { - ointer = interactive; - interactive = 1; - if (confirm("Continue with", "mdelete")) { - mflag++; - } - interactive = ointer; - } + if (argc < 2 && !another(&argc, &argv, "remote-files")) { + printf("usage: %s remote-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + setjmp(jabort); + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + command("DELE %s", cp); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mdelete")) { + mflag++; } + interactive = ointer; + } } - signal(SIGINT, oldintr); - mflag = 0; + } + signal(SIGINT, oldintr); + mflag = 0; } /* @@ -1113,11 +1159,12 @@ ls(int argc, char **argv) return; } if (strcmp(argv[2], "-") && *argv[2] != '|') - if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { - code = -1; - return; - } - recvrequest(cmd, argv[2], argv[1], "w", 0); + if (!globulize(&argv[2]) || !confirm("output to local-file:", + argv[2])) { + code = -1; + return; + } + recvrequest(cmd, argv[2], argv[1], "w", 0, 1); } /* @@ -1154,7 +1201,7 @@ usage: setjmp(jabort); for (i = 1; mflag && i < argc-1; ++i) { *mode = (i == 1) ? 'w' : 'a'; - recvrequest(cmd, dest, argv[i], mode, 0); + recvrequest(cmd, dest, argv[i], mode, 0, 1); if (!mflag && fromatty) { ointer = interactive; interactive = 1; @@ -1193,8 +1240,8 @@ shell(int argc, char **argv) namep = strrchr(shell,'/'); if (namep == NULL) namep = shell; - strcpy(shellnam,"-"); - strcat(shellnam, ++namep); + snprintf (shellnam, sizeof(shellnam), + "-%s", ++namep); if (strcmp(namep, "sh") != 0) shellnam[0] = '+'; if (debug) { @@ -1369,22 +1416,19 @@ site(int argc, char **argv) void quote1(char *initial, int argc, char **argv) { - int i, len; - char buf[BUFSIZ]; /* must be >= sizeof(line) */ + int i; + char buf[BUFSIZ]; /* must be >= sizeof(line) */ - strcpy(buf, initial); - if (argc > 1) { - len = strlen(buf); - len += strlen(strcpy(&buf[len], argv[1])); - for (i = 2; i < argc; i++) { - buf[len++] = ' '; - len += strlen(strcpy(&buf[len], argv[i])); - } - } - if (command(buf) == PRELIM) { - while (getreply(0) == PRELIM) - continue; - } + strcpy_truncate(buf, initial, sizeof(buf)); + for(i = 1; i < argc; i++) { + if(i > 1) + strcat_truncate(buf, " ", sizeof(buf)); + strcat_truncate(buf, argv[i], sizeof(buf)); + } + if (command("%s", buf) == PRELIM) { + while (getreply(0) == PRELIM) + continue; + } } void @@ -1467,7 +1511,7 @@ disconnect(int argc, char **argv) } cout = NULL; connected = 0; - krb4_quit(); + sec_end(); data = -1; if (!proxy) { macnum = 0; @@ -1485,7 +1529,7 @@ confirm(char *cmd, char *file) fflush(stdout); if (fgets(line, sizeof line, stdin) == NULL) return (0); - return (*line != 'n' && *line != 'N'); + return (*line == 'y' || *line == 'Y'); } void @@ -1531,12 +1575,11 @@ account(int argc, char **argv) if (argc > 1) { ++argv; --argc; - strncpy(acct,*argv,49); - acct[49] = '\0'; + strcpy_truncate (acct, *argv, sizeof(acct)); while (argc > 1) { --argc; ++argv; - strncat(acct,*argv, 49-strlen(acct)); + strcat_truncate(acct, *argv, sizeof(acct)); } } else { @@ -1648,14 +1691,12 @@ setntrans(int argc, char **argv) } ntflag++; code = ntflag; - strncpy(ntin, argv[1], 16); - ntin[16] = '\0'; + strcpy_truncate (ntin, argv[1], 17); if (argc == 2) { ntout[0] = '\0'; return; } - strncpy(ntout, argv[2], 16); - ntout[16] = '\0'; + strcpy_truncate (ntout, argv[2], 17); } char * @@ -1712,10 +1753,10 @@ setnmap(int argc, char **argv) cp = strchr(altarg, ' '); } *cp = '\0'; - strncpy(mapin, altarg, MaxPathLen - 1); + strcpy_truncate(mapin, altarg, MaxPathLen); while (*++cp == ' ') continue; - strncpy(mapout, cp, MaxPathLen - 1); + strcpy_truncate(mapout, cp, MaxPathLen); } char * @@ -1967,7 +2008,9 @@ macdef(int argc, char **argv) if (interactive) { printf("Enter macro line by line, terminating it with a null line\n"); } - strncpy(macros[macnum].mac_name, argv[1], 8); + strcpy_truncate(macros[macnum].mac_name, + argv[1], + sizeof(macros[macnum].mac_name)); if (macnum == 0) { macros[macnum].mac_start = macbuf; } @@ -2067,7 +2110,7 @@ void newer(int argc, char **argv) { - if (getit(argc, argv, -1, "w")) + if (getit(argc, argv, -1, curtype == TYPE_I ? "wb" : "w")) printf("Local file \"%s\" is newer than remote file \"%s\"\n", argv[2], argv[1]); } diff --git a/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c index 9567e3c..5dc96ef 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c +++ b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c @@ -105,9 +105,13 @@ char userhelp[] = "send new user information"; char verbosehelp[] = "toggle verbose mode"; char prothelp[] = "set protection level"; +#ifdef KRB4 char kauthhelp[] = "get remote tokens"; char klisthelp[] = "show remote tickets"; -char aklog[] = "obtain remote AFS tokens"; +char kdestroyhelp[] = "destroy remote tickets"; +char krbtkfilehelp[] = "set filename of remote tickets"; +char afsloghelp[] = "obtain remote AFS tokens"; +#endif struct cmd cmdtab[] = { { "!", shellhelp, 0, 0, 0, shell }, @@ -184,8 +188,13 @@ struct cmd cmdtab[] = { { "?", helphelp, 0, 0, 1, help }, { "prot", prothelp, 0, 1, 0, sec_prot }, +#ifdef KRB4 { "kauth", kauthhelp, 0, 1, 0, kauth }, { "klist", klisthelp, 0, 1, 0, klist }, + { "kdestroy", kdestroyhelp, 0, 1, 0, kdestroy }, + { "krbtkfile", krbtkfilehelp, 0, 1, 0, krbtkfile }, + { "afslog", afsloghelp, 0, 1, 0, afslog }, +#endif { 0 }, }; diff --git a/crypto/kerberosIV/appl/ftp/ftp/domacro.c b/crypto/kerberosIV/appl/ftp/ftp/domacro.c index f5a89b9..432e3e5 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/domacro.c +++ b/crypto/kerberosIV/appl/ftp/ftp/domacro.c @@ -32,7 +32,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: domacro.c,v 1.5 1996/11/17 20:23:10 assar Exp $"); +RCSID("$Id: domacro.c,v 1.6 1998/06/09 19:24:21 joda Exp $"); void domacro(int argc, char **argv) @@ -56,7 +56,7 @@ domacro(int argc, char **argv) code = -1; return; } - strcpy(line2, line); + strcpy_truncate(line2, line, sizeof(line2)); TOP: cp1 = macros[i].mac_start; while (cp1 != macros[i].mac_end) { diff --git a/crypto/kerberosIV/appl/ftp/ftp/extern.h b/crypto/kerberosIV/appl/ftp/ftp/extern.h index b830999..5efe918 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/extern.h +++ b/crypto/kerberosIV/appl/ftp/ftp/extern.h @@ -33,7 +33,7 @@ * @(#)extern.h 8.3 (Berkeley) 10/9/94 */ -/* $Id: extern.h,v 1.13 1997/04/20 05:46:48 assar Exp $ */ +/* $Id: extern.h,v 1.16 1999/05/21 09:21:51 assar Exp $ */ #include <setjmp.h> #include <stdlib.h> @@ -107,7 +107,7 @@ void pwd (int, char **); void quit (int, char **); void quote (int, char **); void quote1 (char *, int, char **); -void recvrequest (char *, char *, char *, char *, int); +void recvrequest (char *, char *, char *, char *, int, int); void reget (int, char **); char *remglob (char **, int); void removedir (int, char **); @@ -117,7 +117,7 @@ void restart (int, char **); void rmthelp (int, char **); void rmtstatus (int, char **); int ruserpass (char *, char **, char **, char **); -void sendrequest (char *, char *, char *, int); +void sendrequest (char *, char *, char *, char *, int); void setascii (int, char **); void setbell (int, char **); void setbinary (int, char **); @@ -165,3 +165,9 @@ extern int NCMDS; extern char username[32]; extern char myhostname[]; extern char *mydomain; + +void afslog (int, char **); +void kauth (int, char **); +void kdestroy (int, char **); +void klist (int, char **); +void krbtkfile (int, char **); diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp.c b/crypto/kerberosIV/appl/ftp/ftp/ftp.c index cfabda6..3021a19 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/ftp.c +++ b/crypto/kerberosIV/appl/ftp/ftp/ftp.c @@ -32,42 +32,38 @@ */ #include "ftp_locl.h" -RCSID("$Id: ftp.c,v 1.44 1997/05/18 20:00:31 assar Exp $"); +RCSID ("$Id: ftp.c,v 1.55 1999/06/02 20:12:22 joda Exp $"); -struct sockaddr_in hisctladdr; -struct sockaddr_in data_addr; -int data = -1; -int abrtflag = 0; -jmp_buf ptabort; -int ptabflg; -int ptflag = 0; -struct sockaddr_in myctladdr; -off_t restart_point = 0; +struct sockaddr_in hisctladdr; +struct sockaddr_in data_addr; +int data = -1; +int abrtflag = 0; +jmp_buf ptabort; +int ptabflg; +int ptflag = 0; +struct sockaddr_in myctladdr; +off_t restart_point = 0; -FILE *cin, *cout; +FILE *cin, *cout; -typedef void (*sighand)(int); +typedef void (*sighand) (int); char * -hookup(char *host, int port) +hookup (char *host, int port) { struct hostent *hp = 0; - int s, len, tos; - static char hostnamebuf[80]; + int s, len; + static char hostnamebuf[MaxHostNameLen]; - memset(&hisctladdr, 0, sizeof (hisctladdr)); - if(inet_aton(host, &hisctladdr.sin_addr)){ + memset (&hisctladdr, 0, sizeof (hisctladdr)); + if (inet_aton (host, &hisctladdr.sin_addr)) { hisctladdr.sin_family = AF_INET; - strncpy(hostnamebuf, host, sizeof(hostnamebuf)); + strcpy_truncate (hostnamebuf, host, sizeof (hostnamebuf)); } else { - hp = gethostbyname(host); + hp = gethostbyname (host); if (hp == NULL) { -#ifdef HAVE_H_ERRNO warnx("%s: %s", host, hstrerror(h_errno)); -#else - warnx("%s: %s", host, "unknown error"); -#endif code = -1; return NULL; } @@ -75,73 +71,75 @@ hookup(char *host, int port) memmove(&hisctladdr.sin_addr, hp->h_addr_list[0], sizeof(hisctladdr.sin_addr)); - strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); - hostnamebuf[sizeof(hostnamebuf) - 1] = '\0'; + strcpy_truncate (hostnamebuf, hp->h_name, sizeof (hostnamebuf)); } hostname = hostnamebuf; - s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + s = socket (hisctladdr.sin_family, SOCK_STREAM, 0); if (s < 0) { - warn("socket"); + warn ("socket"); code = -1; return (0); } hisctladdr.sin_port = port; - while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { + while (connect (s, (struct sockaddr *) & hisctladdr, sizeof (hisctladdr)) < 0) { if (hp && hp->h_addr_list[1]) { int oerrno = errno; char *ia; - ia = inet_ntoa(hisctladdr.sin_addr); + ia = inet_ntoa (hisctladdr.sin_addr); errno = oerrno; - warn("connect to address %s", ia); + warn ("connect to address %s", ia); hp->h_addr_list++; - memmove(&hisctladdr.sin_addr, - hp->h_addr_list[0], - sizeof(hisctladdr.sin_addr)); - fprintf(stdout, "Trying %s...\n", - inet_ntoa(hisctladdr.sin_addr)); - close(s); - s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + memmove (&hisctladdr.sin_addr, + hp->h_addr_list[0], + sizeof (hisctladdr.sin_addr)); + fprintf (stdout, "Trying %s...\n", + inet_ntoa (hisctladdr.sin_addr)); + close (s); + s = socket (hisctladdr.sin_family, SOCK_STREAM, 0); if (s < 0) { - warn("socket"); + warn ("socket"); code = -1; return (0); } continue; } - warn("connect"); + warn ("connect"); code = -1; goto bad; } len = sizeof (myctladdr); - if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { - warn("getsockname"); + if (getsockname (s, (struct sockaddr *) & myctladdr, &len) < 0) { + warn ("getsockname"); code = -1; goto bad; } #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) - tos = IPTOS_LOWDELAY; + { + int tos = IPTOS_LOWDELAY; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) warn("setsockopt TOS (ignored)"); + } #endif - cin = fdopen(s, "r"); - cout = fdopen(s, "w"); + cin = fdopen (s, "r"); + cout = fdopen (s, "w"); if (cin == NULL || cout == NULL) { - warnx("fdopen failed."); + warnx ("fdopen failed."); if (cin) - fclose(cin); + fclose (cin); if (cout) - fclose(cout); + fclose (cout); code = -1; goto bad; } if (verbose) - printf("Connected to %s.\n", hostname); - if (getreply(0) > 2) { /* read startup message from server */ + printf ("Connected to %s.\n", hostname); + if (getreply (0) > 2) { /* read startup message from server */ if (cin) - fclose(cin); + fclose (cin); if (cout) - fclose(cout); + fclose (cout); code = -1; goto bad; } @@ -149,21 +147,21 @@ hookup(char *host, int port) { int on = 1; - if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) + if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on)) < 0 && debug) { - warn("setsockopt"); + warn ("setsockopt"); } } -#endif /* SO_OOBINLINE */ +#endif /* SO_OOBINLINE */ return (hostname); bad: - close(s); + close (s); return NULL; } int -login(char *host) +login (char *host) { char tmp[80]; char defaultpass[128]; @@ -172,94 +170,97 @@ login(char *host) char *myname = NULL; struct passwd *pw = k_getpwuid(getuid()); + if (pw != NULL) myname = pw->pw_name; user = pass = acct = 0; - if(do_klogin(host)) + if(sec_login(host)) printf("\n*** Using plaintext user and password ***\n\n"); else{ - printf("Kerberos authentication successful.\n\n"); + printf("Authentication successful.\n\n"); } - if (ruserpass(host, &user, &pass, &acct) < 0) { + if (ruserpass (host, &user, &pass, &acct) < 0) { code = -1; return (0); } while (user == NULL) { if (myname) - printf("Name (%s:%s): ", host, myname); + printf ("Name (%s:%s): ", host, myname); else - printf("Name (%s): ", host); - fgets(tmp, sizeof(tmp) - 1, stdin); - tmp[strlen(tmp) - 1] = '\0'; + printf ("Name (%s): ", host); + fgets (tmp, sizeof (tmp) - 1, stdin); + tmp[strlen (tmp) - 1] = '\0'; if (*tmp == '\0') user = myname; else user = tmp; } - strcpy(username, user); + strcpy_truncate(username, user, sizeof(username)); n = command("USER %s", user); if (n == CONTINUE) { - if(auth_complete) + if(sec_complete) pass = myname; else if (pass == NULL) { char prompt[128]; if(myname && (!strcmp(user, "ftp") || !strcmp(user, "anonymous"))){ - snprintf(defaultpass, sizeof(defaultpass), "%s@%s", myname, mydomain); - snprintf(prompt, sizeof(prompt), "Password (%s): ", defaultpass); + snprintf(defaultpass, sizeof(defaultpass), + "%s@%s", myname, mydomain); + snprintf(prompt, sizeof(prompt), + "Password (%s): ", defaultpass); }else{ - strcpy(defaultpass, ""); + *defaultpass = '\0'; snprintf(prompt, sizeof(prompt), "Password: "); } pass = defaultpass; - des_read_pw_string (tmp, sizeof(tmp), prompt, 0); - if(tmp[0]) + des_read_pw_string (tmp, sizeof (tmp), prompt, 0); + if (tmp[0]) pass = tmp; } - n = command("PASS %s", pass); + n = command ("PASS %s", pass); } if (n == CONTINUE) { aflag++; acct = tmp; - des_read_pw_string(acct, 128, "Account:", 0); - n = command("ACCT %s", acct); + des_read_pw_string (acct, 128, "Account:", 0); + n = command ("ACCT %s", acct); } if (n != COMPLETE) { - warnx("Login failed."); + warnx ("Login failed."); return (0); } if (!aflag && acct != NULL) - command("ACCT %s", acct); + command ("ACCT %s", acct); if (proxy) return (1); for (n = 0; n < macnum; ++n) { if (!strcmp("init", macros[n].mac_name)) { - strcpy(line, "$init"); + strcpy_truncate (line, "$init", sizeof (line)); makeargv(); domacro(margc, margv); break; } } - sec_set_protection_level(); + sec_set_protection_level (); return (1); } void -cmdabort(int sig) +cmdabort (int sig) { - printf("\n"); - fflush(stdout); + printf ("\n"); + fflush (stdout); abrtflag++; if (ptflag) - longjmp(ptabort,1); + longjmp (ptabort, 1); } int -command(char *fmt, ...) +command (char *fmt,...) { va_list ap; int r; @@ -267,7 +268,7 @@ command(char *fmt, ...) abrtflag = 0; if (cout == NULL) { - warn("No control connection for command"); + warn ("No control connection for command"); code = -1; return (0); } @@ -281,29 +282,26 @@ command(char *fmt, ...) vfprintf(stdout, fmt, ap); va_start(ap, fmt); } - if(auth_complete) - krb4_write_enc(cout, fmt, ap); - else - vfprintf(cout, fmt, ap); + sec_vfprintf(cout, fmt, ap); va_end(ap); if(debug){ printf("\n"); fflush(stdout); } - fprintf(cout, "\r\n"); - fflush(cout); + fprintf (cout, "\r\n"); + fflush (cout); cpend = 1; - r = getreply(!strcmp(fmt, "QUIT")); + r = getreply (!strcmp (fmt, "QUIT")); if (abrtflag && oldintr != SIG_IGN) - (*oldintr)(SIGINT); - signal(SIGINT, oldintr); + (*oldintr) (SIGINT); + signal (SIGINT, oldintr); return (r); } -char reply_string[BUFSIZ]; /* last line of previous reply */ +char reply_string[BUFSIZ]; /* last line of previous reply */ int -getreply(int expecteof) +getreply (int expecteof) { char *p; char *lead_string; @@ -311,80 +309,82 @@ getreply(int expecteof) struct sigaction sa, osa; char buf[1024]; - sigemptyset(&sa.sa_mask); + sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = cmdabort; - sigaction(SIGINT, &sa, &osa); - + sigaction (SIGINT, &sa, &osa); + p = buf; - while(1){ - c = getc(cin); - switch(c){ + while (1) { + c = getc (cin); + switch (c) { case EOF: if (expecteof) { - sigaction(SIGINT,&osa, NULL); + sigaction (SIGINT, &osa, NULL); code = 221; return 0; } - lostpeer(0); + lostpeer (0); if (verbose) { - printf("421 Service not available, " - "remote server has closed connection\n"); - fflush(stdout); + printf ("421 Service not available, " + "remote server has closed connection\n"); + fflush (stdout); } code = 421; return (4); - break; case IAC: - c = getc(cin); - if(c == WILL || c == WONT) - fprintf(cout, "%c%c%c", IAC, DONT, getc(cin)); - if(c == DO || c == DONT) - fprintf(cout, "%c%c%c", IAC, WONT, getc(cin)); + c = getc (cin); + if (c == WILL || c == WONT) + fprintf (cout, "%c%c%c", IAC, DONT, getc (cin)); + if (c == DO || c == DONT) + fprintf (cout, "%c%c%c", IAC, WONT, getc (cin)); continue; case '\n': - *p++ = 0; + *p++ = '\0'; if(isdigit(buf[0])){ sscanf(buf, "%d", &code); if(code == 631){ - krb4_read_mic(buf); + sec_read_msg(buf, prot_safe); sscanf(buf, "%d", &code); lead_string = "S:"; } else if(code == 632){ - krb4_read_enc(buf); + sec_read_msg(buf, prot_private); sscanf(buf, "%d", &code); lead_string = "P:"; }else if(code == 633){ - printf("Received confidential reply!\n"); - }else if(auth_complete) + sec_read_msg(buf, prot_confidential); + sscanf(buf, "%d", &code); + lead_string = "C:"; + }else if(sec_complete) lead_string = "!!"; else lead_string = ""; - if(verbose > 0 || (verbose > -1 && code > 499)) - fprintf(stdout, "%s%s\n", lead_string, buf); - if(buf[3] == ' '){ - strcpy(reply_string, buf); + if (verbose > 0 || (verbose > -1 && code > 499)) + fprintf (stdout, "%s%s\n", lead_string, buf); + if (buf[3] == ' ') { + strcpy (reply_string, buf); if (code >= 200) cpend = 0; - sigaction(SIGINT, &osa, NULL); + sigaction (SIGINT, &osa, NULL); if (code == 421) - lostpeer(0); + lostpeer (0); #if 1 - if (abrtflag && - osa.sa_handler != cmdabort && + if (abrtflag && + osa.sa_handler != cmdabort && osa.sa_handler != SIG_IGN) - osa.sa_handler(SIGINT); + osa.sa_handler (SIGINT); #endif - if(code == 227){ + if (code == 227) { char *p, *q; + pasv[0] = 0; - p = strchr(reply_string, '('); - if(p){ + p = strchr (reply_string, '('); + if (p) { p++; q = strchr(p, ')'); if(q){ - strncpy(pasv, p, q - p); + memcpy (pasv, p, q - p); pasv[q - p] = 0; } } @@ -393,7 +393,7 @@ getreply(int expecteof) } }else{ if(verbose > 0 || (verbose > -1 && code > 499)){ - if(auth_complete) + if(sec_complete) fprintf(stdout, "!!"); fprintf(stdout, "%s\n", buf); } @@ -404,13 +404,13 @@ getreply(int expecteof) *p++ = c; } } - + } #if 0 int -getreply(int expecteof) +getreply (int expecteof) { int c, n; int dig; @@ -419,24 +419,24 @@ getreply(int expecteof) int pflag = 0; char *cp, *pt = pasv; - oldintr = signal(SIGINT, cmdabort); + oldintr = signal (SIGINT, cmdabort); for (;;) { dig = n = code = 0; cp = reply_string; - while ((c = getc(cin)) != '\n') { - if (c == IAC) { /* handle telnet commands */ - switch (c = getc(cin)) { + while ((c = getc (cin)) != '\n') { + if (c == IAC) { /* handle telnet commands */ + switch (c = getc (cin)) { case WILL: case WONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, DONT, c); - fflush(cout); + c = getc (cin); + fprintf (cout, "%c%c%c", IAC, DONT, c); + fflush (cout); break; case DO: case DONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, WONT, c); - fflush(cout); + c = getc (cin); + fprintf (cout, "%c%c%c", IAC, WONT, c); + fflush (cout); break; default: break; @@ -446,14 +446,14 @@ getreply(int expecteof) dig++; if (c == EOF) { if (expecteof) { - signal(SIGINT,oldintr); + signal (SIGINT, oldintr); code = 221; return (0); } - lostpeer(0); + lostpeer (0); if (verbose) { - printf("421 Service not available, remote server has closed connection\n"); - fflush(stdout); + printf ("421 Service not available, remote server has closed connection\n"); + fflush (stdout); } code = 421; return (4); @@ -462,14 +462,14 @@ getreply(int expecteof) (verbose > -1 && n == '5' && dig > 4))) { if (proxflag && (dig == 1 || dig == 5 && verbose == 0)) - printf("%s:",hostname); - putchar(c); + printf ("%s:", hostname); + putchar (c); } - if (dig < 4 && isdigit(c)) + if (dig < 4 && isdigit (c)) code = code * 10 + (c - '0'); if (!pflag && code == 227) pflag = 1; - if (dig > 4 && pflag == 1 && isdigit(c)) + if (dig > 4 && pflag == 1 && isdigit (c)) pflag = 2; if (pflag == 2) { if (c != '\r' && c != ')') @@ -486,11 +486,11 @@ getreply(int expecteof) } if (n == 0) n = c; - if (cp < &reply_string[sizeof(reply_string) - 1]) + if (cp < &reply_string[sizeof (reply_string) - 1]) *cp++ = c; } if (verbose > 0 || verbose > -1 && n == '5') { - putchar(c); + putchar (c); fflush (stdout); } if (continuation && code != originalcode) { @@ -499,112 +499,114 @@ getreply(int expecteof) continue; } *cp = '\0'; - if(auth_complete){ + if(sec_complete){ if(code == 631) - krb4_read_mic(reply_string); - else - krb4_read_enc(reply_string); + sec_read_msg(reply_string, prot_safe); + else if(code == 632) + sec_read_msg(reply_string, prot_private); + else if(code == 633) + sec_read_msg(reply_string, prot_confidential); n = code / 100 + '0'; } - if (n != '1') cpend = 0; - signal(SIGINT,oldintr); + signal (SIGINT, oldintr); if (code == 421 || originalcode == 421) - lostpeer(0); + lostpeer (0); if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) - (*oldintr)(SIGINT); + (*oldintr) (SIGINT); return (n - '0'); } } + #endif int -empty(fd_set *mask, int sec) +empty (fd_set * mask, int sec) { struct timeval t; t.tv_sec = (long) sec; t.tv_usec = 0; - return (select(32, mask, NULL, NULL, &t)); + return (select (32, mask, NULL, NULL, &t)); } -jmp_buf sendabort; +jmp_buf sendabort; static RETSIGTYPE -abortsend(int sig) +abortsend (int sig) { mflag = 0; abrtflag = 0; - printf("\nsend aborted\nwaiting for remote to finish abort\n"); - fflush(stdout); - longjmp(sendabort, 1); + printf ("\nsend aborted\nwaiting for remote to finish abort\n"); + fflush (stdout); + longjmp (sendabort, 1); } #define HASHBYTES 1024 static int -copy_stream(FILE *from, FILE *to) +copy_stream (FILE * from, FILE * to) { static size_t bufsize; static char *buf; int n; int bytes = 0; - int werr; + int werr = 0; int hashbytes = HASHBYTES; struct stat st; - -#ifdef HAVE_MMAP + +#if defined(HAVE_MMAP) && !defined(NO_MMAP) void *chunk; #ifndef MAP_FAILED #define MAP_FAILED (-1) #endif - if(fstat(fileno(from), &st) == 0 && S_ISREG(st.st_mode)){ - chunk = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(from), 0); - if (chunk != (void *)MAP_FAILED) { + if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) { + chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0); + if (chunk != (void *) MAP_FAILED) { int res; - res = sec_write(fileno(to), chunk, st.st_size); - if (munmap(chunk, st.st_size) < 0) + res = sec_write (fileno (to), chunk, st.st_size); + if (munmap (chunk, st.st_size) < 0) warn ("munmap"); - sec_fflush(to); + sec_fflush (to); return res; } } #endif buf = alloc_buffer (buf, &bufsize, - fstat(fileno(from), &st) >= 0 ? &st : NULL); + fstat (fileno (from), &st) >= 0 ? &st : NULL); if (buf == NULL) return -1; - while((n = read(fileno(from), buf, bufsize)) > 0){ - werr = sec_write(fileno(to), buf, n); - if(werr < 0) + while ((n = read (fileno (from), buf, bufsize)) > 0) { + werr = sec_write (fileno (to), buf, n); + if (werr < 0) break; bytes += werr; - while(hash && bytes > hashbytes){ - putchar('#'); + while (hash && bytes > hashbytes) { + putchar ('#'); hashbytes += HASHBYTES; } } - sec_fflush(to); - if(n < 0) - warn("local"); + sec_fflush (to); + if (n < 0) + warn ("local"); - if(werr < 0){ - if(errno != EPIPE) - warn("netout"); + if (werr < 0) { + if (errno != EPIPE) + warn ("netout"); bytes = -1; } return bytes; } void -sendrequest(char *cmd, char *local, char *remote, int printnames) +sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames) { struct stat st; struct timeval start, stop; @@ -613,124 +615,123 @@ sendrequest(char *cmd, char *local, char *remote, int printnames) int (*closefunc) (FILE *); RETSIGTYPE (*oldintr)(), (*oldintp)(); long bytes = 0, hashbytes = HASHBYTES; - char *lmode; + char *rmode = "w"; if (verbose && printnames) { - if (local && *local != '-') - printf("local: %s ", local); + if (local && strcmp (local, "-") != 0) + printf ("local: %s ", local); if (remote) - printf("remote: %s\n", remote); + printf ("remote: %s\n", remote); } if (proxy) { - proxtrans(cmd, local, remote); + proxtrans (cmd, local, remote); return; } if (curtype != type) - changetype(type, 0); + changetype (type, 0); closefunc = NULL; oldintr = NULL; oldintp = NULL; - lmode = "w"; - if (setjmp(sendabort)) { + + if (setjmp (sendabort)) { while (cpend) { - getreply(0); + getreply (0); } if (data >= 0) { - close(data); + close (data); data = -1; } if (oldintr) - signal(SIGINT,oldintr); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE,oldintp); + signal (SIGPIPE, oldintp); code = -1; return; } - oldintr = signal(SIGINT, abortsend); - if (strcmp(local, "-") == 0) + oldintr = signal (SIGINT, abortsend); + if (strcmp (local, "-") == 0) fin = stdin; else if (*local == '|') { - oldintp = signal(SIGPIPE,SIG_IGN); - fin = popen(local + 1, "r"); + oldintp = signal (SIGPIPE, SIG_IGN); + fin = popen (local + 1, lmode); if (fin == NULL) { - warn("%s", local + 1); - signal(SIGINT, oldintr); - signal(SIGPIPE, oldintp); + warn ("%s", local + 1); + signal (SIGINT, oldintr); + signal (SIGPIPE, oldintp); code = -1; return; } closefunc = pclose; } else { - fin = fopen(local, "r"); + fin = fopen (local, lmode); if (fin == NULL) { - warn("local: %s", local); - signal(SIGINT, oldintr); + warn ("local: %s", local); + signal (SIGINT, oldintr); code = -1; return; } closefunc = fclose; - if (fstat(fileno(fin), &st) < 0 || - (st.st_mode&S_IFMT) != S_IFREG) { - fprintf(stdout, "%s: not a plain file.\n", local); - signal(SIGINT, oldintr); - fclose(fin); + if (fstat (fileno (fin), &st) < 0 || + (st.st_mode & S_IFMT) != S_IFREG) { + fprintf (stdout, "%s: not a plain file.\n", local); + signal (SIGINT, oldintr); + fclose (fin); code = -1; return; } } - if (initconn()) { - signal(SIGINT, oldintr); + if (initconn ()) { + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); code = -1; if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } - if (setjmp(sendabort)) + if (setjmp (sendabort)) goto abort; if (restart_point && - (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { + (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) { int rc; switch (curtype) { case TYPE_A: - rc = fseek(fin, (long) restart_point, SEEK_SET); + rc = fseek (fin, (long) restart_point, SEEK_SET); break; case TYPE_I: case TYPE_L: - rc = lseek(fileno(fin), restart_point, SEEK_SET); + rc = lseek (fileno (fin), restart_point, SEEK_SET); break; } if (rc < 0) { - warn("local: %s", local); + warn ("local: %s", local); restart_point = 0; if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } - if (command("REST %ld", (long) restart_point) + if (command ("REST %ld", (long) restart_point) != CONTINUE) { restart_point = 0; if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } restart_point = 0; - lmode = "r+w"; + rmode = "r+w"; } if (remote) { - if (command("%s %s", cmd, remote) != PRELIM) { - signal(SIGINT, oldintr); + if (command ("%s %s", cmd, remote) != PRELIM) { + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } - } else - if (command("%s", cmd) != PRELIM) { + } else if (command ("%s", cmd) != PRELIM) { signal(SIGINT, oldintr); if (oldintp) signal(SIGPIPE, oldintp); @@ -738,101 +739,102 @@ sendrequest(char *cmd, char *local, char *remote, int printnames) (*closefunc)(fin); return; } - dout = dataconn(lmode); + dout = dataconn(rmode); if (dout == NULL) goto abort; - set_buffer_size(fileno(dout), 0); - gettimeofday(&start, (struct timezone *)0); - oldintp = signal(SIGPIPE, SIG_IGN); + set_buffer_size (fileno (dout), 0); + gettimeofday (&start, (struct timezone *) 0); + oldintp = signal (SIGPIPE, SIG_IGN); switch (curtype) { case TYPE_I: case TYPE_L: errno = d = c = 0; - bytes = copy_stream(fin, dout); + bytes = copy_stream (fin, dout); break; case TYPE_A: - while ((c = getc(fin)) != EOF) { + while ((c = getc (fin)) != EOF) { if (c == '\n') { while (hash && (bytes >= hashbytes)) { - putchar('#'); - fflush(stdout); + putchar ('#'); + fflush (stdout); hashbytes += HASHBYTES; } - if (ferror(dout)) + if (ferror (dout)) break; - sec_putc('\r', dout); + sec_putc ('\r', dout); bytes++; } - sec_putc(c, dout); + sec_putc (c, dout); bytes++; } - sec_fflush(dout); + sec_fflush (dout); if (hash) { if (bytes < hashbytes) - putchar('#'); - putchar('\n'); - fflush(stdout); + putchar ('#'); + putchar ('\n'); + fflush (stdout); } - if (ferror(fin)) - warn("local: %s", local); - if (ferror(dout)) { + if (ferror (fin)) + warn ("local: %s", local); + if (ferror (dout)) { if (errno != EPIPE) - warn("netout"); + warn ("netout"); bytes = -1; } break; } if (closefunc != NULL) - (*closefunc)(fin); - fclose(dout); - gettimeofday(&stop, (struct timezone *)0); - getreply(0); - signal(SIGINT, oldintr); + (*closefunc) (fin); + fclose (dout); + gettimeofday (&stop, (struct timezone *) 0); + getreply (0); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); if (bytes > 0) - ptransfer("sent", bytes, &start, &stop); + ptransfer ("sent", bytes, &start, &stop); return; abort: - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); if (!cpend) { code = -1; return; } if (data >= 0) { - close(data); + close (data); data = -1; } if (dout) - fclose(dout); - getreply(0); + fclose (dout); + getreply (0); code = -1; if (closefunc != NULL && fin != NULL) - (*closefunc)(fin); - gettimeofday(&stop, (struct timezone *)0); + (*closefunc) (fin); + gettimeofday (&stop, (struct timezone *) 0); if (bytes > 0) - ptransfer("sent", bytes, &start, &stop); + ptransfer ("sent", bytes, &start, &stop); } -jmp_buf recvabort; +jmp_buf recvabort; void -abortrecv(int sig) +abortrecv (int sig) { mflag = 0; abrtflag = 0; - printf("\nreceive aborted\nwaiting for remote to finish abort\n"); - fflush(stdout); - longjmp(recvabort, 1); + printf ("\nreceive aborted\nwaiting for remote to finish abort\n"); + fflush (stdout); + longjmp (recvabort, 1); } void -recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) +recvrequest (char *cmd, char *local, char *remote, + char *lmode, int printnames, int local_given) { FILE *fout, *din = 0; int (*closefunc) (FILE *); @@ -844,72 +846,71 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) struct timeval start, stop; struct stat st; - is_retr = strcmp(cmd, "RETR") == 0; + is_retr = strcmp (cmd, "RETR") == 0; if (is_retr && verbose && printnames) { - if (local && *local != '-') - printf("local: %s ", local); + if (local && strcmp (local, "-") != 0) + printf ("local: %s ", local); if (remote) - printf("remote: %s\n", remote); + printf ("remote: %s\n", remote); } if (proxy && is_retr) { - proxtrans(cmd, local, remote); + proxtrans (cmd, local, remote); return; } closefunc = NULL; oldintr = NULL; oldintp = NULL; tcrflag = !crflag && is_retr; - if (setjmp(recvabort)) { + if (setjmp (recvabort)) { while (cpend) { - getreply(0); + getreply (0); } if (data >= 0) { - close(data); + close (data); data = -1; } if (oldintr) - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); code = -1; return; } - oldintr = signal(SIGINT, abortrecv); - if (strcmp(local, "-") && *local != '|') { - if (access(local, 2) < 0) { - char *dir = strrchr(local, '/'); + oldintr = signal (SIGINT, abortrecv); + if (!local_given || (strcmp (local, "-") && *local != '|')) { + if (access (local, 2) < 0) { + char *dir = strrchr (local, '/'); if (errno != ENOENT && errno != EACCES) { - warn("local: %s", local); - signal(SIGINT, oldintr); + warn ("local: %s", local); + signal (SIGINT, oldintr); code = -1; return; } if (dir != NULL) *dir = 0; - d = access(dir ? local : ".", 2); + d = access (dir ? local : ".", 2); if (dir != NULL) *dir = '/'; if (d < 0) { - warn("local: %s", local); - signal(SIGINT, oldintr); + warn ("local: %s", local); + signal (SIGINT, oldintr); code = -1; return; } if (!runique && errno == EACCES && - chmod(local, 0600) < 0) { - warn("local: %s", local); - signal(SIGINT, oldintr); - signal(SIGINT, oldintr); + chmod (local, 0600) < 0) { + warn ("local: %s", local); + signal (SIGINT, oldintr); + signal (SIGINT, oldintr); code = -1; return; } if (runique && errno == EACCES && - (local = gunique(local)) == NULL) { - signal(SIGINT, oldintr); + (local = gunique (local)) == NULL) { + signal (SIGINT, oldintr); code = -1; return; } - } - else if (runique && (local = gunique(local)) == NULL) { + } else if (runique && (local = gunique (local)) == NULL) { signal(SIGINT, oldintr); code = -1; return; @@ -917,98 +918,98 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) } if (!is_retr) { if (curtype != TYPE_A) - changetype(TYPE_A, 0); + changetype (TYPE_A, 0); } else if (curtype != type) - changetype(type, 0); - if (initconn()) { - signal(SIGINT, oldintr); + changetype (type, 0); + if (initconn ()) { + signal (SIGINT, oldintr); code = -1; return; } - if (setjmp(recvabort)) + if (setjmp (recvabort)) goto abort; if (is_retr && restart_point && - command("REST %ld", (long) restart_point) != CONTINUE) + command ("REST %ld", (long) restart_point) != CONTINUE) return; if (remote) { - if (command("%s %s", cmd, remote) != PRELIM) { - signal(SIGINT, oldintr); + if (command ("%s %s", cmd, remote) != PRELIM) { + signal (SIGINT, oldintr); return; } } else { - if (command("%s", cmd) != PRELIM) { - signal(SIGINT, oldintr); + if (command ("%s", cmd) != PRELIM) { + signal (SIGINT, oldintr); return; } } - din = dataconn("r"); + din = dataconn ("r"); if (din == NULL) goto abort; - set_buffer_size(fileno(din), 1); - if (strcmp(local, "-") == 0) + set_buffer_size (fileno (din), 1); + if (local_given && strcmp (local, "-") == 0) fout = stdout; - else if (*local == '|') { - oldintp = signal(SIGPIPE, SIG_IGN); - fout = popen(local + 1, "w"); + else if (local_given && *local == '|') { + oldintp = signal (SIGPIPE, SIG_IGN); + fout = popen (local + 1, "w"); if (fout == NULL) { - warn("%s", local+1); + warn ("%s", local + 1); goto abort; } closefunc = pclose; } else { - fout = fopen(local, lmode); + fout = fopen (local, lmode); if (fout == NULL) { - warn("local: %s", local); + warn ("local: %s", local); goto abort; } closefunc = fclose; } buf = alloc_buffer (buf, &bufsize, - fstat(fileno(fout), &st) >= 0 ? &st : NULL); + fstat (fileno (fout), &st) >= 0 ? &st : NULL); if (buf == NULL) goto abort; - gettimeofday(&start, (struct timezone *)0); + gettimeofday (&start, (struct timezone *) 0); switch (curtype) { case TYPE_I: case TYPE_L: if (restart_point && - lseek(fileno(fout), restart_point, SEEK_SET) < 0) { - warn("local: %s", local); + lseek (fileno (fout), restart_point, SEEK_SET) < 0) { + warn ("local: %s", local); if (closefunc != NULL) - (*closefunc)(fout); + (*closefunc) (fout); return; } errno = d = 0; - while ((c = sec_read(fileno(din), buf, bufsize)) > 0) { - if ((d = write(fileno(fout), buf, c)) != c) + while ((c = sec_read (fileno (din), buf, bufsize)) > 0) { + if ((d = write (fileno (fout), buf, c)) != c) break; bytes += c; if (hash) { while (bytes >= hashbytes) { - putchar('#'); + putchar ('#'); hashbytes += HASHBYTES; } - fflush(stdout); + fflush (stdout); } } if (hash && bytes > 0) { if (bytes < HASHBYTES) - putchar('#'); - putchar('\n'); - fflush(stdout); + putchar ('#'); + putchar ('\n'); + fflush (stdout); } if (c < 0) { if (errno != EPIPE) - warn("netin"); + warn ("netin"); bytes = -1; } if (d < c) { if (d < 0) - warn("local: %s", local); + warn ("local: %s", local); else - warnx("%s: short write", local); + warnx ("%s: short write", local); } break; @@ -1016,38 +1017,37 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) if (restart_point) { int i, n, ch; - if (fseek(fout, 0L, SEEK_SET) < 0) + if (fseek (fout, 0L, SEEK_SET) < 0) goto done; n = restart_point; for (i = 0; i++ < n;) { - if ((ch = sec_getc(fout)) == EOF) + if ((ch = sec_getc (fout)) == EOF) goto done; if (ch == '\n') i++; } - if (fseek(fout, 0L, SEEK_CUR) < 0) { - done: - warn("local: %s", local); + if (fseek (fout, 0L, SEEK_CUR) < 0) { + done: + warn ("local: %s", local); if (closefunc != NULL) - (*closefunc)(fout); + (*closefunc) (fout); return; } } - while ((c = sec_getc(din)) != EOF) { if (c == '\n') bare_lfs++; while (c == '\r') { while (hash && (bytes >= hashbytes)) { - putchar('#'); - fflush(stdout); + putchar ('#'); + fflush (stdout); hashbytes += HASHBYTES; } bytes++; - if ((c = sec_getc(din)) != '\n' || tcrflag) { - if (ferror(fout)) + if ((c = sec_getc (din)) != '\n' || tcrflag) { + if (ferror (fout)) goto break2; - putc('\r', fout); + putc ('\r', fout); if (c == '\0') { bytes++; goto contin2; @@ -1056,69 +1056,68 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) goto contin2; } } - putc(c, fout); + putc (c, fout); bytes++; - contin2: ; + contin2:; } - break2: +break2: if (bare_lfs) { - printf("WARNING! %d bare linefeeds received in ASCII mode\n", - bare_lfs); - printf("File may not have transferred correctly.\n"); + printf ("WARNING! %d bare linefeeds received in ASCII mode\n", + bare_lfs); + printf ("File may not have transferred correctly.\n"); } if (hash) { if (bytes < hashbytes) - putchar('#'); - putchar('\n'); - fflush(stdout); + putchar ('#'); + putchar ('\n'); + fflush (stdout); } - if (ferror(din)) { + if (ferror (din)) { if (errno != EPIPE) - warn("netin"); + warn ("netin"); bytes = -1; } - if (ferror(fout)) - warn("local: %s", local); + if (ferror (fout)) + warn ("local: %s", local); break; } if (closefunc != NULL) - (*closefunc)(fout); - signal(SIGINT, oldintr); + (*closefunc) (fout); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); - fclose(din); - gettimeofday(&stop, (struct timezone *)0); - getreply(0); + signal (SIGPIPE, oldintp); + fclose (din); + gettimeofday (&stop, (struct timezone *) 0); + getreply (0); if (bytes > 0 && is_retr) - ptransfer("received", bytes, &start, &stop); + ptransfer ("received", bytes, &start, &stop); return; abort: /* abort using RFC959 recommended IP,SYNC sequence */ if (oldintp) - signal(SIGPIPE, oldintr); - signal(SIGINT, SIG_IGN); + signal (SIGPIPE, oldintr); + signal (SIGINT, SIG_IGN); if (!cpend) { code = -1; - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); return; } - abort_remote(din); code = -1; if (data >= 0) { - close(data); + close (data); data = -1; } if (closefunc != NULL && fout != NULL) - (*closefunc)(fout); + (*closefunc) (fout); if (din) - fclose(din); - gettimeofday(&stop, (struct timezone *)0); + fclose (din); + gettimeofday (&stop, (struct timezone *) 0); if (bytes > 0) - ptransfer("received", bytes, &start, &stop); - signal(SIGINT, oldintr); + ptransfer ("received", bytes, &start, &stop); + signal (SIGINT, oldintr); } /* @@ -1126,112 +1125,110 @@ abort: * otherwise the server's connect may fail. */ int -initconn(void) +initconn (void) { int result, len, tmpno = 0; int on = 1; int a0, a1, a2, a3, p0, p1; if (passivemode) { - data = socket(AF_INET, SOCK_STREAM, 0); + data = socket (AF_INET, SOCK_STREAM, 0); if (data < 0) { - perror("ftp: socket"); - return(1); + perror ("ftp: socket"); + return (1); } #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) if ((options & SO_DEBUG) && - setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, - sizeof (on)) < 0) - perror("ftp: setsockopt (ignored)"); + setsockopt (data, SOL_SOCKET, SO_DEBUG, (char *) &on, + sizeof (on)) < 0) + perror ("ftp: setsockopt (ignored)"); #endif - if (command("PASV") != COMPLETE) { - printf("Passive mode refused.\n"); + if (command ("PASV") != COMPLETE) { + printf ("Passive mode refused.\n"); goto bad; } /* - * What we've got at this point is a string of comma - * separated one-byte unsigned integer values. - * The first four are the an IP address. The fifth is - * the MSB of the port number, the sixth is the LSB. - * From that we'll prepare a sockaddr_in. + * What we've got at this point is a string of comma separated + * one-byte unsigned integer values. The first four are the an IP + * address. The fifth is the MSB of the port number, the sixth is the + * LSB. From that we'll prepare a sockaddr_in. */ - if (sscanf(pasv,"%d,%d,%d,%d,%d,%d", - &a0, &a1, &a2, &a3, &p0, &p1) != 6) { - printf("Passive mode address scan failure. " - "Shouldn't happen!\n"); + if (sscanf (pasv, "%d,%d,%d,%d,%d,%d", + &a0, &a1, &a2, &a3, &p0, &p1) != 6) { + printf ("Passive mode address scan failure. " + "Shouldn't happen!\n"); goto bad; } - if(a0 < 0 || a0 > 255 || - a1 < 0 || a1 > 255 || - a2 < 0 || a2 > 255 || - a3 < 0 || a3 > 255 || - p0 < 0 || p0 > 255 || - p1 < 0 || p1 > 255){ - printf("Can't parse passive mode string.\n"); + if (a0 < 0 || a0 > 255 || + a1 < 0 || a1 > 255 || + a2 < 0 || a2 > 255 || + a3 < 0 || a3 > 255 || + p0 < 0 || p0 > 255 || + p1 < 0 || p1 > 255) { + printf ("Can't parse passive mode string.\n"); goto bad; } - memset(&data_addr, 0, sizeof(data_addr)); data_addr.sin_family = AF_INET; - data_addr.sin_addr.s_addr = htonl((a0 << 24) | (a1 << 16) | - (a2 << 8) | a3); - data_addr.sin_port = htons((p0 << 8) | p1); + data_addr.sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) | + (a2 << 8) | a3); + data_addr.sin_port = htons ((p0 << 8) | p1); - if (connect(data, (struct sockaddr *)&data_addr, - sizeof(data_addr)) < 0) { - perror("ftp: connect"); + if (connect (data, (struct sockaddr *) & data_addr, + sizeof (data_addr)) < 0) { + perror ("ftp: connect"); goto bad; } #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) on = IPTOS_THROUGHPUT; - if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, - sizeof(int)) < 0) - perror("ftp: setsockopt TOS (ignored)"); + if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, + sizeof (int)) < 0) + perror ("ftp: setsockopt TOS (ignored)"); #endif - return(0); + return (0); } - noport: data_addr = myctladdr; if (sendport) - data_addr.sin_port = 0; /* let system pick one */ + data_addr.sin_port = 0; /* let system pick one */ if (data != -1) - close(data); - data = socket(AF_INET, SOCK_STREAM, 0); + close (data); + data = socket (AF_INET, SOCK_STREAM, 0); if (data < 0) { - warn("socket"); + warn ("socket"); if (tmpno) sendport = 1; return (1); } #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) if (!sendport) - if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { - warn("setsockopt (reuse address)"); + if (setsockopt (data, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) { + warn ("setsockopt (reuse address)"); goto bad; } #endif - if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { - warn("bind"); + if (bind (data, (struct sockaddr *) & data_addr, sizeof (data_addr)) < 0) { + warn ("bind"); goto bad; } #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) if (options & SO_DEBUG && - setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) - warn("setsockopt (ignored)"); + setsockopt (data, SOL_SOCKET, SO_DEBUG, (char *) &on, sizeof (on)) < 0) + warn ("setsockopt (ignored)"); #endif len = sizeof (data_addr); - if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { - warn("getsockname"); + if (getsockname (data, (struct sockaddr *) & data_addr, &len) < 0) { + warn ("getsockname"); goto bad; } - if (listen(data, 1) < 0) - warn("listen"); + if (listen (data, 1) < 0) + warn ("listen"); if (sendport) { unsigned int a = ntohl(data_addr.sin_addr.s_addr); unsigned int p = ntohs(data_addr.sin_port); + result = command("PORT %d,%d,%d,%d,%d,%d", (a >> 24) & 0xff, (a >> 16) & 0xff, @@ -1250,88 +1247,88 @@ noport: sendport = 1; #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) on = IPTOS_THROUGHPUT; - if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) - warn("setsockopt TOS (ignored)"); + if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, sizeof (int)) < 0) + warn ("setsockopt TOS (ignored)"); #endif return (0); bad: - close(data), data = -1; + close (data), data = -1; if (tmpno) sendport = 1; return (1); } FILE * -dataconn(char *lmode) +dataconn (char *lmode) { struct sockaddr_in from; int s, fromlen = sizeof (from), tos; if (passivemode) - return (fdopen(data, lmode)); + return (fdopen (data, lmode)); - s = accept(data, (struct sockaddr *) &from, &fromlen); + s = accept (data, (struct sockaddr *) & from, &fromlen); if (s < 0) { - warn("accept"); - close(data), data = -1; + warn ("accept"); + close (data), data = -1; return (NULL); } - close(data); + close (data); data = s; #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) tos = IPTOS_THROUGHPUT; - if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) - warn("setsockopt TOS (ignored)"); + if (setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0) + warn ("setsockopt TOS (ignored)"); #endif - return (fdopen(data, lmode)); + return (fdopen (data, lmode)); } void -ptransfer(char *direction, long int bytes, - struct timeval *t0, struct timeval *t1) +ptransfer (char *direction, long int bytes, + struct timeval * t0, struct timeval * t1) { struct timeval td; float s; float bs; int prec; char *unit; - + if (verbose) { td.tv_sec = t1->tv_sec - t0->tv_sec; td.tv_usec = t1->tv_usec - t0->tv_usec; - if(td.tv_usec < 0){ + if (td.tv_usec < 0) { td.tv_sec--; td.tv_usec += 1000000; } s = td.tv_sec + (td.tv_usec / 1000000.); - bs = bytes / (s?s:1); - if(bs >= 1048576){ + bs = bytes / (s ? s : 1); + if (bs >= 1048576) { bs /= 1048576; unit = "M"; prec = 2; - }else if(bs >= 1024){ + } else if (bs >= 1024) { bs /= 1024; unit = "k"; prec = 1; - }else{ + } else { unit = ""; prec = 0; } - - printf("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n", - bytes, direction, s, prec, bs, unit); + + printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n", + bytes, direction, s, prec, bs, unit); } } void -psabort(int sig) +psabort (int sig) { abrtflag++; } void -pswitch(int flag) +pswitch (int flag) { sighand oldintr; static struct comvars { @@ -1357,7 +1354,7 @@ pswitch(int flag) struct comvars *ip, *op; abrtflag = 0; - oldintr = signal(SIGINT, psabort); + oldintr = signal (SIGINT, psabort); if (flag) { if (proxy) return; @@ -1374,8 +1371,7 @@ pswitch(int flag) ip->connect = connected; connected = op->connect; if (hostname) { - strncpy(ip->name, hostname, sizeof(ip->name) - 1); - ip->name[strlen(ip->name)] = '\0'; + strcpy_truncate (ip->name, hostname, sizeof (ip->name)); } else ip->name[0] = 0; hostname = op->name; @@ -1401,48 +1397,44 @@ pswitch(int flag) mcase = op->mcse; ip->ntflg = ntflag; ntflag = op->ntflg; - strncpy(ip->nti, ntin, 16); - (ip->nti)[strlen(ip->nti)] = '\0'; - strcpy(ntin, op->nti); - strncpy(ip->nto, ntout, 16); - (ip->nto)[strlen(ip->nto)] = '\0'; - strcpy(ntout, op->nto); + strcpy_truncate (ip->nti, ntin, sizeof (ip->nti)); + strcpy_truncate (ntin, op->nti, 17); + strcpy_truncate (ip->nto, ntout, sizeof (ip->nto)); + strcpy_truncate (ntout, op->nto, 17); ip->mapflg = mapflag; mapflag = op->mapflg; - strncpy(ip->mi, mapin, MaxPathLen - 1); - (ip->mi)[strlen(ip->mi)] = '\0'; - strcpy(mapin, op->mi); - strncpy(ip->mo, mapout, MaxPathLen - 1); - (ip->mo)[strlen(ip->mo)] = '\0'; - strcpy(mapout, op->mo); + strcpy_truncate (ip->mi, mapin, MaxPathLen); + strcpy_truncate (mapin, op->mi, MaxPathLen); + strcpy_truncate (ip->mo, mapout, MaxPathLen); + strcpy_truncate (mapout, op->mo, MaxPathLen); signal(SIGINT, oldintr); if (abrtflag) { abrtflag = 0; - (*oldintr)(SIGINT); + (*oldintr) (SIGINT); } } void -abortpt(int sig) +abortpt (int sig) { - printf("\n"); - fflush(stdout); + printf ("\n"); + fflush (stdout); ptabflg++; mflag = 0; abrtflag = 0; - longjmp(ptabort, 1); + longjmp (ptabort, 1); } void -proxtrans(char *cmd, char *local, char *remote) +proxtrans (char *cmd, char *local, char *remote) { sighand oldintr; int secndflag = 0, prox_type, nfnd; char *cmd2; fd_set mask; - if (strcmp(cmd, "RETR")) + if (strcmp (cmd, "RETR")) cmd2 = "RETR"; else cmd2 = runique ? "STOU" : "STOR"; @@ -1453,148 +1445,147 @@ proxtrans(char *cmd, char *local, char *remote) prox_type = TYPE_A; } if (curtype != prox_type) - changetype(prox_type, 1); - if (command("PASV") != COMPLETE) { - printf("proxy server does not support third party transfers.\n"); + changetype (prox_type, 1); + if (command ("PASV") != COMPLETE) { + printf ("proxy server does not support third party transfers.\n"); return; } - pswitch(0); + pswitch (0); if (!connected) { - printf("No primary connection\n"); - pswitch(1); + printf ("No primary connection\n"); + pswitch (1); code = -1; return; } if (curtype != prox_type) - changetype(prox_type, 1); - if (command("PORT %s", pasv) != COMPLETE) { - pswitch(1); + changetype (prox_type, 1); + if (command ("PORT %s", pasv) != COMPLETE) { + pswitch (1); return; } - if (setjmp(ptabort)) + if (setjmp (ptabort)) goto abort; - oldintr = signal(SIGINT, abortpt); - if (command("%s %s", cmd, remote) != PRELIM) { - signal(SIGINT, oldintr); - pswitch(1); + oldintr = signal (SIGINT, abortpt); + if (command ("%s %s", cmd, remote) != PRELIM) { + signal (SIGINT, oldintr); + pswitch (1); return; } - sleep(2); - pswitch(1); + sleep (2); + pswitch (1); secndflag++; - if (command("%s %s", cmd2, local) != PRELIM) + if (command ("%s %s", cmd2, local) != PRELIM) goto abort; ptflag++; - getreply(0); - pswitch(0); - getreply(0); - signal(SIGINT, oldintr); - pswitch(1); + getreply (0); + pswitch (0); + getreply (0); + signal (SIGINT, oldintr); + pswitch (1); ptflag = 0; - printf("local: %s remote: %s\n", local, remote); + printf ("local: %s remote: %s\n", local, remote); return; abort: - signal(SIGINT, SIG_IGN); + signal (SIGINT, SIG_IGN); ptflag = 0; - if (strcmp(cmd, "RETR") && !proxy) - pswitch(1); - else if (!strcmp(cmd, "RETR") && proxy) - pswitch(0); - if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ - if (command("%s %s", cmd2, local) != PRELIM) { - pswitch(0); + if (strcmp (cmd, "RETR") && !proxy) + pswitch (1); + else if (!strcmp (cmd, "RETR") && proxy) + pswitch (0); + if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ + if (command ("%s %s", cmd2, local) != PRELIM) { + pswitch (0); if (cpend) - abort_remote((FILE *) NULL); + abort_remote ((FILE *) NULL); } - pswitch(1); + pswitch (1); if (ptabflg) code = -1; - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); return; } if (cpend) - abort_remote((FILE *) NULL); - pswitch(!proxy); - if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ - if (command("%s %s", cmd2, local) != PRELIM) { - pswitch(0); + abort_remote ((FILE *) NULL); + pswitch (!proxy); + if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ + if (command ("%s %s", cmd2, local) != PRELIM) { + pswitch (0); if (cpend) - abort_remote((FILE *) NULL); - pswitch(1); + abort_remote ((FILE *) NULL); + pswitch (1); if (ptabflg) code = -1; - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); return; } } if (cpend) - abort_remote((FILE *) NULL); - pswitch(!proxy); + abort_remote ((FILE *) NULL); + pswitch (!proxy); if (cpend) { - FD_ZERO(&mask); - FD_SET(fileno(cin), &mask); - if ((nfnd = empty(&mask, 10)) <= 0) { + FD_ZERO (&mask); + FD_SET (fileno (cin), &mask); + if ((nfnd = empty (&mask, 10)) <= 0) { if (nfnd < 0) { - warn("abort"); + warn ("abort"); } if (ptabflg) code = -1; - lostpeer(0); + lostpeer (0); } - getreply(0); - getreply(0); + getreply (0); + getreply (0); } if (proxy) - pswitch(0); - pswitch(1); + pswitch (0); + pswitch (1); if (ptabflg) code = -1; - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); } void -reset(int argc, char **argv) +reset (int argc, char **argv) { fd_set mask; int nfnd = 1; - FD_ZERO(&mask); + FD_ZERO (&mask); while (nfnd > 0) { - FD_SET(fileno(cin), &mask); - if ((nfnd = empty(&mask,0)) < 0) { - warn("reset"); + FD_SET (fileno (cin), &mask); + if ((nfnd = empty (&mask, 0)) < 0) { + warn ("reset"); code = -1; lostpeer(0); - } - else if (nfnd) { + } else if (nfnd) { getreply(0); } } } char * -gunique(char *local) +gunique (char *local) { static char new[MaxPathLen]; - char *cp = strrchr(local, '/'); - int d, count=0; + char *cp = strrchr (local, '/'); + int d, count = 0; char ext = '1'; if (cp) *cp = '\0'; - d = access(cp ? local : ".", 2); + d = access (cp ? local : ".", 2); if (cp) *cp = '/'; if (d < 0) { - warn("local: %s", local); + warn ("local: %s", local); return NULL; } - strcpy(new, local); + strcpy_truncate (new, local, sizeof(new)); cp = new + strlen(new); *cp++ = '.'; while (!d) { if (++count == 100) { - printf("runique: can't find unique file name.\n"); + printf ("runique: can't find unique file name.\n"); return NULL; } *cp++ = ext; @@ -1603,7 +1594,7 @@ gunique(char *local) ext = '0'; else ext++; - if ((d = access(new, 0)) < 0) + if ((d = access (new, 0)) < 0) break; if (ext != '0') cp--; @@ -1618,7 +1609,7 @@ gunique(char *local) } void -abort_remote(FILE *din) +abort_remote (FILE * din) { char buf[BUFSIZ]; int nfnd; @@ -1628,31 +1619,31 @@ abort_remote(FILE *din) * send IAC in urgent mode instead of DM because 4.3BSD places oob mark * after urgent byte rather than before as is protocol now */ - snprintf(buf, sizeof(buf), "%c%c%c", IAC, IP, IAC); - if (send(fileno(cout), buf, 3, MSG_OOB) != 3) - warn("abort"); - fprintf(cout,"%cABOR\r\n", DM); - fflush(cout); - FD_ZERO(&mask); - FD_SET(fileno(cin), &mask); - if (din) { - FD_SET(fileno(din), &mask); - } - if ((nfnd = empty(&mask, 10)) <= 0) { + snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC); + if (send (fileno (cout), buf, 3, MSG_OOB) != 3) + warn ("abort"); + fprintf (cout, "%cABOR\r\n", DM); + fflush (cout); + FD_ZERO (&mask); + FD_SET (fileno (cin), &mask); + if (din) { + FD_SET (fileno (din), &mask); + } + if ((nfnd = empty (&mask, 10)) <= 0) { if (nfnd < 0) { - warn("abort"); + warn ("abort"); } if (ptabflg) code = -1; - lostpeer(0); + lostpeer (0); } - if (din && FD_ISSET(fileno(din), &mask)) { - while (read(fileno(din), buf, BUFSIZ) > 0) - /* LOOP */; + if (din && FD_ISSET (fileno (din), &mask)) { + while (read (fileno (din), buf, BUFSIZ) > 0) + /* LOOP */ ; } - if (getreply(0) == ERROR && code == 552) { + if (getreply (0) == ERROR && code == 552) { /* 552 needed for nic style abort */ - getreply(0); + getreply (0); } - getreply(0); + getreply (0); } diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h index 6ead793..5ae44b1 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h +++ b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,7 +36,7 @@ * SUCH DAMAGE. */ -/* $Id: ftp_locl.h,v 1.29 1997/05/20 18:40:28 bg Exp $ */ +/* $Id: ftp_locl.h,v 1.33 1998/06/13 00:06:40 assar Exp $ */ #ifndef __FTP_LOCL_H__ #define __FTP_LOCL_H__ @@ -45,8 +45,6 @@ #include <config.h> #endif -#include <sys/cdefs.h> - #ifdef HAVE_PWD_H #include <pwd.h> #endif @@ -121,7 +119,12 @@ #ifdef SOCKS #include <socks.h> -extern int LIBPREFIX(fclose) __P((FILE *)); +extern int LIBPREFIX(fclose) (FILE *); + +/* This doesn't belong here. */ +struct tm *localtime(const time_t *); +struct hostent *gethostbyname(const char *); + #endif #include "ftp_var.h" @@ -129,13 +132,9 @@ extern int LIBPREFIX(fclose) __P((FILE *)); #include "common.h" #include "pathnames.h" -#include <des.h> - -#include <krb.h> - -#include "krb4.h" - #include "roken.h" +#include "security.h" +#include <des.h> /* for des_read_pw_string */ #if defined(__sun__) && !defined(__svr4) int fclose(FILE*); diff --git a/crypto/kerberosIV/appl/ftp/ftp/gssapi.c b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c new file mode 100644 index 0000000..bc001a4 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef FTP_SERVER +#include "ftpd_locl.h" +#else +#include "ftp_locl.h" +#endif +#include <gssapi.h> + +RCSID("$Id: gssapi.c,v 1.7 1999/04/10 15:08:39 assar Exp $"); + +struct gss_data { + gss_ctx_id_t context_hdl; + char *client_name; +}; + +static int +gss_init(void *app_data) +{ + struct gss_data *d = app_data; + d->context_hdl = GSS_C_NO_CONTEXT; + return 0; +} + +static int +gss_check_prot(void *app_data, int level) +{ + if(level == prot_confidential) + return -1; + return 0; +} + +static int +gss_decode(void *app_data, void *buf, int len, int level) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc input, output; + gss_qop_t qop_state; + int conf_state; + struct gss_data *d = app_data; + + input.length = len; + input.value = buf; + maj_stat = gss_unwrap (&min_stat, + d->context_hdl, + &input, + &output, + &conf_state, + &qop_state); + if(GSS_ERROR(maj_stat)) + return -1; + memmove(buf, output.value, output.length); + return output.length; +} + +static int +gss_overhead(void *app_data, int level, int len) +{ + return 100; /* dunno? */ +} + + +static int +gss_encode(void *app_data, void *from, int length, int level, void **to) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc input, output; + int conf_state; + struct gss_data *d = app_data; + + input.length = length; + input.value = from; + maj_stat = gss_wrap (&min_stat, + d->context_hdl, + level == prot_private, + GSS_C_QOP_DEFAULT, + &input, + &conf_state, + &output); + *to = output.value; + return output.length; +} + +/* end common stuff */ + +#ifdef FTP_SERVER + +static int +gss_adat(void *app_data, void *buf, size_t len) +{ + char *p = NULL; + gss_buffer_desc input_token, output_token; + OM_uint32 maj_stat, min_stat; + gss_name_t client_name; + struct gss_data *d = app_data; + + gss_channel_bindings_t bindings = malloc(sizeof(*bindings)); + bindings->initiator_addrtype = GSS_C_AF_INET; + bindings->initiator_address.length = 4; + bindings->initiator_address.value = &his_addr.sin_addr; + bindings->acceptor_addrtype = GSS_C_AF_INET; + bindings->acceptor_address.length = 4; + bindings->acceptor_address.value = &ctrl_addr.sin_addr; + bindings->application_data.length = 0; + bindings->application_data.value = NULL; + + input_token.value = buf; + input_token.length = len; + + maj_stat = gss_accept_sec_context (&min_stat, + &d->context_hdl, + GSS_C_NO_CREDENTIAL, + &input_token, + bindings, + &client_name, + NULL, + &output_token, + NULL, + NULL, + NULL); + + if(output_token.length) { + if(base64_encode(output_token.value, output_token.length, &p) < 0) { + reply(535, "Out of memory base64-encoding."); + return -1; + } + } + if(maj_stat == GSS_S_COMPLETE){ + char *name; + gss_buffer_desc export_name; + maj_stat = gss_export_name(&min_stat, client_name, &export_name); + if(maj_stat != 0) { + reply(500, "Error exporting name"); + goto out; + } + name = realloc(export_name.value, export_name.length + 1); + if(name == NULL) { + reply(500, "Out of memory"); + free(export_name.value); + goto out; + } + name[export_name.length] = '\0'; + d->client_name = name; + if(p) + reply(235, "ADAT=%s", p); + else + reply(235, "ADAT Complete"); + sec_complete = 1; + + } else if(maj_stat == GSS_S_CONTINUE_NEEDED) { + if(p) + reply(335, "ADAT=%s", p); + else + reply(335, "OK, need more data"); + } else + reply(535, "foo?"); +out: + free(p); + return 0; +} + +int gss_userok(void*, char*); + +struct sec_server_mech gss_server_mech = { + "GSSAPI", + sizeof(struct gss_data), + gss_init, /* init */ + NULL, /* end */ + gss_check_prot, + gss_overhead, + gss_encode, + gss_decode, + /* */ + NULL, + gss_adat, + NULL, /* pbsz */ + NULL, /* ccc */ + gss_userok +}; + +#else /* FTP_SERVER */ + +extern struct sockaddr_in hisctladdr, myctladdr; + +static int +gss_auth(void *app_data, char *host) +{ + + OM_uint32 maj_stat, min_stat; + gss_buffer_desc name; + gss_name_t target_name; + gss_buffer_desc input, output_token; + int context_established = 0; + char *p; + int n; + gss_channel_bindings_t bindings; + struct gss_data *d = app_data; + + name.length = asprintf((char**)&name.value, "ftp@%s", host); + maj_stat = gss_import_name(&min_stat, + &name, + GSS_C_NT_HOSTBASED_SERVICE, + &target_name); + free(name.value); + + + input.length = 0; + input.value = NULL; + + bindings = malloc(sizeof(*bindings)); + bindings->initiator_addrtype = GSS_C_AF_INET; + bindings->initiator_address.length = 4; + bindings->initiator_address.value = &myctladdr.sin_addr; + bindings->acceptor_addrtype = GSS_C_AF_INET; + bindings->acceptor_address.length = 4; + bindings->acceptor_address.value = &hisctladdr.sin_addr; + bindings->application_data.length = 0; + bindings->application_data.value = NULL; + + while(!context_established) { + maj_stat = gss_init_sec_context(&min_stat, + GSS_C_NO_CREDENTIAL, + &d->context_hdl, + target_name, + GSS_C_NO_OID, + GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG, + 0, + bindings, + &input, + NULL, + &output_token, + NULL, + NULL); + if (GSS_ERROR(maj_stat)) { + int new_stat; + int msg_ctx = 0; + gss_buffer_desc status_string; + + gss_display_status(&new_stat, + min_stat, + GSS_C_MECH_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + printf("Error initializing security context: %s\n", + (char*)status_string.value); + gss_release_buffer(&new_stat, &status_string); + return AUTH_CONTINUE; + } + + gss_release_buffer(&min_stat, &input); + if (output_token.length != 0) { + base64_encode(output_token.value, output_token.length, &p); + gss_release_buffer(&min_stat, &output_token); + n = command("ADAT %s", p); + free(p); + } + if (GSS_ERROR(maj_stat)) { + if (d->context_hdl != GSS_C_NO_CONTEXT) + gss_delete_sec_context (&min_stat, + &d->context_hdl, + GSS_C_NO_BUFFER); + break; + } + if (maj_stat & GSS_S_CONTINUE_NEEDED) { + p = strstr(reply_string, "ADAT="); + if(p == NULL){ + printf("Error: expected ADAT in reply.\n"); + return AUTH_ERROR; + } else { + p+=5; + input.value = malloc(strlen(p)); + input.length = base64_decode(p, input.value); + } + } else { + if(code != 235) { + printf("Unrecognized response code: %d\n", code); + return AUTH_ERROR; + } + context_established = 1; + } + } + return AUTH_OK; +} + +struct sec_client_mech gss_client_mech = { + "GSSAPI", + sizeof(struct gss_data), + gss_init, + gss_auth, + NULL, /* end */ + gss_check_prot, + gss_overhead, + gss_encode, + gss_decode, +}; + +#endif /* FTP_SERVER */ diff --git a/crypto/kerberosIV/appl/ftp/ftp/kauth.c b/crypto/kerberosIV/appl/ftp/ftp/kauth.c index 8bc9b9b..434dfb8 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/kauth.c +++ b/crypto/kerberosIV/appl/ftp/ftp/kauth.c @@ -37,9 +37,11 @@ */ #include "ftp_locl.h" -RCSID("$Id: kauth.c,v 1.14 1997/05/11 04:08:04 assar Exp $"); +#include <krb.h> +RCSID("$Id: kauth.c,v 1.17 1998/03/26 02:55:38 joda Exp $"); -void kauth(int argc, char **argv) +void +kauth(int argc, char **argv) { int ret; char buf[1024]; @@ -120,7 +122,11 @@ void kauth(int argc, char **argv) memset(key, 0, sizeof(key)); memset(schedule, 0, sizeof(schedule)); memset(passwd, 0, sizeof(passwd)); - base64_encode(tktcopy.dat, tktcopy.length, &p); + if(base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) { + printf("Out of memory base64-encoding.\n"); + code = -1; + return; + } memset (tktcopy.dat, 0, tktcopy.length); ret = command("SITE KAUTH %s %s", name, p); free(p); @@ -131,7 +137,8 @@ void kauth(int argc, char **argv) code = 0; } -void klist(int argc, char **argv) +void +klist(int argc, char **argv) { int ret; if(argc != 1){ @@ -143,3 +150,45 @@ void klist(int argc, char **argv) ret = command("SITE KLIST"); code = (ret == COMPLETE); } + +void +kdestroy(int argc, char **argv) +{ + int ret; + if (argc != 1) { + printf("usage: %s\n", argv[0]); + code = -1; + return; + } + ret = command("SITE KDESTROY"); + code = (ret == COMPLETE); +} + +void +krbtkfile(int argc, char **argv) +{ + int ret; + if(argc != 2) { + printf("usage: %s tktfile\n", argv[0]); + code = -1; + return; + } + ret = command("SITE KRBTKFILE %s", argv[1]); + code = (ret == COMPLETE); +} + +void +afslog(int argc, char **argv) +{ + int ret; + if(argc > 2) { + printf("usage: %s [cell]\n", argv[0]); + code = -1; + return; + } + if(argc == 2) + ret = command("SITE AFSLOG %s", argv[1]); + else + ret = command("SITE AFSLOG"); + code = (ret == COMPLETE); +} diff --git a/crypto/kerberosIV/appl/ftp/ftp/krb4.c b/crypto/kerberosIV/appl/ftp/ftp/krb4.c index 872c5bc..5b9b9b8 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/krb4.c +++ b/crypto/kerberosIV/appl/ftp/ftp/krb4.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,532 +36,260 @@ * SUCH DAMAGE. */ +#ifdef FTP_SERVER +#include "ftpd_locl.h" +#else #include "ftp_locl.h" - -RCSID("$Id: krb4.c,v 1.18 1997/05/11 04:08:05 assar Exp $"); - -static KTEXT_ST krb4_adat; - -static des_cblock key; -static des_key_schedule schedule; - -static char *data_buffer; - -extern struct sockaddr_in hisctladdr, myctladdr; - -int auth_complete; - -static int command_prot; - -static int auth_pbsz; -static int data_prot; - -static int request_data_prot; - - -static struct { - int level; - char *name; -} level_names[] = { - { prot_clear, "clear" }, - { prot_safe, "safe" }, - { prot_confidential, "confidential" }, - { prot_private, "private" } +#endif +#include <krb.h> + +RCSID("$Id: krb4.c,v 1.30 1999/06/15 03:50:28 assar Exp $"); + +#ifdef FTP_SERVER +#define LOCAL_ADDR ctrl_addr +#define REMOTE_ADDR his_addr +#else +#define LOCAL_ADDR myctladdr +#define REMOTE_ADDR hisctladdr +#endif +extern struct sockaddr_in LOCAL_ADDR, REMOTE_ADDR; + +struct krb4_data { + des_cblock key; + des_key_schedule schedule; + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; }; -static char *level_to_name(int level) -{ - int i; - for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) - if(level_names[i].level == level) - return level_names[i].name; - return "unknown"; -} - -static int name_to_level(char *name) -{ - int i; - for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) - if(!strncasecmp(level_names[i].name, name, strlen(name))) - return level_names[i].level; - return -1; -} - -void sec_status(void) -{ - if(auth_complete){ - printf("Using KERBEROS_V4 for authentication.\n"); - - command_prot = prot_private; /* this variable is not used */ - - printf("Using %s command channel.\n", - level_to_name(command_prot)); - - printf("Using %s data channel.\n", - level_to_name(data_prot)); - if(auth_pbsz > 0) - printf("Protection buffer size: %d.\n", auth_pbsz); - }else{ - printf("Not using any security mechanism.\n"); - } -} - static int -sec_prot_internal(int level) +krb4_check_prot(void *app_data, int level) { - int ret; - char *p; - int s = 1048576; - - int old_verbose = verbose; - verbose = 0; - - if(!auth_complete){ - printf("No security data exchange has taken place.\n"); + if(level == prot_confidential) return -1; - } - - if(level){ - ret = command("PBSZ %d", s); - if(ret != COMPLETE){ - printf("Failed to set protection buffer size.\n"); - return -1; - } - auth_pbsz = s; - p = strstr(reply_string, "PBSZ="); - if(p) - sscanf(p, "PBSZ=%d", &s); - if(s < auth_pbsz) - auth_pbsz = s; - if(data_buffer) - free(data_buffer); - data_buffer = malloc(auth_pbsz); - } - verbose = old_verbose; - ret = command("PROT %c", level["CSEP"]); /* XXX :-) */ - if(ret != COMPLETE){ - printf("Failed to set protection level.\n"); - return -1; - } - - data_prot = level; return 0; } - -void -sec_prot(int argc, char **argv) +static int +krb4_decode(void *app_data, void *buf, int len, int level) { - int level = -1; - - if(argc != 2){ - printf("usage: %s (clear | safe | confidential | private)\n", - argv[0]); - code = -1; - return; - } - if(!auth_complete){ - printf("No security data exchange has taken place.\n"); - code = -1; - return; - } - level = name_to_level(argv[1]); - - if(level == -1){ - printf("usage: %s (clear | safe | confidential | private)\n", - argv[0]); - code = -1; - return; - } + MSG_DAT m; + int e; + struct krb4_data *d = app_data; - if(level == prot_confidential){ - printf("Confidential protection is not defined with Kerberos.\n"); - code = -1; - return; - } - - if(sec_prot_internal(level) < 0){ - code = -1; - return; - } - code = 0; -} - -void -sec_set_protection_level(void) -{ - if(auth_complete && data_prot != request_data_prot) - sec_prot_internal(request_data_prot); -} - - -int -sec_request_prot(char *level) -{ - int l = name_to_level(level); - if(l == -1) - return -1; - request_data_prot = l; - return 0; -} - - -int sec_getc(FILE *F) -{ - if(auth_complete && data_prot) - return krb4_getc(F); + if(level == prot_safe) + e = krb_rd_safe(buf, len, &d->key, &REMOTE_ADDR, &LOCAL_ADDR, &m); else - return getc(F); + e = krb_rd_priv(buf, len, d->schedule, &d->key, + &REMOTE_ADDR, &LOCAL_ADDR, &m); + if(e){ + return -1; + } + memmove(buf, m.app_data, m.app_length); + return m.app_length; } -int sec_read(int fd, void *data, int length) +static int +krb4_overhead(void *app_data, int level, int len) { - if(auth_complete && data_prot) - return krb4_read(fd, data, length); - else - return read(fd, data, length); + return 31; } static int -krb4_recv(int fd) +krb4_encode(void *app_data, void *from, int length, int level, void **to) { - int len; - MSG_DAT m; - int kerror; - - krb_net_read(fd, &len, sizeof(len)); - len = ntohl(len); - krb_net_read(fd, data_buffer, len); - if(data_prot == prot_safe) - kerror = krb_rd_safe(data_buffer, len, &key, - &hisctladdr, &myctladdr, &m); + struct krb4_data *d = app_data; + *to = malloc(length + 31); + if(level == prot_safe) + return krb_mk_safe(from, *to, length, &d->key, + &LOCAL_ADDR, &REMOTE_ADDR); + else if(level == prot_private) + return krb_mk_priv(from, *to, length, d->schedule, &d->key, + &LOCAL_ADDR, &REMOTE_ADDR); else - kerror = krb_rd_priv(data_buffer, len, schedule, &key, - &hisctladdr, &myctladdr, &m); - if(kerror){ return -1; - } - memmove(data_buffer, m.app_data, m.app_length); - return m.app_length; } +#ifdef FTP_SERVER -int krb4_getc(FILE *F) +static int +krb4_adat(void *app_data, void *buf, size_t len) { - static int bytes; - static int index; - if(bytes == 0){ - bytes = krb4_recv(fileno(F)); - index = 0; - } - if(bytes){ - bytes--; - return (unsigned char)data_buffer[index++]; + KTEXT_ST tkt; + AUTH_DAT auth_dat; + char *p; + int kerror; + u_int32_t cs; + char msg[35]; /* size of encrypted block */ + int tmp_len; + struct krb4_data *d = app_data; + char inst[INST_SZ]; + + memcpy(tkt.dat, buf, len); + tkt.length = len; + + k_getsockinst(0, inst, sizeof(inst)); + kerror = krb_rd_req(&tkt, "ftp", inst, + his_addr.sin_addr.s_addr, &auth_dat, ""); + if(kerror == RD_AP_UNDEC){ + k_getsockinst(0, inst, sizeof(inst)); + kerror = krb_rd_req(&tkt, "rcmd", inst, + his_addr.sin_addr.s_addr, &auth_dat, ""); } - return EOF; -} - -int krb4_read(int fd, char *data, int length) -{ - static int left; - static int index; - static int eof; - int len = left; - int rx = 0; - if(eof){ - eof = 0; - return 0; + if(kerror){ + reply(535, "Error reading request: %s.", krb_get_err_text(kerror)); + return -1; } - if(left){ - if(length < len) - len = length; - memmove(data, data_buffer + index, len); - length -= len; - index += len; - rx += len; - left -= len; + memcpy(d->key, auth_dat.session, sizeof(d->key)); + des_set_key(&d->key, d->schedule); + + strcpy_truncate(d->name, auth_dat.pname, sizeof(d->name)); + strcpy_truncate(d->instance, auth_dat.pinst, sizeof(d->instance)); + strcpy_truncate(d->realm, auth_dat.prealm, sizeof(d->instance)); + + cs = auth_dat.checksum + 1; + { + unsigned char tmp[4]; + KRB_PUT_INT(cs, tmp, 4, sizeof(tmp)); + tmp_len = krb_mk_safe(tmp, msg, 4, &d->key, &LOCAL_ADDR, &REMOTE_ADDR); } - - while(length){ - len = krb4_recv(fd); - if(len == 0){ - if(rx) - eof = 1; - return rx; - } - if(len > length){ - left = len - length; - len = index = length; - } - memmove(data, data_buffer, len); - length -= len; - data += len; - rx += len; + if(tmp_len < 0){ + reply(535, "Error creating reply: %s.", strerror(errno)); + return -1; } - return rx; -} - - -static int -krb4_encode(char *from, char *to, int length) -{ - if(data_prot == prot_safe) - return krb_mk_safe(from, to, length, &key, - &myctladdr, &hisctladdr); - else - return krb_mk_priv(from, to, length, schedule, &key, - &myctladdr, &hisctladdr); -} - -static int -krb4_overhead(int len) -{ - if(data_prot == prot_safe) - return 31; - else - return 26; -} - -static char p_buf[1024]; -static int p_index; - -int -sec_putc(int c, FILE *F) -{ - if(data_prot){ - if((c == '\n' && p_index) || p_index == sizeof(p_buf)){ - sec_write(fileno(F), p_buf, p_index); - p_index = 0; - } - p_buf[p_index++] = c; - return c; + len = tmp_len; + if(base64_encode(msg, len, &p) < 0) { + reply(535, "Out of memory base64-encoding."); + return -1; } - return putc(c, F); + reply(235, "ADAT=%s", p); + sec_complete = 1; + free(p); + return 0; } static int -sec_send(int fd, char *from, int length) +krb4_userok(void *app_data, char *user) { - int bytes; - bytes = krb4_encode(from, data_buffer, length); - bytes = htonl(bytes); - krb_net_write(fd, &bytes, sizeof(bytes)); - krb_net_write(fd, data_buffer, ntohl(bytes)); - return length; + struct krb4_data *d = app_data; + return krb_kuserok(d->name, d->instance, d->realm, user); } -int -sec_fflush(FILE *F) -{ - if(data_prot){ - if(p_index){ - sec_write(fileno(F), p_buf, p_index); - p_index = 0; - } - sec_send(fileno(F), NULL, 0); - } - fflush(F); - return 0; -} +struct sec_server_mech krb4_server_mech = { + "KERBEROS_V4", + sizeof(struct krb4_data), + NULL, /* init */ + NULL, /* end */ + krb4_check_prot, + krb4_overhead, + krb4_encode, + krb4_decode, + /* */ + NULL, + krb4_adat, + NULL, /* pbsz */ + NULL, /* ccc */ + krb4_userok +}; -int -sec_write(int fd, char *data, int length) -{ - int len = auth_pbsz; - int tx = 0; - - if(data_prot == prot_clear) - return write(fd, data, length); - - len -= krb4_overhead(len); - while(length){ - if(length < len) - len = length; - sec_send(fd, data, len); - length -= len; - data += len; - tx += len; - } - return tx; -} +#else /* FTP_SERVER */ static int -do_auth(char *service, char *host, int checksum) +mk_auth(struct krb4_data *d, KTEXT adat, + char *service, char *host, int checksum) { int ret; CREDENTIALS cred; char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ]; - strcpy(sname, service); - strcpy(inst, krb_get_phost(host)); - strcpy(realm, krb_realmofhost(host)); - ret = krb_mk_req(&krb4_adat, sname, inst, realm, checksum); + + strcpy_truncate(sname, service, sizeof(sname)); + strcpy_truncate(inst, krb_get_phost(host), sizeof(inst)); + strcpy_truncate(realm, krb_realmofhost(host), sizeof(realm)); + ret = krb_mk_req(adat, sname, inst, realm, checksum); if(ret) return ret; - strcpy(sname, service); - strcpy(inst, krb_get_phost(host)); - strcpy(realm, krb_realmofhost(host)); + strcpy_truncate(sname, service, sizeof(sname)); + strcpy_truncate(inst, krb_get_phost(host), sizeof(inst)); + strcpy_truncate(realm, krb_realmofhost(host), sizeof(realm)); ret = krb_get_cred(sname, inst, realm, &cred); - memmove(&key, &cred.session, sizeof(des_cblock)); - des_key_sched(&key, schedule); + memmove(&d->key, &cred.session, sizeof(des_cblock)); + des_key_sched(&d->key, d->schedule); memset(&cred, 0, sizeof(cred)); return ret; } - -int -do_klogin(char *host) +static int +krb4_auth(void *app_data, char *host) { int ret; char *p; int len; - char adat[1024]; + KTEXT_ST adat; MSG_DAT msg_data; int checksum; - - int old_verbose = verbose; - - verbose = 0; - printf("Trying KERBEROS_V4...\n"); - ret = command("AUTH KERBEROS_V4"); - if(ret != CONTINUE){ - if(code == 504){ - printf("Kerberos 4 is not supported by the server.\n"); - }else if(code == 534){ - printf("KERBEROS_V4 rejected as security mechanism.\n"); - }else if(ret == ERROR) - printf("The server doesn't understand the FTP " - "security extensions.\n"); - verbose = old_verbose; - return -1; - } + u_int32_t cs; + struct krb4_data *d = app_data; checksum = getpid(); - ret = do_auth("ftp", host, checksum); + ret = mk_auth(d, &adat, "ftp", host, checksum); if(ret == KDC_PR_UNKNOWN) - ret = do_auth("rcmd", host, checksum); + ret = mk_auth(d, &adat, "rcmd", host, checksum); if(ret){ printf("%s\n", krb_get_err_text(ret)); - verbose = old_verbose; - return ret; + return AUTH_CONTINUE; } - base64_encode(krb4_adat.dat, krb4_adat.length, &p); + if(base64_encode(adat.dat, adat.length, &p) < 0) { + printf("Out of memory base64-encoding.\n"); + return AUTH_CONTINUE; + } ret = command("ADAT %s", p); free(p); if(ret != COMPLETE){ printf("Server didn't accept auth data.\n"); - verbose = old_verbose; - return -1; + return AUTH_ERROR; } p = strstr(reply_string, "ADAT="); if(!p){ printf("Remote host didn't send adat reply.\n"); - verbose = old_verbose; - return -1; + return AUTH_ERROR; } - p+=5; - len = base64_decode(p, adat); + p += 5; + len = base64_decode(p, adat.dat); if(len < 0){ printf("Failed to decode base64 from server.\n"); - verbose = old_verbose; - return -1; + return AUTH_ERROR; } - ret = krb_rd_safe(adat, len, &key, + adat.length = len; + ret = krb_rd_safe(adat.dat, adat.length, &d->key, &hisctladdr, &myctladdr, &msg_data); if(ret){ printf("Error reading reply from server: %s.\n", krb_get_err_text(ret)); - verbose = old_verbose; - return -1; + return AUTH_ERROR; } - { - /* the draft doesn't tell what size the return has */ - int i; - u_int32_t cs = 0; - for(i = 0; i < msg_data.app_length; i++) - cs = (cs<<8) + msg_data.app_data[i]; - if(cs - checksum != 1){ - printf("Bad checksum returned from server.\n"); - verbose = old_verbose; - return -1; - } + krb_get_int(msg_data.app_data, &cs, 4, 0); + if(cs - checksum != 1){ + printf("Bad checksum returned from server.\n"); + return AUTH_ERROR; } - auth_complete = 1; - verbose = old_verbose; - return 0; -} - -void -krb4_quit(void) -{ - auth_complete = 0; -} - -int krb4_write_enc(FILE *F, char *fmt, va_list ap) -{ - int len; - char *p; - char buf[1024]; - char enc[1024]; - - vsnprintf(buf, sizeof(buf), fmt, ap); - len = krb_mk_priv(buf, enc, strlen(buf), schedule, &key, - &myctladdr, &hisctladdr); - base64_encode(enc, len, &p); - - fprintf(F, "ENC %s", p); - free (p); - return 0; + return AUTH_OK; } +struct sec_client_mech krb4_client_mech = { + "KERBEROS_V4", + sizeof(struct krb4_data), + NULL, /* init */ + krb4_auth, + NULL, /* end */ + krb4_check_prot, + krb4_overhead, + krb4_encode, + krb4_decode +}; -int krb4_read_msg(char *s, int priv) -{ - int len; - int ret; - char buf[1024]; - MSG_DAT m; - int code; - - len = base64_decode(s + 4, buf); - if(priv) - ret = krb_rd_priv(buf, len, schedule, &key, - &hisctladdr, &myctladdr, &m); - else - ret = krb_rd_safe(buf, len, &key, &hisctladdr, &myctladdr, &m); - if(ret){ - printf("%s\n", krb_get_err_text(ret)); - return -1; - } - - m.app_data[m.app_length] = 0; - if(m.app_data[3] == '-') - code = 0; - else - sscanf((char*)m.app_data, "%d", &code); - strncpy(s, (char*)m.app_data, strlen((char*)m.app_data)); - - s[m.app_length] = 0; - len = strlen(s); - if(s[len-1] == '\n') - s[len-1] = 0; - - return code; -} - -int -krb4_read_mic(char *s) -{ - return krb4_read_msg(s, 0); -} - -int -krb4_read_enc(char *s) -{ - return krb4_read_msg(s, 1); -} - +#endif /* FTP_SERVER */ diff --git a/crypto/kerberosIV/appl/ftp/ftp/main.c b/crypto/kerberosIV/appl/ftp/ftp/main.c index 4d1b6a5..5b0fe36 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/main.c +++ b/crypto/kerberosIV/appl/ftp/ftp/main.c @@ -36,7 +36,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: main.c,v 1.20 1997/04/20 16:14:55 joda Exp $"); +RCSID("$Id: main.c,v 1.25 1999/05/08 02:22:09 assar Exp $"); int main(int argc, char **argv) @@ -54,8 +54,9 @@ main(int argc, char **argv) doglob = 1; interactive = 1; autologin = 1; + passivemode = 0; /* passive mode not active */ - while ((ch = getopt(argc, argv, "dgintv")) != EOF) { + while ((ch = getopt(argc, argv, "dginptv")) != EOF) { switch (ch) { case 'd': options |= SO_DEBUG; @@ -74,6 +75,9 @@ main(int argc, char **argv) autologin = 0; break; + case 'p': + passivemode = 1; + break; case 't': trace++; break; @@ -84,7 +88,7 @@ main(int argc, char **argv) default: fprintf(stderr, - "usage: ftp [-dgintv] [host [port]]\n"); + "usage: ftp [-dginptv] [host [port]]\n"); exit(1); } } @@ -96,7 +100,6 @@ main(int argc, char **argv) verbose++; cpend = 0; /* no pending replies */ proxy = 0; /* proxy not active */ - passivemode = 0; /* passive mode not active */ crflag = 1; /* strip c.r. on ascii gets */ sendport = -1; /* not using ports */ /* @@ -104,8 +107,8 @@ main(int argc, char **argv) */ pw = k_getpwuid(getuid()); if (pw != NULL) { + strcpy_truncate(homedir, pw->pw_dir, sizeof(homedir)); home = homedir; - strcpy(home, pw->pw_dir); } if (argc > 0) { char *xargv[5]; @@ -174,6 +177,7 @@ lostpeer(int sig) } proxflag = 0; pswitch(0); + sec_end(); SIGRETURN(0); } @@ -242,8 +246,7 @@ cmdscanner(int top) p = readline("ftp> "); if(p == NULL) quit(0, 0); - strncpy(line, p, sizeof(line)); - line[sizeof(line) - 1] = 0; + strcpy_truncate(line, p, sizeof(line)); add_history(p); free(p); } else{ @@ -337,12 +340,16 @@ makeargv(void) for (margc = 0; ; margc++) { /* Expand array if necessary */ if (margc == margvlen) { + int i; + margv = (margvlen == 0) ? (char **)malloc(20 * sizeof(char *)) : (char **)realloc(margv, (margvlen + 20)*sizeof(char *)); if (margv == NULL) errx(1, "cannot realloc argv array"); + for(i = margvlen; i < margvlen + 20; ++i) + margv[i] = NULL; margvlen += 20; argp = margv + margc; } diff --git a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c index 8cea6d4..043e6fb 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c +++ b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c @@ -32,7 +32,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: ruserpass.c,v 1.10 1997/05/02 14:27:55 assar Exp $"); +RCSID("$Id: ruserpass.c,v 1.15 1999/03/11 13:54:58 joda Exp $"); static int token (void); static FILE *cfile; @@ -63,175 +63,213 @@ static struct toktab { { NULL, 0 } }; +/* + * Write a copy of the hostname into `hostname, sz' and return a guess + * as to the `domain' of that hostname. + */ + +static char * +guess_domain (char *hostname, size_t sz) +{ + struct hostent *he; + char *dot; + char *a; + char **aliases; + + if (gethostname (hostname, sz) < 0) { + strcpy_truncate (hostname, "", sz); + return ""; + } + dot = strchr (hostname, '.'); + if (dot != NULL) + return dot + 1; + + he = gethostbyname (hostname); + if (he == NULL) + return hostname; + + dot = strchr (he->h_name, '.'); + if (dot != NULL) { + strcpy_truncate (hostname, he->h_name, sz); + return dot + 1; + } + for (aliases = he->h_aliases; (a = *aliases) != NULL; ++aliases) { + dot = strchr (a, '.'); + if (dot != NULL) { + strcpy_truncate (hostname, a, sz); + return dot + 1; + } + } + return hostname; +} + int ruserpass(char *host, char **aname, char **apass, char **aacct) { - char *hdir, buf[BUFSIZ], *tmp; - int t, i, c, usedefault = 0; - struct stat stb; + char *hdir, buf[BUFSIZ], *tmp; + int t, i, c, usedefault = 0; + struct stat stb; - if(k_gethostname(myhostname, MaxHostNameLen) < 0) - strcpy(myhostname, ""); - if((mydomain = strchr(myhostname, '.')) == NULL) - mydomain = myhostname; - else - mydomain++; - hdir = getenv("HOME"); - if (hdir == NULL) - hdir = "."; - snprintf(buf, sizeof(buf), "%s/.netrc", hdir); - cfile = fopen(buf, "r"); - if (cfile == NULL) { - if (errno != ENOENT) - warn("%s", buf); - return (0); - } + mydomain = guess_domain (myhostname, MaxHostNameLen); + + hdir = getenv("HOME"); + if (hdir == NULL) + hdir = "."; + snprintf(buf, sizeof(buf), "%s/.netrc", hdir); + cfile = fopen(buf, "r"); + if (cfile == NULL) { + if (errno != ENOENT) + warn("%s", buf); + return (0); + } next: - while ((t = token())) switch(t) { + while ((t = token())) switch(t) { - case DEFAULT: - usedefault = 1; - /* FALL THROUGH */ + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ - case MACH: - if (!usedefault) { - if (token() != ID) - continue; - /* - * Allow match either for user's input host name - * or official hostname. Also allow match of - * incompletely-specified host in local domain. - */ - if (strcasecmp(host, tokval) == 0) - goto match; - if (strcasecmp(hostname, tokval) == 0) - goto match; - if ((tmp = strchr(hostname, '.')) != NULL && - tmp++ && - strcasecmp(tmp, mydomain) == 0 && - strncasecmp(hostname, tokval, tmp-hostname) == 0 && - tokval[tmp - hostname] == '\0') - goto match; - if ((tmp = strchr(host, '.')) != NULL && - tmp++ && - strcasecmp(tmp, mydomain) == 0 && - strncasecmp(host, tokval, tmp - host) == 0 && - tokval[tmp - host] == '\0') - goto match; - continue; - } - match: - while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { + case MACH: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's input host name + * or official hostname. Also allow match of + * incompletely-specified host in local domain. + */ + if (strcasecmp(host, tokval) == 0) + goto match; + if (strcasecmp(hostname, tokval) == 0) + goto match; + if ((tmp = strchr(hostname, '.')) != NULL && + tmp++ && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(hostname, tokval, tmp-hostname) == 0 && + tokval[tmp - hostname] == '\0') + goto match; + if ((tmp = strchr(host, '.')) != NULL && + tmp++ && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(host, tokval, tmp - host) == 0 && + tokval[tmp - host] == '\0') + goto match; + continue; + } + match: + while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { - case LOGIN: - if (token()) - if (*aname == 0) { - *aname = strdup(tokval); - } else { - if (strcmp(*aname, tokval)) - goto next; - } - break; - case PASSWD: - if ((*aname == NULL || strcmp(*aname, "anonymous")) && - fstat(fileno(cfile), &stb) >= 0 && - (stb.st_mode & 077) != 0) { - warnx("Error: .netrc file is readable by others."); - warnx("Remove password or make file unreadable by others."); - goto bad; - } - if (token() && *apass == 0) { - *apass = strdup(tokval); - } - break; - case ACCOUNT: - if (fstat(fileno(cfile), &stb) >= 0 - && (stb.st_mode & 077) != 0) { - warnx("Error: .netrc file is readable by others."); - warnx("Remove account or make file unreadable by others."); - goto bad; - } - if (token() && *aacct == 0) { - *aacct = strdup(tokval); - } - break; - case MACDEF: - if (proxy) { - fclose(cfile); - return (0); - } - while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t'); - if (c == EOF || c == '\n') { - printf("Missing macdef name argument.\n"); - goto bad; - } - if (macnum == 16) { - printf("Limit of 16 macros have already been defined\n"); - goto bad; - } - tmp = macros[macnum].mac_name; - *tmp++ = c; - for (i=0; i < 8 && (c=getc(cfile)) != EOF && - !isspace(c); ++i) { - *tmp++ = c; - } - if (c == EOF) { - printf("Macro definition missing null line terminator.\n"); - goto bad; - } - *tmp = '\0'; - if (c != '\n') { - while ((c=getc(cfile)) != EOF && c != '\n'); - } - if (c == EOF) { - printf("Macro definition missing null line terminator.\n"); - goto bad; - } - if (macnum == 0) { - macros[macnum].mac_start = macbuf; - } - else { - macros[macnum].mac_start = macros[macnum-1].mac_end + 1; - } - tmp = macros[macnum].mac_start; - while (tmp != macbuf + 4096) { - if ((c=getc(cfile)) == EOF) { - printf("Macro definition missing null line terminator.\n"); - goto bad; - } - *tmp = c; - if (*tmp == '\n') { - if (*(tmp-1) == '\0') { - macros[macnum++].mac_end = tmp - 1; - break; - } - *tmp = '\0'; - } - tmp++; - } - if (tmp == macbuf + 4096) { - printf("4K macro buffer exceeded\n"); - goto bad; - } - break; - case PROT: - token(); - if(sec_request_prot(tokval) < 0) - warnx("Unknown protection level \"%s\"", tokval); - break; - default: - warnx("Unknown .netrc keyword %s", tokval); + case LOGIN: + if (token()) { + if (*aname == 0) { + *aname = strdup(tokval); + } else { + if (strcmp(*aname, tokval)) + goto next; + } + } + break; + case PASSWD: + if ((*aname == NULL || strcmp(*aname, "anonymous")) && + fstat(fileno(cfile), &stb) >= 0 && + (stb.st_mode & 077) != 0) { + warnx("Error: .netrc file is readable by others."); + warnx("Remove password or make file unreadable by others."); + goto bad; + } + if (token() && *apass == 0) { + *apass = strdup(tokval); + } + break; + case ACCOUNT: + if (fstat(fileno(cfile), &stb) >= 0 + && (stb.st_mode & 077) != 0) { + warnx("Error: .netrc file is readable by others."); + warnx("Remove account or make file unreadable by others."); + goto bad; + } + if (token() && *aacct == 0) { + *aacct = strdup(tokval); + } + break; + case MACDEF: + if (proxy) { + fclose(cfile); + return (0); + } + while ((c=getc(cfile)) != EOF && + (c == ' ' || c == '\t')); + if (c == EOF || c == '\n') { + printf("Missing macdef name argument.\n"); + goto bad; + } + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + goto bad; + } + tmp = macros[macnum].mac_name; + *tmp++ = c; + for (i=0; i < 8 && (c=getc(cfile)) != EOF && + !isspace(c); ++i) { + *tmp++ = c; + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = '\0'; + if (c != '\n') { + while ((c=getc(cfile)) != EOF && c != '\n'); + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum-1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf + 4096) { + if ((c=getc(cfile)) == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = c; + if (*tmp == '\n') { + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; break; + } + *tmp = '\0'; } - goto done; + tmp++; + } + if (tmp == macbuf + 4096) { + printf("4K macro buffer exceeded\n"); + goto bad; + } + break; + case PROT: + token(); + if(sec_request_prot(tokval) < 0) + warnx("Unknown protection level \"%s\"", tokval); + break; + default: + warnx("Unknown .netrc keyword %s", tokval); + break; } + goto done; + } done: - fclose(cfile); - return (0); + fclose(cfile); + return (0); bad: - fclose(cfile); - return (-1); + fclose(cfile); + return (-1); } static int diff --git a/crypto/kerberosIV/appl/ftp/ftp/security.c b/crypto/kerberosIV/appl/ftp/ftp/security.c new file mode 100644 index 0000000..96d598f --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/security.c @@ -0,0 +1,730 @@ +/* + * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef FTP_SERVER +#include "ftpd_locl.h" +#else +#include "ftp_locl.h" +#endif + +RCSID("$Id: security.c,v 1.8 1999/04/07 14:16:48 joda Exp $"); + +static enum protection_level command_prot; +static enum protection_level data_prot; +static size_t buffer_size; + +struct buffer { + void *data; + size_t size; + size_t index; + int eof_flag; +}; + +static struct buffer in_buffer, out_buffer; +int sec_complete; + +static struct { + enum protection_level level; + const char *name; +} level_names[] = { + { prot_clear, "clear" }, + { prot_safe, "safe" }, + { prot_confidential, "confidential" }, + { prot_private, "private" } +}; + +static const char * +level_to_name(enum protection_level level) +{ + int i; + for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) + if(level_names[i].level == level) + return level_names[i].name; + return "unknown"; +} + +#ifndef FTP_SERVER /* not used in server */ +static enum protection_level +name_to_level(const char *name) +{ + int i; + for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) + if(!strncasecmp(level_names[i].name, name, strlen(name))) + return level_names[i].level; + return (enum protection_level)-1; +} +#endif + +#ifdef FTP_SERVER + +static struct sec_server_mech *mechs[] = { +#ifdef KRB5 + &gss_server_mech, +#endif +#ifdef KRB4 + &krb4_server_mech, +#endif + NULL +}; + +static struct sec_server_mech *mech; + +#else + +static struct sec_client_mech *mechs[] = { +#ifdef KRB5 + &gss_client_mech, +#endif +#ifdef KRB4 + &krb4_client_mech, +#endif + NULL +}; + +static struct sec_client_mech *mech; + +#endif + +static void *app_data; + +int +sec_getc(FILE *F) +{ + if(sec_complete && data_prot) { + char c; + if(sec_read(fileno(F), &c, 1) == 0) + return EOF; + return c; + } else + return getc(F); +} + +static int +block_read(int fd, void *buf, size_t len) +{ + unsigned char *p = buf; + int b; + while(len) { + b = read(fd, p, len); + if(b <= 0) + return -1; + len -= b; + p += b; + } + return p - (unsigned char*)buf; +} + +static int +block_write(int fd, void *buf, size_t len) +{ + unsigned char *p = buf; + int b; + while(len) { + b = write(fd, p, len); + if(b < 0) + return -1; + len -= b; + p += b; + } + return p - (unsigned char*)buf; +} + +static int +sec_get_data(int fd, struct buffer *buf, int level) +{ + int len; + + if(block_read(fd, &len, sizeof(len)) < 0) + return -1; + len = ntohl(len); + buf->data = realloc(buf->data, len); + if(block_read(fd, buf->data, len) < 0) + return -1; + buf->size = (*mech->decode)(app_data, buf->data, len, data_prot); + buf->index = 0; + return 0; +} + +static size_t +buffer_read(struct buffer *buf, void *data, size_t len) +{ + len = min(len, buf->size - buf->index); + memcpy(data, (char*)buf->data + buf->index, len); + buf->index += len; + return len; +} + +static size_t +buffer_write(struct buffer *buf, void *data, size_t len) +{ + if(buf->index + len > buf->size) { + void *tmp; + if(buf->data == NULL) + tmp = malloc(1024); + else + tmp = realloc(buf->data, buf->index + len); + if(tmp == NULL) + return -1; + buf->data = tmp; + buf->size = buf->index + len; + } + memcpy((char*)buf->data + buf->index, data, len); + buf->index += len; + return len; +} + +int +sec_read(int fd, void *data, int length) +{ + size_t len; + int rx = 0; + + if(sec_complete == 0 || data_prot == 0) + return read(fd, data, length); + + if(in_buffer.eof_flag){ + in_buffer.eof_flag = 0; + return 0; + } + + len = buffer_read(&in_buffer, data, length); + length -= len; + rx += len; + data = (char*)data + len; + + while(length){ + if(sec_get_data(fd, &in_buffer, data_prot) < 0) + return -1; + if(in_buffer.size == 0) { + if(rx) + in_buffer.eof_flag = 1; + return rx; + } + len = buffer_read(&in_buffer, data, length); + length -= len; + rx += len; + data = (char*)data + len; + } + return rx; +} + +static int +sec_send(int fd, char *from, int length) +{ + int bytes; + void *buf; + bytes = (*mech->encode)(app_data, from, length, data_prot, &buf); + bytes = htonl(bytes); + block_write(fd, &bytes, sizeof(bytes)); + block_write(fd, buf, ntohl(bytes)); + free(buf); + return length; +} + +int +sec_fflush(FILE *F) +{ + if(data_prot != prot_clear) { + if(out_buffer.index > 0){ + sec_write(fileno(F), out_buffer.data, out_buffer.index); + out_buffer.index = 0; + } + sec_send(fileno(F), NULL, 0); + } + fflush(F); + return 0; +} + +int +sec_write(int fd, char *data, int length) +{ + int len = buffer_size; + int tx = 0; + + if(data_prot == prot_clear) + return write(fd, data, length); + + len -= (*mech->overhead)(app_data, data_prot, len); + while(length){ + if(length < len) + len = length; + sec_send(fd, data, len); + length -= len; + data += len; + tx += len; + } + return tx; +} + +int +sec_putc(int c, FILE *F) +{ + char ch = c; + if(data_prot == prot_clear) + return putc(c, F); + + buffer_write(&out_buffer, &ch, 1); + if(c == '\n' || out_buffer.index >= 1024 /* XXX */) { + sec_write(fileno(F), out_buffer.data, out_buffer.index); + out_buffer.index = 0; + } + return c; +} + +int +sec_read_msg(char *s, int level) +{ + int len; + char *buf; + int code; + + buf = malloc(strlen(s)); + len = base64_decode(s + 4, buf); /* XXX */ + + len = (*mech->decode)(app_data, buf, len, level); + if(len < 0) + return -1; + + buf[len] = '\0'; + + if(buf[3] == '-') + code = 0; + else + sscanf(buf, "%d", &code); + if(buf[len-1] == '\n') + buf[len-1] = '\0'; + strcpy(s, buf); + free(buf); + return code; +} + +int +sec_vfprintf(FILE *f, const char *fmt, va_list ap) +{ + char *buf; + void *enc; + int len; + if(!sec_complete) + return vfprintf(f, fmt, ap); + + vasprintf(&buf, fmt, ap); + len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc); + free(buf); + if(len < 0) { + printf("Failed to encode command.\n"); + return -1; + } + if(base64_encode(enc, len, &buf) < 0){ + printf("Out of memory base64-encoding.\n"); + return -1; + } +#ifdef FTP_SERVER + if(command_prot == prot_safe) + fprintf(f, "631 %s\r\n", buf); + else if(command_prot == prot_private) + fprintf(f, "632 %s\r\n", buf); + else if(command_prot == prot_confidential) + fprintf(f, "633 %s\r\n", buf); +#else + if(command_prot == prot_safe) + fprintf(f, "MIC %s", buf); + else if(command_prot == prot_private) + fprintf(f, "ENC %s", buf); + else if(command_prot == prot_confidential) + fprintf(f, "CONF %s", buf); +#endif + free(buf); + return 0; +} + +int +sec_fprintf(FILE *f, const char *fmt, ...) +{ + va_list ap; + int ret; + va_start(ap, fmt); + ret = sec_vfprintf(f, fmt, ap); + va_end(ap); + return ret; +} + +/* end common stuff */ + +#ifdef FTP_SERVER + +void +auth(char *auth_name) +{ + int i; + for(i = 0; (mech = mechs[i]) != NULL; i++){ + if(!strcasecmp(auth_name, mech->name)){ + app_data = realloc(app_data, mech->size); + if(mech->init && (*mech->init)(app_data) != 0) { + reply(431, "Unable to accept %s at this time", mech->name); + return; + } + if(mech->auth) { + (*mech->auth)(app_data); + return; + } + if(mech->adat) + reply(334, "Send authorization data."); + else + reply(234, "Authorization complete."); + return; + } + } + free (app_data); + reply(504, "%s is unknown to me", auth_name); +} + +void +adat(char *auth_data) +{ + if(mech && !sec_complete) { + void *buf = malloc(strlen(auth_data)); + size_t len; + len = base64_decode(auth_data, buf); + (*mech->adat)(app_data, buf, len); + free(buf); + } else + reply(503, "You must %sissue an AUTH first.", mech ? "re-" : ""); +} + +void pbsz(int size) +{ + size_t new = size; + if(!sec_complete) + reply(503, "Incomplete security data exchange."); + if(mech->pbsz) + new = (*mech->pbsz)(app_data, size); + if(buffer_size != new){ + buffer_size = size; + } + if(new != size) + reply(200, "PBSZ=%lu", (unsigned long)new); + else + reply(200, "OK"); +} + +void +prot(char *pl) +{ + int p = -1; + + if(buffer_size == 0){ + reply(503, "No protection buffer size negotiated."); + return; + } + + if(!strcasecmp(pl, "C")) + p = prot_clear; + else if(!strcasecmp(pl, "S")) + p = prot_safe; + else if(!strcasecmp(pl, "E")) + p = prot_confidential; + else if(!strcasecmp(pl, "P")) + p = prot_private; + else { + reply(504, "Unrecognized protection level."); + return; + } + + if(sec_complete){ + if((*mech->check_prot)(app_data, p)){ + reply(536, "%s does not support %s protection.", + mech->name, level_to_name(p)); + }else{ + data_prot = (enum protection_level)p; + reply(200, "Data protection is %s.", level_to_name(p)); + } + }else{ + reply(503, "Incomplete security data exchange."); + } +} + +void ccc(void) +{ + if(sec_complete){ + if(mech->ccc && (*mech->ccc)(app_data) == 0) + command_prot = data_prot = prot_clear; + else + reply(534, "You must be joking."); + }else + reply(503, "Incomplete security data exchange."); +} + +void mec(char *msg, enum protection_level level) +{ + void *buf; + size_t len; + if(!sec_complete) { + reply(503, "Incomplete security data exchange."); + return; + } + buf = malloc(strlen(msg) + 2); /* XXX go figure out where that 2 + comes from :-) */ + len = base64_decode(msg, buf); + command_prot = level; + if(len == (size_t)-1) { + reply(501, "Failed to base64-decode command"); + return; + } + len = (*mech->decode)(app_data, buf, len, level); + if(len == (size_t)-1) { + reply(535, "Failed to decode command"); + return; + } + ((char*)buf)[len] = '\0'; + if(strstr((char*)buf, "\r\n") == NULL) + strcat((char*)buf, "\r\n"); + new_ftp_command(buf); +} + +/* ------------------------------------------------------------ */ + +int +sec_userok(char *user) +{ + if(sec_complete) + return (*mech->userok)(app_data, user); + return 0; +} + +char *ftp_command; + +void +new_ftp_command(char *command) +{ + ftp_command = command; +} + +void +delete_ftp_command(void) +{ + free(ftp_command); + ftp_command = NULL; +} + +int +secure_command(void) +{ + return ftp_command != NULL; +} + +#else /* FTP_SERVER */ + +void +sec_status(void) +{ + if(sec_complete){ + printf("Using %s for authentication.\n", mech->name); + printf("Using %s command channel.\n", level_to_name(command_prot)); + printf("Using %s data channel.\n", level_to_name(data_prot)); + if(buffer_size > 0) + printf("Protection buffer size: %lu.\n", + (unsigned long)buffer_size); + }else{ + printf("Not using any security mechanism.\n"); + } +} + +static int +sec_prot_internal(int level) +{ + int ret; + char *p; + unsigned int s = 1048576; + + int old_verbose = verbose; + verbose = 0; + + if(!sec_complete){ + printf("No security data exchange has taken place.\n"); + return -1; + } + + if(level){ + ret = command("PBSZ %u", s); + if(ret != COMPLETE){ + printf("Failed to set protection buffer size.\n"); + return -1; + } + buffer_size = s; + p = strstr(reply_string, "PBSZ="); + if(p) + sscanf(p, "PBSZ=%u", &s); + if(s < buffer_size) + buffer_size = s; + } + verbose = old_verbose; + ret = command("PROT %c", level["CSEP"]); /* XXX :-) */ + if(ret != COMPLETE){ + printf("Failed to set protection level.\n"); + return -1; + } + + data_prot = (enum protection_level)level; + return 0; +} + +void +sec_prot(int argc, char **argv) +{ + int level = -1; + + if(argc != 2){ + printf("usage: %s (clear | safe | confidential | private)\n", + argv[0]); + code = -1; + return; + } + if(!sec_complete){ + printf("No security data exchange has taken place.\n"); + code = -1; + return; + } + level = name_to_level(argv[1]); + + if(level == -1){ + printf("usage: %s (clear | safe | confidential | private)\n", + argv[0]); + code = -1; + return; + } + + if((*mech->check_prot)(app_data, level)) { + printf("%s does not implement %s protection.\n", + mech->name, level_to_name(level)); + code = -1; + return; + } + + if(sec_prot_internal(level) < 0){ + code = -1; + return; + } + code = 0; +} + +static enum protection_level request_data_prot; + +void +sec_set_protection_level(void) +{ + if(sec_complete && data_prot != request_data_prot) + sec_prot_internal(request_data_prot); +} + + +int +sec_request_prot(char *level) +{ + int l = name_to_level(level); + if(l == -1) + return -1; + request_data_prot = (enum protection_level)l; + return 0; +} + +int +sec_login(char *host) +{ + int ret; + struct sec_client_mech **m; + int old_verbose = verbose; + + verbose = -1; /* shut up all messages this will produce (they + are usually not very user friendly) */ + + for(m = mechs; *m && (*m)->name; m++) { + app_data = realloc(app_data, (*m)->size); + if((*m)->init && (*(*m)->init)(app_data) != 0) { + printf("Skipping %s...\n", (*m)->name); + continue; + } + printf("Trying %s...\n", (*m)->name); + ret = command("AUTH %s", (*m)->name); + if(ret != CONTINUE){ + if(code == 504){ + printf("%s is not supported by the server.\n", (*m)->name); + }else if(code == 534){ + printf("%s rejected as security mechanism.\n", (*m)->name); + }else if(ret == ERROR) { + printf("The server doesn't support the FTP " + "security extensions.\n"); + verbose = old_verbose; + return -1; + } + continue; + } + + ret = (*(*m)->auth)(app_data, host); + + if(ret == AUTH_CONTINUE) + continue; + else if(ret != AUTH_OK){ + /* mechanism is supposed to output error string */ + verbose = old_verbose; + return -1; + } + mech = *m; + sec_complete = 1; + command_prot = prot_safe; + break; + } + + verbose = old_verbose; + return *m == NULL; +} + +void +sec_end(void) +{ + if (mech != NULL) { + if(mech->end) + (*mech->end)(app_data); + memset(app_data, 0, mech->size); + free(app_data); + } + sec_complete = 0; + data_prot = (enum protection_level)0; +} + +#endif /* FTP_SERVER */ + diff --git a/crypto/kerberosIV/appl/ftp/ftp/security.h b/crypto/kerberosIV/appl/ftp/ftp/security.h new file mode 100644 index 0000000..adac689 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/security.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: security.h,v 1.3 1999/04/07 14:15:20 joda Exp $ */ + +#ifndef __security_h__ +#define __security_h__ + +enum protection_level { + prot_clear, + prot_safe, + prot_confidential, + prot_private +}; + +struct sec_client_mech { + char *name; + size_t size; + int (*init)(void *); + int (*auth)(void *, char*); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, void*, int, int, void**); + int (*decode)(void *, void*, int, int); +}; + +struct sec_server_mech { + char *name; + size_t size; + int (*init)(void *); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, void*, int, int, void**); + int (*decode)(void *, void*, int, int); + + int (*auth)(void *); + int (*adat)(void *, void*, size_t); + size_t (*pbsz)(void *, size_t); + int (*ccc)(void*); + int (*userok)(void*, char*); +}; + +#define AUTH_OK 0 +#define AUTH_CONTINUE 1 +#define AUTH_ERROR 2 + +#ifdef FTP_SERVER +extern struct sec_server_mech krb4_server_mech, gss_server_mech; +#else +extern struct sec_client_mech krb4_client_mech, gss_client_mech; +#endif + +extern int sec_complete; + +#ifdef FTP_SERVER +extern char *ftp_command; +void new_ftp_command(char*); +void delete_ftp_command(void); +#endif + +/* ---- */ + + +int sec_fflush (FILE *); +int sec_fprintf (FILE *, const char *, ...); +int sec_getc (FILE *); +int sec_putc (int, FILE *); +int sec_read (int, void *, int); +int sec_read_msg (char *, int); +int sec_vfprintf (FILE *, const char *, va_list); +int sec_write (int, char *, int); + +#ifdef FTP_SERVER +void adat (char *); +void auth (char *); +void ccc (void); +void mec (char *, enum protection_level); +void pbsz (int); +void prot (char *); +void delete_ftp_command (void); +void new_ftp_command (char *); +int sec_userok (char *); +int secure_command (void); +#else +void sec_end (void); +int sec_login (char *); +void sec_prot (int, char **); +int sec_request_prot (char *); +void sec_set_protection_level (void); +void sec_status (void); +#endif + +#endif /* __security_h__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am new file mode 100644 index 0000000..187fca3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am @@ -0,0 +1,53 @@ +# $Id: Makefile.am,v 1.19 1999/04/25 13:24:55 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER + +libexec_PROGRAMS = ftpd + +CHECK_LOCAL = + +if KRB4 +krb4_sources = krb4.c kauth.c +endif +if KRB5 +krb5_sources = gssapi.c gss_userok.c +endif + +ftpd_SOURCES = \ + extern.h \ + ftpcmd.y \ + ftpd.c \ + ftpd_locl.h \ + logwtmp.c \ + pathnames.h \ + popen.c \ + security.c \ + $(krb4_sources) \ + $(krb5_sources) + +EXTRA_ftpd_SOURCES = krb4.c kauth.c gssapi.c gss_userok.c + +$(ftpd_OBJECTS): security.h + +security.c: + @test -f security.c || $(LN_S) $(srcdir)/../ftp/security.c . +security.h: + @test -f security.h || $(LN_S) $(srcdir)/../ftp/security.h . +krb4.c: + @test -f krb4.c || $(LN_S) $(srcdir)/../ftp/krb4.c . +gssapi.c: + @test -f gssapi.c || $(LN_S) $(srcdir)/../ftp/gssapi.c . + +CLEANFILES = security.c security.h krb4.c gssapi.c ftpcmd.c + +LDADD = ../common/libcommon.a \ + $(LIB_kafs) \ + $(LIB_gssapi) \ + $(LIB_krb5) \ + $(LIB_krb4) \ + $(LIB_otp) \ + $(top_builddir)/lib/des/libdes.la \ + $(LIB_roken) \ + $(DBLIB) diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in index 55981de..3b555a6 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in @@ -1,12 +1,12 @@ # -# $Id: Makefile.in,v 1.31 1997/05/02 17:49:27 assar Exp $ +# $Id: Makefile.in,v 1.40 1999/03/10 19:01:11 joda Exp $ # srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -topdir = ../../.. +top_builddir = ../../.. SHELL = /bin/sh @@ -14,7 +14,8 @@ CC = @CC@ YACC = @YACC@ RANLIB = @RANLIB@ DEFS = @DEFS@ -CFLAGS = @CFLAGS@ +WFLAGS = @WFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) LD_FLAGS = @LD_FLAGS@ LIBS = @LIBS@ LIB_DBM = @LIB_DBM@ @@ -23,6 +24,8 @@ MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LN_S = @LN_S@ + prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@ @@ -39,31 +42,42 @@ LIBTOP = $(ATHENA)/lib LIBKAFS = @KRB_KAFS_LIB@ LIBKRB = -L$(LIBTOP)/krb -lkrb LIBDES = -L$(LIBTOP)/des -ldes -LIBOTP = -L$(LIBTOP)/otp -lotp +LIBOTP = @LIB_otp@ LIBROKEN= -L$(LIBTOP)/roken -lroken PROGS = ftpd$(EXECSUFFIX) -ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c popen.c auth.c krb4.c kauth.c -ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o auth.o krb4.o kauth.o +ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c popen.c security.c krb4.c kauth.c +ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o security.o krb4.o kauth.o SOURCES = $(ftpd_SOURCES) OBJECTS = $(ftpd_OBJS) all: $(PROGS) +$(ftpd_OBJS): security.h + +security.c: + $(LN_S) $(srcdir)/../ftp/security.c . +security.h: + $(LN_S) $(srcdir)/../ftp/security.h . +krb4.c: + $(LN_S) $(srcdir)/../ftp/krb4.c . +gssapi.c: + $(LN_S) $(srcdir)/../ftp/gssapi.c . + .c.o: - $(CC) -c $(CFLAGS) -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $< + $(CC) -c -DFTP_SERVER -I. -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $(CFLAGS) $(CPPFLAGS) $< install: all - $(MKINSTALLDIRS) $(libexecdir) + $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir) for x in $(PROGS); do \ - $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ done uninstall: for x in $(PROGS); do \ - rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ done ftpd$(EXECSUFFIX): $(ftpd_OBJS) @@ -77,8 +91,12 @@ ftpcmd.c: ftpcmd.y TAGS: $(SOURCES) etags $(SOURCES) +CLEANFILES = ftpd$(EXECSUFFIX) ftpcmd.c security.c security.h krb4.c gssapi.c + clean cleandir: - rm -f *~ *.o core ftpd ftpcmd.c \#* + rm -f *~ *.o core \#* $(CLEANFILES) distclean: rm -f Makefile + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/ftpd/extern.h b/crypto/kerberosIV/appl/ftp/ftpd/extern.h index f9b800f..e96809e 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/extern.h +++ b/crypto/kerberosIV/appl/ftp/ftpd/extern.h @@ -36,6 +36,9 @@ #ifndef _EXTERN_H_ #define _EXTERN_H_ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif @@ -49,8 +52,13 @@ #ifdef HAVE_PWD_H #include <pwd.h> #endif -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#ifndef NBBY +#define NBBY CHAR_BIT #endif void abor(void); @@ -63,8 +71,8 @@ void fatal(char *); int filename_check(char *); int ftpd_pclose(FILE *); FILE *ftpd_popen(char *, char *, int, int); -char *getline(char *, int); -void logwtmp(char *, char *, char *); +char *ftpd_getline(char *, int); +void ftpd_logwtmp(char *, char *, char *); void lreply(int, const char *, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) @@ -105,6 +113,11 @@ void yyerror(char *); void kauth(char *, char*); void klist(void); +void cond_kdestroy(void); +void kdestroy(void); +void krbtkfile(const char *tkfile); +void afslog(const char *cell); +void afsunlog(void); int find(char *); diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y index 9368cdb..be36ea2 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y @@ -42,73 +42,15 @@ %{ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -RCSID("$Id: ftpcmd.y,v 1.35 1997/05/25 14:38:49 assar Exp $"); - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_FTP_H -#include <arpa/ftp.h> -#endif - -#include <ctype.h> -#include <errno.h> -#include <glob.h> -#ifdef HAVE_PWD_H -#include <pwd.h> -#endif -#include <setjmp.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifdef HAVE_SYSLOG_H -#include <syslog.h> -#endif -#include <time.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_BSD_BSD_H -#include <bsd/bsd.h> -#endif - -#include <roken.h> - -#ifdef SOCKS -#include <socks.h> -extern int LIBPREFIX(fclose) __P((FILE *)); -#endif - -#include "extern.h" -#include "auth.h" +#include "ftpd_locl.h" +RCSID("$Id: ftpcmd.y,v 1.48 1999/05/08 02:22:43 assar Exp $"); off_t restart_point; static int cmd_type; static int cmd_form; static int cmd_bytesz; -char cbuf[512]; +char cbuf[2048]; char *fromname; struct tab { @@ -122,13 +64,13 @@ struct tab { extern struct tab cmdtab[]; extern struct tab sitetab[]; -static char *copy (char *); -static void help (struct tab *, char *); +static char *copy (char *); +static void help (struct tab *, char *); static struct tab * - lookup (struct tab *, char *); -static void sizecmd (char *); -static void toolong (int); -static int yylex (void); + lookup (struct tab *, char *); +static void sizecmd (char *); +static RETSIGTYPE toolong (int); +static int yylex (void); /* This is for bison */ @@ -154,7 +96,7 @@ static int yylex (void); APPE MLFL MAIL MSND MSOM MSAM MRSQ MRCP ALLO REST RNFR RNTO ABOR DELE CWD LIST NLST SITE - STAT HELP NOOP MKD RMD PWD + sTAT HELP NOOP MKD RMD PWD CDUP STOU SMNT SYST SIZE MDTM UMASK IDLE CHMOD @@ -162,14 +104,15 @@ static int yylex (void); AUTH ADAT PROT PBSZ CCC MIC CONF ENC - KAUTH KLIST FIND URL + KAUTH KLIST KDESTROY KRBTKFILE AFSLOG + FIND URL LEXERR %token <s> STRING %token <i> NUMBER -%type <i> check_login check_login_no_guest octal_number byte_size +%type <i> check_login check_login_no_guest check_secure octal_number byte_size %type <i> struct_code mode_code type_code form_code %type <s> pathstring pathname password username @@ -193,38 +136,6 @@ cmd user($3); free($3); } - | AUTH SP STRING CRLF - { - auth($3); - free($3); - } - | ADAT SP STRING CRLF - { - adat($3); - free($3); - } - | PBSZ SP NUMBER CRLF - { - pbsz($3); - } - | PROT SP STRING CRLF - { - prot($3); - } - | CCC CRLF - { - ccc(); - } - | MIC SP STRING CRLF - { - mic($3); - free($3); - } - | CONF SP STRING CRLF - { - conf($3); - free($3); - } | PASS SP password CRLF { pass($3); @@ -311,100 +222,102 @@ cmd { reply(202, "ALLO command ignored."); } - | RETR check_login SP pathname CRLF + | RETR SP pathname CRLF check_login { - if ($2 && $4 != NULL) - retrieve((char *) 0, $4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + retrieve(0, $3); + if ($3 != NULL) + free($3); } - | STOR check_login SP pathname CRLF + | STOR SP pathname CRLF check_login { - if ($2 && $4 != NULL) - do_store($4, "w", 0); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_store($3, "w", 0); + if ($3 != NULL) + free($3); } - | APPE check_login SP pathname CRLF + | APPE SP pathname CRLF check_login { - if ($2 && $4 != NULL) - do_store($4, "a", 0); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_store($3, "a", 0); + if ($3 != NULL) + free($3); } - | NLST check_login CRLF + | NLST CRLF check_login { - if ($2) + if ($3) send_file_list("."); } - | NLST check_login SP STRING CRLF + | NLST SP STRING CRLF check_login { - if ($2 && $4 != NULL) - send_file_list($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + send_file_list($3); + if ($3 != NULL) + free($3); } - | LIST check_login CRLF + | LIST CRLF check_login { #ifdef HAVE_LS_A char *cmd = "/bin/ls -lA"; #else char *cmd = "/bin/ls -la"; #endif - if ($2) + if ($3) retrieve(cmd, ""); } - | LIST check_login SP pathname CRLF + | LIST SP pathname CRLF check_login { #ifdef HAVE_LS_A char *cmd = "/bin/ls -lA %s"; #else char *cmd = "/bin/ls -la %s"; #endif - if ($2 && $4 != NULL) - retrieve(cmd, $4); - if ($4 != NULL) - free($4); - } - | STAT check_login SP pathname CRLF - { - if ($2 && $4 != NULL) - statfilecmd($4); - if ($4 != NULL) - free($4); - } - | STAT CRLF - { - if(oobflag){ - if (file_size != (off_t) -1) - reply(213, "Status: %ld of %ld bytes transferred", - byte_count, file_size); - else - reply(213, "Status: %ld bytes transferred", byte_count); - }else - statcmd(); + if ($5 && $3 != NULL) + retrieve(cmd, $3); + if ($3 != NULL) + free($3); + } + | sTAT SP pathname CRLF check_login + { + if ($5 && $3 != NULL) + statfilecmd($3); + if ($3 != NULL) + free($3); + } + | sTAT CRLF + { + if(oobflag){ + if (file_size != (off_t) -1) + reply(213, "Status: %lu of %lu bytes transferred", + (unsigned long)byte_count, + (unsigned long)file_size); + else + reply(213, "Status: %lu bytes transferred", + (unsigned long)byte_count); + }else + statcmd(); } - | DELE check_login_no_guest SP pathname CRLF + | DELE SP pathname CRLF check_login_no_guest { - if ($2 && $4 != NULL) - do_delete($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_delete($3); + if ($3 != NULL) + free($3); } - | RNTO check_login_no_guest SP pathname CRLF + | RNTO SP pathname CRLF check_login_no_guest { - if($2){ + if($5){ if (fromname) { - renamecmd(fromname, $4); + renamecmd(fromname, $3); free(fromname); fromname = (char *) 0; } else { reply(503, "Bad sequence of commands."); } } - if ($4 != NULL) - free($4); + if ($3 != NULL) + free($3); } | ABOR CRLF { @@ -416,17 +329,17 @@ cmd }else reply(225, "ABOR command successful."); } - | CWD check_login CRLF + | CWD CRLF check_login { - if ($2) + if ($3) cwd(pw->pw_dir); } - | CWD check_login SP pathname CRLF + | CWD SP pathname CRLF check_login { - if ($2 && $4 != NULL) - cwd($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + cwd($3); + if ($3 != NULL) + free($3); } | HELP CRLF { @@ -451,28 +364,28 @@ cmd { reply(200, "NOOP command successful."); } - | MKD check_login SP pathname CRLF + | MKD SP pathname CRLF check_login { - if ($2 && $4 != NULL) - makedir($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + makedir($3); + if ($3 != NULL) + free($3); } - | RMD check_login_no_guest SP pathname CRLF + | RMD SP pathname CRLF check_login_no_guest { - if ($2 && $4 != NULL) - removedir($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + removedir($3); + if ($3 != NULL) + free($3); } - | PWD check_login CRLF + | PWD CRLF check_login { - if ($2) + if ($3) pwd(); } - | CDUP check_login CRLF + | CDUP CRLF check_login { - if ($2) + if ($3) cwd(".."); } | SITE SP HELP CRLF @@ -483,44 +396,40 @@ cmd { help(sitetab, $5); } - | SITE SP UMASK check_login CRLF + | SITE SP UMASK CRLF check_login { - int oldmask; - - if ($4) { - oldmask = umask(0); + if ($5) { + int oldmask = umask(0); umask(oldmask); reply(200, "Current UMASK is %03o", oldmask); } } - | SITE SP UMASK check_login_no_guest SP octal_number CRLF + | SITE SP UMASK SP octal_number CRLF check_login_no_guest { - int oldmask; - - if ($4) { - if (($6 == -1) || ($6 > 0777)) { + if ($7) { + if (($5 == -1) || ($5 > 0777)) { reply(501, "Bad UMASK value"); } else { - oldmask = umask($6); + int oldmask = umask($5); reply(200, - "UMASK set to %03o (was %03o)", - $6, oldmask); + "UMASK set to %03o (was %03o)", + $5, oldmask); } } } - | SITE SP CHMOD check_login_no_guest SP octal_number SP pathname CRLF + | SITE SP CHMOD SP octal_number SP pathname CRLF check_login_no_guest { - if ($4 && $8 != NULL) { - if ($6 > 0777) + if ($9 && $7 != NULL) { + if ($5 > 0777) reply(501, "CHMOD: Mode value must be between 0 and 0777"); - else if (chmod($8, $6) < 0) - perror_reply(550, $8); + else if (chmod($7, $5) < 0) + perror_reply(550, $7); else reply(200, "CHMOD command successful."); } - if ($8 != NULL) - free($8); + if ($7 != NULL) + free($7); } | SITE SP IDLE CRLF { @@ -543,47 +452,102 @@ cmd } } - | SITE SP KAUTH check_login SP STRING CRLF + | SITE SP KAUTH SP STRING CRLF check_login { +#ifdef KRB4 char *p; if(guest) reply(500, "Can't be done as guest."); else{ - if($4 && $6 != NULL){ - p = strpbrk($6, " \t"); + if($7 && $5 != NULL){ + p = strpbrk($5, " \t"); if(p){ *p++ = 0; - kauth($6, p + strspn(p, " \t")); + kauth($5, p + strspn(p, " \t")); }else - kauth($6, NULL); + kauth($5, NULL); } } - if($6 != NULL) - free($6); + if($5 != NULL) + free($5); +#else + reply(500, "Command not implemented."); +#endif } - | SITE SP KLIST check_login CRLF + | SITE SP KLIST CRLF check_login { - if($4) +#ifdef KRB4 + if($5) klist(); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP KDESTROY CRLF check_login + { +#ifdef KRB4 + if($5) + kdestroy(); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP KRBTKFILE SP STRING CRLF check_login + { +#ifdef KRB4 + if(guest) + reply(500, "Can't be done as guest."); + else if($7 && $5) + krbtkfile($5); + if($5) + free($5); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP AFSLOG CRLF check_login + { +#ifdef KRB4 + if(guest) + reply(500, "Can't be done as guest."); + else if($5) + afslog(NULL); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP AFSLOG SP STRING CRLF check_login + { +#ifdef KRB4 + if(guest) + reply(500, "Can't be done as guest."); + else if($7){ + afslog($5); + } + if($5) + free($5); +#else + reply(500, "Command not implemented."); +#endif } - | SITE SP FIND check_login SP STRING CRLF + | SITE SP FIND SP STRING CRLF check_login { - if($4 && $6 != NULL) - find($6); - if($6 != NULL) - free($6); + if($7 && $5 != NULL) + find($5); + if($5 != NULL) + free($5); } | SITE SP URL CRLF { reply(200, "http://www.pdc.kth.se/kth-krb/"); } - | STOU check_login SP pathname CRLF + | STOU SP pathname CRLF check_login { - if ($2 && $4 != NULL) - do_store($4, "w", 1); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_store($3, "w", 1); + if ($3 != NULL) + free($3); } | SYST CRLF { @@ -601,12 +565,12 @@ cmd * Return size of file in a format suitable for * using with RESTART (we just count bytes). */ - | SIZE check_login SP pathname CRLF + | SIZE SP pathname CRLF check_login { - if ($2 && $4 != NULL) - sizecmd($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + sizecmd($3); + if ($3 != NULL) + free($3); } /* @@ -618,15 +582,16 @@ cmd * where xxx is the fractional second (of any precision, * not necessarily 3 digits) */ - | MDTM check_login SP pathname CRLF + | MDTM SP pathname CRLF check_login { - if ($2 && $4 != NULL) { + if ($5 && $3 != NULL) { struct stat stbuf; - if (stat($4, &stbuf) < 0) + if (stat($3, &stbuf) < 0) reply(550, "%s: %s", - $4, strerror(errno)); + $3, strerror(errno)); else if (!S_ISREG(stbuf.st_mode)) { - reply(550, "%s: not a plain file.", $4); + reply(550, + "%s: not a plain file.", $3); } else { struct tm *t; t = gmtime(&stbuf.st_mtime); @@ -640,8 +605,8 @@ cmd t->tm_sec); } } - if ($4 != NULL) - free($4); + if ($3 != NULL) + free($3); } | QUIT CRLF { @@ -654,13 +619,13 @@ cmd } ; rcmd - : RNFR check_login_no_guest SP pathname CRLF + : RNFR SP pathname CRLF check_login_no_guest { restart_point = (off_t) 0; - if ($2 && $4) { - fromname = renamefrom($4); - if (fromname == (char *) 0 && $4) { - free($4); + if ($5 && $3) { + fromname = renamefrom($3); + if (fromname == (char *) 0 && $3) { + free($3); } } } @@ -672,9 +637,41 @@ rcmd (long)restart_point, "Send STORE or RETRIEVE to initiate transfer."); } + | AUTH SP STRING CRLF + { + auth($3); + free($3); + } + | ADAT SP STRING CRLF + { + adat($3); + free($3); + } + | PBSZ SP NUMBER CRLF + { + pbsz($3); + } + | PROT SP STRING CRLF + { + prot($3); + } + | CCC CRLF + { + ccc(); + } + | MIC SP STRING CRLF + { + mec($3, prot_safe); + free($3); + } + | CONF SP STRING CRLF + { + mec($3, prot_confidential); + free($3); + } | ENC SP STRING CRLF { - enc($3); + mec($3, prot_private); free($3); } ; @@ -861,19 +858,24 @@ check_login_no_guest : check_login } ; -check_login - : /* empty */ +check_login : check_secure { - if(auth_complete && prot_level == prot_clear){ - reply(533, "Command protection level denied for paranoid reasons."); - $$ = 0; - }else - if (logged_in) - $$ = 1; - else { + if($1) { + if(($$ = logged_in) == 0) reply(530, "Please login with USER and PASS."); - $$ = 0; - } + } else + $$ = 0; + } + ; + +check_secure : /* empty */ + { + $$ = 1; + if(sec_complete && !secure_command()) { + $$ = 0; + reply(533, "Command protection level denied " + "for paranoid reasons."); + } } ; @@ -925,7 +927,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" }, { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" }, { "SYST", SYST, ARGS, 1, "(get type of operating system)" }, - { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" }, + { "STAT", sTAT, OSTR, 1, "[ <sp> path-name ]" }, { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" }, { "NOOP", NOOP, ARGS, 1, "" }, { "MKD", MKD, STR1, 1, "<sp> path-name" }, @@ -940,7 +942,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "SIZE", SIZE, OSTR, 1, "<sp> path-name" }, { "MDTM", MDTM, OSTR, 1, "<sp> path-name" }, - /* extensions from draft-ietf-cat-ftpsec-08 */ + /* extensions from RFC2228 */ { "AUTH", AUTH, STR1, 1, "<sp> auth-type" }, { "ADAT", ADAT, STR1, 1, "<sp> auth-data" }, { "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" }, @@ -961,6 +963,9 @@ struct tab sitetab[] = { { "KAUTH", KAUTH, STR1, 1, "<sp> principal [ <sp> ticket ]" }, { "KLIST", KLIST, ARGS, 1, "(show ticket file)" }, + { "KDESTROY", KDESTROY, ARGS, 1, "(destroy tickets)" }, + { "KRBTKFILE", KRBTKFILE, STR1, 1, "<sp> ticket-file" }, + { "AFSLOG", AFSLOG, OSTR, 1, "[<sp> cell]" }, { "FIND", FIND, STR1, 1, "<sp> globexpr" }, @@ -979,13 +984,11 @@ lookup(struct tab *p, char *cmd) return (0); } -#include <arpa/telnet.h> - /* - * getline - a hacked up version of fgets to ignore TELNET escape codes. + * ftpd_getline - a hacked up version of fgets to ignore TELNET escape codes. */ char * -getline(char *s, int n) +ftpd_getline(char *s, int n) { int c; char *cs; @@ -993,7 +996,7 @@ getline(char *s, int n) cs = s; /* tmpline may contain saved command from urgent mode interruption */ if(ftp_command){ - strncpy(s, ftp_command, n); + strcpy_truncate(s, ftp_command, n); if (debug) syslog(LOG_DEBUG, "command: %s", s); #ifdef XXX @@ -1001,7 +1004,6 @@ getline(char *s, int n) #endif return s; } - prot_level = prot_clear; while ((c = getc(stdin)) != EOF) { c &= 0377; if (c == IAC) { @@ -1087,15 +1089,15 @@ yylex(void) case CMD: signal(SIGALRM, toolong); alarm((unsigned) ftpd_timeout); - if (getline(cbuf, sizeof(cbuf)-1) == NULL) { + if (ftpd_getline(cbuf, sizeof(cbuf)-1) == NULL) { reply(221, "You could at least say goodbye."); dologout(0); } alarm(0); -#ifdef HASSETPROCTITLE +#ifdef HAVE_SETPROCTITLE if (strncasecmp(cbuf, "PASS", 4) != NULL) setproctitle("%s: %s", proctitle, cbuf); -#endif /* HASSETPROCTITLE */ +#endif /* HAVE_SETPROCTITLE */ if ((cp = strchr(cbuf, '\r'))) { *cp++ = '\n'; *cp = '\0'; @@ -1333,16 +1335,21 @@ help(struct tab *ctab, char *s) columns = 1; lines = (NCMDS + columns - 1) / columns; for (i = 0; i < lines; i++) { - strcpy (buf, " "); + strcpy_truncate (buf, " ", sizeof(buf)); for (j = 0; j < columns; j++) { c = ctab + j * lines + i; - snprintf (buf + strlen(buf), sizeof(buf) - strlen(buf), - "%s%c", c->name, c->implemented ? ' ' : '*'); + snprintf (buf + strlen(buf), + sizeof(buf) - strlen(buf), + "%s%c", + c->name, + c->implemented ? ' ' : '*'); if (c + lines >= &ctab[NCMDS]) break; w = strlen(c->name) + 1; while (w < width) { - strcat(buf, " "); + strcat_truncate (buf, + " ", + sizeof(buf)); w++; } } @@ -1375,11 +1382,12 @@ sizecmd(char *filename) reply(550, "%s: not a plain file.", filename); else reply(213, "%lu", (unsigned long)stbuf.st_size); - break; } + break; + } case TYPE_A: { FILE *fin; int c; - off_t count; + size_t count; struct stat stbuf; fin = fopen(filename, "r"); if (fin == NULL) { @@ -1400,8 +1408,9 @@ sizecmd(char *filename) } fclose(fin); - reply(213, "%ld", count); - break; } + reply(213, "%lu", (unsigned long)count); + break; + } default: reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); } diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c index 17cd3b9..fa87fc2 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c @@ -31,122 +31,13 @@ * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include <config.h> -RCSID("$Id: ftpd.c,v 1.88 1997/06/01 03:13:48 assar Exp $"); -#endif - -/* - * FTP server. - */ -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4 -#include <sys/ioctl.h> -#endif -#ifdef TIME_WITH_SYS_TIME -#include <sys/time.h> -#include <time.h> -#elif defined(HAVE_SYS_TIME_H) -#include <sys/time.h> -#else -#include <time.h> -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif -#ifdef HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_NETINET_IN_SYSTM_H -#include <netinet/in_systm.h> -#endif -#ifdef HAVE_NETINET_IP_H -#include <netinet/ip.h> -#endif - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - #define FTP_NAMES -#include <arpa/ftp.h> -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#ifdef HAVE_ARPA_TELNET_H -#include <arpa/telnet.h> +#include "ftpd_locl.h" +#ifdef KRB5 +#include <krb5.h> #endif -#include <ctype.h> -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#include <errno.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <glob.h> -#include <limits.h> -#ifdef HAVE_PWD_H -#include <pwd.h> -#endif -#include <setjmp.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#ifdef HAVE_SYSLOG_H -#include <syslog.h> -#endif -#include <time.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_GRP_H -#include <grp.h> -#endif - -#include <err.h> - -#include "pathnames.h" -#include "extern.h" -#include "common.h" - -#include "auth.h" - -#include <krb.h> - -#include <kafs.h> -#include "roken.h" - -#include <otp.h> - -#ifdef SOCKS -#include <socks.h> -extern int LIBPREFIX(fclose) __P((FILE *)); -#endif - -void yyparse(); - -#ifndef LOG_FTP -#define LOG_FTP LOG_DAEMON -#endif +RCSID("$Id: ftpd.c,v 1.115 1999/06/15 03:51:47 assar Exp $"); static char version[] = "Version 6.00"; @@ -164,7 +55,7 @@ jmp_buf errcatch, urgcatch; int oobflag; int logged_in; struct passwd *pw; -int debug; +int debug = 0; int ftpd_timeout = 900; /* timeout after 15 minutes of inactivity */ int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ int logging; @@ -248,12 +139,12 @@ static void usage(void); static char * curdir(void) { - static char path[MaxPathLen+1+1]; /* path + '/' + '\0' */ + static char path[MaxPathLen+1]; /* path + '/' + '\0' */ - if (getcwd(path, sizeof(path)-2) == NULL) + if (getcwd(path, sizeof(path)-1) == NULL) return (""); if (path[1] != '\0') /* special case for root dir. */ - strcat(path, "/"); + strcat_truncate(path, "/", sizeof(path)); /* For guest account, skip / since it's chrooted */ return (guest ? path+1 : path); } @@ -274,8 +165,10 @@ parse_auth_level(char *str) p = strtok_r(NULL, ",", &foo)) { if(strcmp(p, "user") == 0) ; +#ifdef OTP else if(strcmp(p, "otp") == 0) ret |= AUTH_PLAIN|AUTH_OTP; +#endif else if(strcmp(p, "ftp") == 0 || strcmp(p, "safe") == 0) ret |= AUTH_FTP; @@ -313,18 +206,20 @@ main(int argc, char **argv) int not_inetd = 0; int port; struct servent *sp; - char tkfile[1024]; set_progname (argv[0]); +#ifdef KRB4 /* detach from any tickets and tokens */ - - snprintf(tkfile, sizeof(tkfile), - "/tmp/ftp_%u", (unsigned)getpid()); - krb_set_tkt_string(tkfile); - if(k_hasafs()) - k_setpag(); - + { + char tkfile[1024]; + snprintf(tkfile, sizeof(tkfile), + "/tmp/ftp_%u", (unsigned)getpid()); + krb_set_tkt_string(tkfile); + if(k_hasafs()) + k_setpag(); + } +#endif sp = getservbyname("ftp", "tcp"); if(sp) port = sp->s_port; @@ -426,7 +321,6 @@ main(int argc, char **argv) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); - debug = 0; /* set this here so it can be put in wtmp */ snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid()); @@ -440,8 +334,6 @@ main(int argc, char **argv) syslog(LOG_ERR, "signal: %m"); #endif - auth_init(); - /* Try to handle urgent data inline */ #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on, @@ -486,9 +378,22 @@ main(int argc, char **argv) fclose(fd); /* reply(220,) must follow */ } - k_gethostname(hostname, sizeof(hostname)); - reply(220, "%s FTP server (%s+%s) ready.", hostname, - version, krb4_version); + gethostname(hostname, sizeof(hostname)); + reply(220, "%s FTP server (%s" +#ifdef KRB5 + "+%s" +#endif +#ifdef KRB4 + "+%s" +#endif + ") ready.", hostname, version +#ifdef KRB5 + ,heimdal_version +#endif +#ifdef KRB4 + ,krb4_version +#endif + ); setjmp(errcatch); for (;;) yyparse(); @@ -552,7 +457,9 @@ sgetpwnam(char *name) static int login_attempts; /* number of failed login attempts */ static int askpasswd; /* had user command, ask for passwd */ static char curname[10]; /* current USER name */ +#ifdef OTP OtpContext otp_ctx; +#endif /* * USER command. @@ -570,7 +477,7 @@ user(char *name) { char *cp, *shell; - if(auth_level == 0 && !auth_complete){ + if(auth_level == 0 && !sec_complete){ reply(530, "No login allowed without authorization."); return; } @@ -605,7 +512,7 @@ user(char *name) remotehost, inet_ntoa(his_addr.sin_addr)); return; } - if((auth_level & AUTH_PLAIN) == 0 && !auth_complete){ + if((auth_level & AUTH_PLAIN) == 0 && !sec_complete){ reply(530, "Only authorized and anonymous login allowed."); return; } @@ -630,26 +537,37 @@ user(char *name) } } if (logging) - strncpy(curname, name, sizeof(curname)-1); - if(auth_ok()) - ct->userok(name); - else { + strcpy_truncate(curname, name, sizeof(curname)); + if(sec_complete) { + if(sec_userok(name) == 0) + do_login(232, name); + else + reply(530, "User %s access denied.", name); + } else { char ss[256]; +#ifdef OTP if (otp_challenge(&otp_ctx, name, ss, sizeof(ss)) == 0) { reply(331, "Password %s for %s required.", ss, name); askpasswd = 1; - } else if ((auth_level & AUTH_OTP) == 0) { + } else +#endif + if ((auth_level & AUTH_OTP) == 0) { reply(331, "Password required for %s.", name); askpasswd = 1; } else { char *s; - if (s = otp_error (&otp_ctx)) +#ifdef OTP + if ((s = otp_error (&otp_ctx)) != NULL) lreply(530, "OTP: %s", s); +#endif reply(530, - "Only authorized, anonymous and OTP " + "Only authorized, anonymous" +#ifdef OTP + " and OTP " +#endif "login allowed."); } @@ -706,11 +624,7 @@ checkuser(char *fname, char *name) static int match(const char *pattern, const char *string) { -#ifdef HAVE_FNMATCH return fnmatch(pattern, string, FNM_NOESCAPE); -#else - return strcmp(pattern, "*") != 0 && strcmp(pattern, string) != 0; -#endif } static int @@ -759,7 +673,7 @@ int do_login(int code, char *passwd) initgroups(pw->pw_name, pw->pw_gid); /* open wtmp before chroot */ - logwtmp(ttyline, pw->pw_name, remotehost); + ftpd_logwtmp(ttyline, pw->pw_name, remotehost); logged_in = 1; dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name); @@ -842,7 +756,7 @@ end_login(void) seteuid((uid_t)0); if (logged_in) - logwtmp(ttyline, "", ""); + ftpd_logwtmp(ttyline, "", ""); pw = NULL; logged_in = 0; guest = 0; @@ -869,23 +783,33 @@ pass(char *passwd) if (!guest) { /* "ftp" is only account allowed no password */ if (pw == NULL) rval = 1; /* failure below */ +#ifdef OTP else if (otp_verify_user (&otp_ctx, passwd) == 0) { rval = 0; - } else if((auth_level & AUTH_OTP) == 0) { + } +#endif + else if((auth_level & AUTH_OTP) == 0) { +#ifdef KRB4 char realm[REALM_SZ]; if((rval = krb_get_lrealm(realm, 1)) == KSUCCESS) - rval = krb_verify_user(pw->pw_name, "", realm, - passwd, 1, NULL); - if (rval == KSUCCESS ){ + rval = krb_verify_user(pw->pw_name, + "", realm, + passwd, + KRB_VERIFY_SECURE, NULL); + if (rval == KSUCCESS ) { + chown (tkt_string(), pw->pw_uid, pw->pw_gid); if(k_hasafs()) - k_afsklog(0, 0); - }else + krb_afslog(0, 0); + } else +#endif rval = unix_verify_user(pw->pw_name, passwd); } else { char *s; - if (s = otp_error(&otp_ctx)) +#ifdef OTP + if ((s = otp_error(&otp_ctx)) != NULL) lreply(530, "OTP: %s", s); +#endif } memset (passwd, 0, strlen(passwd)); @@ -935,14 +859,15 @@ retrieve(char *cmd, char *name) st.st_size = 0; if(fin == NULL){ struct cmds { - char *ext; - char *cmd; + const char *ext; + const char *cmd; + const char *rev_cmd; } cmds[] = { - {".tar", "/bin/gtar cPf - %s"}, - {".tar.gz", "/bin/gtar zcPf - %s"}, - {".tar.Z", "/bin/gtar ZcPf - %s"}, - {".gz", "/bin/gzip -c %s"}, - {".Z", "/bin/compress -c %s"}, + {".tar", "/bin/gtar cPf - %s", NULL}, + {".tar.gz", "/bin/gtar zcPf - %s", NULL}, + {".tar.Z", "/bin/gtar ZcPf - %s", NULL}, + {".gz", "/bin/gzip -c %s", "/bin/gzip -c -d %s"}, + {".Z", "/bin/compress -c %s", "/bin/uncompress -c -d %s"}, {NULL, NULL} }; struct cmds *p; @@ -958,6 +883,21 @@ retrieve(char *cmd, char *name) break; } *tail = c; + if (p->rev_cmd != NULL) { + char *ext; + + asprintf(&ext, "%s%s", name, p->ext); + if (ext != NULL) { + if (access(ext, R_OK) == 0) { + snprintf (line, sizeof(line), + p->rev_cmd, ext); + free(ext); + break; + } + free(ext); + } + } + } if(p->ext){ fin = ftpd_popen(line, "r", 0, 0); @@ -1173,14 +1113,14 @@ dataconn(char *name, off_t size, char *mode) { char sizebuf[32]; FILE *file; - int retry = 0, tos; + int retry = 0; file_size = size; byte_count = 0; - if (size != (off_t) -1) - snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", size); + if (size >= 0) + snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", (long)size); else - strcpy(sizebuf, ""); + *sizebuf = '\0'; if (pdata >= 0) { struct sockaddr_in from; int s, fromlen = sizeof(from); @@ -1195,9 +1135,12 @@ dataconn(char *name, off_t size, char *mode) close(pdata); pdata = s; #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) - tos = IPTOS_THROUGHPUT; - setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos, - sizeof(int)); + { + int tos = IPTOS_THROUGHPUT; + + setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos, + sizeof(tos)); + } #endif reply(150, "Opening %s mode data connection for '%s'%s.", type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); @@ -1249,8 +1192,6 @@ send_data(FILE *instr, FILE *outstr) int c, cnt, filefd, netfd; static char *buf; static size_t bufsize; - int i = 0; - char s[1024]; transflag++; if (setjmp(urgcatch)) { @@ -1260,31 +1201,24 @@ send_data(FILE *instr, FILE *outstr) switch (type) { case TYPE_A: - while ((c = getc(instr)) != EOF) { - byte_count++; - if(i > 1022){ - auth_write(fileno(outstr), s, i); - i = 0; - } - if(c == '\n') - s[i++] = '\r'; - s[i++] = c; - } - if(i) - auth_write(fileno(outstr), s, i); - auth_write(fileno(outstr), s, 0); - fflush(outstr); - transflag = 0; - if (ferror(instr)) - goto file_err; - if (ferror(outstr)) - goto data_err; - reply(226, "Transfer complete."); - return; + while ((c = getc(instr)) != EOF) { + byte_count++; + if(c == '\n') + sec_putc('\r', outstr); + sec_putc(c, outstr); + } + sec_fflush(outstr); + transflag = 0; + if (ferror(instr)) + goto file_err; + if (ferror(outstr)) + goto data_err; + reply(226, "Transfer complete."); + return; case TYPE_I: case TYPE_L: -#ifdef HAVE_MMAP +#if defined(HAVE_MMAP) && !defined(NO_MMAP) #ifndef MAP_FAILED #define MAP_FAILED (-1) #endif @@ -1294,13 +1228,13 @@ send_data(FILE *instr, FILE *outstr) int in = fileno(instr); if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)) { chunk = mmap(0, st.st_size, PROT_READ, MAP_SHARED, in, 0); - if(chunk != (void *)MAP_FAILED) { + if((void *)chunk != (void *)MAP_FAILED) { cnt = st.st_size - restart_point; - auth_write(fileno(outstr), + sec_write(fileno(outstr), chunk + restart_point, cnt); munmap(chunk, st.st_size); - auth_write(fileno(outstr), NULL, 0); + sec_fflush(outstr); byte_count = cnt; transflag = 0; } @@ -1321,9 +1255,9 @@ send_data(FILE *instr, FILE *outstr) return; } while ((cnt = read(filefd, buf, bufsize)) > 0 && - auth_write(netfd, buf, cnt) == cnt) + sec_write(netfd, buf, cnt) == cnt) byte_count += cnt; - auth_write(netfd, buf, 0); /* to end an encrypted stream */ + sec_fflush(outstr); /* to end an encrypted stream */ transflag = 0; if (cnt != 0) { if (cnt < 0) @@ -1381,7 +1315,7 @@ receive_data(FILE *instr, FILE *outstr) case TYPE_I: case TYPE_L: - while ((cnt = auth_read(fileno(instr), buf, bufsize)) > 0) { + while ((cnt = sec_read(fileno(instr), buf, bufsize)) > 0) { if (write(fileno(outstr), buf, cnt) != cnt) goto file_err; byte_count += cnt; @@ -1400,7 +1334,7 @@ receive_data(FILE *instr, FILE *outstr) { char *p, *q; int cr_flag = 0; - while ((cnt = auth_read(fileno(instr), + while ((cnt = sec_read(fileno(instr), buf + cr_flag, bufsize - cr_flag)) > 0){ byte_count += cnt; @@ -1409,7 +1343,7 @@ receive_data(FILE *instr, FILE *outstr) for(p = buf, q = buf; p < buf + cnt;) { if(*p == '\n') bare_lfs++; - if(*p == '\r') + if(*p == '\r') { if(p == buf + cnt - 1){ cr_flag = 1; p++; @@ -1419,6 +1353,7 @@ receive_data(FILE *instr, FILE *outstr) p += 2; continue; } + } *q++ = *p++; } fwrite(buf, q - buf, 1, outstr); @@ -1563,21 +1498,21 @@ __attribute__ ((format (printf, 3, 0))) static void int_reply(int n, char *c, const char *fmt, va_list ap) { - char buf[10240]; - char *p; - p=buf; - if(n){ - snprintf(p, sizeof(buf), "%d%s", n, c); - p+=strlen(p); - } - vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap); - p+=strlen(p); - snprintf(p, sizeof(buf) - strlen(p), "\r\n"); - p+=strlen(p); - auth_printf("%s", buf); - fflush(stdout); - if (debug) - syslog(LOG_DEBUG, "<--- %s- ", buf); + char buf[10240]; + char *p; + p=buf; + if(n){ + snprintf(p, sizeof(buf), "%d%s", n, c); + p+=strlen(p); + } + vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap); + p+=strlen(p); + snprintf(p, sizeof(buf) - strlen(p), "\r\n"); + p+=strlen(p); + sec_fprintf(stdout, "%s", buf); + fflush(stdout); + if (debug) + syslog(LOG_DEBUG, "<--- %s- ", buf); } void @@ -1698,7 +1633,7 @@ removedir(char *name) void pwd(void) { - char path[MaxPathLen + 1]; + char path[MaxPathLen]; char *ret; /* SunOS has a broken getcwd that does popen(pwd) (!!!), this @@ -1762,10 +1697,10 @@ dologout(int status) transflag = 0; if (logged_in) { seteuid((uid_t)0); - logwtmp(ttyline, "", ""); - dest_tkt(); - if(k_hasafs()) - k_unlog(); + ftpd_logwtmp(ttyline, "", ""); +#ifdef KRB4 + cond_kdestroy(); +#endif } /* beware of flushing buffers after a SIGPIPE */ #ifdef XXX @@ -1801,7 +1736,7 @@ myoob(int signo) #if 0 cp = tmpline; - if (getline(cp, 7) == NULL) { + if (ftpd_getline(cp, 7) == NULL) { reply(221, "You could at least say goodbye."); dologout(0); } @@ -1982,7 +1917,7 @@ send_file_list(char *whichf) } snprintf(buf, sizeof(buf), "%s%s\n", dirname, type == TYPE_A ? "\r" : ""); - auth_write(fileno(dout), buf, strlen(buf)); + sec_write(fileno(dout), buf, strlen(buf)); byte_count += strlen(dirname) + 1; continue; } else if (!S_ISDIR(st.st_mode)) @@ -2019,7 +1954,7 @@ send_file_list(char *whichf) else snprintf(buf, sizeof(buf), "%s%s\n", nbuf, type == TYPE_A ? "\r" : ""); - auth_write(fileno(dout), buf, strlen(buf)); + sec_write(fileno(dout), buf, strlen(buf)); byte_count += strlen(nbuf) + 1; } } @@ -2034,7 +1969,7 @@ send_file_list(char *whichf) transflag = 0; if (dout != NULL){ - auth_write(fileno(dout), buf, 0); /* XXX flush */ + sec_write(fileno(dout), buf, 0); /* XXX flush */ fclose(dout); } diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h new file mode 100644 index 0000000..4bb3ad3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: ftpd_locl.h,v 1.5.2.1 1999/07/22 03:24:42 assar Exp $ */ + +#ifndef __ftpd_locl_h__ +#define __ftpd_locl_h__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* + * FTP server. + */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 +#include <sys/ioctl.h> +#endif +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif + +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +#include <arpa/ftp.h> +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif + +#include <ctype.h> +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif +#include <errno.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <glob.h> +#include <limits.h> +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif +#include <time.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_GRP_H +#include <grp.h> +#endif +#include <fnmatch.h> + +#ifdef HAVE_BSD_BSD_H +#include <bsd/bsd.h> +#endif + +#include <err.h> + +#include "pathnames.h" +#include "extern.h" +#include "common.h" + +#include "security.h" + +#include "roken.h" + +#ifdef KRB4 +#include <krb.h> +#include <kafs.h> +#endif + +#ifdef OTP +#include <otp.h> +#endif + +#ifdef SOCKS +#include <socks.h> +extern int LIBPREFIX(fclose) (FILE *); +#endif + +int yyparse(); + +#ifndef LOG_FTP +#define LOG_FTP LOG_DAEMON +#endif + +#endif /* __ftpd_locl_h__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c new file mode 100644 index 0000000..8a1a8e3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ftpd_locl.h" +#include <gssapi.h> +#include <krb5.h> + +RCSID("$Id: gss_userok.c,v 1.1 1998/05/12 12:15:22 joda Exp $"); + +/* XXX a bit too much of krb5 dependency here... + What is the correct way to do this? + */ + +extern krb5_context gssapi_krb5_context; + +/* XXX sync with gssapi.c */ +struct gss_data { + gss_ctx_id_t context_hdl; + char *client_name; +}; + +int gss_userok(void*, char*); /* to keep gcc happy */ + +int +gss_userok(void *app_data, char *username) +{ + struct gss_data *data = app_data; + if(gssapi_krb5_context) { + krb5_principal client; + krb5_error_code ret; + ret = krb5_parse_name(gssapi_krb5_context, data->client_name, &client); + if(ret) + return 1; + ret = krb5_kuserok(gssapi_krb5_context, client, username); + krb5_free_principal(gssapi_krb5_context, client); + return !ret; + } + return 1; +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c index 02d23d6..33795b6 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,34 +36,9 @@ * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -RCSID("$Id: kauth.c,v 1.14 1997/05/07 02:21:30 assar Exp $"); - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <time.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#include <roken.h> - -#include <des.h> -#include <krb.h> -#include <kafs.h> +#include "ftpd_locl.h" -#include "extern.h" -#include "krb4.h" -#include "auth.h" -#include "base64.h" +RCSID("$Id: kauth.c,v 1.22 1999/06/29 21:19:33 bg Exp $"); static KTEXT_ST cip; static unsigned int lifetime; @@ -71,9 +46,15 @@ static time_t local_time; static krb_principal pr; +static int do_destroy_tickets = 1; + static int -save_tkt(char *user, char *instance, char *realm, void *arg, - int (*key_proc)(char*, char*, char*, void*, des_cblock*), KTEXT *cipp) +save_tkt(const char *user, + const char *instance, + const char *realm, + const void *arg, + key_proc_t key_proc, + KTEXT *cipp) { local_time = time(0); memmove(&cip, *cipp, sizeof(cip)); @@ -89,11 +70,9 @@ store_ticket(KTEXT cip) unsigned char kvno; KTEXT_ST tkt; int left = cip->length; - + int len; int kerror; - time_t kdc_time; - ptr = (char *) cip->dat; /* extract session key */ @@ -101,29 +80,32 @@ store_ticket(KTEXT cip) ptr += 8; left -= 8; - if (strnlen(ptr, left) == left) + len = strnlen(ptr, left); + if (len == left) return(INTK_BADPW); /* extract server's name */ - strcpy(sp.name, ptr); - ptr += strlen(sp.name) + 1; - left -= strlen(sp.name) + 1; + strcpy_truncate(sp.name, ptr, sizeof(sp.name)); + ptr += len + 1; + left -= len + 1; - if (strnlen(ptr, left) == left) + len = strnlen(ptr, left); + if (len == left) return(INTK_BADPW); - + /* extract server's instance */ - strcpy(sp.instance, ptr); - ptr += strlen(sp.instance) + 1; - left -= strlen(sp.instance) + 1; + strcpy_truncate(sp.instance, ptr, sizeof(sp.instance)); + ptr += len + 1; + left -= len + 1; - if (strnlen(ptr, left) == left) + len = strnlen(ptr, left); + if (len == left) return(INTK_BADPW); - + /* extract server's realm */ - strcpy(sp.realm,ptr); - ptr += strlen(sp.realm) + 1; - left -= strlen(sp.realm) + 1; + strcpy_truncate(sp.realm, ptr, sizeof(sp.realm)); + ptr += len + 1; + left -= len + 1; if(left < 3) return INTK_BADPW; @@ -154,14 +136,18 @@ store_ticket(KTEXT cip) #if 0 /* check KDC time stamp */ - memmove(&kdc_time, ptr, sizeof(kdc_time)); - if (swap_bytes) swap_u_long(kdc_time); + { + time_t kdc_time; - ptr += 4; + memmove(&kdc_time, ptr, sizeof(kdc_time)); + if (swap_bytes) swap_u_long(kdc_time); + + ptr += 4; - if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) { - return(RD_AP_TIME); /* XXX should probably be better + if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) { + return(RD_AP_TIME); /* XXX should probably be better code */ + } } #endif @@ -184,7 +170,8 @@ store_ticket(KTEXT cip) return(kerror); } -void kauth(char *principal, char *ticket) +void +kauth(char *principal, char *ticket) { char *p; int ret; @@ -209,8 +196,10 @@ void kauth(char *principal, char *ticket) memset(&cip, 0, sizeof(cip)); return; } + do_destroy_tickets = 1; + if(k_hasafs()) - k_afsklog(0, 0); + krb_afslog(0, 0); reply(200, "Tickets will be destroyed on exit."); return; } @@ -226,7 +215,10 @@ void kauth(char *principal, char *ticket) reply(500, "Kerberos error: %s.", krb_get_err_text(ret)); return; } - base64_encode(cip.dat, cip.length, &p); + if(base64_encode(cip.dat, cip.length, &p) < 0) { + reply(500, "Out of memory while base64-encoding."); + return; + } reply(300, "P=%s T=%s", krb_unparse_name(&pr), p); free(p); memset(&cip, 0, sizeof(cip)); @@ -245,7 +237,8 @@ short_date(int32_t dp) return (cp); } -void klist(void) +void +klist(void) { int err; @@ -302,6 +295,8 @@ void klist(void) * it was done before tf_init. */ + lreply(200, "Ticket file: %s", tkt_string()); + lreply(200, "Principal: %s", krb_unparse_name(&pr)); while ((err = tf_get_cred(&c)) == KSUCCESS) { if (header) { @@ -309,17 +304,63 @@ void klist(void) " Issued", " Expires", " Principal (kvno)"); header = 0; } - strcpy(buf1, short_date(c.issue_date)); + strcpy_truncate(buf1, short_date(c.issue_date), sizeof(buf1)); c.issue_date = krb_life_to_time(c.issue_date, c.lifetime); if (time(0) < (unsigned long) c.issue_date) - strcpy(buf2, short_date(c.issue_date)); + strcpy_truncate(buf2, short_date(c.issue_date), sizeof(buf2)); else - strcpy(buf2, ">>> Expired <<< "); + strcpy_truncate(buf2, ">>> Expired <<< ", sizeof(buf2)); lreply(200, "%s %s %s (%d)", buf1, buf2, krb_unparse_name_long(c.service, c.instance, c.realm), c.kvno); } if (header && err == EOF) { lreply(200, "No tickets in file."); } - reply(200, ""); + reply(200, " "); +} + +/* + * Only destroy if we created the tickets + */ + +void +cond_kdestroy(void) +{ + if (do_destroy_tickets) + dest_tkt(); + afsunlog(); +} + +void +kdestroy(void) +{ + dest_tkt(); + afsunlog(); + reply(200, "Tickets destroyed"); +} + +void +krbtkfile(const char *tkfile) +{ + do_destroy_tickets = 0; + krb_set_tkt_string(tkfile); + reply(200, "Using ticket file %s", tkfile); +} + +void +afslog(const char *cell) +{ + if(k_hasafs()) { + krb_afslog(cell, 0); + reply(200, "afslog done"); + } else { + reply(200, "no AFS present"); + } +} + +void +afsunlog(void) +{ + if(k_hasafs()) + k_unlog(); } diff --git a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c index 95ab216..d948a5a 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c @@ -38,7 +38,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: logwtmp.c,v 1.10 1997/05/25 15:17:56 assar Exp $"); +RCSID("$Id: logwtmp.c,v 1.13 1999/03/01 09:49:37 joda Exp $"); #endif #include <stdio.h> @@ -74,18 +74,20 @@ RCSID("$Id: logwtmp.c,v 1.10 1997/05/25 15:17:56 assar Exp $"); #endif void -logwtmp(char *line, char *name, char *host) +ftpd_logwtmp(char *line, char *name, char *host) { static int init = 0; - static int fd, fdx; - struct timeval tv; + static int fd; +#ifdef WTMPX_FILE + static int fdx; +#endif struct utmp ut; #ifdef WTMPX_FILE struct utmpx utx; #endif memset(&ut, 0, sizeof(struct utmp)); -#ifdef HAVE_UT_TYPE +#ifdef HAVE_STRUCT_UTMP_UT_TYPE if(name[0]) ut.ut_type = USER_PROCESS; else @@ -93,10 +95,10 @@ logwtmp(char *line, char *name, char *host) #endif strncpy(ut.ut_line, line, sizeof(ut.ut_line)); strncpy(ut.ut_name, name, sizeof(ut.ut_name)); -#ifdef HAVE_UT_PID +#ifdef HAVE_STRUCT_UTMP_UT_PID ut.ut_pid = getpid(); #endif -#ifdef HAVE_UT_HOST +#ifdef HAVE_STRUCT_UTMP_UT_HOST strncpy(ut.ut_host, host, sizeof(ut.ut_host)); #endif ut.ut_time = time(NULL); @@ -105,14 +107,18 @@ logwtmp(char *line, char *name, char *host) strncpy(utx.ut_line, line, sizeof(utx.ut_line)); strncpy(utx.ut_user, name, sizeof(utx.ut_user)); strncpy(utx.ut_host, host, sizeof(utx.ut_host)); -#ifdef HAVE_UT_SYSLEN +#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN utx.ut_syslen = strlen(host) + 1; if (utx.ut_syslen > sizeof(utx.ut_host)) utx.ut_syslen = sizeof(utx.ut_host); #endif - gettimeofday (&tv, 0); - utx.ut_tv.tv_sec = tv.tv_sec; - utx.ut_tv.tv_usec = tv.tv_usec; + { + struct timeval tv; + + gettimeofday (&tv, 0); + utx.ut_tv.tv_sec = tv.tv_sec; + utx.ut_tv.tv_usec = tv.tv_usec; + } if(name[0]) utx.ut_type = USER_PROCESS; diff --git a/crypto/kerberosIV/appl/ftp/ftpd/popen.c b/crypto/kerberosIV/appl/ftp/ftpd/popen.c index 58c4985..4bd5e04 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/popen.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/popen.c @@ -37,7 +37,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: popen.c,v 1.16 1997/06/01 03:14:06 assar Exp $"); +RCSID("$Id: popen.c,v 1.18 1998/06/09 19:24:24 joda Exp $"); #endif #include <sys/types.h> @@ -89,10 +89,10 @@ ftp_rooted(const char *path) if(!home[0]) if((pwd = k_getpwnam("ftp"))) - strcpy(home, pwd->pw_dir); + strcpy_truncate(home, pwd->pw_dir, sizeof(home)); snprintf(newpath, sizeof(newpath), "%s/%s", home, path); if(access(newpath, X_OK)) - strcpy(newpath, path); + strcpy_truncate(newpath, path, sizeof(newpath)); return newpath; } @@ -125,8 +125,8 @@ ftpd_popen(char *program, char *type, int do_stderr, int no_glob) return (NULL); /* break up string into pieces */ + foo = NULL; for (argc = 0, cp = program;; cp = NULL) { - foo = NULL; if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo))) break; } diff --git a/crypto/kerberosIV/appl/kauth/ChangeLog b/crypto/kerberosIV/appl/kauth/ChangeLog new file mode 100644 index 0000000..ad849a2 --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/ChangeLog @@ -0,0 +1,24 @@ +Thu Apr 15 15:05:33 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * kauth.c: add `-v' + +Thu Mar 18 11:17:14 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * Makefile.am: include Makefile.am.common + +Sun Nov 22 10:30:47 1998 Assar Westerlund <assar@sics.se> + + * Makefile.in (WFLAGS): set + +Tue May 26 17:41:47 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * kauth.c: use krb_enable_debug + +Fri May 1 07:15:18 1998 Assar Westerlund <assar@sics.se> + + * rkinit.c: unifdef -DHAVE_H_ERRNO + +Thu Mar 19 16:07:18 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * kauth.c: Check for negative return value from krb_afslog(). + diff --git a/crypto/kerberosIV/appl/kauth/Makefile.am b/crypto/kerberosIV/appl/kauth/Makefile.am new file mode 100644 index 0000000..a5bf0fdaca --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/Makefile.am @@ -0,0 +1,42 @@ +# $Id: Makefile.am,v 1.7 1999/04/09 18:22:45 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += $(INCLUDE_krb4) + +bin_PROGRAMS = kauth +bin_SCRIPTS = ksrvtgt +libexec_PROGRAMS = kauthd + +EXTRA_DIST = zrefresh ksrvtgt.in + +kauth_SOURCES = \ + kauth.c \ + kauth.h \ + rkinit.c \ + marshall.c \ + encdata.c + +kauthd_SOURCES = \ + kauthd.c \ + kauth.h \ + marshall.c \ + encdata.c + +ksrvtgt: ksrvtgt.in + sed -e "s!%bindir%!$(bindir)!" $(srcdir)/ksrvtgt.in > $@ + chmod +x $@ + +install-exec-local: + if test -f $(bindir)/zrefresh -o -r $(bindir)/zrefresh; then \ + true; \ + else \ + $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(bindir)/`echo zrefresh | sed '$(transform)'`; \ + fi + +LDADD = \ + $(LIB_kafs) \ + $(LIB_krb5) \ + $(LIB_krb4) \ + $(top_builddir)/lib/des/libdes.la \ + $(LIB_roken) diff --git a/crypto/kerberosIV/appl/kauth/Makefile.in b/crypto/kerberosIV/appl/kauth/Makefile.in index 97bfdb4..278facc 100644 --- a/crypto/kerberosIV/appl/kauth/Makefile.in +++ b/crypto/kerberosIV/appl/kauth/Makefile.in @@ -1,17 +1,19 @@ -# $Id: Makefile.in,v 1.33 1997/04/05 21:24:35 assar Exp $ +# $Id: Makefile.in,v 1.40 1999/03/10 19:01:11 joda Exp $ SHELL = /bin/sh srcdir = @srcdir@ VPATH = @srcdir@ -topdir = ../.. +top_builddir = ../.. CC = @CC@ +LINK = @LINK@ AR = ar RANLIB = @RANLIB@ DEFS = @DEFS@ -DBINDIR='"$(bindir)"' -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ LD_FLAGS = @LD_FLAGS@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -49,28 +51,28 @@ Wall: make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" .c.o: - $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $< + $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $< install: all - $(MKINSTALLDIRS) $(bindir) $(libexecdir) + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) $(DESTDIR)$(libexecdir) for x in $(PROG_BIN); do \ - $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x| sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \ done - if test -f $(bindir)/zrefresh -o -r $(bindir)/zrefresh; then \ + if test -f $(DESTDIR)$(bindir)/zrefresh -o -r $(DESTDIR)$(bindir)/zrefresh; then \ true; \ else \ - $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(bindir)/`echo zrefresh | sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(DESTDIR)$(bindir)/`echo zrefresh | sed '$(transform)'`; \ fi for x in $(PROG_LIBEXEC); do \ - $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \ done uninstall: for x in $(PROG_BIN); do \ - rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \ + rm -f $(DESTDIR)$(bindir)/`echo $$x| sed '$(transform)'`; \ done for x in $(PROG_LIBEXEC); do \ - rm -f $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + rm -f $(DESTDIR)$(libexecdir)/`echo $$x| sed '$(transform)'`; \ done TAGS: $(SOURCES) @@ -89,20 +91,14 @@ distclean: clean realclean: distclean rm -f TAGS -dist: $(DISTFILES) - for file in $(DISTFILES); do \ - ln $$file ../`cat ../.fname`/lib \ - || cp -p $$file ../`cat ../.fname`/lib; \ - done - KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes LIBROKEN=-L../../lib/roken -lroken kauth$(EXECSUFFIX): $(OBJECTS_KAUTH) $(OBJECTS_COMMON) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTH) $(OBJECTS_COMMON) $(KRB_KAFS_LIB) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTH) $(OBJECTS_COMMON) $(KRB_KAFS_LIB) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) kauthd$(EXECSUFFIX): $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) ksrvtgt: ksrvtgt.in sed -e "s!%bindir%!$(bindir)!" $(srcdir)/ksrvtgt.in > $@ @@ -110,3 +106,5 @@ ksrvtgt: ksrvtgt.in $(OBJECTS): ../../include/config.h + +.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean diff --git a/crypto/kerberosIV/appl/kauth/kauth.c b/crypto/kerberosIV/appl/kauth/kauth.c index 84614b0..ae5454e 100644 --- a/crypto/kerberosIV/appl/kauth/kauth.c +++ b/crypto/kerberosIV/appl/kauth/kauth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -46,12 +46,12 @@ #include "kauth.h" -RCSID("$Id: kauth.c,v 1.75 1997/05/02 15:09:24 assar Exp $"); +RCSID("$Id: kauth.c,v 1.92 1999/06/29 21:19:35 bg Exp $"); krb_principal princ; -static char srvtab[MaxPathLen + 1]; +static char srvtab[MaxPathLen]; static int lifetime = DEFAULT_TKT_LIFE; -static char remote_tktfile[MaxPathLen + 1]; +static char remote_tktfile[MaxPathLen]; static char remoteuser[100]; static char *cell = 0; @@ -59,41 +59,31 @@ static void usage(void) { fprintf(stderr, - "Usage: %s [-n <name>] [-r remoteuser] [-t remote ticketfile]" - "[-l lifetime (in minutes) ] [-h hosts... ]" - "[-f srvtab ] [-c AFS cell name ] [command ... ]\n", + "Usage: %s -n <name> [-r remoteuser] [-t remote ticketfile] " + "[-l lifetime (in minutes) ] [-f srvtab ] " + "[-c AFS cell name ] [-h hosts... [--]] [command ... ]\n", __progname); fprintf(stderr, "\nA fully qualified name can be given user[.instance][@realm]\nRealm is converted to uppercase!\n"); exit(1); } -static void +#define EX_NOEXEC 126 +#define EX_NOTFOUND 127 + +static int doexec(int argc, char **argv) { - int status; - pid_t ret; - - switch (fork()) { - case -1: - err (1, "fork"); - break; - case 0: - /* in child */ - execvp(argv[0], argv); - err (1, "Can't exec program ``%s''", argv[0]); - break; - default: - /* in parent */ - do { - ret = wait(&status); - } while ((ret > 0 && !WIFEXITED(status)) || (ret < 0 && errno == EINTR)); - if (ret < 0) - perror("wait"); - dest_tkt(); - if (k_hasafs()) - k_unlog(); - break; - } + int ret = simple_execvp(argv[0], argv); + if(ret == -2) + warn ("fork"); + if(ret == -3) + warn("waitpid"); + if(ret < 0) + return EX_NOEXEC; + if(ret == EX_NOEXEC || ret == EX_NOTFOUND) + warnx("Can't exec program ``%s''", argv[0]); + + return ret; } static RETSIGTYPE @@ -110,7 +100,7 @@ renew(int sig) warnx ("%s", krb_get_err_text(code)); else if (k_hasafs()) { - if ((code = k_afsklog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) { + if ((code = krb_afslog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) { warnx ("%s", krb_get_err_text(code)); } } @@ -139,7 +129,10 @@ zrefresh(void) } static int -key_to_key(char *user, char *instance, char *realm, void *arg, +key_to_key(const char *user, + char *instance, + const char *realm, + const void *arg, des_cblock *key) { memcpy(key, arg, sizeof(des_cblock)); @@ -154,6 +147,7 @@ main(int argc, char **argv) int c; char *file; int pflag = 0; + int version_flag = 0; char passwd[100]; des_cblock key; char **host; @@ -169,17 +163,31 @@ main(int argc, char **argv) memset(srvtab, 0, sizeof(srvtab)); *remoteuser = '\0'; nhost = 0; + host = NULL; - while ((c = getopt(argc, argv, "r:t:f:hl:n:c:")) != EOF) + /* Look for kerberos name */ + if (argc > 1 && + argv[1][0] != '-' && + krb_parse_name(argv[1], &princ) == 0) + { + argc--; argv++; + strupr(princ.realm); + } + + while ((c = getopt(argc, argv, "r:t:f:hdl:n:c:v")) != EOF) switch (c) { + case 'd': + krb_enable_debug(); + _kafs_debug = 1; + break; case 'f': - strncpy(srvtab, optarg, sizeof(srvtab)); + strcpy_truncate(srvtab, optarg, sizeof(srvtab)); break; case 't': - strncpy(remote_tktfile, optarg, sizeof(remote_tktfile)); + strcpy_truncate(remote_tktfile, optarg, sizeof(remote_tktfile)); break; case 'r': - strncpy(remoteuser, optarg, sizeof(remoteuser)); + strcpy_truncate(remoteuser, optarg, sizeof(remoteuser)); break; case 'l': lifetime = atoi(optarg); @@ -208,31 +216,38 @@ main(int argc, char **argv) for(nhost = 0; optind < argc && *argv[optind] != '-'; ++optind) ++nhost; break; + case 'v': + version_flag++; + print_version(NULL); + break; case '?': default: usage(); break; } - /* Look for kerberos name */ - if (!pflag && optind < argc && krb_parse_name(argv[optind], &princ) == 0) { - ++optind; - strupr(princ.realm); + if(version_flag) { + print_version(NULL); + exit(0); } - if (princ.name[0] == '\0' && krb_get_default_principal (princ.name, princ.instance, princ.realm) < 0) errx (1, "Could not get default principal"); - if (*remoteuser == '\0') - strcpy (remoteuser, princ.name); + /* With root tickets assume remote user is root */ + if (*remoteuser == '\0') { + if (strcmp(princ.instance, "root") == 0) + strcpy_truncate(remoteuser, princ.instance, sizeof(remoteuser)); + else + strcpy_truncate(remoteuser, princ.name, sizeof(remoteuser)); + } more_args = argc - optind; if (princ.realm[0] == '\0') if (krb_get_lrealm(princ.realm, 1) != KSUCCESS) - strcpy(princ.realm, KRB_REALM); + strcpy_truncate(princ.realm, KRB_REALM, REALM_SZ); if (more_args) { int f; @@ -271,18 +286,10 @@ main(int argc, char **argv) memset(passwd, 0, sizeof(passwd)); exit(1); } - des_string_to_key (passwd, &key); - code = krb_get_in_tkt (princ.name, princ.instance, princ.realm, - KRB_TICKET_GRANTING_TICKET, - princ.realm, lifetime, - key_to_key, NULL, key); - if(code == INTK_BADPW) { - afs_string_to_key (passwd, princ.realm, &key); - code = krb_get_in_tkt (princ.name, princ.instance, princ.realm, - KRB_TICKET_GRANTING_TICKET, - princ.realm, lifetime, - key_to_key, NULL, key); - } + code = krb_get_pw_in_tkt2(princ.name, princ.instance, princ.realm, + KRB_TICKET_GRANTING_TICKET, princ.realm, + lifetime, passwd, &key); + memset(passwd, 0, sizeof(passwd)); } if (code) { @@ -293,8 +300,12 @@ main(int argc, char **argv) if (k_hasafs()) { if (more_args) k_setpag(); - if ((code = k_afsklog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) - warnx ("%s", krb_get_err_text(code)); + if ((code = krb_afslog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) { + if(code > 0) + warnx ("%s", krb_get_err_text(code)); + else + warnx ("failed to store AFS token"); + } } for(ret = 0; nhost-- > 0; host++) @@ -303,10 +314,14 @@ main(int argc, char **argv) if (ret) return ret; - if (more_args) - doexec(more_args, &argv[optind]); + if (more_args) { + ret = doexec(more_args, &argv[optind]); + dest_tkt(); + if (k_hasafs()) + k_unlog(); + } else zrefresh(); - return 0; + return ret; } diff --git a/crypto/kerberosIV/appl/kauth/kauth.h b/crypto/kerberosIV/appl/kauth/kauth.h index 2c48fcc..c5a4517 100644 --- a/crypto/kerberosIV/appl/kauth/kauth.h +++ b/crypto/kerberosIV/appl/kauth/kauth.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. */ -/* $Id: kauth.h,v 1.18 1997/05/20 18:40:31 bg Exp $ */ +/* $Id: kauth.h,v 1.20 1998/06/13 00:06:45 assar Exp $ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -92,6 +92,9 @@ #endif #ifdef SOCKS #include <socks.h> +/* This doesn't belong here. */ +struct tm *localtime(const time_t *); +struct hostent *gethostbyname(const char *); #endif #include <err.h> @@ -113,6 +116,6 @@ int write_encrypted (int, void*, size_t, des_key_schedule, int read_encrypted (int, void*, size_t, void **, des_key_schedule, des_cblock*, struct sockaddr_in*, struct sockaddr_in*); -unsigned pack_args (char *, krb_principal*, int, char*, char*); +int pack_args (char *, size_t, krb_principal*, int, const char*, const char*); -int unpack_args (char*, krb_principal*, int*, char*, char*); +int unpack_args (const char*, krb_principal*, int*, char*, char*); diff --git a/crypto/kerberosIV/appl/kauth/kauthd.c b/crypto/kerberosIV/appl/kauth/kauthd.c index b6a40cf..0018a13 100644 --- a/crypto/kerberosIV/appl/kauth/kauthd.c +++ b/crypto/kerberosIV/appl/kauth/kauthd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -38,12 +38,12 @@ #include "kauth.h" -RCSID("$Id: kauthd.c,v 1.22 1997/05/18 20:37:55 assar Exp $"); +RCSID("$Id: kauthd.c,v 1.24 1999/06/29 21:19:35 bg Exp $"); krb_principal princ; -static char locuser[SNAME_SZ + 1]; +static char locuser[SNAME_SZ]; static int lifetime; -static char tktfile[MaxPathLen + 1]; +static char tktfile[MaxPathLen]; struct remote_args { int sock; @@ -53,8 +53,12 @@ struct remote_args { }; static int -decrypt_remote_tkt (char *user, char *inst, char *realm, void *varg, - key_proc_t key_proc, KTEXT *cipp) +decrypt_remote_tkt (const char *user, + const char *inst, + const char *realm, + const void *varg, + key_proc_t key_proc, + KTEXT *cipp) { char buf[BUFSIZ]; void *ptr; @@ -78,7 +82,7 @@ doit(int sock) int status; KTEXT_ST ticket; AUTH_DAT auth; - char instance[INST_SZ + 1]; + char instance[INST_SZ]; des_key_schedule schedule; struct sockaddr_in thisaddr, thataddr; int addrlen; diff --git a/crypto/kerberosIV/appl/kauth/ksrvtgt.in b/crypto/kerberosIV/appl/kauth/ksrvtgt.in index 30d9e15..c2f33bb 100644 --- a/crypto/kerberosIV/appl/kauth/ksrvtgt.in +++ b/crypto/kerberosIV/appl/kauth/ksrvtgt.in @@ -1,5 +1,5 @@ #! /bin/sh -# $Id: ksrvtgt.in,v 1.2 1997/04/05 21:29:17 assar Exp $ +# $Id: ksrvtgt.in,v 1.3 1997/09/13 03:39:03 joda Exp $ usage="Usage: `basename $0` name instance [[realm] srvtab]" @@ -11,4 +11,4 @@ fi srvtab="${4-${3-/etc/srvtab}}" realm="${4+@$3}" -%bindir%/kauth -n "$1.$2$realm" -l 5 -f "$srvtab " +%bindir%/kauth -n "$1.$2$realm" -l 5 -f "$srvtab" diff --git a/crypto/kerberosIV/appl/kauth/marshall.c b/crypto/kerberosIV/appl/kauth/marshall.c index 4f1bfeb..dc28ae5 100644 --- a/crypto/kerberosIV/appl/kauth/marshall.c +++ b/crypto/kerberosIV/appl/kauth/marshall.c @@ -38,60 +38,94 @@ #include "kauth.h" -RCSID("$Id: marshall.c,v 1.7 1997/04/01 08:17:32 joda Exp $"); +RCSID("$Id: marshall.c,v 1.8 1998/06/09 19:24:26 joda Exp $"); -unsigned -pack_args (char *buf, krb_principal *pr, int lifetime, - char *locuser, char *tktfile) +int +pack_args (char *buf, + size_t sz, + krb_principal *pr, + int lifetime, + const char *locuser, + const char *tktfile) { - char *p; + char *p = buf; + int len; p = buf; - strcpy (p, pr->name); - p += strlen (pr->name) + 1; - strcpy (p, pr->instance); - p += strlen (pr->instance) + 1; - strcpy (p, pr->realm); - p += strlen (pr->realm) + 1; + + len = strlen(pr->name); + if (len >= sz) + return -1; + memcpy (p, pr->name, len + 1); + p += len + 1; + sz -= len + 1; + + len = strlen(pr->instance); + if (len >= sz) + return -1; + memcpy (p, pr->instance, len + 1); + p += len + 1; + sz -= len + 1; + + len = strlen(pr->realm); + if (len >= sz) + return -1; + memcpy(p, pr->realm, len + 1); + p += len + 1; + sz -= len + 1; + + if (sz < 1) + return -1; *p++ = (unsigned char)lifetime; - strcpy(p, locuser); - p += strlen (locuser) + 1; - strcpy(p, tktfile); - p += strlen(tktfile) + 1; + + len = strlen(locuser); + if (len >= sz) + return -1; + memcpy (p, locuser, len + 1); + p += len + 1; + sz -= len + 1; + + len = strlen(tktfile); + if (len >= sz) + return -1; + memcpy (p, tktfile, len + 1); + p += len + 1; + sz -= len + 1; + return p - buf; } int -unpack_args (char *buf, krb_principal *pr, int *lifetime, +unpack_args (const char *buf, krb_principal *pr, int *lifetime, char *locuser, char *tktfile) { int len; len = strlen(buf); - if (len > SNAME_SZ) + if (len >= SNAME_SZ) return -1; - strncpy(pr->name, buf, len + 1); + strcpy_truncate (pr->name, buf, ANAME_SZ); buf += len + 1; len = strlen (buf); - if (len > INST_SZ) + if (len >= INST_SZ) return -1; - strncpy (pr->instance, buf, len + 1); + strcpy_truncate (pr->instance, buf, INST_SZ); buf += len + 1; len = strlen (buf); - if (len > REALM_SZ) + if (len >= REALM_SZ) return -1; - strncpy (pr->realm, buf, len + 1); + strcpy_truncate (pr->realm, buf, REALM_SZ); buf += len + 1; *lifetime = (unsigned char)*buf++; len = strlen(buf); - if (len > SNAME_SZ) + if (len >= SNAME_SZ) return -1; - strncpy (locuser, buf, len + 1); + strcpy_truncate (locuser, buf, SNAME_SZ); buf += len + 1; len = strlen(buf); - if (len > MaxPathLen) + if (len >= MaxPathLen) return -1; - strncpy (tktfile, buf, len + 1); + strcpy_truncate (tktfile, buf, MaxPathLen); buf += len + 1; return 0; } diff --git a/crypto/kerberosIV/appl/kauth/rkinit.c b/crypto/kerberosIV/appl/kauth/rkinit.c index ec75d46..d736ddc 100644 --- a/crypto/kerberosIV/appl/kauth/rkinit.c +++ b/crypto/kerberosIV/appl/kauth/rkinit.c @@ -38,7 +38,7 @@ #include "kauth.h" -RCSID("$Id: rkinit.c,v 1.19 1997/04/01 08:17:33 joda Exp $"); +RCSID("$Id: rkinit.c,v 1.21 1998/06/09 19:24:26 joda Exp $"); static struct in_addr * getalladdrs (char *hostname, unsigned *count) @@ -53,12 +53,7 @@ getalladdrs (char *hostname, unsigned *count) if (hostent == NULL) { warnx ("gethostbyname '%s' failed: %s\n", hostname, -#ifdef HAVE_H_ERRNO - hstrerror(h_errno) -#else - "unknown error" -#endif - ); + hstrerror(h_errno)); return NULL; } maxaddr = 1; @@ -126,7 +121,12 @@ doit_host (krb_principal *princ, int lifetime, char *locuser, warnx ("%s: %s\n", hostname, krb_get_err_text(status)); return 1; } - inlen = pack_args (buf, princ, lifetime, locuser, tktfile); + inlen = pack_args (buf, sizeof(buf), + princ, lifetime, locuser, tktfile); + if (inlen < 0) { + warn ("cannot marshall arguments to %s", hostname); + return 1; + } if (write_encrypted(s, buf, inlen, schedule, &cred.session, &thisaddr, &thataddr) < 0) { diff --git a/crypto/kerberosIV/appl/kip/Makefile.in b/crypto/kerberosIV/appl/kip/Makefile.in index 690a661..801c3f9 100644 --- a/crypto/kerberosIV/appl/kip/Makefile.in +++ b/crypto/kerberosIV/appl/kip/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.12 1997/03/23 13:04:03 assar Exp $ +# $Id: Makefile.in,v 1.18 1999/03/10 19:01:11 joda Exp $ SHELL = /bin/sh @@ -6,9 +6,11 @@ srcdir = @srcdir@ VPATH = @srcdir@ CC = @CC@ +LINK = @LINK@ AR = ar DEFS = @DEFS@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ LD_FLAGS = @LD_FLAGS@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -43,23 +45,23 @@ Wall: make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" .c.o: - $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $< + $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $< install: all - $(MKINSTALLDIRS) $(bindir) $(libexecdir) + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) $(DESTDIR)$(libexecdir) for x in $(PROG_BIN); do \ - $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done for x in $(PROG_LIBEXEC); do \ - $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ done uninstall: for x in $(PROG_BIN); do \ - rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \ + rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done for x in $(PROG_LIBEXEC); do \ - rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ done TAGS: $(SOURCES) @@ -78,19 +80,15 @@ distclean: clean realclean: distclean rm -f TAGS -dist: $(DISTFILES) - for file in $(DISTFILES); do \ - ln $$file ../`cat ../.fname`/lib \ - || cp -p $$file ../`cat ../.fname`/lib; \ - done - KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes LIBROKEN=-L../../lib/roken -lroken kip$(EXECSUFFIX): $(OBJECTS_KIP) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIP) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIP) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) kipd$(EXECSUFFIX): $(OBJECTS_KIPD) - $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIPD) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIPD) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) $(OBJECTS): ../../include/config.h + +.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean diff --git a/crypto/kerberosIV/appl/kip/kip.c b/crypto/kerberosIV/appl/kip/kip.c index e324a28..990583b 100644 --- a/crypto/kerberosIV/appl/kip/kip.c +++ b/crypto/kerberosIV/appl/kip/kip.c @@ -38,10 +38,10 @@ #include "kip.h" -RCSID("$Id: kip.c,v 1.15 1997/05/11 10:54:51 assar Exp $"); +RCSID("$Id: kip.c,v 1.17 1998/05/01 05:20:11 assar Exp $"); static void -usage() +usage(void) { fprintf (stderr, "Usage: %s host\n", __progname); @@ -69,12 +69,7 @@ connect_host (char *host, des_cblock *key, des_key_schedule schedule) hostent = gethostbyname (host); if (hostent == NULL) { warnx ("gethostbyname '%s': %s", host, -#ifdef HAVE_H_ERRNO - hstrerror(h_errno) -#else - "unknown error" -#endif - ); + hstrerror(h_errno)); return -1; } @@ -83,8 +78,6 @@ connect_host (char *host, des_cblock *key, des_key_schedule schedule) thataddr.sin_port = k_getportbyname ("kip", "tcp", htons(KIPPORT)); for(p = hostent->h_addr_list; *p; ++p) { - int one = 1; - memcpy (&thataddr.sin_addr, *p, sizeof(thataddr.sin_addr)); s = socket (AF_INET, SOCK_STREAM, 0); @@ -94,7 +87,12 @@ connect_host (char *host, des_cblock *key, des_key_schedule schedule) } #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) - setsockopt (s, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one)); + { + int one = 1; + + setsockopt (s, IPPROTO_TCP, TCP_NODELAY, + (void *)&one, sizeof(one)); + } #endif if (connect (s, (struct sockaddr *)&thataddr, sizeof(thataddr)) < 0) { @@ -151,8 +149,6 @@ doit (char *host) des_key_schedule schedule; des_cblock iv; int other, this; - struct ifreq ifreq; - int sock; other = connect_host (host, &iv, schedule); if (other < 0) diff --git a/crypto/kerberosIV/appl/kip/kip.h b/crypto/kerberosIV/appl/kip/kip.h index 94e30a5..ed9874a 100644 --- a/crypto/kerberosIV/appl/kip/kip.h +++ b/crypto/kerberosIV/appl/kip/kip.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. */ -/* $Id: kip.h,v 1.16 1997/05/20 18:40:31 bg Exp $ */ +/* $Id: kip.h,v 1.17 1997/12/14 23:57:21 assar Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -73,6 +73,9 @@ #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif #include <netdb.h> #include <sys/sockio.h> #include <net/if.h> diff --git a/crypto/kerberosIV/appl/kip/kipd.c b/crypto/kerberosIV/appl/kip/kipd.c index 6d9d334..6990d05 100644 --- a/crypto/kerberosIV/appl/kip/kipd.c +++ b/crypto/kerberosIV/appl/kip/kipd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -38,7 +38,7 @@ #include "kip.h" -RCSID("$Id: kipd.c,v 1.13 1997/05/18 20:38:01 assar Exp $"); +RCSID("$Id: kipd.c,v 1.15 1999/03/10 18:33:24 joda Exp $"); static int fatal (int fd, char *s) @@ -58,7 +58,7 @@ recv_conn (int sock, des_cblock *key, des_key_schedule schedule, int status; KTEXT_ST ticket; AUTH_DAT auth; - char instance[INST_SZ + 1]; + char instance[INST_SZ]; struct sockaddr_in thisaddr, thataddr; int addrlen; char version[KRB_SENDAUTH_VLEN + 1]; @@ -122,7 +122,7 @@ main (int argc, char **argv) { set_progname (argv[0]); - openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON); + roken_openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON); signal (SIGCHLD, childhandler); return doit(0); } diff --git a/crypto/kerberosIV/appl/sample/Makefile.in b/crypto/kerberosIV/appl/sample/Makefile.in new file mode 100644 index 0000000..d88023a --- /dev/null +++ b/crypto/kerberosIV/appl/sample/Makefile.in @@ -0,0 +1,83 @@ +# $Id: Makefile.in,v 1.18 1999/03/10 19:01:13 joda Exp $ + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +top_builddir = ../.. + +CC = @CC@ +LINK = @LINK@ +AR = ar +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ +LD_FLAGS = @LD_FLAGS@ +INSTALL = @INSTALL@ +LIBS = @LIBS@ +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +bindir = @bindir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +PROG_BIN = sample_client$(EXECSUFFIX) \ + simple_client$(EXECSUFFIX) +PROG_LIBEXEC = sample_server$(EXECSUFFIX) \ + simple_server$(EXECSUFFIX) +PROGS = $(PROG_BIN) $(PROG_LIBEXEC) + +OBJECTS = sample_client.o sample_server.o simple_client.o simple_server.o +SOURCES = sample_client.c sample_server.c simple_client.c simple_server.c + +all: $(PROGS) + +Wall: + make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +.c.o: + $(CC) -c $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $< + +install: all + +uninstall: + +TAGS: $(SOURCES) + etags $(SOURCES) + +check: + +clean: + rm -f *.a *.o $(PROGS) + +mostlyclean: clean + +distclean: clean + rm -f Makefile *.tab.c *~ + +realclean: distclean + rm -f TAGS + +KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes +LIBROKEN=-L../../lib/roken -lroken + +sample_client$(EXECSUFFIX): sample_client.o + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ sample_client.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +simple_client$(EXECSUFFIX): simple_client.o + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ simple_client.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +sample_server$(EXECSUFFIX): sample_server.o + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ sample_server.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +simple_server$(EXECSUFFIX): simple_server.o + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ simple_server.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +$(OBJECTS): ../../include/config.h + +.PHONY: all Wall install uninstall check clean mostlyclean distclean realclean diff --git a/crypto/kerberosIV/appl/sample/sample.h b/crypto/kerberosIV/appl/sample/sample.h new file mode 100644 index 0000000..a5880ab --- /dev/null +++ b/crypto/kerberosIV/appl/sample/sample.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: sample.h,v 1.10 1998/06/13 00:06:49 assar Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#include <errno.h> +#ifdef SOCKS +#include <socks.h> +/* This doesn't belong here. */ +struct tm *localtime(const time_t *); +struct hostent *gethostbyname(const char *); +#endif + +#include <err.h> +#include <krb.h> + +#include <roken.h> + +#define SAMPLE_PORT 6354 + +#define SAMPLE_SERVICE "sample" +#define SAMPLE_VERSION "VERSION9" diff --git a/crypto/kerberosIV/appl/sample/sample_client.c b/crypto/kerberosIV/appl/sample/sample_client.c new file mode 100644 index 0000000..8c45ae5 --- /dev/null +++ b/crypto/kerberosIV/appl/sample/sample_client.c @@ -0,0 +1,168 @@ +/* + * + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, + * please see the file <mit-copyright.h>. + * + * sample_client: + * A sample Kerberos client, which connects to a server on a remote host, + * at port "sample" (be sure to define it in /etc/services) + * and authenticates itself to the server. The server then writes back + * (in ASCII) the authenticated name. + * + * Usage: + * sample_client <hostname> <checksum> + * + * <hostname> is the name of the foreign host to contact. + * + * <checksum> is an integer checksum to be used for the call to krb_mk_req() + * and mutual authentication + * + */ + +#include "sample.h" + +RCSID("$Id: sample_client.c,v 1.19 1999/05/08 02:23:43 assar Exp $"); + +static void +usage (void) +{ + fprintf (stderr, "Usage: %s [-s service] [-p port] hostname checksum\n", + __progname); + exit (1); +} + +int +main(int argc, char **argv) +{ + struct hostent *hp; + struct sockaddr_in sin, lsin; + char *remote_host; + int status; + int namelen; + int sock = -1; + KTEXT_ST ticket; + char buf[512]; + long authopts; + MSG_DAT msg_data; + CREDENTIALS cred; + des_key_schedule sched; + u_int32_t cksum; + int c; + char service[SNAME_SZ]; + u_int16_t port; + struct servent *serv; + char **h_addr_list; + + set_progname (argv[0]); + strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service)); + port = 0; + + while ((c = getopt(argc, argv, "s:p:")) != EOF) + switch(c) { + case 's' : + strcpy_truncate (service, optarg, sizeof(service)); + break; + case 'p' : + serv = getservbyname (optarg, "tcp"); + if (serv) + port = serv->s_port; + else + port = htons(atoi(optarg)); + break; + case '?' : + default : + usage(); + } + + argc -= optind; + argv += optind; + + if (argc != 2) + usage (); + + /* convert cksum to internal rep */ + cksum = atoi(argv[1]); + + printf("Setting checksum to %ld\n", (long)cksum); + + /* clear out the structure first */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + if (port) + sin.sin_port = port; + else + sin.sin_port = k_getportbyname (service, "tcp", htons(SAMPLE_PORT)); + + /* look up the server host */ + hp = gethostbyname(argv[0]); + if (hp == NULL) + errx (1, "gethostbyname(%s): %s", argv[0], + hstrerror(h_errno)); + + /* copy the hostname into non-volatile storage */ + remote_host = strdup(hp->h_name); + if (remote_host == NULL) + errx (1, "strdup: out of memory"); + + /* set up the address of the foreign socket for connect() */ + sin.sin_family = hp->h_addrtype; + + for (h_addr_list = hp->h_addr_list; + *h_addr_list; + ++h_addr_list) { + memcpy(&sin.sin_addr, *h_addr_list, sizeof(sin.sin_addr)); + fprintf (stderr, "Trying %s...\n", inet_ntoa(sin.sin_addr)); + + /* open a TCP socket */ + sock = socket(PF_INET, SOCK_STREAM, 0); + if (sock < 0) + err (1, "socket"); + + /* connect to the server */ + if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + break; + close (sock); + } + + if (*h_addr_list == NULL) + err (1, "connect"); + + /* find out who I am, now that we are connected and therefore bound */ + namelen = sizeof(lsin); + if (getsockname(sock, (struct sockaddr *) &lsin, &namelen) < 0) { + close (sock); + err (1, "getsockname"); + } + + /* call Kerberos library routine to obtain an authenticator, + pass it over the socket to the server, and obtain mutual + authentication. */ + + authopts = KOPT_DO_MUTUAL; + status = krb_sendauth(authopts, sock, &ticket, + service, remote_host, + NULL, cksum, &msg_data, &cred, + sched, &lsin, &sin, SAMPLE_VERSION); + if (status != KSUCCESS) + errx (1, "cannot authenticate to server: %s", + krb_get_err_text(status)); + + /* After we send the authenticator to the server, it will write + back the name we authenticated to. Read what it has to say. */ + status = read(sock, buf, sizeof(buf)); + if (status < 0) + errx(1, "read"); + + /* make sure it's null terminated before printing */ + if (status < sizeof(buf)) + buf[status] = '\0'; + else + buf[sizeof(buf) - 1] = '\0'; + + printf("The server says:\n%s\n", buf); + + close(sock); + return 0; +} diff --git a/crypto/kerberosIV/appl/sample/sample_server.c b/crypto/kerberosIV/appl/sample/sample_server.c new file mode 100644 index 0000000..a1a92d1 --- /dev/null +++ b/crypto/kerberosIV/appl/sample/sample_server.c @@ -0,0 +1,153 @@ +/* + * + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, + * please see the file <mit-copyright.h>. + * + * sample_server: + * A sample Kerberos server, which reads a ticket from a TCP socket, + * decodes it, and writes back the results (in ASCII) to the client. + * + * Usage: + * sample_server + * + * file descriptor 0 (zero) should be a socket connected to the requesting + * client (this will be correct if this server is started by inetd). + */ + +#include "sample.h" + +RCSID("$Id: sample_server.c,v 1.12 1999/03/10 18:33:53 joda Exp $"); + +static void +usage (void) +{ + fprintf (stderr, "Usage: %s [-i] [-s service] [-t srvtab]\n", + __progname); + exit (1); +} + +int +main(int argc, char **argv) +{ + struct sockaddr_in peername, myname; + int namelen = sizeof(peername); + int status, count, len; + long authopts; + AUTH_DAT auth_data; + KTEXT_ST clt_ticket; + des_key_schedule sched; + char instance[INST_SZ]; + char service[ANAME_SZ]; + char version[KRB_SENDAUTH_VLEN+1]; + char retbuf[512]; + char lname[ANAME_SZ]; + char srvtab[MaxPathLen]; + int c; + int no_inetd = 0; + + /* open a log connection */ + + set_progname (argv[0]); + + roken_openlog(__progname, LOG_ODELAY, LOG_DAEMON); + + strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service)); + *srvtab = '\0'; + + while ((c = getopt (argc, argv, "s:t:i")) != EOF) + switch (c) { + case 's' : + strcpy_truncate (service, optarg, sizeof(service)); + break; + case 't' : + strcpy_truncate (srvtab, optarg, sizeof(srvtab)); + break; + case 'i': + no_inetd = 1; + break; + case '?' : + default : + usage (); + } + + if (no_inetd) + mini_inetd (htons(SAMPLE_PORT)); + + /* + * To verify authenticity, we need to know the address of the + * client. + */ + if (getpeername(STDIN_FILENO, + (struct sockaddr *)&peername, + &namelen) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + return 1; + } + + /* for mutual authentication, we need to know our address */ + namelen = sizeof(myname); + if (getsockname(STDIN_FILENO, (struct sockaddr *)&myname, &namelen) < 0) { + syslog(LOG_ERR, "getsocknamename: %m"); + return 1; + } + + /* read the authenticator and decode it. Using `k_getsockinst' we + * always get the right instance on a multi-homed host. + */ + k_getsockinst (STDIN_FILENO, instance, sizeof(instance)); + + /* we want mutual authentication */ + authopts = KOPT_DO_MUTUAL; + status = krb_recvauth(authopts, STDIN_FILENO, &clt_ticket, + service, instance, &peername, &myname, + &auth_data, srvtab, + sched, version); + if (status != KSUCCESS) { + snprintf(retbuf, sizeof(retbuf), + "Kerberos error: %s\n", + krb_get_err_text(status)); + syslog(LOG_ERR, retbuf); + } else { + /* Check the version string (KRB_SENDAUTH_VLEN chars) */ + if (strncmp(version, SAMPLE_VERSION, KRB_SENDAUTH_VLEN)) { + /* didn't match the expected version */ + /* could do something different, but we just log an error + and continue */ + version[8] = '\0'; /* make sure null term */ + syslog(LOG_ERR, "Version mismatch: '%s' isn't '%s'", + version, SAMPLE_VERSION); + } + /* now that we have decoded the authenticator, translate + the kerberos principal.instance@realm into a local name */ + if (krb_kntoln(&auth_data, lname) != KSUCCESS) + strcpy_truncate(lname, + "*No local name returned by krb_kntoln*", + sizeof(lname)); + /* compose the reply */ + snprintf(retbuf, sizeof(retbuf), + "You are %s.%s@%s (local name %s),\n at address %s, version %s, cksum %ld\n", + auth_data.pname, + auth_data.pinst, + auth_data.prealm, + lname, + inet_ntoa(peername.sin_addr), + version, + (long)auth_data.checksum); + } + + /* write back the response */ + if ((count = write(0, retbuf, (len = strlen(retbuf) + 1))) < 0) { + syslog(LOG_ERR,"write: %m"); + return 1; + } else if (count != len) { + syslog(LOG_ERR, "write count incorrect: %d != %d\n", + count, len); + return 1; + } + + /* close up and exit */ + close(0); + return 0; +} diff --git a/crypto/kerberosIV/appl/sample/simple.h b/crypto/kerberosIV/appl/sample/simple.h new file mode 100644 index 0000000..17315b3 --- /dev/null +++ b/crypto/kerberosIV/appl/sample/simple.h @@ -0,0 +1,14 @@ +/* + * $Id: simple.h,v 1.3 1996/09/27 15:54:23 assar Exp $ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * Common definitions for the simple UDP-based Kerberos-mediated + * server & client applications. + */ + +#define SERVICE "sample" +#define HOST "bach" diff --git a/crypto/kerberosIV/appl/sample/simple_client.c b/crypto/kerberosIV/appl/sample/simple_client.c new file mode 100644 index 0000000..8769725 --- /dev/null +++ b/crypto/kerberosIV/appl/sample/simple_client.c @@ -0,0 +1,202 @@ +/* + * + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * Simple UDP-based sample client program. For demonstration. + * This program performs no useful function. + */ + +#include "sample.h" +RCSID("$Id: simple_client.c,v 1.13 1998/06/09 19:24:39 joda Exp $"); + +#define MSG "hi, Jennifer!" /* message text */ + +static int +talkto(char *hostname, char *service, int port) +{ + int flags = 0; /* flags for sendto() */ + long len; + u_long cksum = 0L; /* cksum not used */ + char c_realm[REALM_SZ]; /* local Kerberos realm */ + char *s_realm; /* server's Kerberos realm */ + + KTEXT_ST k; /* Kerberos data */ + KTEXT ktxt = &k; + + int sock, i; + struct hostent *host; + struct sockaddr_in s_sock; /* server address */ + char myhostname[MaxHostNameLen]; /* local hostname */ + + /* for krb_mk_safe/priv */ + struct sockaddr_in c_sock; /* client address */ + CREDENTIALS c; /* ticket & session key */ + CREDENTIALS *cred = &c; + + /* for krb_mk_priv */ + des_key_schedule sched; /* session key schedule */ + + /* Look up server host */ + if ((host = gethostbyname(hostname)) == NULL) { + fprintf(stderr, "%s: unknown host \n", hostname); + return 1; + } + + /* Set server's address */ + memset(&s_sock, 0, sizeof(s_sock)); + memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr)); + s_sock.sin_family = AF_INET; + if (port) + s_sock.sin_port = port; + else + s_sock.sin_port = k_getportbyname (service, "tcp", htons(SAMPLE_PORT)); + + if (gethostname(myhostname, sizeof(myhostname)) < 0) { + warn("gethostname"); + return 1; + } + + if ((host = gethostbyname(myhostname)) == NULL) { + fprintf(stderr, "%s: unknown host\n", myhostname); + return 1; + } + + /* Open a socket */ + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + warn("socket SOCK_DGRAM"); + return 1; + } + + memset(&c_sock, 0, sizeof(c_sock)); + memcpy(&c_sock.sin_addr, host->h_addr, sizeof(c_sock.sin_addr)); + c_sock.sin_family = AF_INET; + + /* Bind it to set the address; kernel will fill in port # */ + if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) { + warn("bind"); + return 1; + } + + /* Get local realm, not needed, just an example */ + if ((i = krb_get_lrealm(c_realm, 1)) != KSUCCESS) { + fprintf(stderr, "can't find local Kerberos realm\n"); + return 1; + } + printf("Local Kerberos realm is %s\n", c_realm); + + /* Get Kerberos realm of host */ + s_realm = krb_realmofhost(hostname); + + /* PREPARE KRB_MK_REQ MESSAGE */ + + /* Get credentials for server, create krb_mk_req message */ + if ((i = krb_mk_req(ktxt, service, hostname, s_realm, cksum)) + != KSUCCESS) { + fprintf(stderr, "%s\n", krb_get_err_text(i)); + return 1; + } + printf("Got credentials for %s.\n", service); + + /* Send authentication info to server */ + i = sendto(sock, (char *)ktxt->dat, ktxt->length, flags, + (struct sockaddr *)&s_sock, sizeof(s_sock)); + if (i < 0) + warn("sending datagram message"); + printf("Sent authentication data: %d bytes\n", i); + + /* PREPARE KRB_MK_SAFE MESSAGE */ + + /* Get my address */ + memset(&c_sock, 0, sizeof(c_sock)); + i = sizeof(c_sock); + if (getsockname(sock, (struct sockaddr *)&c_sock, &i) < 0) { + warn("getsockname"); + return 1; + } + + /* Get session key */ + i = krb_get_cred(service, hostname, s_realm, cred); + if (i != KSUCCESS) + return 1; + + /* Make the safe message */ + len = krb_mk_safe(MSG, ktxt->dat, strlen(MSG)+1, + &cred->session, &c_sock, &s_sock); + + /* Send it */ + i = sendto(sock, (char *)ktxt->dat, (int) len, flags, + (struct sockaddr *)&s_sock, sizeof(s_sock)); + if (i < 0) + warn("sending safe message"); + printf("Sent checksummed message: %d bytes\n", i); + + /* PREPARE KRB_MK_PRIV MESSAGE */ + +#ifdef NOENCRYPTION + memset(sched, 0, sizeof(sched)); +#else + /* Get key schedule for session key */ + des_key_sched(&cred->session, sched); +#endif + + /* Make the encrypted message */ + len = krb_mk_priv(MSG, ktxt->dat, strlen(MSG)+1, + sched, &cred->session, &c_sock, &s_sock); + + /* Send it */ + i = sendto(sock, (char *)ktxt->dat, (int) len, flags, + (struct sockaddr *)&s_sock, sizeof(s_sock)); + if (i < 0) + warn("sending encrypted message"); + printf("Sent encrypted message: %d bytes\n", i); + return 0; +} + +static void +usage (void) +{ + fprintf (stderr, "Usage: %s [-s service] [-p port] hostname\n", + __progname); + exit (1); +} + +int +main(int argc, char **argv) +{ + int ret = 0; + int port = 0; + char service[SNAME_SZ]; + struct servent *serv; + int c; + + set_progname (argv[0]); + + strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service)); + + while ((c = getopt(argc, argv, "s:p:")) != EOF) + switch(c) { + case 's' : + strcpy_truncate (service, optarg, sizeof(service)); + break; + case 'p' : + serv = getservbyname (optarg, "tcp"); + if (serv) + port = serv->s_port; + else + port = htons(atoi(optarg)); + break; + case '?' : + default : + usage(); + } + + argc -= optind; + argv += optind; + + while (argc-- > 0) + ret &= talkto (*argv++, service, port); + return ret; +} diff --git a/crypto/kerberosIV/appl/sample/simple_server.c b/crypto/kerberosIV/appl/sample/simple_server.c new file mode 100644 index 0000000..2b950c7 --- /dev/null +++ b/crypto/kerberosIV/appl/sample/simple_server.c @@ -0,0 +1,140 @@ +/* + * + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * Simple UDP-based server application. For demonstration. + * This program performs no useful function. + */ + +#include "sample.h" + +RCSID("$Id: simple_server.c,v 1.9 1998/06/09 19:24:39 joda Exp $"); + +static void +usage (void) +{ + fprintf (stderr, "Usage: %s [-p port] [-s service] [-t srvtab]\n", + __progname); + exit (1); +} + +int +main(int argc, char **argv) +{ + char service[SNAME_SZ]; + char instance[INST_SZ]; + int port; + char srvtab[MaxPathLen]; + struct sockaddr_in addr, otheraddr; + int c; + int sock; + int i; + int len; + KTEXT_ST k; + KTEXT ktxt = &k; + AUTH_DAT ad; + MSG_DAT msg_data; + des_key_schedule sched; + + set_progname (argv[0]); + strcpy_truncate (service, SAMPLE_SERVICE, sizeof(service)); + strcpy_truncate (instance, "*", sizeof(instance)); + *srvtab = '\0'; + port = 0; + + while ((c = getopt (argc, argv, "p:s:t:")) != EOF) + switch (c) { + case 'p' : { + struct servent *sp; + + sp = getservbyname (optarg, "udp"); + if (sp) + port = sp->s_port; + else + port = htons(atoi(optarg)); + break; + } + case 's' : + strcpy_truncate (service, optarg, sizeof(service)); + break; + case 't' : + strcpy_truncate (srvtab, optarg, sizeof(srvtab)); + break; + case '?' : + default : + usage (); + } + + if(port == 0) + port = k_getportbyname (SAMPLE_SERVICE, "udp", htons(SAMPLE_PORT)); + + memset (&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = port; + + sock = socket (AF_INET, SOCK_DGRAM, 0); + if (sock < 0) + err (1, "socket"); + + if (bind (sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) + err (1, "bind"); + + /* GET KRB_MK_REQ MESSAGE */ + + i = read(sock, ktxt->dat, MAX_KTXT_LEN); + if (i < 0) + err (1, "read"); + + printf("Received %d bytes\n", i); + ktxt->length = i; + + /* Check authentication info */ + i = krb_rd_req(ktxt, service, instance, 0, &ad, ""); + if (i != KSUCCESS) + errx (1, "krb_rd_req: %s", krb_get_err_text(i)); + printf("Got authentication info from %s%s%s@%s\n", ad.pname, + *ad.pinst ? "." : "", ad.pinst, ad.prealm); + + /* GET KRB_MK_SAFE MESSAGE */ + + /* use "recvfrom" so we know client's address */ + len = sizeof(otheraddr); + i = recvfrom(sock, ktxt->dat, MAX_KTXT_LEN, 0, + (struct sockaddr *)&otheraddr, &len); + if (i < 0) + err (1, "recvfrom"); + printf("Received %d bytes\n", i); + + /* Verify the checksummed message */ + i = krb_rd_safe(ktxt->dat, i, &ad.session, &otheraddr, + &addr, &msg_data); + if (i != KSUCCESS) + errx (1, "krb_rd_safe: %s", krb_get_err_text(i)); + printf("Safe message is: %s\n", msg_data.app_data); + + /* NOW GET ENCRYPTED MESSAGE */ + +#ifdef NOENCRYPTION + memset(sched, 0, sizeof(sched)); +#else + /* need key schedule for session key */ + des_key_sched(&ad.session, sched); +#endif + + /* use "recvfrom" so we know client's address */ + len = sizeof(otheraddr); + i = recvfrom(sock, ktxt->dat, MAX_KTXT_LEN, 0, + (struct sockaddr *)&otheraddr, &len); + if (i < 0) + err (1, "recvfrom"); + printf("Received %d bytes\n", i); + i = krb_rd_priv(ktxt->dat, i, sched, &ad.session, &otheraddr, + &addr, &msg_data); + if (i != KSUCCESS) + errx (1, "krb_rd_priv: %s", krb_get_err_text(i)); + printf("Decrypted message is: %s\n", msg_data.app_data); + return(0); +} diff --git a/crypto/kerberosIV/appl/telnet/ChangeLog b/crypto/kerberosIV/appl/telnet/ChangeLog new file mode 100644 index 0000000..5681679 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/ChangeLog @@ -0,0 +1,232 @@ +1999-07-07 Assar Westerlund <assar@sics.se> + + * telnet/commands.c (tn): extra bogus const-cast + +1999-07-06 Assar Westerlund <assar@sics.se> + + * telnetd/sys_term.c (start_login): print a different warning with + `-a otp' + +1999-06-24 Assar Westerlund <assar@sics.se> + + * libtelnet/kerberos5.c (kerberos5_send): set the addresses in the + auth_context + +1999-06-23 Assar Westerlund <assar@sics.se> + + * telnet/Makefile.am (INCLUDES): add $(INCLUDE_krb4) + + * telnet/commands.c (togkrbdebug): conditionalize on + krb_disable_debug + +1999-06-16 Johan Danielsson <joda@pdc.kth.se> + + * telnet/commands.c: add kerberos debugging option + +1999-06-15 Assar Westerlund <assar@sics.se> + + * telnet/commands.c (tn): use get_default_username + +1999-05-14 Assar Westerlund <assar@sics.se> + + * telnetd/state.c (telrcv): magic patch to make it work against + DOS Clarkson Telnet. From Miroslav Ruda <ruda@ics.muni.cz> + +1999-04-25 Assar Westerlund <assar@sics.se> + + * libtelnet/kerberos5.c (kerberos5_send): use + `krb5_auth_setkeytype' instead of `krb5_auth_setenctype' to make + sure we get a DES session key. + +Thu Apr 1 16:59:27 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * telnetd/Makefile.am: don't run check-local + + * telnet/Makefile.am: don't run check-local + +Mon Mar 29 16:11:33 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * telnetd/sys_term.c: _CRAY -> HAVE_STRUCT_UTMP_UT_ID + +Sat Mar 20 00:12:54 1999 Assar Westerlund <assar@sics.se> + + * telnet/authenc.c (telnet_gets): remove old extern declarations + +Thu Mar 18 11:20:16 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * telnetd/Makefile.am: include Makefile.am.common + + * telnet/Makefile.am: include Makefile.am.common + + * libtelnet/Makefile.am: include Makefile.am.common + + * Makefile.am: include Makefile.am.common + +Mon Mar 15 17:40:53 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * telnetd/telnetd.c: replace perror/exit with fatalperror + +Sat Mar 13 22:18:57 1999 Assar Westerlund <assar@sics.se> + + * telnetd/telnetd.c (main): 0 -> STDIN_FILENO. remove abs + + * libtelnet/kerberos.c (kerberos4_is): syslog root logins + +Thu Mar 11 14:48:54 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * telnetd/Makefile.in: add WFLAGS + + * telnet/Makefile.in: add WFLAGS + + * libtelnet/Makefile.in: add WFLAGS + + * telnetd/sys_term.c: remove unused variables + + * telnet/telnet.c: fix some warnings + + * telnet/main.c: fix some warnings + + * telnet/commands.c: fix types in format string + + * libtelnet/auth.c: fix types in format string + +Mon Mar 1 10:50:30 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * telnetd/sys_term.c: HAVE_UT_* -> HAVE_STRUCT_UTMP*_UT_* + +Mon Feb 1 04:08:36 1999 Assar Westerlund <assar@sics.se> + + * telnet/commands.c (tn): only call gethostbyname2 with AF_INET6 + if we actually have IPv6. From "Brandon S. Allbery KF8NH" + <allbery@kf8nh.apk.net> + +Sat Nov 21 16:51:00 1998 Johan Danielsson <joda@hella.pdc.kth.se> + + * telnetd/sys_term.c (cleanup): don't call vhangup() on sgi:s + +Fri Aug 14 16:29:18 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * libtelnet/kerberos.c: krb_put_int -> KRB_PUT_INT + +Thu Jul 23 20:29:05 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * libtelnet/kerberos5.c: use krb5_verify_authenticator_checksum + +Mon Jul 13 22:00:09 1998 Assar Westerlund <assar@sics.se> + + * telnet/commands.c (tn): don't advance hostent->h_addr_list, use + a copy instead + +Wed May 27 04:19:17 1998 Assar Westerlund <assar@sics.se> + + * telnet/sys_bsd.c (process_rings): correct call to `stilloob' + +Fri May 15 19:38:19 1998 Johan Danielsson <joda@blubb.pdc.kth.se> + + * libtelnet/kerberos5.c: Always print errors from mk_req. + +Fri May 1 07:16:59 1998 Assar Westerlund <assar@sics.se> + + * telnet/commands.c: unifdef -DHAVE_H_ERRNO + +Sat Apr 4 15:00:29 1998 Assar Westerlund <assar@sics.se> + + * telnet/commands.c (tn): moved the printing of `trying...' to the + loop + +Thu Mar 12 02:33:48 1998 Assar Westerlund <assar@sics.se> + + * telnet/telnet_locl.h: include <term.h>. From Gregory S. Stark + <gsstark@mit.edu> + +Sat Feb 21 15:12:38 1998 Assar Westerlund <assar@sics.se> + + * telnetd/ext.h: add prototype for login_tty + + * telnet/utilities.c (printsub): `direction' is now an int. + + * libtelnet/misc-proto.h: add prototype for `printsub' + +Tue Feb 17 02:45:01 1998 Assar Westerlund <assar@sics.se> + + * libtelnet/kerberos.c (kerberos4_is): cred.pname should be + cred.pinst. From <art@stacken.kth.se> + +Sun Feb 15 02:46:39 1998 Assar Westerlund <assar@sics.se> + + * telnet/*/*.c: renamed `telnet' to `my_telnet' to avoid + conflicts with system header files on mklinux. + +Tue Feb 10 02:09:03 1998 Assar Westerlund <assar@sics.se> + + * telnetd/telnetd.c: new signature for `getterminaltype' and + `auth_wait' + + * libtelnet: changed the signature of the authentication method + `status' + +Sat Feb 7 07:21:29 1998 Assar Westerlund <assar@sics.se> + + * */*.c: replace HAS_GETTOS by HAVE_PARSETOS and HAVE_GETTOSBYNAME + +Fri Dec 26 16:17:10 1997 Assar Westerlund <assar@sics.se> + + * telnet/commands.c (tn): repair support for numeric addresses + +Sun Dec 21 09:40:31 1997 Assar Westerlund <assar@sics.se> + + * libtelnet/kerberos.c: fix up lots of stuff related to the + forwarding of v4 tickets. + + * libtelnet/kerberos5.c (kerberos5_forward): zero out `creds'. + +Mon Dec 15 20:53:13 1997 Johan Danielsson <joda@emma.pdc.kth.se> + + * telnet/sys_bsd.c: Don't turn off OPOST in 8bit-mode. + +Tue Dec 9 19:26:50 1997 Assar Westerlund <assar@sics.se> + + * telnet/main.c (main): add 'b' to getopt + +Sat Nov 29 03:28:54 1997 Johan Danielsson <joda@emma.pdc.kth.se> + + * telnet/telnet.c: Change binary mode to do just that, and add a + eight-bit mode for just passing all characters. + +Sun Nov 16 04:37:02 1997 Assar Westerlund <assar@sics.se> + + * libtelnet/kerberos5.c (kerberos5_send): always ask for a session + key of type DES + + * libtelnet/kerberos5.c: remove old garbage and fix call to + krb5_auth_con_setaddrs_from_fd + +Fri Nov 14 20:35:18 1997 Johan Danielsson <joda@emma.pdc.kth.se> + + * telnetd/telnetd.c: Output contents of /etc/issue. + +Mon Nov 3 07:09:16 1997 Assar Westerlund <assar@sics.se> + + * telnet/telnet_locl.h: only include <sys/termio.h> iff + !defined(HAVE_TERMIOS_H) + + * libtelnet/kerberos.c (kerberos4_is): send the peer address to + krb_rd_req + + * telnetd/telnetd.c (terminaltypeok): always return OK. It used + to call `tgetent' to figure if it was a defined terminal type. + It's possible to overflow tgetent so that's a bad idea. The worst + that could happen by saying yes to all terminals is that the user + ends up with a terminal that has no definition on the local + system. And besides, most telnet client has no support for + falling back to a different terminal type. + +Mon Oct 20 05:47:19 1997 Assar Westerlund <assar@sics.se> + + * libtelnet/kerberos5.c: remove lots of old junk. clean-up. + better error checking and reporting. tell the user permission + denied much earlier. + + * libtelnet/kerberos.c (kerberos4_is): only print + UserNameRequested if != NULL + diff --git a/crypto/kerberosIV/appl/telnet/Makefile.am b/crypto/kerberosIV/appl/telnet/Makefile.am new file mode 100644 index 0000000..eec013b --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/Makefile.am @@ -0,0 +1,11 @@ +# $Id: Makefile.am,v 1.6 1999/03/20 13:58:15 joda Exp $ + +include $(top_srcdir)/Makefile.am.common + +SUBDIRS = libtelnet telnet telnetd + +dist-hook: + $(mkinstalldirs) $(distdir)/arpa + $(INSTALL_DATA) $(srcdir)/arpa/telnet.h $(distdir)/arpa + +EXTRA_DIST = README.ORIG telnet.state diff --git a/crypto/kerberosIV/appl/telnet/Makefile.in b/crypto/kerberosIV/appl/telnet/Makefile.in new file mode 100644 index 0000000..840e757 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/Makefile.in @@ -0,0 +1,42 @@ +# $Id: Makefile.in,v 1.20 1998/05/31 18:04:50 joda Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh + +@SET_MAKE@ + +CC = @CC@ +LINK = @LINK@ +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ + +INSTALL = @INSTALL@ + +SUBDIRS=libtelnet telnet telnetd + +all: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) all); done + +install: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) install); done + +uninstall: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) uninstall); done + +clean cleandir: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) clean); done + +distclean: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) distclean); done + rm -f Makefile *~ + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/telnet/README.ORIG b/crypto/kerberosIV/appl/telnet/README.ORIG new file mode 100644 index 0000000..37b588f --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/README.ORIG @@ -0,0 +1,743 @@ + +This is a distribution of both client and server telnet. These programs +have been compiled on: + telnet telnetd + 4.4 BSD-Lite x x + 4.3 BSD Reno X X + UNICOS 9.1 X X + UNICOS 9.0 X X + UNICOS 8.0 X X + BSDI 2.0 X X + Solaris 2.4 x x (no linemode in server) + SunOs 4.1.4 X X (no linemode in server) + Ultrix 4.3 X X (no linemode in server) + Ultrix 4.1 X X (no linemode in server) + +In addition, previous versions have been compiled on the following +machines, but were not available for testing this version. + telnet telnetd + Next1.0 X X + UNICOS 8.3 X X + UNICOS 7.C X X + UNICOS 7.0 X X + SunOs 4.0.3c X X (no linemode in server) + 4.3 BSD X X (no linemode in server) + DYNIX V3.0.12 X X (no linemode in server) + Ultrix 3.1 X X (no linemode in server) + Ultrix 4.0 X X (no linemode in server) + SunOs 3.5 X X (no linemode in server) + SunOs 4.1.3 X X (no linemode in server) + Solaris 2.2 x x (no linemode in server) + Solaris 2.3 x x (no linemode in server) + BSDI 1.0 X X + BSDI 1.1 X X + DYNIX V3.0.17.9 X X (no linemode in server) + HP-UX 8.0 x x (no linemode in server) + +This code should work, but there are no guarantees. + +May 30, 1995 + +This release represents what is on the 4.4BSD-Lite2 release, which +should be the final BSD release. I will continue to support of +telnet, The code (without encryption) is available via anonymous ftp +from ftp.cray.com, in src/telnet/telnet.YY.MM.DD.NE.tar.Z, where +YY.MM.DD is replaced with the year, month and day of the release. +If you can't find it at one of these places, at some point in the +near future information about the latest releases should be available +from ftp.borman.com. + +In addition, the version with the encryption code is available via +ftp from net-dist.mit.edu, in the directory /pub/telnet. There +is a README file there that gives further information on how +to get the distribution. + +Questions, comments, bug reports and bug fixes can be sent to +one of these addresses: + dab@borman.com + dab@cray.com + dab@bsdi.com + +This release is mainly bug fixes and code cleanup. + + Replace all calls to bcopy()/bzero() with calls to + memmove()/memset() and all calls to index()/rindex() + with calls to strchr()/strrchr(). + + Add some missing diagnostics for option tracing + to telnetd. + + Add support for BSDI 2.0 and Solaris 2.4. + + Add support for UNICOS 8.0 + + Get rid of expanded tabs and trailing white spaces. + + From Paul Vixie: + Fix for telnet going into an endless spin + when the session dies abnormally. + + From Jef Poskanzer: + Changes to allow telnet to compile + under SunOS 3.5. + + From Philip Guenther: + makeutx() doesn't expand utmpx, + use pututxline() instead. + + From Chris Torek: + Add a sleep(1) before execing login + to avoid race condition that can eat + up the login prompt. + Use terminal speed directly if it is + not an encoded value. + + From Steve Parker: + Fix to realloc() call. Fix for execing + login on solaris with no user name. + +January 19, 1994 + +This is a list of some of the changes since the last tar release +of telnet/telnetd. There are probably other changes that aren't +listed here, but this should hit a lot of the main ones. + + General: + Changed #define for AUTHENTICATE to AUTHENTICATION + Changed #define for ENCRYPT to ENCRYPTION + Changed #define for DES_ENCRYPT to DES_ENCRYPTION + + Added support for SPX authentication: -DSPX + + Added support for Kerberos Version 5 authentication: -DKRB5 + + Added support for ANSI C function prototypes + + Added support for the NEW-ENVIRON option (RFC-1572) + including support for USERVAR. + + Made support for the old Environment Option (RFC-1408) + conditional on -DOLD_ENVIRON + + Added #define ENV_HACK - support for RFC 1571 + + The encryption code is removed from the public distributions. + Domestic 4.4 BSD distributions contain the encryption code. + + ENV_HACK: Code to deal with systems that only implement + the old ENVIRON option, and have reversed definitions + of ENV_VAR and ENV_VAL. Also fixes ENV processing in + client to handle things besides just the default set... + + NO_BSD_SETJMP: UNICOS configuration for + UNICOS 6.1/6.0/5.1/5.0 systems. + + STREAMSPTY: Use /dev/ptmx to get a clean pty. This + is for SVr4 derivatives (Like Solaris) + + UTMPX: For systems that have /etc/utmpx. This is for + SVr4 derivatives (Like Solaris) + + Definitions for BSDI 1.0 + + Definitions for 4.3 Reno and 4.4 BSD. + + Definitions for UNICOS 8.0 and UNICOS 7.C + + Definitions for Solaris 2.0 + + Definitions for HP-UX 8.0 + + Latest Copyright notices from Berkeley. + + FLOW-CONTROL: support for RFC-XXXx + + + Client Specific: + + Fix the "send" command to not send garbage... + + Fix status message for "skiprc" + + Make sure to send NAWS after telnet has been suspended + or an external command has been run, if the window size + has changed. + + sysV88 support. + + Server Specific: + + Support flowcontrol option in non-linemode servers. + + -k Server supports Kludge Linemode, but will default to + either single character mode or real Linemode support. + The user will have to explicitly ask to switch into + kludge linemode. ("stty extproc", or escape back to + to telnet and say "mode line".) + + -u Specify the length of the hostname field in the utmp + file. Hostname longer than this length will be put + into the utmp file in dotted decimal notation, rather + than putting in a truncated hostname. + + -U Registered hosts only. If a reverse hostname lookup + fails, the connection will be refused. + + -f/-F + Allows forwarding of credentials for KRB5. + +Februrary 22, 1991: + + Features: + + This version of telnet/telnetd has support for both + the AUTHENTICATION and ENCRYPTION options. The + AUTHENTICATION option is fairly well defined, and + an option number has been assigned to it. The + ENCRYPTION option is still in a state of flux; an + option number has been assigned to, but it is still + subject to change. The code is provided in this release + for experimental and testing purposes. + + The telnet "send" command can now be used to send + do/dont/will/wont commands, with any telnet option + name. The rules for when do/dont/will/wont are sent + are still followed, so just because the user requests + that one of these be sent doesn't mean that it will + be sent... + + The telnet "getstatus" command no longer requires + that option printing be enabled to see the response + to the "DO STATUS" command. + + A -n flag has been added to telnetd to disable + keepalives. + + A new telnet command, "auth" has been added (if + AUTHENTICATE is defined). It has four sub-commands, + "status", "disable", "enable" and "help". + + A new telnet command, "encrypt" has been added (if + ENCRYPT is defined). It has many sub-commands: + "enable", "type", "start", "stop", "input", + "-input", "output", "-output", "status", and "help". + + The LOGOUT option is now supported by both telnet + and telnetd, a new command, "logout", was added + to support this. + + Several new toggle options were added: + "autoencrypt", "autodecrypt", "autologin", "authdebug", + "encdebug", "skiprc", "verbose_encrypt" + + An "rlogin" interface has been added. If the program + is named "rlogin", or the "-r" flag is given, then + an rlogin type of interface will be used. + ~. Terminates the session + ~<susp> Suspend the session + ~^] Escape to telnet command mode + ~~ Pass through the ~. + BUG: If you type the rlogin escape character + in the middle of a line while in rlogin + mode, you cannot erase it or any characters + before it. Hopefully this can be fixed + in a future release... + + General changes: + + A "libtelnet.a" has now been created. This libraray + contains code that is common to both telnet and + telnetd. This is also where library routines that + are needed, but are not in the standard C library, + are placed. + + The makefiles have been re-done. All of the site + specific configuration information has now been put + into a single "Config.generic" file, in the top level + directory. Changing this one file will take care of + all three subdirectories. Also, to add a new/local + definition, a "Config.local" file may be created + at the top level; if that file exists, the subdirectories + will use that file instead of "Config.generic". + + Many 1-2 line functions in commands.c have been + removed, and just inserted in-line, or replaced + with a macro. + + Bug Fixes: + + The non-termio code in both telnet and telnetd was + setting/clearing CTLECH in the sg_flags word. This + was incorrect, and has been changed to set/clear the + LCTLECH bit in the local mode word. + + The SRCRT #define has been removed. If IP_OPTIONS + and IPPROTO_IP are defined on the system, then the + source route code is automatically enabled. + + The NO_GETTYTAB #define has been removed; there + is a compatability routine that can be built into + libtelnet to achive the same results. + + The server, telnetd, has been switched to use getopt() + for parsing the argument list. + + The code for getting the input/output speeds via + cfgetispeed()/cfgetospeed() was still not quite + right in telnet. Posix says if the ispeed is 0, + then it is really equal to the ospeed. + + The suboption processing code in telnet now has + explicit checks to make sure that we received + the entire suboption (telnetd was already doing this). + + The telnet code for processing the terminal type + could cause a core dump if an existing connection + was closed, and a new connection opened without + exiting telnet. + + Telnetd was doing a TCSADRAIN when setting the new + terminal settings; This is not good, because it means + that the tcsetattr() will hang waiting for output to + drain, and telnetd is the only one that will drain + the output... The fix is to use TCSANOW which does + not wait. + + Telnetd was improperly setting/clearing the ISTRIP + flag in the c_lflag field, it should be using the + c_iflag field. + + When the child process of telnetd was opening the + slave side of the pty, it was re-setting the EXTPROC + bit too early, and some of the other initialization + code was wiping it out. This would cause telnetd + to go out of linemode and into single character mode. + + One instance of leaving linemode in telnetd forgot + to send a WILL ECHO to the client, the net result + would be that the user would see double character + echo. + + If the MODE was being changed several times very + quickly, telnetd could get out of sync with the + state changes and the returning acks; and wind up + being left in the wrong state. + +September 14, 1990: + + Switch the client to use getopt() for parsing the + argument list. The 4.3Reno getopt.c is included for + systems that don't have getopt(). + + Use the posix _POSIX_VDISABLE value for what value + to use when disabling special characters. If this + is undefined, it defaults to 0x3ff. + + For non-termio systems, TIOCSETP was being used to + change the state of the terminal. This causes the + input queue to be flushed, which we don't want. This + is now changed to TIOCSETN. + + Take out the "#ifdef notdef" around the code in the + server that generates a "sync" when the pty oputput + is flushed. The potential problem is that some older + telnet clients may go into an infinate loop when they + receive a "sync", if so, the server can be compiled + with "NO_URGENT" defined. + + Fix the client where it was setting/clearing the OPOST + bit in the c_lflag field, not the c_oflag field. + + Fix the client where it was setting/clearing the ISTRIP + bit in the c_lflag field, not the c_iflag field. (On + 4.3Reno, this is the ECHOPRT bit in the c_lflag field.) + The client also had its interpretation of WILL BINARY + and DO BINARY reversed. + + Fix a bug in client that would cause a core dump when + attempting to remove the last environment variable. + + In the client, there were a few places were switch() + was being passed a character, and if it was a negative + value, it could get sign extended, and not match + the 8 bit case statements. The fix is to and the + switch value with 0xff. + + Add a couple more printoption() calls in the client, I + don't think there are any more places were a telnet + command can be received and not printed out when + "options" is on. + + A new flag has been added to the client, "-a". Currently, + this just causes the USER name to be sent across, in + the future this may be used to signify that automatic + authentication is requested. + + The USER variable is now only sent by the client if + the "-a" or "-l user" options are explicity used, or + if the user explicitly asks for the "USER" environment + variable to be exported. In the server, if it receives + the "USER" environment variable, it won't print out the + banner message, so that only "Password:" will be printed. + This makes the symantics more like rlogin, and should be + more familiar to the user. (People are not used to + getting a banner message, and then getting just a + "Password:" prompt.) + + Re-vamp the code for starting up the child login + process. The code was getting ugly, and it was + hard to tell what was really going on. What we + do now is after the fork(), in the child: + 1) make sure we have no controlling tty + 2) open and initialize the tty + 3) do a setsid()/setpgrp() + 4) makes the tty our controlling tty. + On some systems, #2 makes the tty our controlling + tty, and #4 is a no-op. The parent process does + a gets rid of any controlling tty after the child + is fork()ed. + + Use the strdup() library routine in telnet, instead + of the local savestr() routine. If you don't have + strdup(), you need to define NO_STRDUP. + + Add support for ^T (SIGINFO/VSTATUS), found in the + 4.3Reno distribution. This maps to the AYT character. + You need a 4-line bugfix in the kernel to get this + to work properly: + + > *** tty_pty.c.ORG Tue Sep 11 09:41:53 1990 + > --- tty_pty.c Tue Sep 11 17:48:03 1990 + > *************** + > *** 609,613 **** + > if ((tp->t_lflag&NOFLSH) == 0) + > ttyflush(tp, FREAD|FWRITE); + > ! pgsignal(tp->t_pgrp, *(unsigned int *)data); + > return(0); + > } + > --- 609,616 ---- + > if ((tp->t_lflag&NOFLSH) == 0) + > ttyflush(tp, FREAD|FWRITE); + > ! pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); + > ! if ((*(unsigned int *)data == SIGINFO) && + > ! ((tp->t_lflag&NOKERNINFO) == 0)) + > ! ttyinfo(tp); + > return(0); + > } + + The client is now smarter when setting the telnet escape + character; it only sets it to one of VEOL and VEOL2 if + one of them is undefined, and the other one is not already + defined to the telnet escape character. + + Handle TERMIOS systems that have seperate input and output + line speed settings imbedded in the flags. + + Many other minor bug fixes. + +June 20, 1990: + Re-organize makefiles and source tree. The telnet/Source + directory is now gone, and all the source that was in + telnet/Source is now just in the telnet directory. + + Seperate makefile for each system are now gone. There + are two makefiles, Makefile and Makefile.generic. + The "Makefile" has the definitions for the various + system, and "Makefile.generic" does all the work. + There is a variable called "WHAT" that is used to + specify what to make. For example, in the telnet + directory, you might say: + make 4.4bsd WHAT=clean + to clean out the directory. + + Add support for the ENVIRON and XDISPLOC options. + In order for the server to work, login has to have + the "-p" option to preserve environment variables. + + Add the SOFT_TAB and LIT_ECHO modes in the LINEMODE support. + + Add the "-l user" option to command line and open command + (This is passed through the ENVIRON option). + + Add the "-e" command line option, for setting the escape + character. + + Add the "-D", diagnostic, option to the server. This allows + the server to print out debug information, which is very + useful when trying to debug a telnet that doesn't have any + debugging ability. + + Turn off the literal next character when not in LINEMODE. + + Don't recognize ^Y locally, just pass it through. + + Make minor modifications for Sun4.0 and Sun4.1 + + Add support for both FORW1 and FORW2 characters. The + telnet escpape character is set to whichever of the + two is not being used. If both are in use, the escape + character is not set, so when in linemode the user will + have to follow the escape character with a <CR> or <EOF) + to get it passed through. + + Commands can now be put in single and double quotes, and + a backslash is now an escape character. This is needed + for allowing arbitrary strings to be assigned to environment + variables. + + Switch telnetd to use macros like telnet for keeping + track of the state of all the options. + + Fix telnetd's processing of options so that we always do + the right processing of the LINEMODE option, regardless + of who initiates the request to turn it on. Also, make + sure that if the other side went "WILL ECHO" in response + to our "DO ECHO", that we send a "DONT ECHO" to get the + option turned back off! + + Fix the TERMIOS setting of the terminal speed to handle both + BSD's seperate fields, and the SYSV method of CBAUD bits. + + Change how we deal with the other side refusing to enable + an option. The sequence used to be: send DO option; receive + WONT option; send DONT option. Now, the sequence is: send + DO option; receive WONT option. Both should be valid + according to the spec, but there has been at least one + client implementation of telnet identified that can get + really confused by this. (The exact sequence, from a trace + on the server side, is (numbers are number of responses that + we expect to get after that line...): + + send WILL ECHO 1 (initial request) + send WONT ECHO 2 (server is changing state) + recv DO ECHO 1 (first reply, ok. expect DONT ECHO next) + send WILL ECHO 2 (server changes state again) + recv DONT ECHO 1 (second reply, ok. expect DO ECHO next) + recv DONT ECHO 0 (third reply, wrong answer. got DONT!!!) + *** send WONT ECHO (send WONT to acknowledge the DONT) + send WILL ECHO 1 (ask again to enable option) + recv DO ECHO 0 + + recv DONT ECHO 0 + send WONT ECHO 1 + recv DONT ECHO 0 + recv DO ECHO 1 + send WILL ECHO 0 + (and the last 5 lines loop forever) + + The line with the "***" is last of the WILL/DONT/WONT sequence. + The change to the server to not generate that makes this same + example become: + + send will ECHO 1 + send wont ECHO 2 + recv do ECHO 1 + send will ECHO 2 + recv dont ECHO 1 + recv dont ECHO 0 + recv do ECHO 1 + send will ECHO 0 + + There is other option negotiation going on, and not sending + the third part changes some of the timings, but this specific + example no longer gets stuck in a loop. The "telnet.state" + file has been modified to reflect this change to the algorithm. + + A bunch of miscellaneous bug fixes and changes to make + lint happier. + + This version of telnet also has some KERBEROS stuff in + it. This has not been tested, it uses an un-authorized + telnet option number, and uses an out-of-date version + of the (still being defined) AUTHENTICATION option. + There is no support for this code, do not enable it. + + +March 1, 1990: +CHANGES/BUGFIXES SINCE LAST RELEASE: + Some support for IP TOS has been added. Requires that the + kernel support the IP_TOS socket option (currently this + is only in UNICOS 6.0). + + Both telnet and telnetd now use the cc_t typedef. typedefs are + included for systems that don't have it (in termios.h). + + SLC_SUSP was not supported properly before. It is now. + + IAC EOF was not translated properly in telnetd for SYSV_TERMIO + when not in linemode. It now saves a copy of the VEOF character, + so that when ICANON is turned off and we can't trust it anymore + (because it is now the VMIN character) we use the saved value. + + There were two missing "break" commands in the linemode + processing code in telnetd. + + Telnetd wasn't setting the kernel window size information + properly. It was using the rows for both rows and columns... + +Questions/comments go to + David Borman + Cray Research, Inc. + 655F Lone Oak Drive + Eagan, MN 55123 + dab@cray.com. + +README: You are reading it. + +Config.generic: + This file contains all the OS specific definitions. It + has pre-definitions for many common system types, and is + in standard makefile fromat. See the comments at the top + of the file for more information. + +Config.local: + This is not part of the distribution, but if this file exists, + it is used instead of "Config.generic". This allows site + specific configuration without having to modify the distributed + "Config.generic" file. + +kern.diff: + This file contains the diffs for the changes needed for the + kernel to support LINEMODE is the server. These changes are + for a 4.3BSD system. You may need to make some changes for + your particular system. + + There is a new bit in the terminal state word, TS_EXTPROC. + When this bit is set, several aspects of the terminal driver + are disabled. Input line editing, character echo, and + mapping of signals are all disabled. This allows the telnetd + to turn of these functions when in linemode, but still keep + track of what state the user wants the terminal to be in. + + New ioctl()s: + + TIOCEXT Turn on/off the TS_EXTPROC bit + TIOCGSTATE Get t_state of tty to look at TS_EXTPROC bit + TIOCSIG Generate a signal to processes in the + current process group of the pty. + + There is a new mode for packet driver, the TIOCPKT_IOCTL bit. + When packet mode is turned on in the pty, and the TS_EXTPROC + bit is set, then whenever the state of the pty is changed, the + next read on the master side of the pty will have the TIOCPKT_IOCTL + bit set, and the data will contain the following: + struct xx { + struct sgttyb a; + struct tchars b; + struct ltchars c; + int t_state; + int t_flags; + } + This allows the process on the server side of the pty to know + when the state of the terminal has changed, and what the new + state is. + + However, if you define USE_TERMIO or SYSV_TERMIO, the code will + expect that the structure returned in the TIOCPKT_IOCTL is + the termio/termios structure. + +stty.diff: + This file contains the changes needed for the stty(1) program + to report on the current status of the TS_EXTPROC bit. It also + allows the user to turn on/off the TS_EXTPROC bit. This is useful + because it allows the user to say "stty -extproc", and the + LINEMODE option will be automatically disabled, and saying "stty + extproc" will re-enable the LINEMODE option. + +telnet.state: + Both the client and server have code in them to deal + with option negotiation loops. The algorithm that is + used is described in this file. + +telnet: + This directory contains the client code. No kernel changes are + needed to use this code. + +telnetd: + This directory contains the server code. If LINEMODE or KLUDGELINEMODE + are defined, then the kernel modifications listed above are needed. + +libtelnet: + This directory contains code that is common to both the client + and the server. + +arpa: + This directory has a new <arpa/telnet.h> + +libtelnet/Makefile.4.4: +telnet/Makefile.4.4: +telnetd/Makefile.4.4: + These are the makefiles that can be used on a 4.3Reno + system when this software is installed in /usr/src/lib/libtelnet, + /usr/src/libexec/telnetd, and /usr/src/usr.bin/telnet. + + +The following TELNET options are supported: + + LINEMODE: + The LINEMODE option is supported as per RFC1116. The + FORWARDMASK option is not currently supported. + + BINARY: The client has the ability to turn on/off the BINARY + option in each direction. Turning on BINARY from + server to client causes the LITOUT bit to get set in + the terminal driver on both ends, turning on BINARY + from the client to the server causes the PASS8 bit + to get set in the terminal driver on both ends. + + TERMINAL-TYPE: + This is supported as per RFC1091. On the server side, + when a terminal type is received, termcap/terminfo + is consulted to determine if it is a known terminal + type. It keeps requesting terminal types until it + gets one that it recongnizes, or hits the end of the + list. The server side looks up the entry in the + termcap/terminfo data base, and generates a list of + names which it then passes one at a time to each + request for a terminal type, duplicating the last + entry in the list before cycling back to the beginning. + + NAWS: The Negotiate about Window Size, as per RFC 1073. + + TERMINAL-SPEED: + Implemented as per RFC 1079 + + TOGGLE-FLOW-CONTROL: + Implemented as per RFC 1080 + + TIMING-MARK: + As per RFC 860 + + SGA: As per RFC 858 + + ECHO: As per RFC 857 + + LOGOUT: As per RFC 727 + + STATUS: + The server will send its current status upon + request. It does not ask for the clients status. + The client will request the servers current status + from the "send getstatus" command. + + ENVIRON: + This option is currently being defined by the IETF + Telnet Working Group, and an RFC has not yet been + issued, but should be in the near future... + + X-DISPLAY-LOCATION: + This functionality can be done through the ENVIRON + option, it is added here for completeness. + + AUTHENTICATION: + This option is currently being defined by the IETF + Telnet Working Group, and an RFC has not yet been + issued. The basic framework is pretty much decided, + but the definitions for the specific authentication + schemes is still in a state of flux. + + ENCRYPTION: + This option is currently being defined by the IETF + Telnet Working Group, and an RFC has not yet been + issued. The draft RFC is still in a state of flux, + so this code may change in the future. diff --git a/crypto/kerberosIV/appl/telnet/arpa/telnet.h b/crypto/kerberosIV/appl/telnet/arpa/telnet.h new file mode 100644 index 0000000..5d9ef60 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/arpa/telnet.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)telnet.h 8.2 (Berkeley) 12/15/93 + */ + +#ifndef _TELNET_H_ +#define _TELNET_H_ + +/* + * Definitions for the TELNET protocol. + */ +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#ifdef TELCMDS +char *telcmds[] = { + "EOF", "SUSP", "ABORT", "EOR", + "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", + "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0, +}; +#else +extern char *telcmds[]; +#endif + +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ + (unsigned int)(x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascic character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_XDISPLOC 35 /* X Display Location */ +#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ +#define TELOPT_AUTHENTICATION 37/* Authenticate */ +#define TELOPT_ENCRYPT 38 /* Encryption option */ +#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ +#define TELOPT_EXOPL 255 /* extended-options-list */ + + +#define NTELOPTS (1+TELOPT_NEW_ENVIRON) +#ifdef TELOPTS +char *telopts[NTELOPTS+1] = { + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", + "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", + "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", + "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", + "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", + "TACACS UID", "OUTPUT MARKING", "TTYLOC", + "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", + "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", + "ENCRYPT", "NEW-ENVIRON", + 0, +}; +#define TELOPT_FIRST TELOPT_BINARY +#define TELOPT_LAST TELOPT_NEW_ENVIRON +#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) +#define TELOPT(x) telopts[(x)-TELOPT_FIRST] +#endif + +/* sub-option qualifiers */ +#define TELQUAL_IS 0 /* option is... */ +#define TELQUAL_SEND 1 /* send option */ +#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ +#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ +#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ + +#define LFLOW_OFF 0 /* Disable remote flow control */ +#define LFLOW_ON 1 /* Enable remote flow control */ +#define LFLOW_RESTART_ANY 2 /* Restart output on any char */ +#define LFLOW_RESTART_XON 3 /* Restart output only on XON */ + +/* + * LINEMODE suboptions + */ + +#define LM_MODE 1 +#define LM_FORWARDMASK 2 +#define LM_SLC 3 + +#define MODE_EDIT 0x01 +#define MODE_TRAPSIG 0x02 +#define MODE_ACK 0x04 +#define MODE_SOFT_TAB 0x08 +#define MODE_LIT_ECHO 0x10 + +#define MODE_MASK 0x1f + +/* Not part of protocol, but needed to simplify things... */ +#define MODE_FLOW 0x0100 +#define MODE_ECHO 0x0200 +#define MODE_INBIN 0x0400 +#define MODE_OUTBIN 0x0800 +#define MODE_FORCE 0x1000 + +#define SLC_SYNCH 1 +#define SLC_BRK 2 +#define SLC_IP 3 +#define SLC_AO 4 +#define SLC_AYT 5 +#define SLC_EOR 6 +#define SLC_ABORT 7 +#define SLC_EOF 8 +#define SLC_SUSP 9 +#define SLC_EC 10 +#define SLC_EL 11 +#define SLC_EW 12 +#define SLC_RP 13 +#define SLC_LNEXT 14 +#define SLC_XON 15 +#define SLC_XOFF 16 +#define SLC_FORW1 17 +#define SLC_FORW2 18 + +#define NSLC 18 + +/* + * For backwards compatability, we define SLC_NAMES to be the + * list of names if SLC_NAMES is not defined. + */ +#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ + "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ + "LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0, +#ifdef SLC_NAMES +char *slc_names[] = { + SLC_NAMELIST +}; +#else +extern char *slc_names[]; +#define SLC_NAMES SLC_NAMELIST +#endif + +#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) +#define SLC_NAME(x) slc_names[x] + +#define SLC_NOSUPPORT 0 +#define SLC_CANTCHANGE 1 +#define SLC_VARIABLE 2 +#define SLC_DEFAULT 3 +#define SLC_LEVELBITS 0x03 + +#define SLC_FUNC 0 +#define SLC_FLAGS 1 +#define SLC_VALUE 2 + +#define SLC_ACK 0x80 +#define SLC_FLUSHIN 0x40 +#define SLC_FLUSHOUT 0x20 + +#define OLD_ENV_VAR 1 +#define OLD_ENV_VALUE 0 +#define NEW_ENV_VAR 0 +#define NEW_ENV_VALUE 1 +#define ENV_ESC 2 +#define ENV_USERVAR 3 + +/* + * AUTHENTICATION suboptions + */ + +/* + * Who is authenticating who ... + */ +#define AUTH_WHO_CLIENT 0 /* Client authenticating server */ +#define AUTH_WHO_SERVER 1 /* Server authenticating client */ +#define AUTH_WHO_MASK 1 + +/* + * amount of authentication done + */ +#define AUTH_HOW_ONE_WAY 0 +#define AUTH_HOW_MUTUAL 2 +#define AUTH_HOW_MASK 2 + +#define AUTHTYPE_NULL 0 +#define AUTHTYPE_KERBEROS_V4 1 +#define AUTHTYPE_KERBEROS_V5 2 +#define AUTHTYPE_SPX 3 +#define AUTHTYPE_MINK 4 +#define AUTHTYPE_SRA 5 +#define AUTHTYPE_CNT 6 +/* #define AUTHTYPE_UNSECURE 6 */ + +#define AUTHTYPE_TEST 99 + +#ifdef AUTH_NAMES +char *authtype_names[] = { + "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", + "SRA", 0, +}; +#else +extern char *authtype_names[]; +#endif + +#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) +#define AUTHTYPE_NAME(x) authtype_names[x] + +/* + * ENCRYPTion suboptions + */ +#define ENCRYPT_IS 0 /* I pick encryption type ... */ +#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ +#define ENCRYPT_REPLY 2 /* Initial setup response */ +#define ENCRYPT_START 3 /* Am starting to send encrypted */ +#define ENCRYPT_END 4 /* Am ending encrypted */ +#define ENCRYPT_REQSTART 5 /* Request you start encrypting */ +#define ENCRYPT_REQEND 6 /* Request you send encrypting */ +#define ENCRYPT_ENC_KEYID 7 +#define ENCRYPT_DEC_KEYID 8 +#define ENCRYPT_CNT 9 + +#define ENCTYPE_ANY 0 +#define ENCTYPE_DES_CFB64 1 +#define ENCTYPE_DES_OFB64 2 +#define ENCTYPE_CNT 3 + +#ifdef ENCRYPT_NAMES +char *encrypt_names[] = { + "IS", "SUPPORT", "REPLY", "START", "END", + "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", + 0, +}; +char *enctype_names[] = { + "ANY", "DES_CFB64", "DES_OFB64", 0, +}; +#else +extern char *encrypt_names[]; +extern char *enctype_names[]; +#endif + + +#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) +#define ENCRYPT_NAME(x) encrypt_names[x] + +#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) +#define ENCTYPE_NAME(x) enctype_names[x] + +#endif /* !_TELNET_H_ */ diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.am b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.am new file mode 100644 index 0000000..8806f88 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.am @@ -0,0 +1,24 @@ +# $Id: Makefile.am,v 1.8 1999/03/20 13:58:15 joda Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += -I$(srcdir)/.. $(INCLUDE_krb4) + +noinst_LIBRARIES = libtelnet.a + +libtelnet_a_SOURCES = \ + auth-proto.h \ + auth.c \ + auth.h \ + enc-proto.h \ + enc_des.c \ + encrypt.c \ + encrypt.h \ + genget.c \ + kerberos.c \ + kerberos5.c \ + misc-proto.h \ + misc.c \ + misc.h + +EXTRA_DIST = krb4encpwd.c rsaencpwd.c spx.c diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.in b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.in new file mode 100644 index 0000000..b8ca629 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/Makefile.in @@ -0,0 +1,54 @@ +# $Id: Makefile.in,v 1.28 1999/03/11 13:50:00 joda Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh + +CC = @CC@ +LINK = @LINK@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ +LIBNAME = $(LIBPREFIX)telnet +LIBEXT = a +LIBPREFIX = @LIBPREFIX@ +LIB = $(LIBNAME).$(LIBEXT) + +prefix = @prefix@ + +SOURCES=auth.c encrypt.c genget.c enc_des.c misc.c kerberos.c kerberos5.c + +OBJECTS=auth.o encrypt.o genget.o enc_des.o misc.o kerberos.o kerberos5.o + +all: $(LIB) + +libtop = @libtop@ + +.c.o: + $(CC) -c $(DEFS) -I../../../include -I$(srcdir)/.. $(CFLAGS) $(CPPFLAGS) $< + +$(LIB): $(OBJECTS) + rm -f $@ + $(AR) cr $@ $(OBJECTS) + -$(RANLIB) $@ + +install: + @true + +uninstall: + @true + +TAGS: $(SOURCES) + etags $(SOURCES) + +clean cleandir: + rm -f *.o *.a \#* *~ core + +distclean: clean + rm -f Makefile *~ + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/auth-proto.h b/crypto/kerberosIV/appl/telnet/libtelnet/auth-proto.h new file mode 100644 index 0000000..bcc4c64 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/auth-proto.h @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)auth-proto.h 8.1 (Berkeley) 6/4/93 + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* $Id: auth-proto.h,v 1.9 1998/06/09 19:24:40 joda Exp $ */ + +#ifdef AUTHENTICATION +Authenticator *findauthenticator (int, int); + +int auth_wait (char *, size_t); +void auth_disable_name (char *); +void auth_finished (Authenticator *, int); +void auth_gen_printsub (unsigned char *, int, unsigned char *, int); +void auth_init (char *, int); +void auth_is (unsigned char *, int); +void auth_name(unsigned char*, int); +void auth_reply (unsigned char *, int); +void auth_request (void); +void auth_send (unsigned char *, int); +void auth_send_retry (void); +void auth_printsub(unsigned char*, int, unsigned char*, int); +int getauthmask(char *type, int *maskp); +int auth_enable(char *type); +int auth_disable(char *type); +int auth_onoff(char *type, int on); +int auth_togdebug(int on); +int auth_status(void); +int auth_sendname(unsigned char *cp, int len); +void auth_debug(int mode); +void auth_gen_printsub(unsigned char *data, int cnt, + unsigned char *buf, int buflen); + +#ifdef UNSAFE +int unsafe_init (Authenticator *, int); +int unsafe_send (Authenticator *); +void unsafe_is (Authenticator *, unsigned char *, int); +void unsafe_reply (Authenticator *, unsigned char *, int); +int unsafe_status (Authenticator *, char *, int); +void unsafe_printsub (unsigned char *, int, unsigned char *, int); +#endif + +#ifdef SRA +int sra_init (Authenticator *, int); +int sra_send (Authenticator *); +void sra_is (Authenticator *, unsigned char *, int); +void sra_reply (Authenticator *, unsigned char *, int); +int sra_status (Authenticator *, char *, int); +void sra_printsub (unsigned char *, int, unsigned char *, int); +#endif + +#ifdef KRB4 +int kerberos4_init (Authenticator *, int); +int kerberos4_send_mutual (Authenticator *); +int kerberos4_send_oneway (Authenticator *); +void kerberos4_is (Authenticator *, unsigned char *, int); +void kerberos4_reply (Authenticator *, unsigned char *, int); +int kerberos4_status (Authenticator *, char *, size_t, int); +void kerberos4_printsub (unsigned char *, int, unsigned char *, int); +int kerberos4_forward(Authenticator *ap, void *); +#endif + +#ifdef KRB5 +int kerberos5_init (Authenticator *, int); +int kerberos5_send_mutual (Authenticator *); +int kerberos5_send_oneway (Authenticator *); +void kerberos5_is (Authenticator *, unsigned char *, int); +void kerberos5_reply (Authenticator *, unsigned char *, int); +int kerberos5_status (Authenticator *, char *, size_t, int); +void kerberos5_printsub (unsigned char *, int, unsigned char *, int); +#endif +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/auth.c b/crypto/kerberosIV/appl/telnet/libtelnet/auth.c new file mode 100644 index 0000000..31d3ede --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/auth.c @@ -0,0 +1,657 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include <config.h> + +RCSID("$Id: auth.c,v 1.22 1999/03/11 13:48:52 joda Exp $"); + +#if defined(AUTHENTICATION) +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <signal.h> +#define AUTH_NAMES +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include <roken.h> + +#ifdef SOCKS +#include <socks.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc-proto.h" +#include "auth-proto.h" + +#define typemask(x) (1<<((x)-1)) + +#ifdef KRB4_ENCPWD +extern krb4encpwd_init(); +extern krb4encpwd_send(); +extern krb4encpwd_is(); +extern krb4encpwd_reply(); +extern krb4encpwd_status(); +extern krb4encpwd_printsub(); +#endif + +#ifdef RSA_ENCPWD +extern rsaencpwd_init(); +extern rsaencpwd_send(); +extern rsaencpwd_is(); +extern rsaencpwd_reply(); +extern rsaencpwd_status(); +extern rsaencpwd_printsub(); +#endif + +int auth_debug_mode = 0; +static char *Name = "Noname"; +static int Server = 0; +static Authenticator *authenticated = 0; +static int authenticating = 0; +static int validuser = 0; +static unsigned char _auth_send_data[256]; +static unsigned char *auth_send_data; +static int auth_send_cnt = 0; + +/* + * Authentication types supported. Plese note that these are stored + * in priority order, i.e. try the first one first. + */ +Authenticator authenticators[] = { +#ifdef UNSAFE + { AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + unsafe_init, + unsafe_send, + unsafe_is, + unsafe_reply, + unsafe_status, + unsafe_printsub }, +#endif +#ifdef SRA + { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + sra_init, + sra_send, + sra_is, + sra_reply, + sra_status, + sra_printsub }, +#endif +#ifdef SPX + { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, + spx_init, + spx_send, + spx_is, + spx_reply, + spx_status, + spx_printsub }, + { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + spx_init, + spx_send, + spx_is, + spx_reply, + spx_status, + spx_printsub }, +#endif +#ifdef KRB5 + { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, + kerberos5_init, + kerberos5_send_mutual, + kerberos5_is, + kerberos5_reply, + kerberos5_status, + kerberos5_printsub }, + { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + kerberos5_init, + kerberos5_send_oneway, + kerberos5_is, + kerberos5_reply, + kerberos5_status, + kerberos5_printsub }, +#endif +#ifdef KRB4 + { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, + kerberos4_init, + kerberos4_send_mutual, + kerberos4_is, + kerberos4_reply, + kerberos4_status, + kerberos4_printsub }, + { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + kerberos4_init, + kerberos4_send_oneway, + kerberos4_is, + kerberos4_reply, + kerberos4_status, + kerberos4_printsub }, +#endif +#ifdef KRB4_ENCPWD + { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, + krb4encpwd_init, + krb4encpwd_send, + krb4encpwd_is, + krb4encpwd_reply, + krb4encpwd_status, + krb4encpwd_printsub }, +#endif +#ifdef RSA_ENCPWD + { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + rsaencpwd_init, + rsaencpwd_send, + rsaencpwd_is, + rsaencpwd_reply, + rsaencpwd_status, + rsaencpwd_printsub }, +#endif + { 0, }, +}; + +static Authenticator NoAuth = { 0 }; + +static int i_support = 0; +static int i_wont_support = 0; + +Authenticator * +findauthenticator(int type, int way) +{ + Authenticator *ap = authenticators; + + while (ap->type && (ap->type != type || ap->way != way)) + ++ap; + return(ap->type ? ap : 0); +} + +void +auth_init(char *name, int server) +{ + Authenticator *ap = authenticators; + + Server = server; + Name = name; + + i_support = 0; + authenticated = 0; + authenticating = 0; + while (ap->type) { + if (!ap->init || (*ap->init)(ap, server)) { + i_support |= typemask(ap->type); + if (auth_debug_mode) + printf(">>>%s: I support auth type %d %d\r\n", + Name, + ap->type, ap->way); + } + else if (auth_debug_mode) + printf(">>>%s: Init failed: auth type %d %d\r\n", + Name, ap->type, ap->way); + ++ap; + } +} + +void +auth_disable_name(char *name) +{ + int x; + for (x = 0; x < AUTHTYPE_CNT; ++x) { + if (!strcasecmp(name, AUTHTYPE_NAME(x))) { + i_wont_support |= typemask(x); + break; + } + } +} + +int +getauthmask(char *type, int *maskp) +{ + int x; + + if (!strcasecmp(type, AUTHTYPE_NAME(0))) { + *maskp = -1; + return(1); + } + + for (x = 1; x < AUTHTYPE_CNT; ++x) { + if (!strcasecmp(type, AUTHTYPE_NAME(x))) { + *maskp = typemask(x); + return(1); + } + } + return(0); +} + +int +auth_enable(char *type) +{ + return(auth_onoff(type, 1)); +} + +int +auth_disable(char *type) +{ + return(auth_onoff(type, 0)); +} + +int +auth_onoff(char *type, int on) +{ + int i, mask = -1; + Authenticator *ap; + + if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) { + printf("auth %s 'type'\n", on ? "enable" : "disable"); + printf("Where 'type' is one of:\n"); + printf("\t%s\n", AUTHTYPE_NAME(0)); + mask = 0; + for (ap = authenticators; ap->type; ap++) { + if ((mask & (i = typemask(ap->type))) != 0) + continue; + mask |= i; + printf("\t%s\n", AUTHTYPE_NAME(ap->type)); + } + return(0); + } + + if (!getauthmask(type, &mask)) { + printf("%s: invalid authentication type\n", type); + return(0); + } + if (on) + i_wont_support &= ~mask; + else + i_wont_support |= mask; + return(1); +} + +int +auth_togdebug(int on) +{ + if (on < 0) + auth_debug_mode ^= 1; + else + auth_debug_mode = on; + printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled"); + return(1); +} + +int +auth_status(void) +{ + Authenticator *ap; + int i, mask; + + if (i_wont_support == -1) + printf("Authentication disabled\n"); + else + printf("Authentication enabled\n"); + + mask = 0; + for (ap = authenticators; ap->type; ap++) { + if ((mask & (i = typemask(ap->type))) != 0) + continue; + mask |= i; + printf("%s: %s\n", AUTHTYPE_NAME(ap->type), + (i_wont_support & typemask(ap->type)) ? + "disabled" : "enabled"); + } + return(1); +} + +/* + * This routine is called by the server to start authentication + * negotiation. + */ +void +auth_request(void) +{ + static unsigned char str_request[64] = { IAC, SB, + TELOPT_AUTHENTICATION, + TELQUAL_SEND, }; + Authenticator *ap = authenticators; + unsigned char *e = str_request + 4; + + if (!authenticating) { + authenticating = 1; + while (ap->type) { + if (i_support & ~i_wont_support & typemask(ap->type)) { + if (auth_debug_mode) { + printf(">>>%s: Sending type %d %d\r\n", + Name, ap->type, ap->way); + } + *e++ = ap->type; + *e++ = ap->way; + } + ++ap; + } + *e++ = IAC; + *e++ = SE; + telnet_net_write(str_request, e - str_request); + printsub('>', &str_request[2], e - str_request - 2); + } +} + +/* + * This is called when an AUTH SEND is received. + * It should never arrive on the server side (as only the server can + * send an AUTH SEND). + * You should probably respond to it if you can... + * + * If you want to respond to the types out of order (i.e. even + * if he sends LOGIN KERBEROS and you support both, you respond + * with KERBEROS instead of LOGIN (which is against what the + * protocol says)) you will have to hack this code... + */ +void +auth_send(unsigned char *data, int cnt) +{ + Authenticator *ap; + static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_IS, AUTHTYPE_NULL, 0, + IAC, SE }; + if (Server) { + if (auth_debug_mode) { + printf(">>>%s: auth_send called!\r\n", Name); + } + return; + } + + if (auth_debug_mode) { + printf(">>>%s: auth_send got:", Name); + printd(data, cnt); printf("\r\n"); + } + + /* + * Save the data, if it is new, so that we can continue looking + * at it if the authorization we try doesn't work + */ + if (data < _auth_send_data || + data > _auth_send_data + sizeof(_auth_send_data)) { + auth_send_cnt = cnt > sizeof(_auth_send_data) + ? sizeof(_auth_send_data) + : cnt; + memmove(_auth_send_data, data, auth_send_cnt); + auth_send_data = _auth_send_data; + } else { + /* + * This is probably a no-op, but we just make sure + */ + auth_send_data = data; + auth_send_cnt = cnt; + } + while ((auth_send_cnt -= 2) >= 0) { + if (auth_debug_mode) + printf(">>>%s: He supports %d\r\n", + Name, *auth_send_data); + if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) { + ap = findauthenticator(auth_send_data[0], + auth_send_data[1]); + if (ap && ap->send) { + if (auth_debug_mode) + printf(">>>%s: Trying %d %d\r\n", + Name, auth_send_data[0], + auth_send_data[1]); + if ((*ap->send)(ap)) { + /* + * Okay, we found one we like + * and did it. + * we can go home now. + */ + if (auth_debug_mode) + printf(">>>%s: Using type %d\r\n", + Name, *auth_send_data); + auth_send_data += 2; + return; + } + } + /* else + * just continue on and look for the + * next one if we didn't do anything. + */ + } + auth_send_data += 2; + } + telnet_net_write(str_none, sizeof(str_none)); + printsub('>', &str_none[2], sizeof(str_none) - 2); + if (auth_debug_mode) + printf(">>>%s: Sent failure message\r\n", Name); + auth_finished(0, AUTH_REJECT); +#ifdef KANNAN + /* + * We requested strong authentication, however no mechanisms worked. + * Therefore, exit on client end. + */ + printf("Unable to securely authenticate user ... exit\n"); + exit(0); +#endif /* KANNAN */ +} + +void +auth_send_retry(void) +{ + /* + * if auth_send_cnt <= 0 then auth_send will end up rejecting + * the authentication and informing the other side of this. + */ + auth_send(auth_send_data, auth_send_cnt); +} + +void +auth_is(unsigned char *data, int cnt) +{ + Authenticator *ap; + + if (cnt < 2) + return; + + if (data[0] == AUTHTYPE_NULL) { + auth_finished(0, AUTH_REJECT); + return; + } + + if ((ap = findauthenticator(data[0], data[1]))) { + if (ap->is) + (*ap->is)(ap, data+2, cnt-2); + } else if (auth_debug_mode) + printf(">>>%s: Invalid authentication in IS: %d\r\n", + Name, *data); +} + +void +auth_reply(unsigned char *data, int cnt) +{ + Authenticator *ap; + + if (cnt < 2) + return; + + if ((ap = findauthenticator(data[0], data[1]))) { + if (ap->reply) + (*ap->reply)(ap, data+2, cnt-2); + } else if (auth_debug_mode) + printf(">>>%s: Invalid authentication in SEND: %d\r\n", + Name, *data); +} + +void +auth_name(unsigned char *data, int cnt) +{ + char savename[256]; + + if (cnt < 1) { + if (auth_debug_mode) + printf(">>>%s: Empty name in NAME\r\n", Name); + return; + } + if (cnt > sizeof(savename) - 1) { + if (auth_debug_mode) + printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n", + Name, cnt, (unsigned long)(sizeof(savename)-1)); + return; + } + memmove(savename, data, cnt); + savename[cnt] = '\0'; /* Null terminate */ + if (auth_debug_mode) + printf(">>>%s: Got NAME [%s]\r\n", Name, savename); + auth_encrypt_user(savename); +} + +int +auth_sendname(unsigned char *cp, int len) +{ + static unsigned char str_request[256+6] + = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; + unsigned char *e = str_request + 4; + unsigned char *ee = &str_request[sizeof(str_request)-2]; + + while (--len >= 0) { + if ((*e++ = *cp++) == IAC) + *e++ = IAC; + if (e >= ee) + return(0); + } + *e++ = IAC; + *e++ = SE; + telnet_net_write(str_request, e - str_request); + printsub('>', &str_request[2], e - &str_request[2]); + return(1); +} + +void +auth_finished(Authenticator *ap, int result) +{ + if (!(authenticated = ap)) + authenticated = &NoAuth; + validuser = result; +} + +/* ARGSUSED */ +static void +auth_intr(int sig) +{ + auth_finished(0, AUTH_REJECT); +} + +int +auth_wait(char *name, size_t name_sz) +{ + if (auth_debug_mode) + printf(">>>%s: in auth_wait.\r\n", Name); + + if (Server && !authenticating) + return(0); + + signal(SIGALRM, auth_intr); + alarm(30); + while (!authenticated) + if (telnet_spin()) + break; + alarm(0); + signal(SIGALRM, SIG_DFL); + + /* + * Now check to see if the user is valid or not + */ + if (!authenticated || authenticated == &NoAuth) + return(AUTH_REJECT); + + if (validuser == AUTH_VALID) + validuser = AUTH_USER; + + if (authenticated->status) + validuser = (*authenticated->status)(authenticated, + name, name_sz, + validuser); + return(validuser); +} + +void +auth_debug(int mode) +{ + auth_debug_mode = mode; +} + +void +auth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) +{ + Authenticator *ap; + + if ((ap = findauthenticator(data[1], data[2])) && ap->printsub) + (*ap->printsub)(data, cnt, buf, buflen); + else + auth_gen_printsub(data, cnt, buf, buflen); +} + +void +auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) +{ + unsigned char *cp; + unsigned char tbuf[16]; + + cnt -= 3; + data += 3; + buf[buflen-1] = '\0'; + buf[buflen-2] = '*'; + buflen -= 2; + for (; cnt > 0; cnt--, data++) { + snprintf(tbuf, sizeof(tbuf), " %d", *data); + for (cp = tbuf; *cp && buflen > 0; --buflen) + *buf++ = *cp++; + if (buflen <= 0) + return; + } + *buf = '\0'; +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/auth.h b/crypto/kerberosIV/appl/telnet/libtelnet/auth.h new file mode 100644 index 0000000..83dd701 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/auth.h @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)auth.h 8.1 (Berkeley) 6/4/93 + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* $Id: auth.h,v 1.4 1998/06/09 19:24:41 joda Exp $ */ + +#ifndef __AUTH__ +#define __AUTH__ + +#define AUTH_REJECT 0 /* Rejected */ +#define AUTH_UNKNOWN 1 /* We don't know who he is, but he's okay */ +#define AUTH_OTHER 2 /* We know him, but not his name */ +#define AUTH_USER 3 /* We know he name */ +#define AUTH_VALID 4 /* We know him, and he needs no password */ + +typedef struct XauthP { + int type; + int way; + int (*init) (struct XauthP *, int); + int (*send) (struct XauthP *); + void (*is) (struct XauthP *, unsigned char *, int); + void (*reply) (struct XauthP *, unsigned char *, int); + int (*status) (struct XauthP *, char *, size_t, int); + void (*printsub) (unsigned char *, int, unsigned char *, int); +} Authenticator; + +#include "auth-proto.h" + +extern int auth_debug_mode; +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/enc-proto.h b/crypto/kerberosIV/appl/telnet/libtelnet/enc-proto.h new file mode 100644 index 0000000..cb0077d --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/enc-proto.h @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)enc-proto.h 8.1 (Berkeley) 6/4/93 + * + * @(#)enc-proto.h 5.2 (Berkeley) 3/22/91 + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* $Id: enc-proto.h,v 1.9 1998/07/09 23:16:22 assar Exp $ */ + +#if defined(ENCRYPTION) +Encryptions *findencryption (int); +Encryptions *finddecryption(int); +int EncryptAutoDec(int); +int EncryptAutoEnc(int); +int EncryptDebug(int); +int EncryptDisable(char*, char*); +int EncryptEnable(char*, char*); +int EncryptStart(char*); +int EncryptStartInput(void); +int EncryptStartOutput(void); +int EncryptStatus(void); +int EncryptStop(char*); +int EncryptStopInput(void); +int EncryptStopOutput(void); +int EncryptType(char*, char*); +int EncryptVerbose(int); +void decrypt_auto(int); +void encrypt_auto(int); +void encrypt_debug(int); +void encrypt_dec_keyid(unsigned char*, int); +void encrypt_display(void); +void encrypt_enc_keyid(unsigned char*, int); +void encrypt_end(void); +void encrypt_gen_printsub(unsigned char*, int, unsigned char*, int); +void encrypt_init(char*, int); +void encrypt_is(unsigned char*, int); +void encrypt_list_types(void); +void encrypt_not(void); +void encrypt_printsub(unsigned char*, int, unsigned char*, int); +void encrypt_reply(unsigned char*, int); +void encrypt_request_end(void); +void encrypt_request_start(unsigned char*, int); +void encrypt_send_end(void); +void encrypt_send_keyid(int, unsigned char*, int, int); +void encrypt_send_request_end(void); +void encrypt_send_request_start(void); +void encrypt_send_support(void); +void encrypt_session_key(Session_Key*, int); +void encrypt_start(unsigned char*, int); +void encrypt_start_output(int); +void encrypt_support(unsigned char*, int); +void encrypt_verbose_quiet(int); +void encrypt_wait(void); +int encrypt_delay(void); + +#ifdef TELENTD +void encrypt_wait (void); +#else +void encrypt_display (void); +#endif + +void cfb64_encrypt (unsigned char *, int); +int cfb64_decrypt (int); +void cfb64_init (int); +int cfb64_start (int, int); +int cfb64_is (unsigned char *, int); +int cfb64_reply (unsigned char *, int); +void cfb64_session (Session_Key *, int); +int cfb64_keyid (int, unsigned char *, int *); +void cfb64_printsub (unsigned char *, int, unsigned char *, int); + +void ofb64_encrypt (unsigned char *, int); +int ofb64_decrypt (int); +void ofb64_init (int); +int ofb64_start (int, int); +int ofb64_is (unsigned char *, int); +int ofb64_reply (unsigned char *, int); +void ofb64_session (Session_Key *, int); +int ofb64_keyid (int, unsigned char *, int *); +void ofb64_printsub (unsigned char *, int, unsigned char *, int); + +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c b/crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c new file mode 100644 index 0000000..a24bfa7 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/enc_des.c @@ -0,0 +1,671 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +RCSID("$Id: enc_des.c,v 1.16 1998/07/09 23:16:23 assar Exp $"); + +#if defined(AUTHENTICATION) && defined(ENCRYPTION) && defined(DES_ENCRYPTION) +#include <arpa/telnet.h> +#include <stdio.h> +#ifdef __STDC__ +#include <stdlib.h> +#include <string.h> +#endif +#include <roken.h> +#ifdef SOCKS +#include <socks.h> +#endif + +#include "encrypt.h" +#include "misc-proto.h" + +#include <des.h> + +extern int encrypt_debug_mode; + +#define CFB 0 +#define OFB 1 + +#define NO_SEND_IV 1 +#define NO_RECV_IV 2 +#define NO_KEYID 4 +#define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) +#define SUCCESS 0 +#define FAILED -1 + + +struct stinfo { + des_cblock str_output; + des_cblock str_feed; + des_cblock str_iv; + des_cblock str_ikey; + des_key_schedule str_sched; + int str_index; + int str_flagshift; +}; + +struct fb { + des_cblock krbdes_key; + des_key_schedule krbdes_sched; + des_cblock temp_feed; + unsigned char fb_feed[64]; + int need_start; + int state[2]; + int keyid[2]; + int once; + struct stinfo streams[2]; +}; + +static struct fb fb[2]; + +struct keyidlist { + char *keyid; + int keyidlen; + char *key; + int keylen; + int flags; +} keyidlist [] = { + { "\0", 1, 0, 0, 0 }, /* default key of zero */ + { 0, 0, 0, 0, 0 } +}; + +#define KEYFLAG_MASK 03 + +#define KEYFLAG_NOINIT 00 +#define KEYFLAG_INIT 01 +#define KEYFLAG_OK 02 +#define KEYFLAG_BAD 03 + +#define KEYFLAG_SHIFT 2 + +#define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) + +#define FB64_IV 1 +#define FB64_IV_OK 2 +#define FB64_IV_BAD 3 + + +void fb64_stream_iv (des_cblock, struct stinfo *); +void fb64_init (struct fb *); +static int fb64_start (struct fb *, int, int); +int fb64_is (unsigned char *, int, struct fb *); +int fb64_reply (unsigned char *, int, struct fb *); +static void fb64_session (Session_Key *, int, struct fb *); +void fb64_stream_key (des_cblock, struct stinfo *); +int fb64_keyid (int, unsigned char *, int *, struct fb *); + +void cfb64_init(int server) +{ + fb64_init(&fb[CFB]); + fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; + fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); + fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); +} + + +void ofb64_init(int server) +{ + fb64_init(&fb[OFB]); + fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; + fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); + fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); +} + +void fb64_init(struct fb *fbp) +{ + memset(fbp,0, sizeof(*fbp)); + fbp->state[0] = fbp->state[1] = FAILED; + fbp->fb_feed[0] = IAC; + fbp->fb_feed[1] = SB; + fbp->fb_feed[2] = TELOPT_ENCRYPT; + fbp->fb_feed[3] = ENCRYPT_IS; +} + +/* + * Returns: + * -1: some error. Negotiation is done, encryption not ready. + * 0: Successful, initial negotiation all done. + * 1: successful, negotiation not done yet. + * 2: Not yet. Other things (like getting the key from + * Kerberos) have to happen before we can continue. + */ +int cfb64_start(int dir, int server) +{ + return(fb64_start(&fb[CFB], dir, server)); +} + +int ofb64_start(int dir, int server) +{ + return(fb64_start(&fb[OFB], dir, server)); +} + +static int fb64_start(struct fb *fbp, int dir, int server) +{ + int x; + unsigned char *p; + int state; + + switch (dir) { + case DIR_DECRYPT: + /* + * This is simply a request to have the other side + * start output (our input). He will negotiate an + * IV so we need not look for it. + */ + state = fbp->state[dir-1]; + if (state == FAILED) + state = IN_PROGRESS; + break; + + case DIR_ENCRYPT: + state = fbp->state[dir-1]; + if (state == FAILED) + state = IN_PROGRESS; + else if ((state & NO_SEND_IV) == 0) { + break; + } + + if (!VALIDKEY(fbp->krbdes_key)) { + fbp->need_start = 1; + break; + } + + state &= ~NO_SEND_IV; + state |= NO_RECV_IV; + if (encrypt_debug_mode) + printf("Creating new feed\r\n"); + /* + * Create a random feed and send it over. + */ +#ifndef OLD_DES_RANDOM_KEY + des_new_random_key(&fbp->temp_feed); +#else + /* + * From des_cryp.man "If the des_check_key flag is non-zero, + * des_set_key will check that the key passed is + * of odd parity and is not a week or semi-weak key." + */ + do { + des_random_key(fbp->temp_feed); + des_set_odd_parity(fbp->temp_feed); + } while (des_is_weak_key(fbp->temp_feed)); +#endif + des_ecb_encrypt(&fbp->temp_feed, + &fbp->temp_feed, + fbp->krbdes_sched, 1); + p = fbp->fb_feed + 3; + *p++ = ENCRYPT_IS; + p++; + *p++ = FB64_IV; + for (x = 0; x < sizeof(des_cblock); ++x) { + if ((*p++ = fbp->temp_feed[x]) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); + telnet_net_write(fbp->fb_feed, p - fbp->fb_feed); + break; + default: + return(FAILED); + } + return(fbp->state[dir-1] = state); +} + +/* + * Returns: + * -1: some error. Negotiation is done, encryption not ready. + * 0: Successful, initial negotiation all done. + * 1: successful, negotiation not done yet. + */ + +int cfb64_is(unsigned char *data, int cnt) +{ + return(fb64_is(data, cnt, &fb[CFB])); +} + +int ofb64_is(unsigned char *data, int cnt) +{ + return(fb64_is(data, cnt, &fb[OFB])); +} + + +int fb64_is(unsigned char *data, int cnt, struct fb *fbp) +{ + unsigned char *p; + int state = fbp->state[DIR_DECRYPT-1]; + + if (cnt-- < 1) + goto failure; + + switch (*data++) { + case FB64_IV: + if (cnt != sizeof(des_cblock)) { + if (encrypt_debug_mode) + printf("CFB64: initial vector failed on size\r\n"); + state = FAILED; + goto failure; + } + + if (encrypt_debug_mode) + printf("CFB64: initial vector received\r\n"); + + if (encrypt_debug_mode) + printf("Initializing Decrypt stream\r\n"); + + fb64_stream_iv(data, &fbp->streams[DIR_DECRYPT-1]); + + p = fbp->fb_feed + 3; + *p++ = ENCRYPT_REPLY; + p++; + *p++ = FB64_IV_OK; + *p++ = IAC; + *p++ = SE; + printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); + telnet_net_write(fbp->fb_feed, p - fbp->fb_feed); + + state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; + break; + + default: + if (encrypt_debug_mode) { + printf("Unknown option type: %d\r\n", *(data-1)); + printd(data, cnt); + printf("\r\n"); + } + /* FALL THROUGH */ + failure: + /* + * We failed. Send an FB64_IV_BAD option + * to the other side so it will know that + * things failed. + */ + p = fbp->fb_feed + 3; + *p++ = ENCRYPT_REPLY; + p++; + *p++ = FB64_IV_BAD; + *p++ = IAC; + *p++ = SE; + printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); + telnet_net_write(fbp->fb_feed, p - fbp->fb_feed); + + break; + } + return(fbp->state[DIR_DECRYPT-1] = state); +} + +/* + * Returns: + * -1: some error. Negotiation is done, encryption not ready. + * 0: Successful, initial negotiation all done. + * 1: successful, negotiation not done yet. + */ + +int cfb64_reply(unsigned char *data, int cnt) +{ + return(fb64_reply(data, cnt, &fb[CFB])); +} + +int ofb64_reply(unsigned char *data, int cnt) +{ + return(fb64_reply(data, cnt, &fb[OFB])); +} + + +int fb64_reply(unsigned char *data, int cnt, struct fb *fbp) +{ + int state = fbp->state[DIR_ENCRYPT-1]; + + if (cnt-- < 1) + goto failure; + + switch (*data++) { + case FB64_IV_OK: + fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); + if (state == FAILED) + state = IN_PROGRESS; + state &= ~NO_RECV_IV; + encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); + break; + + case FB64_IV_BAD: + memset(fbp->temp_feed, 0, sizeof(des_cblock)); + fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); + state = FAILED; + break; + + default: + if (encrypt_debug_mode) { + printf("Unknown option type: %d\r\n", data[-1]); + printd(data, cnt); + printf("\r\n"); + } + /* FALL THROUGH */ + failure: + state = FAILED; + break; + } + return(fbp->state[DIR_ENCRYPT-1] = state); +} + +void cfb64_session(Session_Key *key, int server) +{ + fb64_session(key, server, &fb[CFB]); +} + +void ofb64_session(Session_Key *key, int server) +{ + fb64_session(key, server, &fb[OFB]); +} + +static void fb64_session(Session_Key *key, int server, struct fb *fbp) +{ + + if (!key || key->type != SK_DES) { + if (encrypt_debug_mode) + printf("Can't set krbdes's session key (%d != %d)\r\n", + key ? key->type : -1, SK_DES); + return; + } + memcpy(fbp->krbdes_key, key->data, sizeof(des_cblock)); + + fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); + fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); + + if (fbp->once == 0) { +#ifndef OLD_DES_RANDOM_KEY + des_init_random_number_generator(&fbp->krbdes_key); +#endif + fbp->once = 1; + } + des_key_sched(&fbp->krbdes_key, fbp->krbdes_sched); + /* + * Now look to see if krbdes_start() was was waiting for + * the key to show up. If so, go ahead an call it now + * that we have the key. + */ + if (fbp->need_start) { + fbp->need_start = 0; + fb64_start(fbp, DIR_ENCRYPT, server); + } +} + +/* + * We only accept a keyid of 0. If we get a keyid of + * 0, then mark the state as SUCCESS. + */ + +int cfb64_keyid(int dir, unsigned char *kp, int *lenp) +{ + return(fb64_keyid(dir, kp, lenp, &fb[CFB])); +} + +int ofb64_keyid(int dir, unsigned char *kp, int *lenp) +{ + return(fb64_keyid(dir, kp, lenp, &fb[OFB])); +} + +int fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp) +{ + int state = fbp->state[dir-1]; + + if (*lenp != 1 || (*kp != '\0')) { + *lenp = 0; + return(state); + } + + if (state == FAILED) + state = IN_PROGRESS; + + state &= ~NO_KEYID; + + return(fbp->state[dir-1] = state); +} + +void fb64_printsub(unsigned char *data, int cnt, + unsigned char *buf, int buflen, char *type) +{ + char lbuf[32]; + int i; + char *cp; + + buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ + buflen -= 1; + + switch(data[2]) { + case FB64_IV: + snprintf(lbuf, sizeof(lbuf), "%s_IV", type); + cp = lbuf; + goto common; + + case FB64_IV_OK: + snprintf(lbuf, sizeof(lbuf), "%s_IV_OK", type); + cp = lbuf; + goto common; + + case FB64_IV_BAD: + snprintf(lbuf, sizeof(lbuf), "%s_IV_BAD", type); + cp = lbuf; + goto common; + + default: + snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[2]); + cp = lbuf; + common: + for (; (buflen > 0) && (*buf = *cp++); buf++) + buflen--; + for (i = 3; i < cnt; i++) { + snprintf(lbuf, sizeof(lbuf), " %d", data[i]); + for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) + buflen--; + } + break; + } +} + +void cfb64_printsub(unsigned char *data, int cnt, + unsigned char *buf, int buflen) +{ + fb64_printsub(data, cnt, buf, buflen, "CFB64"); +} + +void ofb64_printsub(unsigned char *data, int cnt, + unsigned char *buf, int buflen) +{ + fb64_printsub(data, cnt, buf, buflen, "OFB64"); +} + +void fb64_stream_iv(des_cblock seed, struct stinfo *stp) +{ + + memcpy(stp->str_iv, seed,sizeof(des_cblock)); + memcpy(stp->str_output, seed, sizeof(des_cblock)); + + des_key_sched(&stp->str_ikey, stp->str_sched); + + stp->str_index = sizeof(des_cblock); +} + +void fb64_stream_key(des_cblock key, struct stinfo *stp) +{ + memcpy(stp->str_ikey, key, sizeof(des_cblock)); + des_key_sched((des_cblock*)key, stp->str_sched); + + memcpy(stp->str_output, stp->str_iv, sizeof(des_cblock)); + + stp->str_index = sizeof(des_cblock); +} + +/* + * DES 64 bit Cipher Feedback + * + * key --->+-----+ + * +->| DES |--+ + * | +-----+ | + * | v + * INPUT --(--------->(+)+---> DATA + * | | + * +-------------+ + * + * + * Given: + * iV: Initial vector, 64 bits (8 bytes) long. + * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). + * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. + * + * V0 = DES(iV, key) + * On = Dn ^ Vn + * V(n+1) = DES(On, key) + */ + +void cfb64_encrypt(unsigned char *s, int c) +{ + struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; + int index; + + index = stp->str_index; + while (c-- > 0) { + if (index == sizeof(des_cblock)) { + des_cblock b; + des_ecb_encrypt(&stp->str_output, &b,stp->str_sched, 1); + memcpy(stp->str_feed, b, sizeof(des_cblock)); + index = 0; + } + + /* On encryption, we store (feed ^ data) which is cypher */ + *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); + s++; + index++; + } + stp->str_index = index; +} + +int cfb64_decrypt(int data) +{ + struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; + int index; + + if (data == -1) { + /* + * Back up one byte. It is assumed that we will + * never back up more than one byte. If we do, this + * may or may not work. + */ + if (stp->str_index) + --stp->str_index; + return(0); + } + + index = stp->str_index++; + if (index == sizeof(des_cblock)) { + des_cblock b; + des_ecb_encrypt(&stp->str_output,&b, stp->str_sched, 1); + memcpy(stp->str_feed, b, sizeof(des_cblock)); + stp->str_index = 1; /* Next time will be 1 */ + index = 0; /* But now use 0 */ + } + + /* On decryption we store (data) which is cypher. */ + stp->str_output[index] = data; + return(data ^ stp->str_feed[index]); +} + +/* + * DES 64 bit Output Feedback + * + * key --->+-----+ + * +->| DES |--+ + * | +-----+ | + * +-----------+ + * v + * INPUT -------->(+) ----> DATA + * + * Given: + * iV: Initial vector, 64 bits (8 bytes) long. + * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). + * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. + * + * V0 = DES(iV, key) + * V(n+1) = DES(Vn, key) + * On = Dn ^ Vn + */ + +void ofb64_encrypt(unsigned char *s, int c) +{ + struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; + int index; + + index = stp->str_index; + while (c-- > 0) { + if (index == sizeof(des_cblock)) { + des_cblock b; + des_ecb_encrypt(&stp->str_feed,&b, stp->str_sched, 1); + memcpy(stp->str_feed, b, sizeof(des_cblock)); + index = 0; + } + *s++ ^= stp->str_feed[index]; + index++; + } + stp->str_index = index; +} + +int ofb64_decrypt(int data) +{ + struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; + int index; + + if (data == -1) { + /* + * Back up one byte. It is assumed that we will + * never back up more than one byte. If we do, this + * may or may not work. + */ + if (stp->str_index) + --stp->str_index; + return(0); + } + + index = stp->str_index++; + if (index == sizeof(des_cblock)) { + des_cblock b; + des_ecb_encrypt(&stp->str_feed,&b,stp->str_sched, 1); + memcpy(stp->str_feed, b, sizeof(des_cblock)); + stp->str_index = 1; /* Next time will be 1 */ + index = 0; /* But now use 0 */ + } + + return(data ^ stp->str_feed[index]); +} +#endif + diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.c b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.c new file mode 100644 index 0000000..21f7a85 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.c @@ -0,0 +1,995 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + + +#include <config.h> + +RCSID("$Id: encrypt.c,v 1.21 1998/07/09 23:16:25 assar Exp $"); + +#if defined(ENCRYPTION) + +#define ENCRYPT_NAMES +#include <arpa/telnet.h> + +#include "encrypt.h" +#include "misc.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <roken.h> +#ifdef SOCKS +#include <socks.h> +#endif + + +/* + * These functions pointers point to the current routines + * for encrypting and decrypting data. + */ +void (*encrypt_output) (unsigned char *, int); +int (*decrypt_input) (int); +char *nclearto; + +int encrypt_debug_mode = 0; +static int decrypt_mode = 0; +static int encrypt_mode = 0; +static int encrypt_verbose = 0; +static int autoencrypt = 0; +static int autodecrypt = 0; +static int havesessionkey = 0; +static int Server = 0; +static char *Name = "Noname"; + +#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) + +static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64) + | typemask(ENCTYPE_DES_OFB64); + static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64) + | typemask(ENCTYPE_DES_OFB64); + static long i_wont_support_encrypt = 0; + static long i_wont_support_decrypt = 0; +#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) +#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) + + static long remote_supports_encrypt = 0; + static long remote_supports_decrypt = 0; + + static Encryptions encryptions[] = { +#if defined(DES_ENCRYPTION) + { "DES_CFB64", ENCTYPE_DES_CFB64, + cfb64_encrypt, + cfb64_decrypt, + cfb64_init, + cfb64_start, + cfb64_is, + cfb64_reply, + cfb64_session, + cfb64_keyid, + cfb64_printsub }, + { "DES_OFB64", ENCTYPE_DES_OFB64, + ofb64_encrypt, + ofb64_decrypt, + ofb64_init, + ofb64_start, + ofb64_is, + ofb64_reply, + ofb64_session, + ofb64_keyid, + ofb64_printsub }, +#endif + { 0, }, + }; + +static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, + ENCRYPT_SUPPORT }; +static unsigned char str_suplen = 0; +static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; +static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; + +Encryptions * +findencryption(int type) +{ + Encryptions *ep = encryptions; + + if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) + return(0); + while (ep->type && ep->type != type) + ++ep; + return(ep->type ? ep : 0); +} + +Encryptions * +finddecryption(int type) +{ + Encryptions *ep = encryptions; + + if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) + return(0); + while (ep->type && ep->type != type) + ++ep; + return(ep->type ? ep : 0); +} + +#define MAXKEYLEN 64 + +static struct key_info { + unsigned char keyid[MAXKEYLEN]; + int keylen; + int dir; + int *modep; + Encryptions *(*getcrypt)(); +} ki[2] = { + { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, + { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, +}; + +void +encrypt_init(char *name, int server) +{ + Encryptions *ep = encryptions; + + Name = name; + Server = server; + i_support_encrypt = i_support_decrypt = 0; + remote_supports_encrypt = remote_supports_decrypt = 0; + encrypt_mode = 0; + decrypt_mode = 0; + encrypt_output = 0; + decrypt_input = 0; +#ifdef notdef + encrypt_verbose = !server; +#endif + + str_suplen = 4; + + while (ep->type) { + if (encrypt_debug_mode) + printf(">>>%s: I will support %s\r\n", + Name, ENCTYPE_NAME(ep->type)); + i_support_encrypt |= typemask(ep->type); + i_support_decrypt |= typemask(ep->type); + if ((i_wont_support_decrypt & typemask(ep->type)) == 0) + if ((str_send[str_suplen++] = ep->type) == IAC) + str_send[str_suplen++] = IAC; + if (ep->init) + (*ep->init)(Server); + ++ep; + } + str_send[str_suplen++] = IAC; + str_send[str_suplen++] = SE; +} + +void +encrypt_list_types(void) +{ + Encryptions *ep = encryptions; + + printf("Valid encryption types:\n"); + while (ep->type) { + printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type); + ++ep; + } +} + +int +EncryptEnable(char *type, char *mode) +{ + if (isprefix(type, "help") || isprefix(type, "?")) { + printf("Usage: encrypt enable <type> [input|output]\n"); + encrypt_list_types(); + return(0); + } + if (EncryptType(type, mode)) + return(EncryptStart(mode)); + return(0); +} + +int +EncryptDisable(char *type, char *mode) +{ + Encryptions *ep; + int ret = 0; + + if (isprefix(type, "help") || isprefix(type, "?")) { + printf("Usage: encrypt disable <type> [input|output]\n"); + encrypt_list_types(); + } else if ((ep = (Encryptions *)genget(type, (char**)encryptions, + sizeof(Encryptions))) == 0) { + printf("%s: invalid encryption type\n", type); + } else if (Ambiguous(ep)) { + printf("Ambiguous type '%s'\n", type); + } else { + if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { + if (decrypt_mode == ep->type) + EncryptStopInput(); + i_wont_support_decrypt |= typemask(ep->type); + ret = 1; + } + if ((mode == 0) || (isprefix(mode, "output"))) { + if (encrypt_mode == ep->type) + EncryptStopOutput(); + i_wont_support_encrypt |= typemask(ep->type); + ret = 1; + } + if (ret == 0) + printf("%s: invalid encryption mode\n", mode); + } + return(ret); +} + +int +EncryptType(char *type, char *mode) +{ + Encryptions *ep; + int ret = 0; + + if (isprefix(type, "help") || isprefix(type, "?")) { + printf("Usage: encrypt type <type> [input|output]\n"); + encrypt_list_types(); + } else if ((ep = (Encryptions *)genget(type, (char**)encryptions, + sizeof(Encryptions))) == 0) { + printf("%s: invalid encryption type\n", type); + } else if (Ambiguous(ep)) { + printf("Ambiguous type '%s'\n", type); + } else { + if ((mode == 0) || isprefix(mode, "input")) { + decrypt_mode = ep->type; + i_wont_support_decrypt &= ~typemask(ep->type); + ret = 1; + } + if ((mode == 0) || isprefix(mode, "output")) { + encrypt_mode = ep->type; + i_wont_support_encrypt &= ~typemask(ep->type); + ret = 1; + } + if (ret == 0) + printf("%s: invalid encryption mode\n", mode); + } + return(ret); +} + +int +EncryptStart(char *mode) +{ + int ret = 0; + if (mode) { + if (isprefix(mode, "input")) + return(EncryptStartInput()); + if (isprefix(mode, "output")) + return(EncryptStartOutput()); + if (isprefix(mode, "help") || isprefix(mode, "?")) { + printf("Usage: encrypt start [input|output]\n"); + return(0); + } + printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode); + return(0); + } + ret += EncryptStartInput(); + ret += EncryptStartOutput(); + return(ret); +} + +int +EncryptStartInput(void) +{ + if (decrypt_mode) { + encrypt_send_request_start(); + return(1); + } + printf("No previous decryption mode, decryption not enabled\r\n"); + return(0); +} + +int +EncryptStartOutput(void) +{ + if (encrypt_mode) { + encrypt_start_output(encrypt_mode); + return(1); + } + printf("No previous encryption mode, encryption not enabled\r\n"); + return(0); +} + +int +EncryptStop(char *mode) +{ + int ret = 0; + if (mode) { + if (isprefix(mode, "input")) + return(EncryptStopInput()); + if (isprefix(mode, "output")) + return(EncryptStopOutput()); + if (isprefix(mode, "help") || isprefix(mode, "?")) { + printf("Usage: encrypt stop [input|output]\n"); + return(0); + } + printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode); + return(0); + } + ret += EncryptStopInput(); + ret += EncryptStopOutput(); + return(ret); +} + +int +EncryptStopInput(void) +{ + encrypt_send_request_end(); + return(1); +} + +int +EncryptStopOutput(void) +{ + encrypt_send_end(); + return(1); +} + +void +encrypt_display(void) +{ + printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n", + autoencrypt?"on":"off", autodecrypt?"on":"off"); + + if (encrypt_output) + printf("Currently encrypting output with %s\r\n", + ENCTYPE_NAME(encrypt_mode)); + else + printf("Currently not encrypting output\r\n"); + + if (decrypt_input) + printf("Currently decrypting input with %s\r\n", + ENCTYPE_NAME(decrypt_mode)); + else + printf("Currently not decrypting input\r\n"); +} + +int +EncryptStatus(void) +{ + printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n", + autoencrypt?"on":"off", autodecrypt?"on":"off"); + + if (encrypt_output) + printf("Currently encrypting output with %s\r\n", + ENCTYPE_NAME(encrypt_mode)); + else if (encrypt_mode) { + printf("Currently output is clear text.\r\n"); + printf("Last encryption mode was %s\r\n", + ENCTYPE_NAME(encrypt_mode)); + } else + printf("Currently not encrypting output\r\n"); + + if (decrypt_input) { + printf("Currently decrypting input with %s\r\n", + ENCTYPE_NAME(decrypt_mode)); + } else if (decrypt_mode) { + printf("Currently input is clear text.\r\n"); + printf("Last decryption mode was %s\r\n", + ENCTYPE_NAME(decrypt_mode)); + } else + printf("Currently not decrypting input\r\n"); + + return 1; +} + +void +encrypt_send_support(void) +{ + if (str_suplen) { + /* + * If the user has requested that decryption start + * immediatly, then send a "REQUEST START" before + * we negotiate the type. + */ + if (!Server && autodecrypt) + encrypt_send_request_start(); + telnet_net_write(str_send, str_suplen); + printsub('>', &str_send[2], str_suplen - 2); + str_suplen = 0; + } +} + +int +EncryptDebug(int on) +{ + if (on < 0) + encrypt_debug_mode ^= 1; + else + encrypt_debug_mode = on; + printf("Encryption debugging %s\r\n", + encrypt_debug_mode ? "enabled" : "disabled"); + return(1); +} + +/* turn on verbose encryption, but dont keep telling the whole world + */ +void encrypt_verbose_quiet(int on) +{ + if(on < 0) + encrypt_verbose ^= 1; + else + encrypt_verbose = on ? 1 : 0; +} + +int +EncryptVerbose(int on) +{ + encrypt_verbose_quiet(on); + printf("Encryption %s verbose\r\n", + encrypt_verbose ? "is" : "is not"); + return(1); +} + +int +EncryptAutoEnc(int on) +{ + encrypt_auto(on); + printf("Automatic encryption of output is %s\r\n", + autoencrypt ? "enabled" : "disabled"); + return(1); +} + +int +EncryptAutoDec(int on) +{ + decrypt_auto(on); + printf("Automatic decryption of input is %s\r\n", + autodecrypt ? "enabled" : "disabled"); + return(1); +} + +/* Called when we receive a WONT or a DONT ENCRYPT after we sent a DO + encrypt */ +void +encrypt_not(void) +{ + if (encrypt_verbose) + printf("[ Connection is NOT encrypted ]\r\n"); + else + printf("\r\n*** Connection not encrypted! " + "Communication may be eavesdropped. ***\r\n"); +} + +/* + * Called when ENCRYPT SUPPORT is received. + */ +void +encrypt_support(unsigned char *typelist, int cnt) +{ + int type, use_type = 0; + Encryptions *ep; + + /* + * Forget anything the other side has previously told us. + */ + remote_supports_decrypt = 0; + + while (cnt-- > 0) { + type = *typelist++; + if (encrypt_debug_mode) + printf(">>>%s: He is supporting %s (%d)\r\n", + Name, + ENCTYPE_NAME(type), type); + if ((type < ENCTYPE_CNT) && + (I_SUPPORT_ENCRYPT & typemask(type))) { + remote_supports_decrypt |= typemask(type); + if (use_type == 0) + use_type = type; + } + } + if (use_type) { + ep = findencryption(use_type); + if (!ep) + return; + type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0; + if (encrypt_debug_mode) + printf(">>>%s: (*ep->start)() returned %d\r\n", + Name, type); + if (type < 0) + return; + encrypt_mode = use_type; + if (type == 0) + encrypt_start_output(use_type); + } +} + +void +encrypt_is(unsigned char *data, int cnt) +{ + Encryptions *ep; + int type, ret; + + if (--cnt < 0) + return; + type = *data++; + if (type < ENCTYPE_CNT) + remote_supports_encrypt |= typemask(type); + if (!(ep = finddecryption(type))) { + if (encrypt_debug_mode) + printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", + Name, + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + return; + } + if (!ep->is) { + if (encrypt_debug_mode) + printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", + Name, + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + ret = 0; + } else { + ret = (*ep->is)(data, cnt); + if (encrypt_debug_mode) + printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt, + (ret < 0) ? "FAIL " : + (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); + } + if (ret < 0) { + autodecrypt = 0; + } else { + decrypt_mode = type; + if (ret == 0 && autodecrypt) + encrypt_send_request_start(); + } +} + +void +encrypt_reply(unsigned char *data, int cnt) +{ + Encryptions *ep; + int ret, type; + + if (--cnt < 0) + return; + type = *data++; + if (!(ep = findencryption(type))) { + if (encrypt_debug_mode) + printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", + Name, + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + return; + } + if (!ep->reply) { + if (encrypt_debug_mode) + printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", + Name, + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + ret = 0; + } else { + ret = (*ep->reply)(data, cnt); + if (encrypt_debug_mode) + printf("(*ep->reply)(%p, %d) returned %s(%d)\n", + data, cnt, + (ret < 0) ? "FAIL " : + (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); + } + if (encrypt_debug_mode) + printf(">>>%s: encrypt_reply returned %d\n", Name, ret); + if (ret < 0) { + autoencrypt = 0; + } else { + encrypt_mode = type; + if (ret == 0 && autoencrypt) + encrypt_start_output(type); + } +} + +/* + * Called when a ENCRYPT START command is received. + */ +void +encrypt_start(unsigned char *data, int cnt) +{ + Encryptions *ep; + + if (!decrypt_mode) { + /* + * Something is wrong. We should not get a START + * command without having already picked our + * decryption scheme. Send a REQUEST-END to + * attempt to clear the channel... + */ + printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); + encrypt_send_request_end(); + return; + } + + if ((ep = finddecryption(decrypt_mode))) { + decrypt_input = ep->input; + if (encrypt_verbose) + printf("[ Input is now decrypted with type %s ]\r\n", + ENCTYPE_NAME(decrypt_mode)); + if (encrypt_debug_mode) + printf(">>>%s: Start to decrypt input with type %s\r\n", + Name, ENCTYPE_NAME(decrypt_mode)); + } else { + printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", + Name, + ENCTYPE_NAME_OK(decrypt_mode) + ? ENCTYPE_NAME(decrypt_mode) + : "(unknown)", + decrypt_mode); + encrypt_send_request_end(); + } +} + +void +encrypt_session_key(Session_Key *key, int server) +{ + Encryptions *ep = encryptions; + + havesessionkey = 1; + + while (ep->type) { + if (ep->session) + (*ep->session)(key, server); + ++ep; + } +} + +/* + * Called when ENCRYPT END is received. + */ +void +encrypt_end(void) +{ + decrypt_input = 0; + if (encrypt_debug_mode) + printf(">>>%s: Input is back to clear text\r\n", Name); + if (encrypt_verbose) + printf("[ Input is now clear text ]\r\n"); +} + +/* + * Called when ENCRYPT REQUEST-END is received. + */ +void +encrypt_request_end(void) +{ + encrypt_send_end(); +} + +/* + * Called when ENCRYPT REQUEST-START is received. If we receive + * this before a type is picked, then that indicates that the + * other side wants us to start encrypting data as soon as we + * can. + */ +void +encrypt_request_start(unsigned char *data, int cnt) +{ + if (encrypt_mode == 0) { + if (Server) + autoencrypt = 1; + return; + } + encrypt_start_output(encrypt_mode); +} + +static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; + +static void +encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len) +{ + Encryptions *ep; + int dir = kp->dir; + int ret = 0; + + if (!(ep = (*kp->getcrypt)(*kp->modep))) { + if (len == 0) + return; + kp->keylen = 0; + } else if (len == 0) { + /* + * Empty option, indicates a failure. + */ + if (kp->keylen == 0) + return; + kp->keylen = 0; + if (ep->keyid) + (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); + + } else if ((len != kp->keylen) || (memcmp(keyid,kp->keyid,len) != 0)) { + /* + * Length or contents are different + */ + kp->keylen = len; + memcpy(kp->keyid,keyid, len); + if (ep->keyid) + (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); + } else { + if (ep->keyid) + ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); + if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) + encrypt_start_output(*kp->modep); + return; + } + + encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); +} + +void encrypt_enc_keyid(unsigned char *keyid, int len) +{ + encrypt_keyid(&ki[1], keyid, len); +} + +void encrypt_dec_keyid(unsigned char *keyid, int len) +{ + encrypt_keyid(&ki[0], keyid, len); +} + + +void encrypt_send_keyid(int dir, unsigned char *keyid, int keylen, int saveit) +{ + unsigned char *strp; + + str_keyid[3] = (dir == DIR_ENCRYPT) + ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; + if (saveit) { + struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; + memcpy(kp->keyid,keyid, keylen); + kp->keylen = keylen; + } + + for (strp = &str_keyid[4]; keylen > 0; --keylen) { + if ((*strp++ = *keyid++) == IAC) + *strp++ = IAC; + } + *strp++ = IAC; + *strp++ = SE; + telnet_net_write(str_keyid, strp - str_keyid); + printsub('>', &str_keyid[2], strp - str_keyid - 2); +} + +void +encrypt_auto(int on) +{ + if (on < 0) + autoencrypt ^= 1; + else + autoencrypt = on ? 1 : 0; +} + +void +decrypt_auto(int on) +{ + if (on < 0) + autodecrypt ^= 1; + else + autodecrypt = on ? 1 : 0; +} + +void +encrypt_start_output(int type) +{ + Encryptions *ep; + unsigned char *p; + int i; + + if (!(ep = findencryption(type))) { + if (encrypt_debug_mode) { + printf(">>>%s: Can't encrypt with type %s (%d)\r\n", + Name, + ENCTYPE_NAME_OK(type) + ? ENCTYPE_NAME(type) : "(unknown)", + type); + } + return; + } + if (ep->start) { + i = (*ep->start)(DIR_ENCRYPT, Server); + if (encrypt_debug_mode) { + printf(">>>%s: Encrypt start: %s (%d) %s\r\n", + Name, + (i < 0) ? "failed" : + "initial negotiation in progress", + i, ENCTYPE_NAME(type)); + } + if (i) + return; + } + p = str_start + 3; + *p++ = ENCRYPT_START; + for (i = 0; i < ki[0].keylen; ++i) { + if ((*p++ = ki[0].keyid[i]) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + telnet_net_write(str_start, p - str_start); + net_encrypt(); + printsub('>', &str_start[2], p - &str_start[2]); + /* + * If we are already encrypting in some mode, then + * encrypt the ring (which includes our request) in + * the old mode, mark it all as "clear text" and then + * switch to the new mode. + */ + encrypt_output = ep->output; + encrypt_mode = type; + if (encrypt_debug_mode) + printf(">>>%s: Started to encrypt output with type %s\r\n", + Name, ENCTYPE_NAME(type)); + if (encrypt_verbose) + printf("[ Output is now encrypted with type %s ]\r\n", + ENCTYPE_NAME(type)); +} + +void +encrypt_send_end(void) +{ + if (!encrypt_output) + return; + + str_end[3] = ENCRYPT_END; + telnet_net_write(str_end, sizeof(str_end)); + net_encrypt(); + printsub('>', &str_end[2], sizeof(str_end) - 2); + /* + * Encrypt the output buffer now because it will not be done by + * netflush... + */ + encrypt_output = 0; + if (encrypt_debug_mode) + printf(">>>%s: Output is back to clear text\r\n", Name); + if (encrypt_verbose) + printf("[ Output is now clear text ]\r\n"); +} + +void +encrypt_send_request_start(void) +{ + unsigned char *p; + int i; + + p = &str_start[3]; + *p++ = ENCRYPT_REQSTART; + for (i = 0; i < ki[1].keylen; ++i) { + if ((*p++ = ki[1].keyid[i]) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + telnet_net_write(str_start, p - str_start); + printsub('>', &str_start[2], p - &str_start[2]); + if (encrypt_debug_mode) + printf(">>>%s: Request input to be encrypted\r\n", Name); +} + +void +encrypt_send_request_end(void) +{ + str_end[3] = ENCRYPT_REQEND; + telnet_net_write(str_end, sizeof(str_end)); + printsub('>', &str_end[2], sizeof(str_end) - 2); + + if (encrypt_debug_mode) + printf(">>>%s: Request input to be clear text\r\n", Name); +} + + +void encrypt_wait(void) +{ + if (encrypt_debug_mode) + printf(">>>%s: in encrypt_wait\r\n", Name); + if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt)) + return; + while (autoencrypt && !encrypt_output) + if (telnet_spin()) + return; +} + +int +encrypt_delay(void) +{ + if(!havesessionkey || + (I_SUPPORT_ENCRYPT & remote_supports_decrypt) == 0 || + (I_SUPPORT_DECRYPT & remote_supports_encrypt) == 0) + return 0; + if(!(encrypt_output && decrypt_input)) + return 1; + return 0; +} + +void +encrypt_debug(int mode) +{ + encrypt_debug_mode = mode; +} + +void encrypt_gen_printsub(unsigned char *data, int cnt, + unsigned char *buf, int buflen) +{ + char tbuf[16], *cp; + + cnt -= 2; + data += 2; + buf[buflen-1] = '\0'; + buf[buflen-2] = '*'; + buflen -= 2;; + for (; cnt > 0; cnt--, data++) { + snprintf(tbuf, sizeof(tbuf), " %d", *data); + for (cp = tbuf; *cp && buflen > 0; --buflen) + *buf++ = *cp++; + if (buflen <= 0) + return; + } + *buf = '\0'; +} + +void +encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) +{ + Encryptions *ep; + int type = data[1]; + + for (ep = encryptions; ep->type && ep->type != type; ep++) + ; + + if (ep->printsub) + (*ep->printsub)(data, cnt, buf, buflen); + else + encrypt_gen_printsub(data, cnt, buf, buflen); +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.h b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.h new file mode 100644 index 0000000..5919db5 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/encrypt.h @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)encrypt.h 8.1 (Berkeley) 6/4/93 + * + * @(#)encrypt.h 5.2 (Berkeley) 3/22/91 + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* $Id: encrypt.h,v 1.4 1997/01/24 23:10:56 assar Exp $ */ + +#ifndef __ENCRYPT__ +#define __ENCRYPT__ + +#define DIR_DECRYPT 1 +#define DIR_ENCRYPT 2 + +#define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \ + key[4] | key[5] | key[6] | key[7]) + +#define SAMEKEY(k1, k2) (!memcmp(k1, k2, sizeof(des_cblock))) + +typedef struct { + short type; + int length; + unsigned char *data; +} Session_Key; + +typedef struct { + char *name; + int type; + void (*output) (unsigned char *, int); + int (*input) (int); + void (*init) (int); + int (*start) (int, int); + int (*is) (unsigned char *, int); + int (*reply) (unsigned char *, int); + void (*session) (Session_Key *, int); + int (*keyid) (int, unsigned char *, int *); + void (*printsub) (unsigned char *, int, unsigned char *, int); +} Encryptions; + +#define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */ + +#include "enc-proto.h" + +extern int encrypt_debug_mode; +extern int (*decrypt_input) (int); +extern void (*encrypt_output) (unsigned char *, int); +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/genget.c b/crypto/kerberosIV/appl/telnet/libtelnet/genget.c new file mode 100644 index 0000000..c17a7bd --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/genget.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> +#include "misc-proto.h" + +RCSID("$Id: genget.c,v 1.6 1997/05/04 09:01:34 assar Exp $"); + +#include <ctype.h> + +#define LOWER(x) (isupper(x) ? tolower(x) : (x)) +/* + * The prefix function returns 0 if *s1 is not a prefix + * of *s2. If *s1 exactly matches *s2, the negative of + * the length is returned. If *s1 is a prefix of *s2, + * the length of *s1 is returned. + */ + +int +isprefix(char *s1, char *s2) +{ + char *os1; + char c1, c2; + + if (*s1 == '\0') + return(-1); + os1 = s1; + c1 = *s1; + c2 = *s2; + while (LOWER(c1) == LOWER(c2)) { + if (c1 == '\0') + break; + c1 = *++s1; + c2 = *++s2; + } + return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); +} + +static char *ambiguous; /* special return value for command routines */ + +char ** +genget(char *name, char **table, int stlen) + /* name to match */ + /* name entry in table */ + +{ + char **c, **found; + int n; + + if (name == 0) + return 0; + + found = 0; + for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { + if ((n = isprefix(name, *c)) == 0) + continue; + if (n < 0) /* exact match */ + return(c); + if (found) + return(&ambiguous); + found = c; + } + return(found); +} + +/* + * Function call version of Ambiguous() + */ +int +Ambiguous(void *s) +{ + return((char **)s == &ambiguous); +} diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c new file mode 100644 index 0000000..b5c0953 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos.c @@ -0,0 +1,717 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +RCSID("$Id: kerberos.c,v 1.45 1999/03/13 21:18:55 assar Exp $"); + +#ifdef KRB4 +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif +#include <stdio.h> +#include <des.h> /* BSD wont include this in krb.h, so we do it here */ +#include <krb.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <roken.h> +#ifdef SOCKS +#include <socks.h> +#endif + + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +int kerberos4_cksum (unsigned char *, int); +extern int auth_debug_mode; + +static unsigned char str_data[2048] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_KERBEROS_V4, }; + +#define KRB_AUTH 0 /* Authentication data follows */ +#define KRB_REJECT 1 /* Rejected (reason might follow) */ +#define KRB_ACCEPT 2 /* Accepted */ +#define KRB_CHALLENGE 3 /* Challenge for mutual auth. */ +#define KRB_RESPONSE 4 /* Response for mutual auth. */ + +#define KRB_FORWARD 5 /* */ +#define KRB_FORWARD_ACCEPT 6 /* */ +#define KRB_FORWARD_REJECT 7 /* */ + +#define KRB_SERVICE_NAME "rcmd" + +static KTEXT_ST auth; +static char name[ANAME_SZ]; +static AUTH_DAT adat; +static des_cblock session_key; +static des_cblock cred_session; +static des_key_schedule sched; +static des_cblock challenge; +static int auth_done; /* XXX */ + +static int pack_cred(CREDENTIALS *cred, unsigned char *buf); +static int unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred); + + +static int +Data(Authenticator *ap, int type, const void *d, int c) +{ + unsigned char *p = str_data + 4; + const unsigned char *cd = (const unsigned char *)d; + + if (c == -1) + c = strlen((const char *)cd); + + if (auth_debug_mode) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - (&str_data[2])); + return(telnet_net_write(str_data, p - str_data)); +} + +int +kerberos4_init(Authenticator *ap, int server) +{ + FILE *fp; + + if (server) { + str_data[3] = TELQUAL_REPLY; + if ((fp = fopen(KEYFILE, "r")) == NULL) + return(0); + fclose(fp); + } else { + str_data[3] = TELQUAL_IS; + } + return(1); +} + +char dst_realm_buf[REALM_SZ], *dest_realm = NULL; +int dst_realm_sz = REALM_SZ; + +static int +kerberos4_send(char *name, Authenticator *ap) +{ + KTEXT_ST auth; + char instance[INST_SZ]; + char *realm; + CREDENTIALS cred; + int r; + + printf("[ Trying %s ... ]\r\n", name); + if (!UserNameRequested) { + if (auth_debug_mode) { + printf("Kerberos V4: no user name supplied\r\n"); + } + return(0); + } + + memset(instance, 0, sizeof(instance)); + + strcpy_truncate (instance, + krb_get_phost(RemoteHostName), + INST_SZ); + + realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName); + + if (!realm) { + printf("Kerberos V4: no realm for %s\r\n", RemoteHostName); + return(0); + } + r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L); + if (r) { + printf("mk_req failed: %s\r\n", krb_get_err_text(r)); + return(0); + } + r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred); + if (r) { + printf("get_cred failed: %s\r\n", krb_get_err_text(r)); + return(0); + } + if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + if (auth_debug_mode) + printf("Not enough room for user name\r\n"); + return(0); + } + if (auth_debug_mode) + printf("Sent %d bytes of authentication data\r\n", auth.length); + if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + return(0); + } +#ifdef ENCRYPTION + /* create challenge */ + if ((ap->way & AUTH_HOW_MASK)==AUTH_HOW_MUTUAL) { + int i; + + des_key_sched(&cred.session, sched); + memcpy (&cred_session, &cred.session, sizeof(cred_session)); + des_init_random_number_generator(&cred.session); + des_new_random_key(&session_key); + des_ecb_encrypt(&session_key, &session_key, sched, 0); + des_ecb_encrypt(&session_key, &challenge, sched, 0); + + /* + old code + Some CERT Advisory thinks this is a bad thing... + + des_init_random_number_generator(&cred.session); + des_new_random_key(&challenge); + des_ecb_encrypt(&challenge, &session_key, sched, 1); + */ + + /* + * Increment the challenge by 1, and encrypt it for + * later comparison. + */ + for (i = 7; i >= 0; --i) + if(++challenge[i] != 0) /* No carry! */ + break; + des_ecb_encrypt(&challenge, &challenge, sched, 1); + } + +#endif + + if (auth_debug_mode) { + printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); + printd(auth.dat, auth.length); + printf("\r\n"); + printf("Sent Kerberos V4 credentials to server\r\n"); + } + return(1); +} +int +kerberos4_send_mutual(Authenticator *ap) +{ + return kerberos4_send("mutual KERBEROS4", ap); +} + +int +kerberos4_send_oneway(Authenticator *ap) +{ + return kerberos4_send("KERBEROS4", ap); +} + +void +kerberos4_is(Authenticator *ap, unsigned char *data, int cnt) +{ + struct sockaddr_in addr; + char realm[REALM_SZ]; + char instance[INST_SZ]; + int r; + int addr_len; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_AUTH: + if (krb_get_lrealm(realm, 1) != KSUCCESS) { + Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("No local realm\r\n"); + return; + } + memmove(auth.dat, data, auth.length = cnt); + if (auth_debug_mode) { + printf("Got %d bytes of authentication data\r\n", cnt); + printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); + printd(auth.dat, auth.length); + printf("\r\n"); + } + k_getsockinst(0, instance, sizeof(instance)); + addr_len = sizeof(addr); + if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) { + if(auth_debug_mode) + printf("getpeername failed\r\n"); + Data(ap, KRB_REJECT, "getpeername failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + if (addr.sin_family != AF_INET) { + if (auth_debug_mode) + printf("unknown address family: %d\r\n", addr.sin_family); + Data(ap, KRB_REJECT, "bad address family", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + r = krb_rd_req(&auth, KRB_SERVICE_NAME, + instance, addr.sin_addr.s_addr, &adat, ""); + if (r) { + if (auth_debug_mode) + printf("Kerberos failed him as %s\r\n", name); + Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1); + auth_finished(ap, AUTH_REJECT); + return; + } + /* save the session key */ + memmove(session_key, adat.session, sizeof(adat.session)); + krb_kntoln(&adat, name); + + if (UserNameRequested && !kuserok(&adat, UserNameRequested)){ + char ts[MaxPathLen]; + struct passwd *pw = getpwnam(UserNameRequested); + + if(pw){ + snprintf(ts, sizeof(ts), + "%s%u", + TKT_ROOT, + (unsigned)pw->pw_uid); + setenv("KRBTKFILE", ts, 1); + + if (pw->pw_uid == 0) + syslog(LOG_INFO|LOG_AUTH, + "ROOT Kerberos login from %s on %s\n", + krb_unparse_name_long(adat.pname, + adat.pinst, + adat.prealm), + RemoteHostName); + } + Data(ap, KRB_ACCEPT, NULL, 0); + } else { + char *msg; + + asprintf (&msg, "user `%s' is not authorized to " + "login as `%s'", + krb_unparse_name_long(adat.pname, + adat.pinst, + adat.prealm), + UserNameRequested ? UserNameRequested : "<nobody>"); + if (msg == NULL) + Data(ap, KRB_REJECT, NULL, 0); + else { + Data(ap, KRB_REJECT, (void *)msg, -1); + free(msg); + } + } + auth_finished(ap, AUTH_USER); + break; + + case KRB_CHALLENGE: +#ifndef ENCRYPTION + Data(ap, KRB_RESPONSE, NULL, 0); +#else + if(!VALIDKEY(session_key)){ + Data(ap, KRB_RESPONSE, NULL, 0); + break; + } + des_key_sched(&session_key, sched); + { + des_cblock d_block; + int i; + Session_Key skey; + + memmove(d_block, data, sizeof(d_block)); + + /* make a session key for encryption */ + des_ecb_encrypt(&d_block, &session_key, sched, 1); + skey.type=SK_DES; + skey.length=8; + skey.data=session_key; + encrypt_session_key(&skey, 1); + + /* decrypt challenge, add one and encrypt it */ + des_ecb_encrypt(&d_block, &challenge, sched, 0); + for (i = 7; i >= 0; i--) + if(++challenge[i] != 0) + break; + des_ecb_encrypt(&challenge, &challenge, sched, 1); + Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge)); + } +#endif + break; + + case KRB_FORWARD: + { + des_key_schedule ks; + unsigned char netcred[sizeof(CREDENTIALS)]; + CREDENTIALS cred; + int ret; + if(cnt > sizeof(cred)) + abort(); + + memcpy (session_key, adat.session, sizeof(session_key)); + des_set_key(&session_key, ks); + des_pcbc_encrypt((void*)data, (void*)netcred, cnt, + ks, &session_key, DES_DECRYPT); + unpack_cred(netcred, cnt, &cred); + { + if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) || + strncmp(cred.instance, cred.realm, sizeof(cred.instance)) || + cred.lifetime < 0 || cred.lifetime > 255 || + cred.kvno < 0 || cred.kvno > 255 || + cred.issue_date < 0 || + cred.issue_date > time(0) + CLOCK_SKEW || + strncmp(cred.pname, adat.pname, sizeof(cred.pname)) || + strncmp(cred.pinst, adat.pinst, sizeof(cred.pinst))){ + Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1); + }else{ + if((ret = tf_setup(&cred, + cred.pname, + cred.pinst)) == KSUCCESS){ + struct passwd *pw = getpwnam(UserNameRequested); + + if (pw) + chown(tkt_string(), pw->pw_uid, pw->pw_gid); + Data(ap, KRB_FORWARD_ACCEPT, 0, 0); + } else{ + Data(ap, KRB_FORWARD_REJECT, + krb_get_err_text(ret), -1); + } + } + } + memset(data, 0, cnt); + memset(ks, 0, sizeof(ks)); + memset(&cred, 0, sizeof(cred)); + } + + break; + + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + Data(ap, KRB_REJECT, 0, 0); + break; + } +} + +void +kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt) +{ + Session_Key skey; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_REJECT: + if(auth_done){ /* XXX Ick! */ + printf("[ Kerberos V4 received unknown opcode ]\r\n"); + }else{ + printf("[ Kerberos V4 refuses authentication "); + if (cnt > 0) + printf("because %.*s ", cnt, data); + printf("]\r\n"); + auth_send_retry(); + } + return; + case KRB_ACCEPT: + printf("[ Kerberos V4 accepts you ]\r\n"); + auth_done = 1; + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* + * Send over the encrypted challenge. + */ + Data(ap, KRB_CHALLENGE, session_key, + sizeof(session_key)); + des_ecb_encrypt(&session_key, &session_key, sched, 1); + skey.type = SK_DES; + skey.length = 8; + skey.data = session_key; + encrypt_session_key(&skey, 0); +#if 0 + kerberos4_forward(ap, &cred_session); +#endif + return; + } + auth_finished(ap, AUTH_USER); + return; + case KRB_RESPONSE: + /* make sure the response is correct */ + if ((cnt != sizeof(des_cblock)) || + (memcmp(data, challenge, sizeof(challenge)))){ + printf("[ Kerberos V4 challenge failed!!! ]\r\n"); + auth_send_retry(); + return; + } + printf("[ Kerberos V4 challenge successful ]\r\n"); + auth_finished(ap, AUTH_USER); + break; + case KRB_FORWARD_ACCEPT: + printf("[ Kerberos V4 accepted forwarded credentials ]\r\n"); + break; + case KRB_FORWARD_REJECT: + printf("[ Kerberos V4 rejected forwarded credentials: `%.*s']\r\n", + cnt, data); + break; + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + return; + } +} + +int +kerberos4_status(Authenticator *ap, char *name, size_t name_sz, int level) +{ + if (level < AUTH_USER) + return(level); + + if (UserNameRequested && !kuserok(&adat, UserNameRequested)) { + strcpy_truncate(name, UserNameRequested, name_sz); + return(AUTH_VALID); + } else + return(AUTH_USER); +} + +#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} +#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} + +void +kerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) +{ + int i; + + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; + + switch(data[3]) { + case KRB_REJECT: /* Rejected (reason might follow) */ + strcpy_truncate((char *)buf, " REJECT ", buflen); + goto common; + + case KRB_ACCEPT: /* Accepted (name might follow) */ + strcpy_truncate((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; + + case KRB_AUTH: /* Authentication data follows */ + strcpy_truncate((char *)buf, " AUTH", buflen); + goto common2; + + case KRB_CHALLENGE: + strcpy_truncate((char *)buf, " CHALLENGE", buflen); + goto common2; + + case KRB_RESPONSE: + strcpy_truncate((char *)buf, " RESPONSE", buflen); + goto common2; + + default: + snprintf(buf, buflen, " %d (unknown)", data[3]); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + snprintf(buf, buflen, " %d", data[i]); + BUMP(buf, buflen); + } + break; + } +} + +int +kerberos4_cksum(unsigned char *d, int n) +{ + int ck = 0; + + /* + * A comment is probably needed here for those not + * well versed in the "C" language. Yes, this is + * supposed to be a "switch" with the body of the + * "switch" being a "while" statement. The whole + * purpose of the switch is to allow us to jump into + * the middle of the while() loop, and then not have + * to do any more switch()s. + * + * Some compilers will spit out a warning message + * about the loop not being entered at the top. + */ + switch (n&03) + while (n > 0) { + case 0: + ck ^= (int)*d++ << 24; + --n; + case 3: + ck ^= (int)*d++ << 16; + --n; + case 2: + ck ^= (int)*d++ << 8; + --n; + case 1: + ck ^= (int)*d++; + --n; + } + return(ck); +} + +static int +pack_cred(CREDENTIALS *cred, unsigned char *buf) +{ + unsigned char *p = buf; + + memcpy (p, cred->service, ANAME_SZ); + p += ANAME_SZ; + memcpy (p, cred->instance, INST_SZ); + p += INST_SZ; + memcpy (p, cred->realm, REALM_SZ); + p += REALM_SZ; + memcpy(p, cred->session, 8); + p += 8; + p += KRB_PUT_INT(cred->lifetime, p, 4, 4); + p += KRB_PUT_INT(cred->kvno, p, 4, 4); + p += KRB_PUT_INT(cred->ticket_st.length, p, 4, 4); + memcpy(p, cred->ticket_st.dat, cred->ticket_st.length); + p += cred->ticket_st.length; + p += KRB_PUT_INT(0, p, 4, 4); + p += KRB_PUT_INT(cred->issue_date, p, 4, 4); + memcpy (p, cred->pname, ANAME_SZ); + p += ANAME_SZ; + memcpy (p, cred->pinst, INST_SZ); + p += INST_SZ; + return p - buf; +} + +static int +unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred) +{ + unsigned char *p = buf; + u_int32_t tmp; + + strncpy (cred->service, p, ANAME_SZ); + cred->service[ANAME_SZ - 1] = '\0'; + p += ANAME_SZ; + strncpy (cred->instance, p, INST_SZ); + cred->instance[INST_SZ - 1] = '\0'; + p += INST_SZ; + strncpy (cred->realm, p, REALM_SZ); + cred->realm[REALM_SZ - 1] = '\0'; + p += REALM_SZ; + + memcpy(cred->session, p, 8); + p += 8; + p += krb_get_int(p, &tmp, 4, 0); + cred->lifetime = tmp; + p += krb_get_int(p, &tmp, 4, 0); + cred->kvno = tmp; + + p += krb_get_int(p, &cred->ticket_st.length, 4, 0); + memcpy(cred->ticket_st.dat, p, cred->ticket_st.length); + p += cred->ticket_st.length; + p += krb_get_int(p, &tmp, 4, 0); + cred->ticket_st.mbz = 0; + p += krb_get_int(p, (u_int32_t *)&cred->issue_date, 4, 0); + + strncpy (cred->pname, p, ANAME_SZ); + cred->pname[ANAME_SZ - 1] = '\0'; + p += ANAME_SZ; + strncpy (cred->pinst, p, INST_SZ); + cred->pinst[INST_SZ - 1] = '\0'; + p += INST_SZ; + return 0; +} + + +int +kerberos4_forward(Authenticator *ap, void *v) +{ + des_cblock *key = (des_cblock *)v; + CREDENTIALS cred; + char *realm; + des_key_schedule ks; + int len; + unsigned char netcred[sizeof(CREDENTIALS)]; + int ret; + + realm = krb_realmofhost(RemoteHostName); + if(realm == NULL) + return -1; + memset(&cred, 0, sizeof(cred)); + ret = krb_get_cred(KRB_TICKET_GRANTING_TICKET, + realm, + realm, + &cred); + if(ret) + return ret; + des_set_key(key, ks); + len = pack_cred(&cred, netcred); + des_pcbc_encrypt((void*)netcred, (void*)netcred, len, + ks, key, DES_ENCRYPT); + memset(ks, 0, sizeof(ks)); + Data(ap, KRB_FORWARD, netcred, len); + memset(netcred, 0, sizeof(netcred)); + return 0; +} + +#endif /* KRB4 */ + diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c new file mode 100644 index 0000000..0b7818f --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/kerberos5.c @@ -0,0 +1,734 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include <config.h> + +RCSID("$Id: kerberos5.c,v 1.37 1999/06/24 17:09:10 assar Exp $"); + +#ifdef KRB5 + +#include <arpa/telnet.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> +#include <ctype.h> +#include <pwd.h> +#define Authenticator k5_Authenticator +#include <krb5.h> +#undef Authenticator +#include <roken.h> +#ifdef SOCKS +#include <socks.h> +#endif + + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ + +/* These values need to be the same as those defined in telnet/main.c. */ +/* Either define them in both places, or put in some common header file. */ +#define OPTS_FORWARD_CREDS 0x00000002 +#define OPTS_FORWARDABLE_CREDS 0x00000001 + +void kerberos5_forward (Authenticator *); + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_KERBEROS_V5, }; + +#define KRB_AUTH 0 /* Authentication data follows */ +#define KRB_REJECT 1 /* Rejected (reason might follow) */ +#define KRB_ACCEPT 2 /* Accepted */ +#define KRB_RESPONSE 3 /* Response for mutual auth. */ + +#define KRB_FORWARD 4 /* Forwarded credentials follow */ +#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ +#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ + +static krb5_data auth; +static krb5_ticket *ticket; + +static krb5_context context; +static krb5_auth_context auth_context; + +static int +Data(Authenticator *ap, int type, void *d, int c) +{ + unsigned char *p = str_data + 4; + unsigned char *cd = (unsigned char *)d; + + if (c == -1) + c = strlen(cd); + + if (auth_debug_mode) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - &str_data[2]); + return(telnet_net_write(str_data, p - str_data)); +} + +int +kerberos5_init(Authenticator *ap, int server) +{ + if (server) + str_data[3] = TELQUAL_REPLY; + else + str_data[3] = TELQUAL_IS; + krb5_init_context(&context); + return(1); +} + +static int +kerberos5_send(char *name, Authenticator *ap) +{ + krb5_error_code ret; + krb5_ccache ccache; + int ap_opts; + krb5_data cksum_data; + char foo[2]; + extern int net; + + printf("[ Trying %s ... ]\r\n", name); + if (!UserNameRequested) { + if (auth_debug_mode) { + printf("Kerberos V5: no user name supplied\r\n"); + } + return(0); + } + + ret = krb5_cc_default(context, &ccache); + if (ret) { + if (auth_debug_mode) { + printf("Kerberos V5: could not get default ccache: %s\r\n", + krb5_get_err_text (context, ret)); + } + return 0; + } + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) + ap_opts = AP_OPTS_MUTUAL_REQUIRED; + else + ap_opts = 0; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) { + if (auth_debug_mode) { + printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } + + ret = krb5_auth_con_setaddrs_from_fd (context, + auth_context, + &net); + if (ret) { + if (auth_debug_mode) { + printf ("Kerberos V5:" + " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } + + krb5_auth_setkeytype (context, auth_context, KEYTYPE_DES); + + foo[0] = ap->type; + foo[1] = ap->way; + + cksum_data.length = sizeof(foo); + cksum_data.data = foo; + ret = krb5_mk_req(context, &auth_context, ap_opts, + "host", RemoteHostName, + &cksum_data, ccache, &auth); + + if (ret) { + if (1 || auth_debug_mode) { + printf("Kerberos V5: mk_req failed (%s)\r\n", + krb5_get_err_text(context, ret)); + } + return(0); + } + + if (!auth_sendname((unsigned char *)UserNameRequested, + strlen(UserNameRequested))) { + if (auth_debug_mode) + printf("Not enough room for user name\r\n"); + return(0); + } + if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + return(0); + } + if (auth_debug_mode) { + printf("Sent Kerberos V5 credentials to server\r\n"); + } + return(1); +} + +int +kerberos5_send_mutual(Authenticator *ap) +{ + return kerberos5_send("mutual KERBEROS5", ap); +} + +int +kerberos5_send_oneway(Authenticator *ap) +{ + return kerberos5_send("KERBEROS5", ap); +} + +void +kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) +{ + krb5_error_code ret; + krb5_data outbuf; + krb5_keyblock *key_block; + char *name; + krb5_principal server; + int zero = 0; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_AUTH: + auth.data = (char *)data; + auth.length = cnt; + + auth_context = NULL; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; + } + + ret = krb5_auth_con_setaddrs_from_fd (context, + auth_context, + &zero); + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; + } + + ret = krb5_sock_to_principal (context, + 0, + "host", + KRB5_NT_SRV_HST, + &server); + if (ret) { + Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_sock_to_principal failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; + } + + ret = krb5_rd_req(context, + &auth_context, + &auth, + server, + NULL, + NULL, + &ticket); + krb5_free_principal (context, server); + + if (ret) { + char *errbuf; + + asprintf(&errbuf, + "Read req failed: %s", + krb5_get_err_text(context, ret)); + Data(ap, KRB_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("%s\r\n", errbuf); + free (errbuf); + return; + } + + { + char foo[2]; + + foo[0] = ap->type; + foo[1] = ap->way; + + ret = krb5_verify_authenticator_checksum(context, + auth_context, + foo, + sizeof(foo)); + + if (ret) { + char *errbuf; + asprintf(&errbuf, "Bad checksum: %s", + krb5_get_err_text(context, ret)); + Data(ap, KRB_REJECT, errbuf, -1); + if (auth_debug_mode) + printf ("%s\r\n", errbuf); + free(errbuf); + return; + } + } + ret = krb5_auth_con_getremotesubkey (context, + auth_context, + &key_block); + + if (ret) { + Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_auth_con_getremotesubkey failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; + } + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + ret = krb5_mk_rep(context, &auth_context, &outbuf); + if (ret) { + Data(ap, KRB_REJECT, + "krb5_mk_rep failed", -1); + auth_finished(ap, AUTH_REJECT); + if (auth_debug_mode) + printf("Kerberos V5: " + "krb5_mk_rep failed (%s)\r\n", + krb5_get_err_text(context, ret)); + return; + } + Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); + } + if (krb5_unparse_name(context, ticket->client, &name)) + name = 0; + + if(UserNameRequested && krb5_kuserok(context, + ticket->client, + UserNameRequested)) { + Data(ap, KRB_ACCEPT, name, name ? -1 : 0); + if (auth_debug_mode) { + printf("Kerberos5 identifies him as ``%s''\r\n", + name ? name : ""); + } + + if(key_block->keytype == ETYPE_DES_CBC_MD5 || + key_block->keytype == ETYPE_DES_CBC_MD4 || + key_block->keytype == ETYPE_DES_CBC_CRC) { + Session_Key skey; + + skey.type = SK_DES; + skey.length = 8; + skey.data = key_block->keyvalue.data; + encrypt_session_key(&skey, 0); + } + + } else { + char *msg; + + asprintf (&msg, "user `%s' is not authorized to " + "login as `%s'", + name ? name : "<unknown>", + UserNameRequested ? UserNameRequested : "<nobody>"); + if (msg == NULL) + Data(ap, KRB_REJECT, NULL, 0); + else { + Data(ap, KRB_REJECT, (void *)msg, -1); + free(msg); + } + } + auth_finished(ap, AUTH_USER); + + krb5_free_keyblock_contents(context, key_block); + + break; + case KRB_FORWARD: { + struct passwd *pwd; + char ccname[1024]; /* XXX */ + krb5_data inbuf; + krb5_ccache ccache; + inbuf.data = (char *)data; + inbuf.length = cnt; + + pwd = getpwnam (UserNameRequested); + if (pwd == NULL) + break; + + snprintf (ccname, sizeof(ccname), + "FILE:/tmp/krb5cc_%u", pwd->pw_uid); + + ret = krb5_cc_resolve (context, ccname, &ccache); + if (ret) { + if (auth_debug_mode) + printf ("Kerberos V5: could not get ccache: %s\r\n", + krb5_get_err_text(context, ret)); + break; + } + + ret = krb5_cc_initialize (context, + ccache, + ticket->client); + if (ret) { + if (auth_debug_mode) + printf ("Kerberos V5: could not init ccache: %s\r\n", + krb5_get_err_text(context, ret)); + break; + } + + ret = krb5_rd_cred (context, + auth_context, + ccache, + &inbuf); + if(ret) { + char *errbuf; + + asprintf (&errbuf, + "Read forwarded creds failed: %s", + krb5_get_err_text (context, ret)); + if(errbuf == NULL) + Data(ap, KRB_FORWARD_REJECT, NULL, 0); + else + Data(ap, KRB_FORWARD_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("Could not read forwarded credentials: %s\r\n", + errbuf); + free (errbuf); + } else + Data(ap, KRB_FORWARD_ACCEPT, 0, 0); + chown (ccname + 5, pwd->pw_uid, -1); + if (auth_debug_mode) + printf("Forwarded credentials obtained\r\n"); + break; + } + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + Data(ap, KRB_REJECT, 0, 0); + break; + } +} + +void +kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) +{ + static int mutual_complete = 0; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_REJECT: + if (cnt > 0) { + printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ Kerberos V5 refuses authentication ]\r\n"); + auth_send_retry(); + return; + case KRB_ACCEPT: { + krb5_error_code ret; + Session_Key skey; + krb5_keyblock *keyblock; + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && + !mutual_complete) { + printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); + auth_send_retry(); + return; + } + if (cnt) + printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data); + else + printf("[ Kerberos V5 accepts you ]\r\n"); + + ret = krb5_auth_con_getlocalsubkey (context, + auth_context, + &keyblock); + if (ret) + ret = krb5_auth_con_getkey (context, + auth_context, + &keyblock); + if(ret) { + printf("[ krb5_auth_con_getkey: %s ]\r\n", + krb5_get_err_text(context, ret)); + auth_send_retry(); + return; + } + + skey.type = SK_DES; + skey.length = 8; + skey.data = keyblock->keyvalue.data; + encrypt_session_key(&skey, 0); + krb5_free_keyblock_contents (context, keyblock); + auth_finished(ap, AUTH_USER); + if (forward_flags & OPTS_FORWARD_CREDS) + kerberos5_forward(ap); + break; + } + case KRB_RESPONSE: + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* the rest of the reply should contain a krb_ap_rep */ + krb5_ap_rep_enc_part *reply; + krb5_data inbuf; + krb5_error_code ret; + + inbuf.length = cnt; + inbuf.data = (char *)data; + + ret = krb5_rd_rep(context, auth_context, &inbuf, &reply); + if (ret) { + printf("[ Mutual authentication failed: %s ]\r\n", + krb5_get_err_text (context, ret)); + auth_send_retry(); + return; + } + krb5_free_ap_rep_enc_part(context, reply); + mutual_complete = 1; + } + return; + case KRB_FORWARD_ACCEPT: + printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); + return; + case KRB_FORWARD_REJECT: + printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", + cnt, data); + return; + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + return; + } +} + +int +kerberos5_status(Authenticator *ap, char *name, size_t name_sz, int level) +{ + if (level < AUTH_USER) + return(level); + + if (UserNameRequested && + krb5_kuserok(context, + ticket->client, + UserNameRequested)) + { + strcpy_truncate(name, UserNameRequested, name_sz); + return(AUTH_VALID); + } else + return(AUTH_USER); +} + +#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} +#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} + +void +kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) +{ + int i; + + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; + + switch(data[3]) { + case KRB_REJECT: /* Rejected (reason might follow) */ + strcpy_truncate((char *)buf, " REJECT ", buflen); + goto common; + + case KRB_ACCEPT: /* Accepted (name might follow) */ + strcpy_truncate((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; + + + case KRB_AUTH: /* Authentication data follows */ + strcpy_truncate((char *)buf, " AUTH", buflen); + goto common2; + + case KRB_RESPONSE: + strcpy_truncate((char *)buf, " RESPONSE", buflen); + goto common2; + + case KRB_FORWARD: /* Forwarded credentials follow */ + strcpy_truncate((char *)buf, " FORWARD", buflen); + goto common2; + + case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ + strcpy_truncate((char *)buf, " FORWARD_ACCEPT", buflen); + goto common2; + + case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ + /* (reason might follow) */ + strcpy_truncate((char *)buf, " FORWARD_REJECT", buflen); + goto common2; + + default: + snprintf(buf, buflen, " %d (unknown)", data[3]); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + snprintf(buf, buflen, " %d", data[i]); + BUMP(buf, buflen); + } + break; + } +} + +void +kerberos5_forward(Authenticator *ap) +{ + krb5_error_code ret; + krb5_ccache ccache; + krb5_creds creds; + krb5_kdc_flags flags; + krb5_data out_data; + krb5_principal principal; + + ret = krb5_cc_default (context, &ccache); + if (ret) { + if (auth_debug_mode) + printf ("KerberosV5: could not get default ccache: %s\r\n", + krb5_get_err_text (context, ret)); + return; + } + + ret = krb5_cc_get_principal (context, ccache, &principal); + if (ret) { + if (auth_debug_mode) + printf ("KerberosV5: could not get principal: %s\r\n", + krb5_get_err_text (context, ret)); + return; + } + + memset (&creds, 0, sizeof(creds)); + + creds.client = principal; + + ret = krb5_build_principal (context, + &creds.server, + strlen(principal->realm), + principal->realm, + "krbtgt", + principal->realm, + NULL); + + if (ret) { + if (auth_debug_mode) + printf ("KerberosV5: could not get principal: %s\r\n", + krb5_get_err_text (context, ret)); + return; + } + + creds.times.endtime = 0; + + flags.i = 0; + flags.b.forwarded = 1; + if (forward_flags & OPTS_FORWARDABLE_CREDS) + flags.b.forwardable = 1; + + ret = krb5_get_forwarded_creds (context, + auth_context, + ccache, + flags.i, + RemoteHostName, + &creds, + &out_data); + if (ret) { + if (auth_debug_mode) + printf ("Kerberos V5: error gettting forwarded creds: %s\r\n", + krb5_get_err_text (context, ret)); + return; + } + + if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + } else { + if (auth_debug_mode) + printf("Forwarded local Kerberos V5 credentials to server\r\n"); + } +} + +#endif /* KRB5 */ diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c b/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c new file mode 100644 index 0000000..ee1eee2 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/krb4encpwd.c @@ -0,0 +1,437 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +RCSID("$Id: krb4encpwd.c,v 1.17 1998/07/09 23:16:29 assar Exp $"); + +#ifdef KRB4_ENCPWD +/* + * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION + * ALL RIGHTS RESERVED + * + * "Digital Equipment Corporation authorizes the reproduction, + * distribution and modification of this software subject to the following + * restrictions: + * + * 1. Any partial or whole copy of this software, or any modification + * thereof, must include this copyright notice in its entirety. + * + * 2. This software is supplied "as is" with no warranty of any kind, + * expressed or implied, for any purpose, including any warranty of fitness + * or merchantibility. DIGITAL assumes no responsibility for the use or + * reliability of this software, nor promises to provide any form of + * support for it on any basis. + * + * 3. Distribution of this software is authorized only if no profit or + * remuneration of any kind is received in exchange for such distribution. + * + * 4. This software produces public key authentication certificates + * bearing an expiration date established by DIGITAL and RSA Data + * Security, Inc. It may cease to generate certificates after the expiration + * date. Any modification of this software that changes or defeats + * the expiration date or its effect is unauthorized. + * + * 5. Software that will renew or extend the expiration date of + * authentication certificates produced by this software may be obtained + * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA + * 94065, (415)595-8782, or from DIGITAL" + * + */ + +#include <sys/types.h> +#include <arpa/telnet.h> +#include <pwd.h> +#include <stdio.h> + +#include <des.h> +#include <krb.h> +#include <stdlib.h> +#include <string.h> +#ifdef SOCKS +#include <socks.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +int krb_mk_encpwd_req (KTEXT, char *, char *, char *, char *, char *, char *); +int krb_rd_encpwd_req (KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *); + +extern auth_debug_mode; + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_KRB4_ENCPWD, }; +static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_NAME, }; + +#define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */ +#define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ +#define KRB4_ENCPWD_ACCEPT 2 /* Accepted */ +#define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */ +#define KRB4_ENCPWD_ACK 4 /* Acknowledge */ + +#define KRB_SERVICE_NAME "rcmd" + +static KTEXT_ST auth; +static char name[ANAME_SZ]; +static char user_passwd[ANAME_SZ]; +static AUTH_DAT adat = { 0 }; +static des_key_schedule sched; +static char challenge[REALM_SZ]; + + static int +Data(ap, type, d, c) + Authenticator *ap; + int type; + void *d; + int c; +{ + unsigned char *p = str_data + 4; + unsigned char *cd = (unsigned char *)d; + + if (c == -1) + c = strlen(cd); + + if (0) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - (&str_data[2])); + return(telnet_net_write(str_data, p - str_data)); +} + + int +krb4encpwd_init(ap, server) + Authenticator *ap; + int server; +{ + char hostname[80], *cp, *realm; + des_clock skey; + + if (server) { + str_data[3] = TELQUAL_REPLY; + } else { + str_data[3] = TELQUAL_IS; + gethostname(hostname, sizeof(hostname)); + realm = krb_realmofhost(hostname); + cp = strchr(hostname, '.'); + if (*cp != NULL) *cp = NULL; + if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0, + KEYFILE, (char *)skey)) { + return(0); + } + } + return(1); +} + + int +krb4encpwd_send(ap) + Authenticator *ap; +{ + + printf("[ Trying KRB4ENCPWD ... ]\r\n"); + if (!UserNameRequested) { + return(0); + } + if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + return(0); + } + + if (!Data(ap, KRB4_ENCPWD_ACK, NULL, 0)) { + return(0); + } + + return(1); +} + + void +krb4encpwd_is(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + des_cblock datablock; + char r_passwd[ANAME_SZ], r_user[ANAME_SZ]; + char lhostname[ANAME_SZ], *cp; + int r; + time_t now; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB4_ENCPWD_AUTH: + memmove(auth.dat, data, auth.length = cnt); + + gethostname(lhostname, sizeof(lhostname)); + if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; + + if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) { + Data(ap, KRB4_ENCPWD_REJECT, "Auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + auth_encrypt_userpwd(r_passwd); + if (passwdok(UserNameRequested, UserPassword) == 0) { + /* + * illegal username and password + */ + Data(ap, KRB4_ENCPWD_REJECT, "Illegal password", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + memmove(session_key, adat.session, sizeof(des_cblock)); + Data(ap, KRB4_ENCPWD_ACCEPT, 0, 0); + auth_finished(ap, AUTH_USER); + break; + + case KRB4_ENCPWD_CHALLENGE: + /* + * Take the received random challenge text and save + * for future authentication. + */ + memmove(challenge, data, sizeof(des_cblock)); + break; + + + case KRB4_ENCPWD_ACK: + /* + * Receive ack, if mutual then send random challenge + */ + + /* + * If we are doing mutual authentication, get set up to send + * the challenge, and verify it when the response comes back. + */ + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + int i; + + time(&now); + snprintf(challenge, sizeof(challenge), "%x", now); + Data(ap, KRB4_ENCPWD_CHALLENGE, challenge, strlen(challenge)); + } + break; + + default: + Data(ap, KRB4_ENCPWD_REJECT, 0, 0); + break; + } +} + + + void +krb4encpwd_reply(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + KTEXT_ST krb_token; + des_cblock enckey; + CREDENTIALS cred; + int r; + char randchal[REALM_SZ], instance[ANAME_SZ], *cp; + char hostname[80], *realm; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB4_ENCPWD_REJECT: + if (cnt > 0) { + printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ KRB4_ENCPWD refuses authentication ]\r\n"); + auth_send_retry(); + return; + case KRB4_ENCPWD_ACCEPT: + printf("[ KRB4_ENCPWD accepts you ]\r\n"); + auth_finished(ap, AUTH_USER); + return; + case KRB4_ENCPWD_CHALLENGE: + /* + * Verify that the response to the challenge is correct. + */ + + gethostname(hostname, sizeof(hostname)); + realm = krb_realmofhost(hostname); + memmove(challenge, data, cnt); + memset(user_passwd, 0, sizeof(user_passwd)); + des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); + UserPassword = user_passwd; + Challenge = challenge; + strcpy_truncate(instance, RemoteHostName, sizeof(instance)); + if ((cp = strchr(instance, '.')) != 0) *cp = '\0'; + + if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) { + krb_token.length = 0; + } + + if (!Data(ap, KRB4_ENCPWD_AUTH, krb_token.dat, krb_token.length)) { + return; + } + + break; + + default: + return; + } +} + + int +krb4encpwd_status(ap, name, name_sz, level) + Authenticator *ap; + char *name; + size_t name_sz; + int level; +{ + + if (level < AUTH_USER) + return(level); + + if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) { + strcpy_truncate(name, UserNameRequested, name_sz); + return(AUTH_VALID); + } else { + return(AUTH_USER); + } +} + +#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} +#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} + + void +krb4encpwd_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + int i; + + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; + + switch(data[3]) { + case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */ + strcpy_truncate((char *)buf, " REJECT ", buflen); + goto common; + + case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */ + strcpy_truncate((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; + + case KRB4_ENCPWD_AUTH: /* Authentication data follows */ + strcpy_truncate((char *)buf, " AUTH", buflen); + goto common2; + + case KRB4_ENCPWD_CHALLENGE: + strcpy_truncate((char *)buf, " CHALLENGE", buflen); + goto common2; + + case KRB4_ENCPWD_ACK: + strcpy_truncate((char *)buf, " ACK", buflen); + goto common2; + + default: + snprintf(buf, buflen, " %d (unknown)", data[3]); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + snprintf(buf, buflen, " %d", data[i]); + BUMP(buf, buflen); + } + break; + } +} + +int passwdok(name, passwd) +char *name, *passwd; +{ + char *crypt(); + char *salt, *p; + struct passwd *pwd; + int passwdok_status = 0; + + if (pwd = k_getpwnam(name)) + salt = pwd->pw_passwd; + else salt = "xx"; + + p = crypt(passwd, salt); + + if (pwd && !strcmp(p, pwd->pw_passwd)) { + passwdok_status = 1; + } else passwdok_status = 0; + return(passwdok_status); +} + +#endif + +#ifdef notdef + +prkey(msg, key) + char *msg; + unsigned char *key; +{ + int i; + printf("%s:", msg); + for (i = 0; i < 8; i++) + printf(" %3d", key[i]); + printf("\r\n"); +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/misc-proto.h b/crypto/kerberosIV/appl/telnet/libtelnet/misc-proto.h new file mode 100644 index 0000000..a31d924 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/misc-proto.h @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)misc-proto.h 8.1 (Berkeley) 6/4/93 + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* $Id: misc-proto.h,v 1.7 1998/07/09 23:16:30 assar Exp $ */ + +#ifndef __MISC_PROTO__ +#define __MISC_PROTO__ + +void auth_encrypt_init (char *, char *, char *, int); +void auth_encrypt_user(char *name); +void auth_encrypt_connect (int); +void printd (const unsigned char *, int); + +char** genget (char *name, char **table, int stlen); +int isprefix(char *s1, char *s2); +int Ambiguous(void *s); + +/* + * These functions are imported from the application + */ +int telnet_net_write (unsigned char *, int); +void net_encrypt (void); +int telnet_spin (void); +char *telnet_getenv (char *); +char *telnet_gets (char *, char *, int, int); +void printsub(int direction, unsigned char *pointer, int length); +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/misc.c b/crypto/kerberosIV/appl/telnet/libtelnet/misc.c new file mode 100644 index 0000000..2d9199f --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/misc.c @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +RCSID("$Id: misc.c,v 1.13 1998/06/13 00:06:54 assar Exp $"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <roken.h> +#ifdef SOCKS +#include <socks.h> +#endif +#include "misc.h" +#include "auth.h" +#include "encrypt.h" + + +char *RemoteHostName; +char *LocalHostName; +char *UserNameRequested = 0; +int ConnectedCount = 0; + +void +auth_encrypt_init(char *local, char *remote, char *name, int server) +{ + RemoteHostName = remote; + LocalHostName = local; +#ifdef AUTHENTICATION + auth_init(name, server); +#endif +#ifdef ENCRYPTION + encrypt_init(name, server); +#endif + if (UserNameRequested) { + free(UserNameRequested); + UserNameRequested = 0; + } +} + +void +auth_encrypt_user(char *name) +{ + if (UserNameRequested) + free(UserNameRequested); + UserNameRequested = name ? strdup(name) : 0; +} + +void +auth_encrypt_connect(int cnt) +{ +} + +void +printd(const unsigned char *data, int cnt) +{ + if (cnt > 16) + cnt = 16; + while (cnt-- > 0) { + printf(" %02x", *data); + ++data; + } +} diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/misc.h b/crypto/kerberosIV/appl/telnet/libtelnet/misc.h new file mode 100644 index 0000000..41ffa7f --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/misc.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)misc.h 8.1 (Berkeley) 6/4/93 + */ + +extern char *UserNameRequested; +extern char *LocalHostName; +extern char *RemoteHostName; +extern int ConnectedCount; +extern int ReservedPort; + +#include "misc-proto.h" diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/rsaencpwd.c b/crypto/kerberosIV/appl/telnet/libtelnet/rsaencpwd.c new file mode 100644 index 0000000..267e98e --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/rsaencpwd.c @@ -0,0 +1,487 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +RCSID("$Id: rsaencpwd.c,v 1.17 1998/07/09 23:16:32 assar Exp $"); + +#ifdef RSA_ENCPWD +/* + * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION + * ALL RIGHTS RESERVED + * + * "Digital Equipment Corporation authorizes the reproduction, + * distribution and modification of this software subject to the following + * restrictions: + * + * 1. Any partial or whole copy of this software, or any modification + * thereof, must include this copyright notice in its entirety. + * + * 2. This software is supplied "as is" with no warranty of any kind, + * expressed or implied, for any purpose, including any warranty of fitness + * or merchantibility. DIGITAL assumes no responsibility for the use or + * reliability of this software, nor promises to provide any form of + * support for it on any basis. + * + * 3. Distribution of this software is authorized only if no profit or + * remuneration of any kind is received in exchange for such distribution. + * + * 4. This software produces public key authentication certificates + * bearing an expiration date established by DIGITAL and RSA Data + * Security, Inc. It may cease to generate certificates after the expiration + * date. Any modification of this software that changes or defeats + * the expiration date or its effect is unauthorized. + * + * 5. Software that will renew or extend the expiration date of + * authentication certificates produced by this software may be obtained + * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA + * 94065, (415)595-8782, or from DIGITAL" + * + */ + +#include <sys/types.h> +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif +#include <pwd.h> +#include <stdio.h> + +#include <stdlib.h> +#include <string.h> +#ifdef SOCKS +#include <socks.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" +#include "cdc.h" + +extern auth_debug_mode; + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_RSA_ENCPWD, }; +static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_NAME, }; + +#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */ +#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ +#define RSA_ENCPWD_ACCEPT 2 /* Accepted */ +#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */ + +#define NAME_SZ 40 +#define CHAL_SZ 20 +#define PWD_SZ 40 + +static KTEXT_ST auth; +static char name[NAME_SZ]; +static char user_passwd[PWD_SZ]; +static char key_file[2*NAME_SZ]; +static char lhostname[NAME_SZ]; +static char challenge[CHAL_SZ]; +static int challenge_len; + + static int +Data(ap, type, d, c) + Authenticator *ap; + int type; + void *d; + int c; +{ + unsigned char *p = str_data + 4; + unsigned char *cd = (unsigned char *)d; + + if (c == -1) + c = strlen((char *)cd); + + if (0) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + if (type != NULL) *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - (&str_data[2])); + return(telnet_net_write(str_data, p - str_data)); +} + + int +rsaencpwd_init(ap, server) + Authenticator *ap; + int server; +{ + char *cp; + FILE *fp; + + if (server) { + str_data[3] = TELQUAL_REPLY; + memset(key_file, 0, sizeof(key_file)); + gethostname(lhostname, sizeof(lhostname)); + if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; + snprintf(key_file, sizeof(key_file), + "/etc/.%s_privkey", lhostname); + if ((fp=fopen(key_file, "r"))==NULL) return(0); + fclose(fp); + } else { + str_data[3] = TELQUAL_IS; + } + return(1); +} + + int +rsaencpwd_send(ap) + Authenticator *ap; +{ + + printf("[ Trying RSAENCPWD ... ]\r\n"); + if (!UserNameRequested) { + return(0); + } + if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + return(0); + } + if (!Data(ap, NULL, NULL, 0)) { + return(0); + } + + + return(1); +} + + void +rsaencpwd_is(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + des_cblock datablock; + char r_passwd[PWD_SZ], r_user[NAME_SZ]; + char *cp, key[160]; + char chalkey[160], *ptr; + FILE *fp; + int r, i, j, chalkey_len, len; + time_t now; + + cnt--; + switch (*data++) { + case RSA_ENCPWD_AUTH: + memmove(auth.dat, data, auth.length = cnt); + + if ((fp=fopen(key_file, "r"))==NULL) { + Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + /* + * get privkey + */ + fscanf(fp, "%x;", &len); + for (i=0;i<len;i++) { + j = getc(fp); key[i]=j; + } + fclose(fp); + + r = accept_rsa_encpwd(&auth, key, challenge, + challenge_len, r_passwd); + if (r < 0) { + Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + auth_encrypt_userpwd(r_passwd); + if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) { + /* + * illegal username and password + */ + Data(ap, RSA_ENCPWD_REJECT, "Illegal password", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + Data(ap, RSA_ENCPWD_ACCEPT, 0, 0); + auth_finished(ap, AUTH_USER); + break; + + + case IAC: + + /* + * If we are doing mutual authentication, get set up to send + * the challenge, and verify it when the response comes back. + */ + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) { + int i; + + + time(&now); + if ((now % 2) == 0) { + snprintf(challenge, sizeof(challenge), "%x", now); + challenge_len = strlen(challenge); + } else { + strcpy_truncate(challenge, "randchal", sizeof(challenge)); + challenge_len = 8; + } + + if ((fp=fopen(key_file, "r"))==NULL) { + Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + /* + * skip privkey + */ + fscanf(fp, "%x;", &len); + for (i=0;i<len;i++) { + j = getc(fp); + } + /* + * get pubkey + */ + fscanf(fp, "%x;", &len); + for (i=0;i<len;i++) { + j = getc(fp); key[i]=j; + } + fclose(fp); + chalkey[0] = 0x30; + ptr = (char *) &chalkey[1]; + chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len; + EncodeLength(ptr, chalkey_len); + ptr +=NumEncodeLengthOctets(chalkey_len); + *ptr++ = 0x04; /* OCTET STRING */ + *ptr++ = challenge_len; + memmove(ptr, challenge, challenge_len); + ptr += challenge_len; + *ptr++ = 0x04; /* OCTET STRING */ + EncodeLength(ptr, i); + ptr += NumEncodeLengthOctets(i); + memmove(ptr, key, i); + chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len; + Data(ap, RSA_ENCPWD_CHALLENGEKEY, chalkey, chalkey_len); + } + break; + + default: + Data(ap, RSA_ENCPWD_REJECT, 0, 0); + break; + } +} + + + void +rsaencpwd_reply(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + KTEXT_ST token; + des_cblock enckey; + int r, pubkey_len; + char randchal[CHAL_SZ], *cp; + char chalkey[160], pubkey[128], *ptr; + + if (cnt-- < 1) + return; + switch (*data++) { + case RSA_ENCPWD_REJECT: + if (cnt > 0) { + printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ RSA_ENCPWD refuses authentication ]\r\n"); + auth_send_retry(); + return; + case RSA_ENCPWD_ACCEPT: + printf("[ RSA_ENCPWD accepts you ]\r\n"); + auth_finished(ap, AUTH_USER); + return; + case RSA_ENCPWD_CHALLENGEKEY: + /* + * Verify that the response to the challenge is correct. + */ + + memmove(chalkey, data, cnt); + ptr = (char *) &chalkey[0]; + ptr += DecodeHeaderLength(chalkey); + if (*ptr != 0x04) { + return; + } + *ptr++; + challenge_len = DecodeValueLength(ptr); + ptr += NumEncodeLengthOctets(challenge_len); + memmove(challenge, ptr, challenge_len); + ptr += challenge_len; + if (*ptr != 0x04) { + return; + } + *ptr++; + pubkey_len = DecodeValueLength(ptr); + ptr += NumEncodeLengthOctets(pubkey_len); + memmove(pubkey, ptr, pubkey_len); + memset(user_passwd, 0, sizeof(user_passwd)); + des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); + UserPassword = user_passwd; + Challenge = challenge; + r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey); + if (r < 0) { + token.length = 1; + } + + if (!Data(ap, RSA_ENCPWD_AUTH, token.dat, token.length)) { + return; + } + + break; + + default: + return; + } +} + + int +rsaencpwd_status(ap, name, name_sz, level) + Authenticator *ap; + char *name; + size_t name_sz; + int level; +{ + + if (level < AUTH_USER) + return(level); + + if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) { + strcpy_truncate(name, UserNameRequested, name_sz); + return(AUTH_VALID); + } else { + return(AUTH_USER); + } +} + +#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} +#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} + + void +rsaencpwd_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + int i; + + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; + + switch(data[3]) { + case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */ + strcpy_truncate((char *)buf, " REJECT ", buflen); + goto common; + + case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */ + strcpy_truncate((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; + + case RSA_ENCPWD_AUTH: /* Authentication data follows */ + strcpy_truncate((char *)buf, " AUTH", buflen); + goto common2; + + case RSA_ENCPWD_CHALLENGEKEY: + strcpy_truncate((char *)buf, " CHALLENGEKEY", buflen); + goto common2; + + default: + snprintf(buf, buflen, " %d (unknown)", data[3]); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + snprintf(buf, buflen, " %d", data[i]); + BUMP(buf, buflen); + } + break; + } +} + +int rsaencpwd_passwdok(name, passwd) +char *name, *passwd; +{ + char *crypt(); + char *salt, *p; + struct passwd *pwd; + int passwdok_status = 0; + + if (pwd = k_getpwnam(name)) + salt = pwd->pw_passwd; + else salt = "xx"; + + p = crypt(passwd, salt); + + if (pwd && !strcmp(p, pwd->pw_passwd)) { + passwdok_status = 1; + } else passwdok_status = 0; + return(passwdok_status); +} + +#endif + +#ifdef notdef + +prkey(msg, key) + char *msg; + unsigned char *key; +{ + int i; + printf("%s:", msg); + for (i = 0; i < 8; i++) + printf(" %3d", key[i]); + printf("\r\n"); +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/libtelnet/spx.c b/crypto/kerberosIV/appl/telnet/libtelnet/spx.c new file mode 100644 index 0000000..6d2eefe --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/libtelnet/spx.c @@ -0,0 +1,586 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +RCSID("$Id: spx.c,v 1.16 1998/07/09 23:16:33 assar Exp $"); + +#ifdef SPX +/* + * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION + * ALL RIGHTS RESERVED + * + * "Digital Equipment Corporation authorizes the reproduction, + * distribution and modification of this software subject to the following + * restrictions: + * + * 1. Any partial or whole copy of this software, or any modification + * thereof, must include this copyright notice in its entirety. + * + * 2. This software is supplied "as is" with no warranty of any kind, + * expressed or implied, for any purpose, including any warranty of fitness + * or merchantibility. DIGITAL assumes no responsibility for the use or + * reliability of this software, nor promises to provide any form of + * support for it on any basis. + * + * 3. Distribution of this software is authorized only if no profit or + * remuneration of any kind is received in exchange for such distribution. + * + * 4. This software produces public key authentication certificates + * bearing an expiration date established by DIGITAL and RSA Data + * Security, Inc. It may cease to generate certificates after the expiration + * date. Any modification of this software that changes or defeats + * the expiration date or its effect is unauthorized. + * + * 5. Software that will renew or extend the expiration date of + * authentication certificates produced by this software may be obtained + * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA + * 94065, (415)595-8782, or from DIGITAL" + * + */ + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif +#include <stdio.h> +#include "gssapi_defs.h" +#include <stdlib.h> +#include <string.h> + +#include <pwd.h> +#ifdef SOCKS +#include <socks.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +extern auth_debug_mode; + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_SPX, }; +static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_NAME, }; + +#define SPX_AUTH 0 /* Authentication data follows */ +#define SPX_REJECT 1 /* Rejected (reason might follow) */ +#define SPX_ACCEPT 2 /* Accepted */ + +static des_key_schedule sched; +static des_cblock challenge = { 0 }; + + +/*******************************************************************/ + +gss_OID_set actual_mechs; +gss_OID actual_mech_type, output_name_type; +int major_status, status, msg_ctx = 0, new_status; +int req_flags = 0, ret_flags, lifetime_rec; +gss_cred_id_t gss_cred_handle; +gss_ctx_id_t actual_ctxhandle, context_handle; +gss_buffer_desc output_token, input_token, input_name_buffer; +gss_buffer_desc status_string; +gss_name_t desired_targname, src_name; +gss_channel_bindings input_chan_bindings; +char lhostname[GSS_C_MAX_PRINTABLE_NAME]; +char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; +int to_addr=0, from_addr=0; +char *address; +gss_buffer_desc fullname_buffer; +gss_OID fullname_type; +gss_cred_id_t gss_delegated_cred_handle; + +/*******************************************************************/ + + + + static int +Data(ap, type, d, c) + Authenticator *ap; + int type; + void *d; + int c; +{ + unsigned char *p = str_data + 4; + unsigned char *cd = (unsigned char *)d; + + if (c == -1) + c = strlen((char *)cd); + + if (0) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - (&str_data[2])); + return(telnet_net_write(str_data, p - str_data)); +} + + int +spx_init(ap, server) + Authenticator *ap; + int server; +{ + gss_cred_id_t tmp_cred_handle; + + if (server) { + str_data[3] = TELQUAL_REPLY; + gethostname(lhostname, sizeof(lhostname)); + snprintf (targ_printable, sizeof(targ_printable), + "SERVICE:rcmd@%s", lhostname); + input_name_buffer.length = strlen(targ_printable); + input_name_buffer.value = targ_printable; + major_status = gss_import_name(&status, + &input_name_buffer, + GSS_C_NULL_OID, + &desired_targname); + major_status = gss_acquire_cred(&status, + desired_targname, + 0, + GSS_C_NULL_OID_SET, + GSS_C_ACCEPT, + &tmp_cred_handle, + &actual_mechs, + &lifetime_rec); + if (major_status != GSS_S_COMPLETE) return(0); + } else { + str_data[3] = TELQUAL_IS; + } + return(1); +} + + int +spx_send(ap) + Authenticator *ap; +{ + des_cblock enckey; + int r; + + gss_OID actual_mech_type, output_name_type; + int msg_ctx = 0, new_status, status; + int req_flags = 0, ret_flags, lifetime_rec, major_status; + gss_buffer_desc output_token, input_token, input_name_buffer; + gss_buffer_desc output_name_buffer, status_string; + gss_name_t desired_targname; + gss_channel_bindings input_chan_bindings; + char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; + int from_addr=0, to_addr=0, myhostlen, j; + int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0; + char *address; + + printf("[ Trying SPX ... ]\r\n"); + snprintf (targ_printable, sizeof(targ_printable), + "SERVICE:rcmd@%s", RemoteHostName); + + input_name_buffer.length = strlen(targ_printable); + input_name_buffer.value = targ_printable; + + if (!UserNameRequested) { + return(0); + } + + major_status = gss_import_name(&status, + &input_name_buffer, + GSS_C_NULL_OID, + &desired_targname); + + + major_status = gss_display_name(&status, + desired_targname, + &output_name_buffer, + &output_name_type); + + printf("target is '%s'\n", output_name_buffer.value); fflush(stdout); + + major_status = gss_release_buffer(&status, &output_name_buffer); + + input_chan_bindings = (gss_channel_bindings) + malloc(sizeof(gss_channel_bindings_desc)); + + input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; + input_chan_bindings->initiator_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->initiator_address.value = (char *) address; + address[0] = ((from_addr & 0xff000000) >> 24); + address[1] = ((from_addr & 0xff0000) >> 16); + address[2] = ((from_addr & 0xff00) >> 8); + address[3] = (from_addr & 0xff); + input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; + input_chan_bindings->acceptor_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->acceptor_address.value = (char *) address; + address[0] = ((to_addr & 0xff000000) >> 24); + address[1] = ((to_addr & 0xff0000) >> 16); + address[2] = ((to_addr & 0xff00) >> 8); + address[3] = (to_addr & 0xff); + input_chan_bindings->application_data.length = 0; + + req_flags = 0; + if (deleg_flag) req_flags = req_flags | 1; + if (mutual_flag) req_flags = req_flags | 2; + if (replay_flag) req_flags = req_flags | 4; + if (seq_flag) req_flags = req_flags | 8; + + major_status = gss_init_sec_context(&status, /* minor status */ + GSS_C_NO_CREDENTIAL, /* cred handle */ + &actual_ctxhandle, /* ctx handle */ + desired_targname, /* target name */ + GSS_C_NULL_OID, /* mech type */ + req_flags, /* req flags */ + 0, /* time req */ + input_chan_bindings, /* chan binding */ + GSS_C_NO_BUFFER, /* input token */ + &actual_mech_type, /* actual mech */ + &output_token, /* output token */ + &ret_flags, /* ret flags */ + &lifetime_rec); /* time rec */ + + if ((major_status != GSS_S_COMPLETE) && + (major_status != GSS_S_CONTINUE_NEEDED)) { + gss_display_status(&new_status, + status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + printf("%s\n", status_string.value); + return(0); + } + + if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + return(0); + } + + if (!Data(ap, SPX_AUTH, output_token.value, output_token.length)) { + return(0); + } + + return(1); +} + + void +spx_is(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + des_cblock datablock; + int r; + + if (cnt-- < 1) + return; + switch (*data++) { + case SPX_AUTH: + input_token.length = cnt; + input_token.value = (char *) data; + + gethostname(lhostname, sizeof(lhostname)); + + snprintf(targ_printable, sizeof(targ_printable), + "SERVICE:rcmd@%s", lhostname); + + input_name_buffer.length = strlen(targ_printable); + input_name_buffer.value = targ_printable; + + major_status = gss_import_name(&status, + &input_name_buffer, + GSS_C_NULL_OID, + &desired_targname); + + major_status = gss_acquire_cred(&status, + desired_targname, + 0, + GSS_C_NULL_OID_SET, + GSS_C_ACCEPT, + &gss_cred_handle, + &actual_mechs, + &lifetime_rec); + + major_status = gss_release_name(&status, desired_targname); + + input_chan_bindings = (gss_channel_bindings) + malloc(sizeof(gss_channel_bindings_desc)); + + input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; + input_chan_bindings->initiator_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->initiator_address.value = (char *) address; + address[0] = ((from_addr & 0xff000000) >> 24); + address[1] = ((from_addr & 0xff0000) >> 16); + address[2] = ((from_addr & 0xff00) >> 8); + address[3] = (from_addr & 0xff); + input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; + input_chan_bindings->acceptor_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->acceptor_address.value = (char *) address; + address[0] = ((to_addr & 0xff000000) >> 24); + address[1] = ((to_addr & 0xff0000) >> 16); + address[2] = ((to_addr & 0xff00) >> 8); + address[3] = (to_addr & 0xff); + input_chan_bindings->application_data.length = 0; + + major_status = gss_accept_sec_context(&status, + &context_handle, + gss_cred_handle, + &input_token, + input_chan_bindings, + &src_name, + &actual_mech_type, + &output_token, + &ret_flags, + &lifetime_rec, + &gss_delegated_cred_handle); + + + if (major_status != GSS_S_COMPLETE) { + + major_status = gss_display_name(&status, + src_name, + &fullname_buffer, + &fullname_type); + Data(ap, SPX_REJECT, "auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + major_status = gss_display_name(&status, + src_name, + &fullname_buffer, + &fullname_type); + + + Data(ap, SPX_ACCEPT, output_token.value, output_token.length); + auth_finished(ap, AUTH_USER); + break; + + default: + Data(ap, SPX_REJECT, 0, 0); + break; + } +} + + + void +spx_reply(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + + if (cnt-- < 1) + return; + switch (*data++) { + case SPX_REJECT: + if (cnt > 0) { + printf("[ SPX refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ SPX refuses authentication ]\r\n"); + auth_send_retry(); + return; + case SPX_ACCEPT: + printf("[ SPX accepts you ]\r\n"); + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* + * Send over the encrypted challenge. + */ + input_token.value = (char *) data; + input_token.length = cnt; + + major_status = gss_init_sec_context(&status, /* minor stat */ + GSS_C_NO_CREDENTIAL, /* cred handle */ + &actual_ctxhandle, /* ctx handle */ + desired_targname, /* target name */ + GSS_C_NULL_OID, /* mech type */ + req_flags, /* req flags */ + 0, /* time req */ + input_chan_bindings, /* chan binding */ + &input_token, /* input token */ + &actual_mech_type, /* actual mech */ + &output_token, /* output token */ + &ret_flags, /* ret flags */ + &lifetime_rec); /* time rec */ + + if (major_status != GSS_S_COMPLETE) { + gss_display_status(&new_status, + status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + printf("[ SPX mutual response fails ... '%s' ]\r\n", + status_string.value); + auth_send_retry(); + return; + } + } + auth_finished(ap, AUTH_USER); + return; + + default: + return; + } +} + + int +spx_status(ap, name, name_sz, level) + Authenticator *ap; + char *name; + size_t name_sz; + int level; +{ + + gss_buffer_desc fullname_buffer, acl_file_buffer; + gss_OID fullname_type; + char acl_file[160], fullname[160]; + int major_status, status = 0; + struct passwd *pwd; + + /* + * hard code fullname to + * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan" + * and acl_file to "~kannan/.sphinx" + */ + + pwd = k_getpwnam(UserNameRequested); + if (pwd == NULL) { + return(AUTH_USER); /* not authenticated */ + } + + snprintf (acl_file, sizeof(acl_file), + "%s/.sphinx", pwd->pw_dir); + + acl_file_buffer.value = acl_file; + acl_file_buffer.length = strlen(acl_file); + + major_status = gss_display_name(&status, + src_name, + &fullname_buffer, + &fullname_type); + + if (level < AUTH_USER) + return(level); + + major_status = gss__check_acl(&status, &fullname_buffer, + &acl_file_buffer); + + if (major_status == GSS_S_COMPLETE) { + strcpy_truncate(name, UserNameRequested, name_sz); + return(AUTH_VALID); + } else { + return(AUTH_USER); + } + +} + +#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} +#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} + + void +spx_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + int i; + + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; + + switch(data[3]) { + case SPX_REJECT: /* Rejected (reason might follow) */ + strcpy_truncate((char *)buf, " REJECT ", buflen); + goto common; + + case SPX_ACCEPT: /* Accepted (name might follow) */ + strcpy_truncate((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; + + case SPX_AUTH: /* Authentication data follows */ + strcpy_truncate((char *)buf, " AUTH", buflen); + goto common2; + + default: + snprintf(buf, buflen, " %d (unknown)", data[3]); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + snprintf(buf, buflen, " %d", data[i]); + BUMP(buf, buflen); + } + break; + } +} + +#endif + +#ifdef notdef + +prkey(msg, key) + char *msg; + unsigned char *key; +{ + int i; + printf("%s:", msg); + for (i = 0; i < 8; i++) + printf(" %3d", key[i]); + printf("\r\n"); +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/telnet.state b/crypto/kerberosIV/appl/telnet/telnet.state new file mode 100644 index 0000000..1927a2b --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet.state @@ -0,0 +1,80 @@ + + Three pieces of state need to be kept for each side of each option. + (You need the localside, sending WILL/WONT & receiving DO/DONT, and + the remoteside, sending DO/DONT and receiving WILL/WONT) + + MY_STATE: What state am I in? + WANT_STATE: What state do I want? + WANT_RESP: How many requests have I initiated? + + Default values: + MY_STATE = WANT_STATE = DONT + WANT_RESP = 0 + + The local setup will change based on the state of the Telnet + variables. When we are the originator, we can either make the + local setup changes at option request time (in which case if + the option is denied we need to change things back) or when + the option is acknowledged. + + To initiate a switch to NEW_STATE: + + if ((WANT_RESP == 0 && NEW_STATE == MY_STATE) || + WANT_STATE == NEW_STATE) { + do nothing; + } else { + /* + * This is where the logic goes to change the local setup + * if we are doing so at request initiation + */ + WANT_STATE = NEW_STATE; + send NEW_STATE; + WANT_RESP += 1; + } + + When receiving NEW_STATE: + + if (WANT_RESP) { + --WANT_RESP; + if (WANT_RESP && (NEW_STATE == MY_STATE)) + --WANT_RESP; + } + if (WANT_RESP == 0) { + if (NEW_STATE != WANT_STATE) { + /* + * This is where the logic goes to decide if it is ok + * to switch to NEW_STATE, and if so, do any necessary + * local setup changes. + */ + if (ok_to_switch_to NEW_STATE) + WANT_STATE = NEW_STATE; + else + WANT_RESP++; +* if (MY_STATE != WANT_STATE) + reply with WANT_STATE; + } else { + /* + * This is where the logic goes to change the local setup + * if we are doing so at request acknowledgment + */ + } + } + MY_STATE = NEW_STATE; + +* This if() line is not needed, it should be ok to always do the + "reply with WANT_STATE". With the if() line, asking to turn on + an option that the other side doesn't understand is: + Send DO option + Recv WONT option + Without the if() line, it is: + Send DO option + Recv WONT option + Send DONT option + If the other side does not expect to receive the latter case, + but generates the latter case, then there is a potential for + option negotiation loops. An implementation that does not expect + to get the second case should not generate it, an implementation + that does expect to get it may or may not generate it, and things + will still work. Being conservative in what we send, we have the + if() statement in, but we expect the other side to generate the + last response. diff --git a/crypto/kerberosIV/appl/telnet/telnet/Makefile.am b/crypto/kerberosIV/appl/telnet/telnet/Makefile.am new file mode 100644 index 0000000..882aa24 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/Makefile.am @@ -0,0 +1,20 @@ +# $Id: Makefile.am,v 1.12 1999/06/23 12:37:58 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += -I$(srcdir)/.. $(INCLUDE_krb4) + +bin_PROGRAMS = telnet + +CHECK_LOCAL = + +telnet_SOURCES = authenc.c commands.c main.c network.c ring.c \ + sys_bsd.c telnet.c terminal.c \ + utilities.c defines.h externs.h ring.h telnet_locl.h types.h + +LDADD = ../libtelnet/libtelnet.a \ + $(LIB_krb5) \ + $(LIB_krb4) \ + $(top_builddir)/lib/des/libdes.la \ + $(LIB_tgetent) \ + $(LIB_roken) diff --git a/crypto/kerberosIV/appl/telnet/telnet/Makefile.in b/crypto/kerberosIV/appl/telnet/telnet/Makefile.in new file mode 100644 index 0000000..4da3e05 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/Makefile.in @@ -0,0 +1,75 @@ +# $Id: Makefile.in,v 1.34 1999/03/11 13:50:09 joda Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh + +CC = @CC@ +LINK = @LINK@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ +LD_FLAGS = @LD_FLAGS@ +LIBS = @LIBS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +PROGS = telnet$(EXECSUFFIX) + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +SOURCES=authenc.c commands.c main.c network.c ring.c \ + sys_bsd.c telnet.c terminal.c \ + utilities.c + +OBJECTS=authenc.o commands.o main.o network.o ring.o sys_bsd.o \ + telnet.o terminal.o utilities.o + +libtop=@libtop@ + +LIBKRB = -L../../../lib/krb -lkrb +LIBDES = -L../../../lib/des -ldes +LIBROKEN = -L../../../lib/roken -lroken + +KLIB=$(LIBKRB) $(LIBDES) + + +all: $(PROGS) + +.c.o: + $(CC) -c $(DEFS) -I../../../include -I.. -I$(srcdir)/.. $(CFLAGS) $(CPPFLAGS) $< + +telnet$(EXECSUFFIX): $(OBJECTS) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS) -L../libtelnet -ltelnet $(KLIB) $(LIBROKEN) $(LIBS) @LIB_tgetent@ $(LIBROKEN) + +install: all + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) + for x in $(PROGS); do \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROGS); do \ + rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ + done + +TAGS: $(SOURCES) + etags $(SOURCES) + +clean cleandir: + rm -f *.o *.a telnet$(EXECSUFFIX) \#* *~ core + +distclean: clean + rm -f Makefile *~ + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/telnet/telnet/authenc.c b/crypto/kerberosIV/appl/telnet/telnet/authenc.c new file mode 100644 index 0000000..08da93d --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/authenc.c @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnet_locl.h" + +RCSID("$Id: authenc.c,v 1.9 1999/03/19 23:13:51 assar Exp $"); + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) +int +telnet_net_write(unsigned char *str, int len) +{ + if (NETROOM() > len) { + ring_supply_data(&netoring, str, len); + if (str[0] == IAC && str[1] == SE) + printsub('>', &str[2], len-2); + return(len); + } + return(0); +} + +void +net_encrypt(void) +{ +#if defined(ENCRYPTION) + if (encrypt_output) + ring_encrypt(&netoring, encrypt_output); + else + ring_clearto(&netoring); +#endif +} + +int +telnet_spin(void) +{ + return(-1); +} + +char * +telnet_getenv(char *val) +{ + return((char *)env_getvalue((unsigned char *)val)); +} + +char * +telnet_gets(char *prompt, char *result, int length, int echo) +{ + int om = globalmode; + char *res; + + TerminalNewMode(-1); + if (echo) { + printf("%s", prompt); + res = fgets(result, length, stdin); + } else if ((res = getpass(prompt))) { + strcpy_truncate(result, res, length); + res = result; + } + TerminalNewMode(om); + return(res); +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/telnet/commands.c b/crypto/kerberosIV/appl/telnet/telnet/commands.c new file mode 100644 index 0000000..57803fa --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/commands.c @@ -0,0 +1,2693 @@ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnet_locl.h" + +RCSID("$Id: commands.c,v 1.53 1999/07/07 14:56:17 assar Exp $"); + +#if defined(IPPROTO_IP) && defined(IP_TOS) +int tos = -1; +#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ + +char *hostname; +static char _hostname[MaxHostNameLen]; + +typedef int (*intrtn_t)(int, char**); +static int call(intrtn_t, ...); + +typedef struct { + char *name; /* command name */ + char *help; /* help string (NULL for no help) */ + int (*handler)(); /* routine which executes command */ + int needconnect; /* Do we need to be connected to execute? */ +} Command; + +static char line[256]; +static char saveline[256]; +static int margc; +static char *margv[20]; + +static void +makeargv() +{ + char *cp, *cp2, c; + char **argp = margv; + + margc = 0; + cp = line; + if (*cp == '!') { /* Special case shell escape */ + /* save for shell command */ + strcpy_truncate(saveline, line, sizeof(saveline)); + *argp++ = "!"; /* No room in string to get this */ + margc++; + cp++; + } + while ((c = *cp)) { + int inquote = 0; + while (isspace(c)) + c = *++cp; + if (c == '\0') + break; + *argp++ = cp; + margc += 1; + for (cp2 = cp; c != '\0'; c = *++cp) { + if (inquote) { + if (c == inquote) { + inquote = 0; + continue; + } + } else { + if (c == '\\') { + if ((c = *++cp) == '\0') + break; + } else if (c == '"') { + inquote = '"'; + continue; + } else if (c == '\'') { + inquote = '\''; + continue; + } else if (isspace(c)) + break; + } + *cp2++ = c; + } + *cp2 = '\0'; + if (c == '\0') + break; + cp++; + } + *argp++ = 0; +} + +/* + * Make a character string into a number. + * + * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). + */ + +static char +special(char *s) +{ + char c; + char b; + + switch (*s) { + case '^': + b = *++s; + if (b == '?') { + c = b | 0x40; /* DEL */ + } else { + c = b & 0x1f; + } + break; + default: + c = *s; + break; + } + return c; +} + +/* + * Construct a control character sequence + * for a special character. + */ +static char * +control(cc_t c) +{ + static char buf[5]; + /* + * The only way I could get the Sun 3.5 compiler + * to shut up about + * if ((unsigned int)c >= 0x80) + * was to assign "c" to an unsigned int variable... + * Arggg.... + */ + unsigned int uic = (unsigned int)c; + + if (uic == 0x7f) + return ("^?"); + if (c == (cc_t)_POSIX_VDISABLE) { + return "off"; + } + if (uic >= 0x80) { + buf[0] = '\\'; + buf[1] = ((c>>6)&07) + '0'; + buf[2] = ((c>>3)&07) + '0'; + buf[3] = (c&07) + '0'; + buf[4] = 0; + } else if (uic >= 0x20) { + buf[0] = c; + buf[1] = 0; + } else { + buf[0] = '^'; + buf[1] = '@'+c; + buf[2] = 0; + } + return (buf); +} + + + +/* + * The following are data structures and routines for + * the "send" command. + * + */ + +struct sendlist { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + int needconnect; /* Need to be connected */ + int narg; /* Number of arguments */ + int (*handler)(); /* Routine to perform (for special ops) */ + int nbyte; /* Number of bytes to send this command */ + int what; /* Character to be sent (<0 ==> special) */ +}; + + +static int + send_esc (void), + send_help (void), + send_docmd (char *), + send_dontcmd (char *), + send_willcmd (char *), + send_wontcmd (char *); + +static struct sendlist Sendlist[] = { + { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, + { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, + { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, + { "break", 0, 1, 0, 0, 2, BREAK }, + { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, + { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, + { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, + { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, + { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, + { "intp", 0, 1, 0, 0, 2, IP }, + { "interrupt", 0, 1, 0, 0, 2, IP }, + { "intr", 0, 1, 0, 0, 2, IP }, + { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, + { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, + { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, + { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, + { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, + { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, + { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, + { "?", "Display send options", 0, 0, send_help, 0, 0 }, + { "help", 0, 0, 0, send_help, 0, 0 }, + { "do", 0, 0, 1, send_docmd, 3, 0 }, + { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, + { "will", 0, 0, 1, send_willcmd, 3, 0 }, + { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, + { 0 } +}; + +#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ + sizeof(struct sendlist))) + +static int +sendcmd(int argc, char **argv) +{ + int count; /* how many bytes we are going to need to send */ + int i; + struct sendlist *s; /* pointer to current command */ + int success = 0; + int needconnect = 0; + + if (argc < 2) { + printf("need at least one argument for 'send' command\r\n"); + printf("'send ?' for help\r\n"); + return 0; + } + /* + * First, validate all the send arguments. + * In addition, we see how much space we are going to need, and + * whether or not we will be doing a "SYNCH" operation (which + * flushes the network queue). + */ + count = 0; + for (i = 1; i < argc; i++) { + s = GETSEND(argv[i]); + if (s == 0) { + printf("Unknown send argument '%s'\r\n'send ?' for help.\r\n", + argv[i]); + return 0; + } else if (Ambiguous(s)) { + printf("Ambiguous send argument '%s'\r\n'send ?' for help.\r\n", + argv[i]); + return 0; + } + if (i + s->narg >= argc) { + fprintf(stderr, + "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\r\n", + s->narg, s->narg == 1 ? "" : "s", s->name, s->name); + return 0; + } + count += s->nbyte; + if (s->handler == send_help) { + send_help(); + return 0; + } + + i += s->narg; + needconnect += s->needconnect; + } + if (!connected && needconnect) { + printf("?Need to be connected first.\r\n"); + printf("'send ?' for help\r\n"); + return 0; + } + /* Now, do we have enough room? */ + if (NETROOM() < count) { + printf("There is not enough room in the buffer TO the network\r\n"); + printf("to process your request. Nothing will be done.\r\n"); + printf("('send synch' will throw away most data in the network\r\n"); + printf("buffer, if this might help.)\r\n"); + return 0; + } + /* OK, they are all OK, now go through again and actually send */ + count = 0; + for (i = 1; i < argc; i++) { + if ((s = GETSEND(argv[i])) == 0) { + fprintf(stderr, "Telnet 'send' error - argument disappeared!\r\n"); + quit(); + /*NOTREACHED*/ + } + if (s->handler) { + count++; + success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, + (s->narg > 1) ? argv[i+2] : 0); + i += s->narg; + } else { + NET2ADD(IAC, s->what); + printoption("SENT", IAC, s->what); + } + } + return (count == success); +} + +static int +send_tncmd(void (*func)(), char *cmd, char *name); + +static int +send_esc() +{ + NETADD(escape); + return 1; +} + +static int +send_docmd(char *name) +{ + return(send_tncmd(send_do, "do", name)); +} + +static int +send_dontcmd(char *name) +{ + return(send_tncmd(send_dont, "dont", name)); +} + +static int +send_willcmd(char *name) +{ + return(send_tncmd(send_will, "will", name)); +} + +static int +send_wontcmd(char *name) +{ + return(send_tncmd(send_wont, "wont", name)); +} + +static int +send_tncmd(void (*func)(), char *cmd, char *name) +{ + char **cpp; + extern char *telopts[]; + int val = 0; + + if (isprefix(name, "help") || isprefix(name, "?")) { + int col, len; + + printf("Usage: send %s <value|option>\r\n", cmd); + printf("\"value\" must be from 0 to 255\r\n"); + printf("Valid options are:\r\n\t"); + + col = 8; + for (cpp = telopts; *cpp; cpp++) { + len = strlen(*cpp) + 3; + if (col + len > 65) { + printf("\r\n\t"); + col = 8; + } + printf(" \"%s\"", *cpp); + col += len; + } + printf("\r\n"); + return 0; + } + cpp = genget(name, telopts, sizeof(char *)); + if (Ambiguous(cpp)) { + fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\r\n", + name, cmd); + return 0; + } + if (cpp) { + val = cpp - telopts; + } else { + char *cp = name; + + while (*cp >= '0' && *cp <= '9') { + val *= 10; + val += *cp - '0'; + cp++; + } + if (*cp != 0) { + fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\r\n", + name, cmd); + return 0; + } else if (val < 0 || val > 255) { + fprintf(stderr, "'%s': bad value ('send %s ?' for help).\r\n", + name, cmd); + return 0; + } + } + if (!connected) { + printf("?Need to be connected first.\r\n"); + return 0; + } + (*func)(val, 1); + return 1; +} + +static int +send_help() +{ + struct sendlist *s; /* pointer to current command */ + for (s = Sendlist; s->name; s++) { + if (s->help) + printf("%-15s %s\r\n", s->name, s->help); + } + return(0); +} + +/* + * The following are the routines and data structures referred + * to by the arguments to the "toggle" command. + */ + +static int +lclchars() +{ + donelclchars = 1; + return 1; +} + +static int +togdebug() +{ +#ifndef NOT43 + if (net > 0 && + (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { + perror("setsockopt (SO_DEBUG)"); + } +#else /* NOT43 */ + if (debug) { + if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) + perror("setsockopt (SO_DEBUG)"); + } else + printf("Cannot turn off socket debugging\r\n"); +#endif /* NOT43 */ + return 1; +} + +#if defined(KRB4) && defined(HAVE_KRB_DISABLE_DEBUG) +#include <krb.h> + +static int +togkrbdebug(void) +{ + if(krb_debug) + krb_enable_debug(); + else + krb_disable_debug(); + return 1; +} +#endif + +static int +togcrlf() +{ + if (crlf) { + printf("Will send carriage returns as telnet <CR><LF>.\r\n"); + } else { + printf("Will send carriage returns as telnet <CR><NUL>.\r\n"); + } + return 1; +} + +int binmode; + +static int +togbinary(int val) +{ + donebinarytoggle = 1; + + if (val >= 0) { + binmode = val; + } else { + if (my_want_state_is_will(TELOPT_BINARY) && + my_want_state_is_do(TELOPT_BINARY)) { + binmode = 1; + } else if (my_want_state_is_wont(TELOPT_BINARY) && + my_want_state_is_dont(TELOPT_BINARY)) { + binmode = 0; + } + val = binmode ? 0 : 1; + } + + if (val == 1) { + if (my_want_state_is_will(TELOPT_BINARY) && + my_want_state_is_do(TELOPT_BINARY)) { + printf("Already operating in binary mode with remote host.\r\n"); + } else { + printf("Negotiating binary mode with remote host.\r\n"); + tel_enter_binary(3); + } + } else { + if (my_want_state_is_wont(TELOPT_BINARY) && + my_want_state_is_dont(TELOPT_BINARY)) { + printf("Already in network ascii mode with remote host.\r\n"); + } else { + printf("Negotiating network ascii mode with remote host.\r\n"); + tel_leave_binary(3); + } + } + return 1; +} + +static int +togrbinary(int val) +{ + donebinarytoggle = 1; + + if (val == -1) + val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; + + if (val == 1) { + if (my_want_state_is_do(TELOPT_BINARY)) { + printf("Already receiving in binary mode.\r\n"); + } else { + printf("Negotiating binary mode on input.\r\n"); + tel_enter_binary(1); + } + } else { + if (my_want_state_is_dont(TELOPT_BINARY)) { + printf("Already receiving in network ascii mode.\r\n"); + } else { + printf("Negotiating network ascii mode on input.\r\n"); + tel_leave_binary(1); + } + } + return 1; +} + +static int +togxbinary(int val) +{ + donebinarytoggle = 1; + + if (val == -1) + val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; + + if (val == 1) { + if (my_want_state_is_will(TELOPT_BINARY)) { + printf("Already transmitting in binary mode.\r\n"); + } else { + printf("Negotiating binary mode on output.\r\n"); + tel_enter_binary(2); + } + } else { + if (my_want_state_is_wont(TELOPT_BINARY)) { + printf("Already transmitting in network ascii mode.\r\n"); + } else { + printf("Negotiating network ascii mode on output.\r\n"); + tel_leave_binary(2); + } + } + return 1; +} + + +static int togglehelp (void); +#if defined(AUTHENTICATION) +extern int auth_togdebug (int); +#endif +#if defined(ENCRYPTION) +extern int EncryptAutoEnc (int); +extern int EncryptAutoDec (int); +extern int EncryptDebug (int); +extern int EncryptVerbose (int); +#endif + +struct togglelist { + char *name; /* name of toggle */ + char *help; /* help message */ + int (*handler)(); /* routine to do actual setting */ + int *variable; + char *actionexplanation; +}; + +static struct togglelist Togglelist[] = { + { "autoflush", + "flushing of output when sending interrupt characters", + 0, + &autoflush, + "flush output when sending interrupt characters" }, + { "autosynch", + "automatic sending of interrupt characters in urgent mode", + 0, + &autosynch, + "send interrupt characters in urgent mode" }, +#if defined(AUTHENTICATION) + { "autologin", + "automatic sending of login and/or authentication info", + 0, + &autologin, + "send login name and/or authentication information" }, + { "authdebug", + "Toggle authentication debugging", + auth_togdebug, + 0, + "print authentication debugging information" }, +#endif +#if defined(ENCRYPTION) + { "autoencrypt", + "automatic encryption of data stream", + EncryptAutoEnc, + 0, + "automatically encrypt output" }, + { "autodecrypt", + "automatic decryption of data stream", + EncryptAutoDec, + 0, + "automatically decrypt input" }, + { "verbose_encrypt", + "Toggle verbose encryption output", + EncryptVerbose, + 0, + "print verbose encryption output" }, + { "encdebug", + "Toggle encryption debugging", + EncryptDebug, + 0, + "print encryption debugging information" }, +#endif + { "skiprc", + "don't read ~/.telnetrc file", + 0, + &skiprc, + "skip reading of ~/.telnetrc file" }, + { "binary", + "sending and receiving of binary data", + togbinary, + 0, + 0 }, + { "inbinary", + "receiving of binary data", + togrbinary, + 0, + 0 }, + { "outbinary", + "sending of binary data", + togxbinary, + 0, + 0 }, + { "crlf", + "sending carriage returns as telnet <CR><LF>", + togcrlf, + &crlf, + 0 }, + { "crmod", + "mapping of received carriage returns", + 0, + &crmod, + "map carriage return on output" }, + { "localchars", + "local recognition of certain control characters", + lclchars, + &localchars, + "recognize certain control characters" }, + { " ", "", 0 }, /* empty line */ + { "debug", + "debugging", + togdebug, + &debug, + "turn on socket level debugging" }, +#if defined(KRB4) && defined(HAVE_KRB_DISABLE_DEBUG) + { "krb_debug", + "kerberos 4 debugging", + togkrbdebug, + &krb_debug, + "turn on kerberos 4 debugging" }, +#endif + { "netdata", + "printing of hexadecimal network data (debugging)", + 0, + &netdata, + "print hexadecimal representation of network traffic" }, + { "prettydump", + "output of \"netdata\" to user readable format (debugging)", + 0, + &prettydump, + "print user readable output for \"netdata\"" }, + { "options", + "viewing of options processing (debugging)", + 0, + &showoptions, + "show option processing" }, + { "termdata", + "(debugging) toggle printing of hexadecimal terminal data", + 0, + &termdata, + "print hexadecimal representation of terminal traffic" }, + { "?", + 0, + togglehelp }, + { "help", + 0, + togglehelp }, + { 0 } +}; + +static int +togglehelp() +{ + struct togglelist *c; + + for (c = Togglelist; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s toggle %s\r\n", c->name, c->help); + else + printf("\r\n"); + } + } + printf("\r\n"); + printf("%-15s %s\r\n", "?", "display help information"); + return 0; +} + +static void +settogglehelp(int set) +{ + struct togglelist *c; + + for (c = Togglelist; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s %s\r\n", c->name, set ? "enable" : "disable", + c->help); + else + printf("\r\n"); + } + } +} + +#define GETTOGGLE(name) (struct togglelist *) \ + genget(name, (char **) Togglelist, sizeof(struct togglelist)) + +static int +toggle(int argc, char *argv[]) +{ + int retval = 1; + char *name; + struct togglelist *c; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'toggle' command. 'toggle ?' for help.\r\n"); + return 0; + } + argc--; + argv++; + while (argc--) { + name = *argv++; + c = GETTOGGLE(name); + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\r\n", + name); + return 0; + } else if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\r\n", + name); + return 0; + } else { + if (c->variable) { + *c->variable = !*c->variable; /* invert it */ + if (c->actionexplanation) { + printf("%s %s.\r\n", *c->variable? "Will" : "Won't", + c->actionexplanation); + } + } + if (c->handler) { + retval &= (*c->handler)(-1); + } + } + } + return retval; +} + +/* + * The following perform the "set" command. + */ + +struct termios new_tc = { 0 }; + +struct setlist { + char *name; /* name */ + char *help; /* help information */ + void (*handler)(); + cc_t *charp; /* where it is located at */ +}; + +static struct setlist Setlist[] = { +#ifdef KLUDGELINEMODE + { "echo", "character to toggle local echoing on/off", 0, &echoc }, +#endif + { "escape", "character to escape back to telnet command mode", 0, &escape }, + { "rlogin", "rlogin escape character", 0, &rlogin }, + { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, + { " ", "" }, + { " ", "The following need 'localchars' to be toggled true", 0, 0 }, + { "flushoutput", "character to cause an Abort Output", 0, &termFlushChar }, + { "interrupt", "character to cause an Interrupt Process", 0, &termIntChar }, + { "quit", "character to cause an Abort process", 0, &termQuitChar }, + { "eof", "character to cause an EOF ", 0, &termEofChar }, + { " ", "" }, + { " ", "The following are for local editing in linemode", 0, 0 }, + { "erase", "character to use to erase a character", 0, &termEraseChar }, + { "kill", "character to use to erase a line", 0, &termKillChar }, + { "lnext", "character to use for literal next", 0, &termLiteralNextChar }, + { "susp", "character to cause a Suspend Process", 0, &termSuspChar }, + { "reprint", "character to use for line reprint", 0, &termRprntChar }, + { "worderase", "character to use to erase a word", 0, &termWerasChar }, + { "start", "character to use for XON", 0, &termStartChar }, + { "stop", "character to use for XOFF", 0, &termStopChar }, + { "forw1", "alternate end of line character", 0, &termForw1Char }, + { "forw2", "alternate end of line character", 0, &termForw2Char }, + { "ayt", "alternate AYT character", 0, &termAytChar }, + { 0 } +}; + +static struct setlist * +getset(char *name) +{ + return (struct setlist *) + genget(name, (char **) Setlist, sizeof(struct setlist)); +} + +void +set_escape_char(char *s) +{ + if (rlogin != _POSIX_VDISABLE) { + rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; + printf("Telnet rlogin escape character is '%s'.\r\n", + control(rlogin)); + } else { + escape = (s && *s) ? special(s) : _POSIX_VDISABLE; + printf("Telnet escape character is '%s'.\r\n", control(escape)); + } +} + +static int +setcmd(int argc, char *argv[]) +{ + int value; + struct setlist *ct; + struct togglelist *c; + + if (argc < 2 || argc > 3) { + printf("Format is 'set Name Value'\r\n'set ?' for help.\r\n"); + return 0; + } + if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { + for (ct = Setlist; ct->name; ct++) + printf("%-15s %s\r\n", ct->name, ct->help); + printf("\r\n"); + settogglehelp(1); + printf("%-15s %s\r\n", "?", "display help information"); + return 0; + } + + ct = getset(argv[1]); + if (ct == 0) { + c = GETTOGGLE(argv[1]); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('set ?' for help).\r\n", + argv[1]); + return 0; + } else if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\r\n", + argv[1]); + return 0; + } + if (c->variable) { + if ((argc == 2) || (strcmp("on", argv[2]) == 0)) + *c->variable = 1; + else if (strcmp("off", argv[2]) == 0) + *c->variable = 0; + else { + printf("Format is 'set togglename [on|off]'\r\n'set ?' for help.\r\n"); + return 0; + } + if (c->actionexplanation) { + printf("%s %s.\r\n", *c->variable? "Will" : "Won't", + c->actionexplanation); + } + } + if (c->handler) + (*c->handler)(1); + } else if (argc != 3) { + printf("Format is 'set Name Value'\r\n'set ?' for help.\r\n"); + return 0; + } else if (Ambiguous(ct)) { + fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\r\n", + argv[1]); + return 0; + } else if (ct->handler) { + (*ct->handler)(argv[2]); + printf("%s set to \"%s\".\r\n", ct->name, (char *)ct->charp); + } else { + if (strcmp("off", argv[2])) { + value = special(argv[2]); + } else { + value = _POSIX_VDISABLE; + } + *(ct->charp) = (cc_t)value; + printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp))); + } + slc_check(); + return 1; +} + +static int +unsetcmd(int argc, char *argv[]) +{ + struct setlist *ct; + struct togglelist *c; + char *name; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'unset' command. 'unset ?' for help.\r\n"); + return 0; + } + if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { + for (ct = Setlist; ct->name; ct++) + printf("%-15s %s\r\n", ct->name, ct->help); + printf("\r\n"); + settogglehelp(0); + printf("%-15s %s\r\n", "?", "display help information"); + return 0; + } + + argc--; + argv++; + while (argc--) { + name = *argv++; + ct = getset(name); + if (ct == 0) { + c = GETTOGGLE(name); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\r\n", + name); + return 0; + } else if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\r\n", + name); + return 0; + } + if (c->variable) { + *c->variable = 0; + if (c->actionexplanation) { + printf("%s %s.\r\n", *c->variable? "Will" : "Won't", + c->actionexplanation); + } + } + if (c->handler) + (*c->handler)(0); + } else if (Ambiguous(ct)) { + fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\r\n", + name); + return 0; + } else if (ct->handler) { + (*ct->handler)(0); + printf("%s reset to \"%s\".\r\n", ct->name, (char *)ct->charp); + } else { + *(ct->charp) = _POSIX_VDISABLE; + printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp))); + } + } + return 1; +} + +/* + * The following are the data structures and routines for the + * 'mode' command. + */ +#ifdef KLUDGELINEMODE +extern int kludgelinemode; + +static int +dokludgemode(void) +{ + kludgelinemode = 1; + send_wont(TELOPT_LINEMODE, 1); + send_dont(TELOPT_SGA, 1); + send_dont(TELOPT_ECHO, 1); + return 1; +} +#endif + +static int +dolinemode() +{ +#ifdef KLUDGELINEMODE + if (kludgelinemode) + send_dont(TELOPT_SGA, 1); +#endif + send_will(TELOPT_LINEMODE, 1); + send_dont(TELOPT_ECHO, 1); + return 1; +} + +static int +docharmode() +{ +#ifdef KLUDGELINEMODE + if (kludgelinemode) + send_do(TELOPT_SGA, 1); + else +#endif + send_wont(TELOPT_LINEMODE, 1); + send_do(TELOPT_ECHO, 1); + return 1; +} + +static int +dolmmode(int bit, int on) +{ + unsigned char c; + extern int linemode; + + if (my_want_state_is_wont(TELOPT_LINEMODE)) { + printf("?Need to have LINEMODE option enabled first.\r\n"); + printf("'mode ?' for help.\r\n"); + return 0; + } + + if (on) + c = (linemode | bit); + else + c = (linemode & ~bit); + lm_mode(&c, 1, 1); + return 1; +} + +static int +tn_setmode(int bit) +{ + return dolmmode(bit, 1); +} + +static int +tn_clearmode(int bit) +{ + return dolmmode(bit, 0); +} + +struct modelist { + char *name; /* command name */ + char *help; /* help string */ + int (*handler)(); /* routine which executes command */ + int needconnect; /* Do we need to be connected to execute? */ + int arg1; +}; + +static int modehelp(void); + +static struct modelist ModeList[] = { + { "character", "Disable LINEMODE option", docharmode, 1 }, +#ifdef KLUDGELINEMODE + { "", "(or disable obsolete line-by-line mode)", 0 }, +#endif + { "line", "Enable LINEMODE option", dolinemode, 1 }, +#ifdef KLUDGELINEMODE + { "", "(or enable obsolete line-by-line mode)", 0 }, +#endif + { "", "", 0 }, + { "", "These require the LINEMODE option to be enabled", 0 }, + { "isig", "Enable signal trapping", tn_setmode, 1, MODE_TRAPSIG }, + { "+isig", 0, tn_setmode, 1, MODE_TRAPSIG }, + { "-isig", "Disable signal trapping", tn_clearmode, 1, MODE_TRAPSIG }, + { "edit", "Enable character editing", tn_setmode, 1, MODE_EDIT }, + { "+edit", 0, tn_setmode, 1, MODE_EDIT }, + { "-edit", "Disable character editing", tn_clearmode, 1, MODE_EDIT }, + { "softtabs", "Enable tab expansion", tn_setmode, 1, MODE_SOFT_TAB }, + { "+softtabs", 0, tn_setmode, 1, MODE_SOFT_TAB }, + { "-softtabs", "Disable character editing", tn_clearmode, 1, MODE_SOFT_TAB }, + { "litecho", "Enable literal character echo", tn_setmode, 1, MODE_LIT_ECHO }, + { "+litecho", 0, tn_setmode, 1, MODE_LIT_ECHO }, + { "-litecho", "Disable literal character echo", tn_clearmode, 1, MODE_LIT_ECHO }, + { "help", 0, modehelp, 0 }, +#ifdef KLUDGELINEMODE + { "kludgeline", 0, dokludgemode, 1 }, +#endif + { "", "", 0 }, + { "?", "Print help information", modehelp, 0 }, + { 0 }, +}; + + +static int +modehelp(void) +{ + struct modelist *mt; + + printf("format is: 'mode Mode', where 'Mode' is one of:\r\n\r\n"); + for (mt = ModeList; mt->name; mt++) { + if (mt->help) { + if (*mt->help) + printf("%-15s %s\r\n", mt->name, mt->help); + else + printf("\r\n"); + } + } + return 0; +} + +#define GETMODECMD(name) (struct modelist *) \ + genget(name, (char **) ModeList, sizeof(struct modelist)) + +static int +modecmd(int argc, char **argv) +{ + struct modelist *mt; + + if (argc != 2) { + printf("'mode' command requires an argument\r\n"); + printf("'mode ?' for help.\r\n"); + } else if ((mt = GETMODECMD(argv[1])) == 0) { + fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\r\n", argv[1]); + } else if (Ambiguous(mt)) { + fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\r\n", argv[1]); + } else if (mt->needconnect && !connected) { + printf("?Need to be connected first.\r\n"); + printf("'mode ?' for help.\r\n"); + } else if (mt->handler) { + return (*mt->handler)(mt->arg1); + } + return 0; +} + +/* + * The following data structures and routines implement the + * "display" command. + */ + +static int +display(int argc, char *argv[]) +{ + struct togglelist *tl; + struct setlist *sl; + +#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ + if (*tl->variable) { \ + printf("will"); \ + } else { \ + printf("won't"); \ + } \ + printf(" %s.\r\n", tl->actionexplanation); \ + } + +#define doset(sl) if (sl->name && *sl->name != ' ') { \ + if (sl->handler == 0) \ + printf("%-15s [%s]\r\n", sl->name, control(*sl->charp)); \ + else \ + printf("%-15s \"%s\"\r\n", sl->name, (char *)sl->charp); \ + } + + if (argc == 1) { + for (tl = Togglelist; tl->name; tl++) { + dotog(tl); + } + printf("\r\n"); + for (sl = Setlist; sl->name; sl++) { + doset(sl); + } + } else { + int i; + + for (i = 1; i < argc; i++) { + sl = getset(argv[i]); + tl = GETTOGGLE(argv[i]); + if (Ambiguous(sl) || Ambiguous(tl)) { + printf("?Ambiguous argument '%s'.\r\n", argv[i]); + return 0; + } else if (!sl && !tl) { + printf("?Unknown argument '%s'.\r\n", argv[i]); + return 0; + } else { + if (tl) { + dotog(tl); + } + if (sl) { + doset(sl); + } + } + } + } +/*@*/optionstatus(); +#if defined(ENCRYPTION) + EncryptStatus(); +#endif + return 1; +#undef doset +#undef dotog +} + +/* + * The following are the data structures, and many of the routines, + * relating to command processing. + */ + +/* + * Set the escape character. + */ +static int +setescape(int argc, char *argv[]) +{ + char *arg; + char buf[50]; + + printf( + "Deprecated usage - please use 'set escape%s%s' in the future.\r\n", + (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); + if (argc > 2) + arg = argv[1]; + else { + printf("new escape character: "); + fgets(buf, sizeof(buf), stdin); + arg = buf; + } + if (arg[0] != '\0') + escape = arg[0]; + printf("Escape character is '%s'.\r\n", control(escape)); + + fflush(stdout); + return 1; +} + +static int +togcrmod() +{ + crmod = !crmod; + printf("Deprecated usage - please use 'toggle crmod' in the future.\r\n"); + printf("%s map carriage return on output.\r\n", crmod ? "Will" : "Won't"); + fflush(stdout); + return 1; +} + +static int +telnetsuspend() +{ +#ifdef SIGTSTP + setcommandmode(); + { + long oldrows, oldcols, newrows, newcols, err; + + err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + kill(0, SIGTSTP); + /* + * If we didn't get the window size before the SUSPEND, but we + * can get them now (?), then send the NAWS to make sure that + * we are set up for the right window size. + */ + if (TerminalWindowSize(&newrows, &newcols) && connected && + (err || ((oldrows != newrows) || (oldcols != newcols)))) { + sendnaws(); + } + } + /* reget parameters in case they were changed */ + TerminalSaveState(); + setconnmode(0); +#else + printf("Suspend is not supported. Try the '!' command instead\r\n"); +#endif + return 1; +} + +static int +shell(int argc, char **argv) +{ + long oldrows, oldcols, newrows, newcols, err; + + setcommandmode(); + + err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + switch(fork()) { + case -1: + perror("Fork failed\r\n"); + break; + + case 0: + { + /* + * Fire up the shell in the child. + */ + char *shellp, *shellname; + + shellp = getenv("SHELL"); + if (shellp == NULL) + shellp = "/bin/sh"; + if ((shellname = strrchr(shellp, '/')) == 0) + shellname = shellp; + else + shellname++; + if (argc > 1) + execl(shellp, shellname, "-c", &saveline[1], 0); + else + execl(shellp, shellname, 0); + perror("Execl"); + _exit(1); + } + default: + wait((int *)0); /* Wait for the shell to complete */ + + if (TerminalWindowSize(&newrows, &newcols) && connected && + (err || ((oldrows != newrows) || (oldcols != newcols)))) { + sendnaws(); + } + break; + } + return 1; +} + +static int +bye(int argc, char **argv) +{ + extern int resettermname; + + if (connected) { + shutdown(net, 2); + printf("Connection closed.\r\n"); + NetClose(net); + connected = 0; + resettermname = 1; +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + auth_encrypt_connect(connected); +#endif + /* reset options */ + tninit(); + } + if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) + longjmp(toplevel, 1); + return 0; /* NOTREACHED */ +} + +int +quit(void) +{ + call(bye, "bye", "fromquit", 0); + Exit(0); + return 0; /*NOTREACHED*/ +} + +static int +logout() +{ + send_do(TELOPT_LOGOUT, 1); + netflush(); + return 1; +} + + +/* + * The SLC command. + */ + +struct slclist { + char *name; + char *help; + void (*handler)(); + int arg; +}; + +static void slc_help(void); + +struct slclist SlcList[] = { + { "export", "Use local special character definitions", + slc_mode_export, 0 }, + { "import", "Use remote special character definitions", + slc_mode_import, 1 }, + { "check", "Verify remote special character definitions", + slc_mode_import, 0 }, + { "help", 0, slc_help, 0 }, + { "?", "Print help information", slc_help, 0 }, + { 0 }, +}; + +static void +slc_help(void) +{ + struct slclist *c; + + for (c = SlcList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\r\n", c->name, c->help); + else + printf("\r\n"); + } + } +} + +static struct slclist * +getslc(char *name) +{ + return (struct slclist *) + genget(name, (char **) SlcList, sizeof(struct slclist)); +} + +static int +slccmd(int argc, char **argv) +{ + struct slclist *c; + + if (argc != 2) { + fprintf(stderr, + "Need an argument to 'slc' command. 'slc ?' for help.\r\n"); + return 0; + } + c = getslc(argv[1]); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\r\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\r\n", + argv[1]); + return 0; + } + (*c->handler)(c->arg); + slcstate(); + return 1; +} + +/* + * The ENVIRON command. + */ + +struct envlist { + char *name; + char *help; + void (*handler)(); + int narg; +}; + +static void env_help (void); + +struct envlist EnvList[] = { + { "define", "Define an environment variable", + (void (*)())env_define, 2 }, + { "undefine", "Undefine an environment variable", + env_undefine, 1 }, + { "export", "Mark an environment variable for automatic export", + env_export, 1 }, + { "unexport", "Don't mark an environment variable for automatic export", + env_unexport, 1 }, + { "send", "Send an environment variable", env_send, 1 }, + { "list", "List the current environment variables", + env_list, 0 }, + { "help", 0, env_help, 0 }, + { "?", "Print help information", env_help, 0 }, + { 0 }, +}; + +static void +env_help() +{ + struct envlist *c; + + for (c = EnvList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\r\n", c->name, c->help); + else + printf("\r\n"); + } + } +} + +static struct envlist * +getenvcmd(char *name) +{ + return (struct envlist *) + genget(name, (char **) EnvList, sizeof(struct envlist)); +} + +static int +env_cmd(int argc, char **argv) +{ + struct envlist *c; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'environ' command. 'environ ?' for help.\r\n"); + return 0; + } + c = getenvcmd(argv[1]); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\r\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\r\n", + argv[1]); + return 0; + } + if (c->narg + 2 != argc) { + fprintf(stderr, + "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\r\n", + c->narg < argc + 2 ? "only " : "", + c->narg, c->narg == 1 ? "" : "s", c->name); + return 0; + } + (*c->handler)(argv[2], argv[3]); + return 1; +} + +struct env_lst { + struct env_lst *next; /* pointer to next structure */ + struct env_lst *prev; /* pointer to previous structure */ + unsigned char *var; /* pointer to variable name */ + unsigned char *value; /* pointer to variable value */ + int export; /* 1 -> export with default list of variables */ + int welldefined; /* A well defined variable */ +}; + +struct env_lst envlisthead; + +struct env_lst * +env_find(unsigned char *var) +{ + struct env_lst *ep; + + for (ep = envlisthead.next; ep; ep = ep->next) { + if (strcmp((char *)ep->var, (char *)var) == 0) + return(ep); + } + return(NULL); +} + +#if IRIX == 4 +#define environ _environ +#endif + +void +env_init(void) +{ + extern char **environ; + char **epp, *cp; + struct env_lst *ep; + + for (epp = environ; *epp; epp++) { + if ((cp = strchr(*epp, '='))) { + *cp = '\0'; + ep = env_define((unsigned char *)*epp, + (unsigned char *)cp+1); + ep->export = 0; + *cp = '='; + } + } + /* + * Special case for DISPLAY variable. If it is ":0.0" or + * "unix:0.0", we have to get rid of "unix" and insert our + * hostname. + */ + if ((ep = env_find("DISPLAY")) + && (*ep->value == ':' + || strncmp((char *)ep->value, "unix:", 5) == 0)) { + char hbuf[256+1]; + char *cp2 = strchr((char *)ep->value, ':'); + + /* XXX - should be k_gethostname? */ + gethostname(hbuf, 256); + hbuf[256] = '\0'; + + /* If this is not the full name, try to get it via DNS */ + if (strchr(hbuf, '.') == 0) { + struct hostent *he = roken_gethostbyname(hbuf); + if (he != NULL) + strcpy_truncate(hbuf, he->h_name, 256); + } + + asprintf (&cp, "%s%s", hbuf, cp2); + free (ep->value); + ep->value = (unsigned char *)cp; + } + /* + * If USER is not defined, but LOGNAME is, then add + * USER with the value from LOGNAME. By default, we + * don't export the USER variable. + */ + if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { + env_define((unsigned char *)"USER", ep->value); + env_unexport((unsigned char *)"USER"); + } + env_export((unsigned char *)"DISPLAY"); + env_export((unsigned char *)"PRINTER"); + env_export((unsigned char *)"XAUTHORITY"); +} + +struct env_lst * +env_define(unsigned char *var, unsigned char *value) +{ + struct env_lst *ep; + + if ((ep = env_find(var))) { + if (ep->var) + free(ep->var); + if (ep->value) + free(ep->value); + } else { + ep = (struct env_lst *)malloc(sizeof(struct env_lst)); + ep->next = envlisthead.next; + envlisthead.next = ep; + ep->prev = &envlisthead; + if (ep->next) + ep->next->prev = ep; + } + ep->welldefined = opt_welldefined((char *)var); + ep->export = 1; + ep->var = (unsigned char *)strdup((char *)var); + ep->value = (unsigned char *)strdup((char *)value); + return(ep); +} + +void +env_undefine(unsigned char *var) +{ + struct env_lst *ep; + + if ((ep = env_find(var))) { + ep->prev->next = ep->next; + if (ep->next) + ep->next->prev = ep->prev; + if (ep->var) + free(ep->var); + if (ep->value) + free(ep->value); + free(ep); + } +} + +void +env_export(unsigned char *var) +{ + struct env_lst *ep; + + if ((ep = env_find(var))) + ep->export = 1; +} + +void +env_unexport(unsigned char *var) +{ + struct env_lst *ep; + + if ((ep = env_find(var))) + ep->export = 0; +} + +void +env_send(unsigned char *var) +{ + struct env_lst *ep; + + if (my_state_is_wont(TELOPT_NEW_ENVIRON) +#ifdef OLD_ENVIRON + && my_state_is_wont(TELOPT_OLD_ENVIRON) +#endif + ) { + fprintf(stderr, + "Cannot send '%s': Telnet ENVIRON option not enabled\r\n", + var); + return; + } + ep = env_find(var); + if (ep == 0) { + fprintf(stderr, "Cannot send '%s': variable not defined\r\n", + var); + return; + } + env_opt_start_info(); + env_opt_add(ep->var); + env_opt_end(0); +} + +void +env_list(void) +{ + struct env_lst *ep; + + for (ep = envlisthead.next; ep; ep = ep->next) { + printf("%c %-20s %s\r\n", ep->export ? '*' : ' ', + ep->var, ep->value); + } +} + +unsigned char * +env_default(int init, int welldefined) +{ + static struct env_lst *nep = NULL; + + if (init) { + nep = &envlisthead; + return NULL; + } + if (nep) { + while ((nep = nep->next)) { + if (nep->export && (nep->welldefined == welldefined)) + return(nep->var); + } + } + return(NULL); +} + +unsigned char * +env_getvalue(unsigned char *var) +{ + struct env_lst *ep; + + if ((ep = env_find(var))) + return(ep->value); + return(NULL); +} + + +#if defined(AUTHENTICATION) +/* + * The AUTHENTICATE command. + */ + +struct authlist { + char *name; + char *help; + int (*handler)(); + int narg; +}; + +static int + auth_help (void); + +struct authlist AuthList[] = { + { "status", "Display current status of authentication information", + auth_status, 0 }, + { "disable", "Disable an authentication type ('auth disable ?' for more)", + auth_disable, 1 }, + { "enable", "Enable an authentication type ('auth enable ?' for more)", + auth_enable, 1 }, + { "help", 0, auth_help, 0 }, + { "?", "Print help information", auth_help, 0 }, + { 0 }, +}; + +static int +auth_help() +{ + struct authlist *c; + + for (c = AuthList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\r\n", c->name, c->help); + else + printf("\r\n"); + } + } + return 0; +} + +static int +auth_cmd(int argc, char **argv) +{ + struct authlist *c; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'auth' command. 'auth ?' for help.\r\n"); + return 0; + } + + c = (struct authlist *) + genget(argv[1], (char **) AuthList, sizeof(struct authlist)); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\r\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\r\n", + argv[1]); + return 0; + } + if (c->narg + 2 != argc) { + fprintf(stderr, + "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\r\n", + c->narg < argc + 2 ? "only " : "", + c->narg, c->narg == 1 ? "" : "s", c->name); + return 0; + } + return((*c->handler)(argv[2], argv[3])); +} +#endif + + +#if defined(ENCRYPTION) +/* + * The ENCRYPT command. + */ + +struct encryptlist { + char *name; + char *help; + int (*handler)(); + int needconnect; + int minarg; + int maxarg; +}; + +static int + EncryptHelp (void); + +struct encryptlist EncryptList[] = { + { "enable", "Enable encryption. ('encrypt enable ?' for more)", + EncryptEnable, 1, 1, 2 }, + { "disable", "Disable encryption. ('encrypt enable ?' for more)", + EncryptDisable, 0, 1, 2 }, + { "type", "Set encryptiong type. ('encrypt type ?' for more)", + EncryptType, 0, 1, 1 }, + { "start", "Start encryption. ('encrypt start ?' for more)", + EncryptStart, 1, 0, 1 }, + { "stop", "Stop encryption. ('encrypt stop ?' for more)", + EncryptStop, 1, 0, 1 }, + { "input", "Start encrypting the input stream", + EncryptStartInput, 1, 0, 0 }, + { "-input", "Stop encrypting the input stream", + EncryptStopInput, 1, 0, 0 }, + { "output", "Start encrypting the output stream", + EncryptStartOutput, 1, 0, 0 }, + { "-output", "Stop encrypting the output stream", + EncryptStopOutput, 1, 0, 0 }, + + { "status", "Display current status of authentication information", + EncryptStatus, 0, 0, 0 }, + { "help", 0, EncryptHelp, 0, 0, 0 }, + { "?", "Print help information", EncryptHelp, 0, 0, 0 }, + { 0 }, +}; + +static int +EncryptHelp() +{ + struct encryptlist *c; + + for (c = EncryptList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\r\n", c->name, c->help); + else + printf("\r\n"); + } + } + return 0; +} + +static int +encrypt_cmd(int argc, char **argv) +{ + struct encryptlist *c; + + c = (struct encryptlist *) + genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\r\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\r\n", + argv[1]); + return 0; + } + argc -= 2; + if (argc < c->minarg || argc > c->maxarg) { + if (c->minarg == c->maxarg) { + fprintf(stderr, "Need %s%d argument%s ", + c->minarg < argc ? "only " : "", c->minarg, + c->minarg == 1 ? "" : "s"); + } else { + fprintf(stderr, "Need %s%d-%d arguments ", + c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); + } + fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\r\n", + c->name); + return 0; + } + if (c->needconnect && !connected) { + if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { + printf("?Need to be connected first.\r\n"); + return 0; + } + } + return ((*c->handler)(argc > 0 ? argv[2] : 0, + argc > 1 ? argv[3] : 0, + argc > 2 ? argv[4] : 0)); +} +#endif + + +/* + * Print status about the connection. + */ + +static int +status(int argc, char **argv) +{ + if (connected) { + printf("Connected to %s.\r\n", hostname); + if ((argc < 2) || strcmp(argv[1], "notmuch")) { + int mode = getconnmode(); + + if (my_want_state_is_will(TELOPT_LINEMODE)) { + printf("Operating with LINEMODE option\r\n"); + printf("%s line editing\r\n", (mode&MODE_EDIT) ? "Local" : "No"); + printf("%s catching of signals\r\n", + (mode&MODE_TRAPSIG) ? "Local" : "No"); + slcstate(); +#ifdef KLUDGELINEMODE + } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { + printf("Operating in obsolete linemode\r\n"); +#endif + } else { + printf("Operating in single character mode\r\n"); + if (localchars) + printf("Catching signals locally\r\n"); + } + printf("%s character echo\r\n", (mode&MODE_ECHO) ? "Local" : "Remote"); + if (my_want_state_is_will(TELOPT_LFLOW)) + printf("%s flow control\r\n", (mode&MODE_FLOW) ? "Local" : "No"); +#if defined(ENCRYPTION) + encrypt_display(); +#endif + } + } else { + printf("No connection.\r\n"); + } + printf("Escape character is '%s'.\r\n", control(escape)); + fflush(stdout); + return 1; +} + +#ifdef SIGINFO +/* + * Function that gets called when SIGINFO is received. + */ +void +ayt_status(int ignore) +{ + call(status, "status", "notmuch", 0); +} +#endif + +static Command *getcmd(char *name); + +static void +cmdrc(char *m1, char *m2) +{ + static char rcname[128]; + Command *c; + FILE *rcfile; + int gotmachine = 0; + int l1 = strlen(m1); + int l2 = strlen(m2); + char m1save[64]; + + if (skiprc) + return; + + strcpy_truncate(m1save, m1, sizeof(m1save)); + m1 = m1save; + + if (rcname[0] == 0) { + char *home = getenv("HOME"); + + snprintf (rcname, sizeof(rcname), "%s/.telnetrc", + home ? home : ""); + } + + if ((rcfile = fopen(rcname, "r")) == 0) { + return; + } + + for (;;) { + if (fgets(line, sizeof(line), rcfile) == NULL) + break; + if (line[0] == 0) + break; + if (line[0] == '#') + continue; + if (gotmachine) { + if (!isspace(line[0])) + gotmachine = 0; + } + if (gotmachine == 0) { + if (isspace(line[0])) + continue; + if (strncasecmp(line, m1, l1) == 0) + strncpy(line, &line[l1], sizeof(line) - l1); + else if (strncasecmp(line, m2, l2) == 0) + strncpy(line, &line[l2], sizeof(line) - l2); + else if (strncasecmp(line, "DEFAULT", 7) == 0) + strncpy(line, &line[7], sizeof(line) - 7); + else + continue; + if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') + continue; + gotmachine = 1; + } + makeargv(); + if (margv[0] == 0) + continue; + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("?Ambiguous command: %s\r\n", margv[0]); + continue; + } + if (c == 0) { + printf("?Invalid command: %s\r\n", margv[0]); + continue; + } + /* + * This should never happen... + */ + if (c->needconnect && !connected) { + printf("?Need to be connected first for %s.\r\n", margv[0]); + continue; + } + (*c->handler)(margc, margv); + } + fclose(rcfile); +} + +int +tn(int argc, char **argv) +{ + struct hostent *host = 0; +#ifdef HAVE_IPV6 + struct sockaddr_in6 sin6; +#endif + struct sockaddr_in sin; + struct sockaddr *sa = NULL; + int sa_size = 0; + struct servent *sp = 0; + unsigned long temp; + extern char *inet_ntoa(); +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + char *srp = 0; + int srlen; +#endif + char *cmd, *hostp = 0, *portp = 0; + char *user = 0; + int family, port = 0; + char **addr_list; + + /* clear the socket address prior to use */ + + if (connected) { + printf("?Already connected to %s\r\n", hostname); + setuid(getuid()); + return 0; + } + if (argc < 2) { + strcpy_truncate(line, "open ", sizeof(line)); + printf("(to) "); + fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); + makeargv(); + argc = margc; + argv = margv; + } + cmd = *argv; + --argc; ++argv; + while (argc) { + if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) + goto usage; + if (strcmp(*argv, "-l") == 0) { + --argc; ++argv; + if (argc == 0) + goto usage; + user = strdup(*argv++); + --argc; + continue; + } + if (strcmp(*argv, "-a") == 0) { + --argc; ++argv; + autologin = 1; + continue; + } + if (hostp == 0) { + hostp = *argv++; + --argc; + continue; + } + if (portp == 0) { + portp = *argv++; + --argc; + continue; + } + usage: + printf("usage: %s [-l user] [-a] host-name [port]\r\n", cmd); + setuid(getuid()); + return 0; + } + if (hostp == 0) + goto usage; + +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + if (hostp[0] == '@' || hostp[0] == '!') { + if ((hostname = strrchr(hostp, ':')) == NULL) + hostname = strrchr(hostp, '@'); + hostname++; + srp = 0; + temp = sourceroute(hostp, &srp, &srlen); + if (temp == 0) { + fprintf (stderr, "%s: %s\r\n", srp ? srp : "", hstrerror(h_errno)); + setuid(getuid()); + return 0; + } else if (temp == -1) { + printf("Bad source route option: %s\r\n", hostp); + setuid(getuid()); + return 0; + } else { + abort(); + } + } else { +#endif + memset (&sin, 0, sizeof(sin)); +#ifdef HAVE_IPV6 + memset (&sin6, 0, sizeof(sin6)); + + if(inet_pton(AF_INET6, hostp, &sin6.sin6_addr)) { + sin6.sin6_family = family = AF_INET6; + sa = (struct sockaddr *)&sin6; + sa_size = sizeof(sin6); + strcpy_truncate(_hostname, hostp, sizeof(_hostname)); + hostname =_hostname; + } else +#endif + if(inet_aton(hostp, &sin.sin_addr)){ + sin.sin_family = family = AF_INET; + sa = (struct sockaddr *)&sin; + sa_size = sizeof(sin); + strcpy_truncate(_hostname, hostp, sizeof(_hostname)); + hostname = _hostname; + } else { +#ifdef HAVE_GETHOSTBYNAME2 +#ifdef HAVE_IPV6 + host = gethostbyname2(hostp, AF_INET6); + if(host == NULL) +#endif + host = gethostbyname2(hostp, AF_INET); +#else + host = roken_gethostbyname(hostp); +#endif + if (host) { + strcpy_truncate(_hostname, host->h_name, sizeof(_hostname)); + family = host->h_addrtype; + addr_list = host->h_addr_list; + + switch(family) { + case AF_INET: + memset(&sin, 0, sizeof(sin)); + sa_size = sizeof(sin); + sa = (struct sockaddr *)&sin; + sin.sin_family = family; + sin.sin_addr = *((struct in_addr *)(*addr_list)); + break; +#ifdef HAVE_IPV6 + case AF_INET6: + memset(&sin6, 0, sizeof(sin6)); + sa_size = sizeof(sin6); + sa = (struct sockaddr *)&sin6; + sin6.sin6_family = family; + sin6.sin6_addr = *((struct in6_addr *)(*addr_list)); + break; +#endif + default: + fprintf(stderr, "Bad address family: %d\n", family); + return 0; + } + + _hostname[sizeof(_hostname)-1] = '\0'; + hostname = _hostname; + } else { + fprintf (stderr, "%s: %s\r\n", hostp ? hostp : "", + hstrerror(h_errno)); + setuid(getuid()); + return 0; + } + } +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + } +#endif + if (portp) { + if (*portp == '-') { + portp++; + telnetport = 1; + } else + telnetport = 0; + port = atoi(portp); + if (port == 0) { + sp = roken_getservbyname(portp, "tcp"); + if (sp) + port = sp->s_port; + else { + printf("%s: bad port number\r\n", portp); + setuid(getuid()); + return 0; + } + } else { + port = htons(port); + } + } else { + if (sp == 0) { + sp = roken_getservbyname("telnet", "tcp"); + if (sp == 0) { + fprintf(stderr, "telnet: tcp/telnet: unknown service\r\n"); + setuid(getuid()); + return 0; + } + port = sp->s_port; + } + telnetport = 1; + } + do { + switch(family) { + case AF_INET: + sin.sin_port = port; + printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr)); + break; +#ifdef HAVE_IPV6 + case AF_INET6: { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + + char buf[INET6_ADDRSTRLEN]; + + sin6.sin6_port = port; +#ifdef HAVE_INET_NTOP + printf("Trying %s...\r\n", inet_ntop(AF_INET6, + &sin6.sin6_addr, + buf, + sizeof(buf))); +#endif + break; + } +#endif + default: + abort(); + } + + + net = socket(family, SOCK_STREAM, 0); + setuid(getuid()); + if (net < 0) { + perror("telnet: socket"); + return 0; + } +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) && defined(HAVE_SETSOCKOPT) + if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (void *)srp, + srlen) < 0) + perror("setsockopt (IP_OPTIONS)"); +#endif +#if defined(IPPROTO_IP) && defined(IP_TOS) + { +# if defined(HAVE_GETTOSBYNAME) + struct tosent *tp; + if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) + tos = tp->t_tos; +# endif + if (tos < 0) + tos = 020; /* Low Delay bit */ + if (tos + && (setsockopt(net, IPPROTO_IP, IP_TOS, + (void *)&tos, sizeof(int)) < 0) + && (errno != ENOPROTOOPT)) + perror("telnet: setsockopt (IP_TOS) (ignored)"); + } +#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ + + if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { + perror("setsockopt (SO_DEBUG)"); + } + + if (connect(net, sa, sa_size) < 0) { + if (host && addr_list[1]) { + int oerrno = errno; + + switch(family) { + case AF_INET : + fprintf(stderr, "telnet: connect to address %s: ", + inet_ntoa(sin.sin_addr)); + sin.sin_addr = *((struct in_addr *)(*++addr_list)); + break; +#ifdef HAVE_IPV6 + case AF_INET6: { + char buf[INET6_ADDRSTRLEN]; + + fprintf(stderr, "telnet: connect to address %s: ", + inet_ntop(AF_INET6, &sin6.sin6_addr, buf, + sizeof(buf))); + sin6.sin6_addr = *((struct in6_addr *)(*++addr_list)); + break; + } +#endif + default: + abort(); + } + + errno = oerrno; + perror(NULL); + NetClose(net); + continue; + } + perror("telnet: Unable to connect to remote host"); + return 0; + } + connected++; +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + auth_encrypt_connect(connected); +#endif + } while (connected == 0); + cmdrc(hostp, hostname); + if (autologin && user == NULL) + user = (char *)get_default_username (); + if (user) { + env_define((unsigned char *)"USER", (unsigned char *)user); + env_export((unsigned char *)"USER"); + } + call(status, "status", "notmuch", 0); + if (setjmp(peerdied) == 0) + my_telnet((char *)user); + NetClose(net); + ExitString("Connection closed by foreign host.\r\n",1); + /*NOTREACHED*/ + return 0; +} + +#define HELPINDENT ((int)sizeof ("connect")) + +static char + openhelp[] = "connect to a site", + closehelp[] = "close current connection", + logouthelp[] = "forcibly logout remote user and close the connection", + quithelp[] = "exit telnet", + statushelp[] = "print status information", + helphelp[] = "print help information", + sendhelp[] = "transmit special characters ('send ?' for more)", + sethelp[] = "set operating parameters ('set ?' for more)", + unsethelp[] = "unset operating parameters ('unset ?' for more)", + togglestring[] ="toggle operating parameters ('toggle ?' for more)", + slchelp[] = "change state of special charaters ('slc ?' for more)", + displayhelp[] = "display operating parameters", +#if defined(AUTHENTICATION) + authhelp[] = "turn on (off) authentication ('auth ?' for more)", +#endif +#if defined(ENCRYPTION) + encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", +#endif + zhelp[] = "suspend telnet", + shellhelp[] = "invoke a subshell", + envhelp[] = "change environment variables ('environ ?' for more)", + modestring[] = "try to enter line or character mode ('mode ?' for more)"; + +static int help(int argc, char **argv); + +static Command cmdtab[] = { + { "close", closehelp, bye, 1 }, + { "logout", logouthelp, logout, 1 }, + { "display", displayhelp, display, 0 }, + { "mode", modestring, modecmd, 0 }, + { "open", openhelp, tn, 0 }, + { "quit", quithelp, quit, 0 }, + { "send", sendhelp, sendcmd, 0 }, + { "set", sethelp, setcmd, 0 }, + { "unset", unsethelp, unsetcmd, 0 }, + { "status", statushelp, status, 0 }, + { "toggle", togglestring, toggle, 0 }, + { "slc", slchelp, slccmd, 0 }, +#if defined(AUTHENTICATION) + { "auth", authhelp, auth_cmd, 0 }, +#endif +#if defined(ENCRYPTION) + { "encrypt", encrypthelp, encrypt_cmd, 0 }, +#endif + { "z", zhelp, telnetsuspend, 0 }, + { "!", shellhelp, shell, 0 }, + { "environ", envhelp, env_cmd, 0 }, + { "?", helphelp, help, 0 }, + { 0, 0, 0, 0 } +}; + +static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; +static char escapehelp[] = "deprecated command -- use 'set escape' instead"; + +static Command cmdtab2[] = { + { "help", 0, help, 0 }, + { "escape", escapehelp, setescape, 0 }, + { "crmod", crmodhelp, togcrmod, 0 }, + { 0, 0, 0, 0 } +}; + + +/* + * Call routine with argc, argv set from args (terminated by 0). + */ + +static int +call(intrtn_t routine, ...) +{ + va_list ap; + char *args[100]; + int argno = 0; + + va_start(ap, routine); + while ((args[argno++] = va_arg(ap, char *)) != 0); + va_end(ap); + return (*routine)(argno-1, args); +} + + +static Command +*getcmd(char *name) +{ + Command *cm; + + if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) + return cm; + return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); +} + +void +command(int top, char *tbuf, int cnt) +{ + Command *c; + + setcommandmode(); + if (!top) { + putchar('\n'); + } else { + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + } + for (;;) { + if (rlogin == _POSIX_VDISABLE) + printf("%s> ", prompt); + if (tbuf) { + char *cp; + cp = line; + while (cnt > 0 && (*cp++ = *tbuf++) != '\n') + cnt--; + tbuf = 0; + if (cp == line || *--cp != '\n' || cp == line) + goto getline; + *cp = '\0'; + if (rlogin == _POSIX_VDISABLE) + printf("%s\r\n", line); + } else { + getline: + if (rlogin != _POSIX_VDISABLE) + printf("%s> ", prompt); + if (fgets(line, sizeof(line), stdin) == NULL) { + if (feof(stdin) || ferror(stdin)) { + quit(); + /*NOTREACHED*/ + } + break; + } + } + if (line[0] == 0) + break; + makeargv(); + if (margv[0] == 0) { + break; + } + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("?Ambiguous command\r\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\r\n"); + continue; + } + if (c->needconnect && !connected) { + printf("?Need to be connected first.\r\n"); + continue; + } + if ((*c->handler)(margc, margv)) { + break; + } + } + if (!top) { + if (!connected) { + longjmp(toplevel, 1); + /*NOTREACHED*/ + } + setconnmode(0); + } +} + +/* + * Help command. + */ +static int +help(int argc, char **argv) +{ + Command *c; + + if (argc == 1) { + printf("Commands may be abbreviated. Commands are:\r\n\r\n"); + for (c = cmdtab; c->name; c++) + if (c->help) { + printf("%-*s\t%s\r\n", HELPINDENT, c->name, + c->help); + } + return 0; + } + while (--argc > 0) { + char *arg; + arg = *++argv; + c = getcmd(arg); + if (Ambiguous(c)) + printf("?Ambiguous help command %s\r\n", arg); + else if (c == (Command *)0) + printf("?Invalid help command %s\r\n", arg); + else + printf("%s\r\n", c->help); + } + return 0; +} + + +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + +/* + * Source route is handed in as + * [!]@hop1@hop2...[@|:]dst + * If the leading ! is present, it is a + * strict source route, otherwise it is + * assmed to be a loose source route. + * + * We fill in the source route option as + * hop1,hop2,hop3...dest + * and return a pointer to hop1, which will + * be the address to connect() to. + * + * Arguments: + * arg: pointer to route list to decipher + * + * cpp: If *cpp is not equal to NULL, this is a + * pointer to a pointer to a character array + * that should be filled in with the option. + * + * lenp: pointer to an integer that contains the + * length of *cpp if *cpp != NULL. + * + * Return values: + * + * Returns the address of the host to connect to. If the + * return value is -1, there was a syntax error in the + * option, either unknown characters, or too many hosts. + * If the return value is 0, one of the hostnames in the + * path is unknown, and *cpp is set to point to the bad + * hostname. + * + * *cpp: If *cpp was equal to NULL, it will be filled + * in with a pointer to our static area that has + * the option filled in. This will be 32bit aligned. + * + * *lenp: This will be filled in with how long the option + * pointed to by *cpp is. + * + */ +unsigned long +sourceroute(char *arg, char **cpp, int *lenp) +{ + static char lsr[44]; + char *cp, *cp2, *lsrp, *lsrep; + int tmp; + struct in_addr sin_addr; + struct hostent *host = 0; + char c; + + /* + * Verify the arguments, and make sure we have + * at least 7 bytes for the option. + */ + if (cpp == NULL || lenp == NULL) + return((unsigned long)-1); + if (*cpp != NULL && *lenp < 7) + return((unsigned long)-1); + /* + * Decide whether we have a buffer passed to us, + * or if we need to use our own static buffer. + */ + if (*cpp) { + lsrp = *cpp; + lsrep = lsrp + *lenp; + } else { + *cpp = lsrp = lsr; + lsrep = lsrp + 44; + } + + cp = arg; + + /* + * Next, decide whether we have a loose source + * route or a strict source route, and fill in + * the begining of the option. + */ + if (*cp == '!') { + cp++; + *lsrp++ = IPOPT_SSRR; + } else + *lsrp++ = IPOPT_LSRR; + + if (*cp != '@') + return((unsigned long)-1); + + lsrp++; /* skip over length, we'll fill it in later */ + *lsrp++ = 4; + + cp++; + + sin_addr.s_addr = 0; + + for (c = 0;;) { + if (c == ':') + cp2 = 0; + else for (cp2 = cp; (c = *cp2); cp2++) { + if (c == ',') { + *cp2++ = '\0'; + if (*cp2 == '@') + cp2++; + } else if (c == '@') { + *cp2++ = '\0'; + } else if (c == ':') { + *cp2++ = '\0'; + } else + continue; + break; + } + if (!c) + cp2 = 0; + + if ((tmp = inet_addr(cp)) != -1) { + sin_addr.s_addr = tmp; + } else if ((host = roken_gethostbyname(cp))) { + memmove(&sin_addr, + host->h_addr_list[0], + sizeof(sin_addr)); + } else { + *cpp = cp; + return(0); + } + memmove(lsrp, &sin_addr, 4); + lsrp += 4; + if (cp2) + cp = cp2; + else + break; + /* + * Check to make sure there is space for next address + */ + if (lsrp + 4 > lsrep) + return((unsigned long)-1); + } + if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { + *cpp = 0; + *lenp = 0; + return((unsigned long)-1); + } + *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ + *lenp = lsrp - *cpp; + return(sin_addr.s_addr); +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/telnet/defines.h b/crypto/kerberosIV/appl/telnet/telnet/defines.h new file mode 100644 index 0000000..5c1ac2b --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/defines.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defines.h 8.1 (Berkeley) 6/6/93 + */ + +#define settimer(x) clocks.x = clocks.system++ + +#define NETADD(c) { *netoring.supply = c; ring_supplied(&netoring, 1); } +#define NET2ADD(c1,c2) { NETADD(c1); NETADD(c2); } +#define NETBYTES() (ring_full_count(&netoring)) +#define NETROOM() (ring_empty_count(&netoring)) + +#define TTYADD(c) if (!(SYNCHing||flushout)) { \ + *ttyoring.supply = c; \ + ring_supplied(&ttyoring, 1); \ + } +#define TTYBYTES() (ring_full_count(&ttyoring)) +#define TTYROOM() (ring_empty_count(&ttyoring)) + +/* Various modes */ +#define MODE_LOCAL_CHARS(m) ((m)&(MODE_EDIT|MODE_TRAPSIG)) +#define MODE_LOCAL_ECHO(m) ((m)&MODE_ECHO) +#define MODE_COMMAND_LINE(m) ((m)==-1) + +#define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */ + + +/* XXX extra mode bits, these should be synced with <arpa/telnet.h> */ + +#define MODE_OUT8 0x8000 /* binary mode sans -opost */ diff --git a/crypto/kerberosIV/appl/telnet/telnet/externs.h b/crypto/kerberosIV/appl/telnet/telnet/externs.h new file mode 100644 index 0000000..f8b1668 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/externs.h @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)externs.h 8.3 (Berkeley) 5/30/95 + */ + +/* $Id: externs.h,v 1.18 1998/07/09 23:16:36 assar Exp $ */ + +#ifndef BSD +# define BSD 43 +#endif + +#ifndef _POSIX_VDISABLE +# ifdef sun +# include <sys/param.h> /* pick up VDISABLE definition, mayby */ +# endif +# ifdef VDISABLE +# define _POSIX_VDISABLE VDISABLE +# else +# define _POSIX_VDISABLE ((cc_t)'\377') +# endif +#endif + +#define SUBBUFSIZE 256 + +extern int + autologin, /* Autologin enabled */ + skiprc, /* Don't process the ~/.telnetrc file */ + eight, /* use eight bit mode (binary in and/or out */ + binary, + flushout, /* flush output */ + connected, /* Are we connected to the other side? */ + globalmode, /* Mode tty should be in */ + telnetport, /* Are we connected to the telnet port? */ + localflow, /* Flow control handled locally */ + restartany, /* If flow control, restart output on any character */ + localchars, /* we recognize interrupt/quit */ + donelclchars, /* the user has set "localchars" */ + showoptions, + net, /* Network file descriptor */ + tin, /* Terminal input file descriptor */ + tout, /* Terminal output file descriptor */ + crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */ + autoflush, /* flush output when interrupting? */ + autosynch, /* send interrupt characters with SYNCH? */ + SYNCHing, /* Is the stream in telnet SYNCH mode? */ + donebinarytoggle, /* the user has put us in binary */ + dontlecho, /* do we suppress local echoing right now? */ + crmod, + netdata, /* Print out network data flow */ + prettydump, /* Print "netdata" output in user readable format */ + termdata, /* Print out terminal data flow */ + debug; /* Debug level */ + +extern cc_t escape; /* Escape to command mode */ +extern cc_t rlogin; /* Rlogin mode escape character */ +#ifdef KLUDGELINEMODE +extern cc_t echoc; /* Toggle local echoing */ +#endif + +extern char + *prompt; /* Prompt for command. */ + +extern char + doopt[], + dont[], + will[], + wont[], + options[], /* All the little options */ + *hostname; /* Who are we connected to? */ +#if defined(ENCRYPTION) +extern void (*encrypt_output) (unsigned char *, int); +extern int (*decrypt_input) (int); +#endif + +/* + * We keep track of each side of the option negotiation. + */ + +#define MY_STATE_WILL 0x01 +#define MY_WANT_STATE_WILL 0x02 +#define MY_STATE_DO 0x04 +#define MY_WANT_STATE_DO 0x08 + +/* + * Macros to check the current state of things + */ + +#define my_state_is_do(opt) (options[opt]&MY_STATE_DO) +#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) +#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) +#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) + +#define my_state_is_dont(opt) (!my_state_is_do(opt)) +#define my_state_is_wont(opt) (!my_state_is_will(opt)) +#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) +#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) + +#define set_my_state_do(opt) {options[opt] |= MY_STATE_DO;} +#define set_my_state_will(opt) {options[opt] |= MY_STATE_WILL;} +#define set_my_want_state_do(opt) {options[opt] |= MY_WANT_STATE_DO;} +#define set_my_want_state_will(opt) {options[opt] |= MY_WANT_STATE_WILL;} + +#define set_my_state_dont(opt) {options[opt] &= ~MY_STATE_DO;} +#define set_my_state_wont(opt) {options[opt] &= ~MY_STATE_WILL;} +#define set_my_want_state_dont(opt) {options[opt] &= ~MY_WANT_STATE_DO;} +#define set_my_want_state_wont(opt) {options[opt] &= ~MY_WANT_STATE_WILL;} + +/* + * Make everything symetrical + */ + +#define HIS_STATE_WILL MY_STATE_DO +#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO +#define HIS_STATE_DO MY_STATE_WILL +#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL + +#define his_state_is_do my_state_is_will +#define his_state_is_will my_state_is_do +#define his_want_state_is_do my_want_state_is_will +#define his_want_state_is_will my_want_state_is_do + +#define his_state_is_dont my_state_is_wont +#define his_state_is_wont my_state_is_dont +#define his_want_state_is_dont my_want_state_is_wont +#define his_want_state_is_wont my_want_state_is_dont + +#define set_his_state_do set_my_state_will +#define set_his_state_will set_my_state_do +#define set_his_want_state_do set_my_want_state_will +#define set_his_want_state_will set_my_want_state_do + +#define set_his_state_dont set_my_state_wont +#define set_his_state_wont set_my_state_dont +#define set_his_want_state_dont set_my_want_state_wont +#define set_his_want_state_wont set_my_want_state_dont + + +extern FILE + *NetTrace; /* Where debugging output goes */ +extern char + NetTraceFile[]; /* Name of file where debugging output goes */ +extern void + SetNetTrace (char *); /* Function to change where debugging goes */ + +extern jmp_buf + peerdied, + toplevel; /* For error conditions. */ + +/* authenc.c */ + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) +int telnet_net_write(unsigned char *str, int len); +void net_encrypt(void); +int telnet_spin(void); +char *telnet_getenv(char *val); +char *telnet_gets(char *prompt, char *result, int length, int echo); +#endif + +/* commands.c */ + +struct env_lst *env_define (unsigned char *, unsigned char *); +struct env_lst *env_find(unsigned char *var); +void env_init (void); +void env_undefine (unsigned char *); +void env_export (unsigned char *); +void env_unexport (unsigned char *); +void env_send (unsigned char *); +void env_list (void); +unsigned char * env_default(int init, int welldefined); +unsigned char * env_getvalue(unsigned char *var); + +void set_escape_char(char *s); +unsigned long sourceroute(char *arg, char **cpp, int *lenp); + +#if defined(AUTHENTICATION) +int auth_enable (char *); +int auth_disable (char *); +int auth_status (void); +#endif + +#if defined(ENCRYPTION) +int EncryptEnable (char *, char *); +int EncryptDisable (char *, char *); +int EncryptType (char *, char *); +int EncryptStart (char *); +int EncryptStartInput (void); +int EncryptStartOutput (void); +int EncryptStop (char *); +int EncryptStopInput (void); +int EncryptStopOutput (void); +int EncryptStatus (void); +#endif + +#ifdef SIGINFO +void ayt_status(int); +#endif +int tn(int argc, char **argv); +void command(int top, char *tbuf, int cnt); + +/* main.c */ + +void tninit(void); +void usage(void); + +/* network.c */ + +void init_network(void); +int stilloob(void); +void setneturg(void); +int netflush(void); + +/* sys_bsd.c */ + +void init_sys(void); +int TerminalWrite(char *buf, int n); +int TerminalRead(unsigned char *buf, int n); +int TerminalAutoFlush(void); +int TerminalSpecialChars(int c); +void TerminalFlushOutput(void); +void TerminalSaveState(void); +void TerminalDefaultChars(void); +void TerminalNewMode(int f); +cc_t *tcval(int func); +void TerminalSpeeds(long *input_speed, long *output_speed); +int TerminalWindowSize(long *rows, long *cols); +int NetClose(int fd); +void NetNonblockingIO(int fd, int onoff); +int process_rings(int netin, int netout, int netex, int ttyin, int ttyout, + int poll); + +/* telnet.c */ + +void init_telnet(void); + +void tel_leave_binary(int rw); +void tel_enter_binary(int rw); +int opt_welldefined(char *ep); +int telrcv(void); +int rlogin_susp(void); +void intp(void); +void sendbrk(void); +void sendabort(void); +void sendsusp(void); +void sendeof(void); +void sendayt(void); + +void xmitAO(void); +void xmitEL(void); +void xmitEC(void); + + +void Dump (char, unsigned char *, int); +void printoption (char *, int, int); +void printsub (int, unsigned char *, int); +void sendnaws (void); +void setconnmode (int); +void setcommandmode (void); +void setneturg (void); +void sys_telnet_init (void); +void my_telnet (char *); +void tel_enter_binary (int); +void TerminalFlushOutput (void); +void TerminalNewMode (int); +void TerminalRestoreState (void); +void TerminalSaveState (void); +void tninit (void); +void willoption (int); +void wontoption (int); + + +void send_do (int, int); +void send_dont (int, int); +void send_will (int, int); +void send_wont (int, int); + +void lm_will (unsigned char *, int); +void lm_wont (unsigned char *, int); +void lm_do (unsigned char *, int); +void lm_dont (unsigned char *, int); +void lm_mode (unsigned char *, int, int); + +void slc_init (void); +void slcstate (void); +void slc_mode_export (void); +void slc_mode_import (int); +void slc_import (int); +void slc_export (void); +void slc (unsigned char *, int); +void slc_check (void); +void slc_start_reply (void); +void slc_add_reply (unsigned char, unsigned char, cc_t); +void slc_end_reply (void); +int slc_update (void); + +void env_opt (unsigned char *, int); +void env_opt_start (void); +void env_opt_start_info (void); +void env_opt_add (unsigned char *); +void env_opt_end (int); + +unsigned char *env_default (int, int); +unsigned char *env_getvalue (unsigned char *); + +int get_status (void); +int dosynch (void); + +cc_t *tcval (int); + +int quit (void); + +/* terminal.c */ + +void init_terminal(void); +int ttyflush(int drop); +int getconnmode(void); + +/* utilities.c */ + +int SetSockOpt(int fd, int level, int option, int yesno); +void SetNetTrace(char *file); +void Dump(char direction, unsigned char *buffer, int length); +void printoption(char *direction, int cmd, int option); +void optionstatus(void); +void printsub(int direction, unsigned char *pointer, int length); +void EmptyTerminal(void); +void SetForExit(void); +void Exit(int returnCode); +void ExitString(char *string, int returnCode); + +extern struct termios new_tc; + +# define termEofChar new_tc.c_cc[VEOF] +# define termEraseChar new_tc.c_cc[VERASE] +# define termIntChar new_tc.c_cc[VINTR] +# define termKillChar new_tc.c_cc[VKILL] +# define termQuitChar new_tc.c_cc[VQUIT] + +# ifndef VSUSP +extern cc_t termSuspChar; +# else +# define termSuspChar new_tc.c_cc[VSUSP] +# endif +# if defined(VFLUSHO) && !defined(VDISCARD) +# define VDISCARD VFLUSHO +# endif +# ifndef VDISCARD +extern cc_t termFlushChar; +# else +# define termFlushChar new_tc.c_cc[VDISCARD] +# endif +# ifndef VWERASE +extern cc_t termWerasChar; +# else +# define termWerasChar new_tc.c_cc[VWERASE] +# endif +# ifndef VREPRINT +extern cc_t termRprntChar; +# else +# define termRprntChar new_tc.c_cc[VREPRINT] +# endif +# ifndef VLNEXT +extern cc_t termLiteralNextChar; +# else +# define termLiteralNextChar new_tc.c_cc[VLNEXT] +# endif +# ifndef VSTART +extern cc_t termStartChar; +# else +# define termStartChar new_tc.c_cc[VSTART] +# endif +# ifndef VSTOP +extern cc_t termStopChar; +# else +# define termStopChar new_tc.c_cc[VSTOP] +# endif +# ifndef VEOL +extern cc_t termForw1Char; +# else +# define termForw1Char new_tc.c_cc[VEOL] +# endif +# ifndef VEOL2 +extern cc_t termForw2Char; +# else +# define termForw2Char new_tc.c_cc[VEOL] +# endif +# ifndef VSTATUS +extern cc_t termAytChar; +#else +# define termAytChar new_tc.c_cc[VSTATUS] +#endif + +/* Ring buffer structures which are shared */ + +extern Ring + netoring, + netiring, + ttyoring, + ttyiring; + diff --git a/crypto/kerberosIV/appl/telnet/telnet/main.c b/crypto/kerberosIV/appl/telnet/telnet/main.c new file mode 100644 index 0000000..2c896eb --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/main.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static char *copyright[] = { + "@(#) Copyright (c) 1988, 1990, 1993\n" + "\tThe Regents of the University of California. All rights reserved.\n", + (char*)copyright +}; + +#include "telnet_locl.h" +RCSID("$Id: main.c,v 1.27 1999/03/11 13:49:23 joda Exp $"); + +/* These values need to be the same as defined in libtelnet/kerberos5.c */ +/* Either define them in both places, or put in some common header file. */ +#define OPTS_FORWARD_CREDS 0x00000002 +#define OPTS_FORWARDABLE_CREDS 0x00000001 + +#if KRB5 +#define FORWARD +#endif + +/* + * Initialize variables. + */ +void +tninit(void) +{ + init_terminal(); + + init_network(); + + init_telnet(); + + init_sys(); +} + +void +usage(void) +{ + fprintf(stderr, "Usage: %s %s%s%s%s\n", prompt, +#ifdef AUTHENTICATION + "[-8] [-E] [-K] [-L] [-S tos] [-X atype] [-a] [-c] [-d] [-e char]", + "\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] ", +#else + "[-8] [-E] [-L] [-S tos] [-a] [-c] [-d] [-e char] [-l user]", + "\n\t[-n tracefile]", +#endif + "[-r] ", +#ifdef ENCRYPTION + "[-x] [host-name [port]]" +#else + "[host-name [port]]" +#endif + ); + exit(1); +} + +/* + * main. Parse arguments, invoke the protocol or command parser. + */ + + +#ifdef KRB5 +/* XXX ugly hack to setup dns-proxy stuff */ +#define Authenticator asn1_Authenticator +#include <krb5.h> +static void +krb5_init(void) +{ + krb5_context context; + krb5_init_context(&context); + krb5_free_context(context); + +} +#endif + +int +main(int argc, char **argv) +{ + int ch; + char *user; +#ifdef FORWARD + extern int forward_flags; +#endif /* FORWARD */ + +#ifdef KRB5 + krb5_init(); +#endif + + tninit(); /* Clear out things */ + + TerminalSaveState(); + + if ((prompt = strrchr(argv[0], '/'))) + ++prompt; + else + prompt = argv[0]; + + user = NULL; + + rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE; + + /* + * if AUTHENTICATION and ENCRYPTION is set autologin will be + * se to true after the getopt switch; unless the -K option is + * passed + */ + autologin = -1; + + while((ch = getopt(argc, argv, "78DEKLS:X:abcde:fFk:l:n:rx")) != EOF) { + switch(ch) { + case '8': + eight = 3; /* binary output and input */ + break; + case '7': + eight = 0; + break; + case 'b': + binary = 3; + break; + case 'D': { + /* sometimes we don't want a mangled display */ + char *p; + if((p = getenv("DISPLAY"))) + env_define("DISPLAY", (unsigned char*)p); + break; + } + case 'E': + rlogin = escape = _POSIX_VDISABLE; + break; + case 'K': +#ifdef AUTHENTICATION + autologin = 0; +#endif + break; + case 'L': + eight |= 2; /* binary output only */ + break; + case 'S': + { +#ifdef HAVE_PARSETOS + extern int tos; + + if ((tos = parsetos(optarg, "tcp")) < 0) + fprintf(stderr, "%s%s%s%s\n", + prompt, ": Bad TOS argument '", + optarg, + "; will try to use default TOS"); +#else + fprintf(stderr, + "%s: Warning: -S ignored, no parsetos() support.\n", + prompt); +#endif + } + break; + case 'X': +#ifdef AUTHENTICATION + auth_disable_name(optarg); +#endif + break; + case 'a': + autologin = 1; + break; + case 'c': + skiprc = 1; + break; + case 'd': + debug = 1; + break; + case 'e': + set_escape_char(optarg); + break; + case 'f': +#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) + if (forward_flags & OPTS_FORWARD_CREDS) { + fprintf(stderr, + "%s: Only one of -f and -F allowed.\n", + prompt); + usage(); + } + forward_flags |= OPTS_FORWARD_CREDS; +#else + fprintf(stderr, + "%s: Warning: -f ignored, no Kerberos V5 support.\n", + prompt); +#endif + break; + case 'F': +#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) + if (forward_flags & OPTS_FORWARD_CREDS) { + fprintf(stderr, + "%s: Only one of -f and -F allowed.\n", + prompt); + usage(); + } + forward_flags |= OPTS_FORWARD_CREDS; + forward_flags |= OPTS_FORWARDABLE_CREDS; +#else + fprintf(stderr, + "%s: Warning: -F ignored, no Kerberos V5 support.\n", + prompt); +#endif + break; + case 'k': +#if defined(AUTHENTICATION) && defined(KRB4) + { + extern char *dest_realm, dst_realm_buf[]; + extern int dst_realm_sz; + dest_realm = dst_realm_buf; + strcpy_truncate(dest_realm, optarg, dst_realm_sz); + } +#else + fprintf(stderr, + "%s: Warning: -k ignored, no Kerberos V4 support.\n", + prompt); +#endif + break; + case 'l': + if(autologin == 0){ + fprintf(stderr, "%s: Warning: -K ignored\n", prompt); + autologin = -1; + } + user = optarg; + break; + case 'n': + SetNetTrace(optarg); + break; + case 'r': + rlogin = '~'; + break; + case 'x': +#ifdef ENCRYPTION + encrypt_auto(1); + decrypt_auto(1); + EncryptVerbose(1); +#else + fprintf(stderr, + "%s: Warning: -x ignored, no ENCRYPT support.\n", + prompt); +#endif + break; + case '?': + default: + usage(); + /* NOTREACHED */ + } + } + + if (autologin == -1) { /* esc@magic.fi; force */ +#if defined(AUTHENTICATION) + autologin = 1; +#endif +#if defined(ENCRYPTION) + encrypt_auto(1); + decrypt_auto(1); +#endif + } + + if (autologin == -1) + autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1; + + argc -= optind; + argv += optind; + + if (argc) { + char *args[7], **argp = args; + + if (argc > 2) + usage(); + *argp++ = prompt; + if (user) { + *argp++ = "-l"; + *argp++ = user; + } + *argp++ = argv[0]; /* host */ + if (argc > 1) + *argp++ = argv[1]; /* port */ + *argp = 0; + + if (setjmp(toplevel) != 0) + Exit(0); + if (tn(argp - args, args) == 1) + return (0); + else + return (1); + } + setjmp(toplevel); + for (;;) { + command(1, 0, 0); + } +} diff --git a/crypto/kerberosIV/appl/telnet/telnet/network.c b/crypto/kerberosIV/appl/telnet/telnet/network.c new file mode 100644 index 0000000..faacc30 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/network.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnet_locl.h" + +RCSID("$Id: network.c,v 1.10 1997/05/04 04:01:08 assar Exp $"); + +Ring netoring, netiring; +unsigned char netobuf[2*BUFSIZ], netibuf[BUFSIZ]; + +/* + * Initialize internal network data structures. + */ + +void +init_network(void) +{ + if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) { + exit(1); + } + if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) { + exit(1); + } + NetTrace = stdout; +} + + +/* + * Check to see if any out-of-band data exists on a socket (for + * Telnet "synch" processing). + */ + +int +stilloob(void) +{ + static struct timeval timeout = { 0 }; + fd_set excepts; + int value; + + do { + FD_ZERO(&excepts); + FD_SET(net, &excepts); + value = select(net+1, 0, 0, &excepts, &timeout); + } while ((value == -1) && (errno == EINTR)); + + if (value < 0) { + perror("select"); + quit(); + /* NOTREACHED */ + } + if (FD_ISSET(net, &excepts)) { + return 1; + } else { + return 0; + } +} + + +/* + * setneturg() + * + * Sets "neturg" to the current location. + */ + +void +setneturg(void) +{ + ring_mark(&netoring); +} + + +/* + * netflush + * Send as much data as possible to the network, + * handling requests for urgent data. + * + * The return value indicates whether we did any + * useful work. + */ + + +int +netflush(void) +{ + int n, n1; + +#if defined(ENCRYPTION) + if (encrypt_output) + ring_encrypt(&netoring, encrypt_output); +#endif + if ((n1 = n = ring_full_consecutive(&netoring)) > 0) { + if (!ring_at_mark(&netoring)) { + n = send(net, (char *)netoring.consume, n, 0); /* normal write */ + } else { + /* + * In 4.2 (and 4.3) systems, there is some question about + * what byte in a sendOOB operation is the "OOB" data. + * To make ourselves compatible, we only send ONE byte + * out of band, the one WE THINK should be OOB (though + * we really have more the TCP philosophy of urgent data + * rather than the Unix philosophy of OOB data). + */ + n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */ + } + } + if (n < 0) { + if (errno != ENOBUFS && errno != EWOULDBLOCK) { + setcommandmode(); + perror(hostname); + NetClose(net); + ring_clear_mark(&netoring); + longjmp(peerdied, -1); + /*NOTREACHED*/ + } + n = 0; + } + if (netdata && n) { + Dump('>', netoring.consume, n); + } + if (n) { + ring_consumed(&netoring, n); + /* + * If we sent all, and more to send, then recurse to pick + * up the other half. + */ + if ((n1 == n) && ring_full_consecutive(&netoring)) { + netflush(); + } + return 1; + } else { + return 0; + } +} diff --git a/crypto/kerberosIV/appl/telnet/telnet/ring.c b/crypto/kerberosIV/appl/telnet/telnet/ring.c new file mode 100644 index 0000000..d791476 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/ring.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnet_locl.h" + +RCSID("$Id: ring.c,v 1.10 1997/05/04 04:01:08 assar Exp $"); + +/* + * This defines a structure for a ring buffer. + * + * The circular buffer has two parts: + *((( + * full: [consume, supply) + * empty: [supply, consume) + *]]] + * + */ + +/* Internal macros */ + +#define ring_subtract(d,a,b) (((a)-(b) >= 0)? \ + (a)-(b): (((a)-(b))+(d)->size)) + +#define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ + (a)+(c) : (((a)+(c))-(d)->size)) + +#define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \ + (a)-(c) : (((a)-(c))-(d)->size)) + + +/* + * The following is a clock, used to determine full, empty, etc. + * + * There is some trickiness here. Since the ring buffers are initialized + * to ZERO on allocation, we need to make sure, when interpreting the + * clock, that when the times are EQUAL, then the buffer is FULL. + */ +static u_long ring_clock = 0; + + +#define ring_empty(d) (((d)->consume == (d)->supply) && \ + ((d)->consumetime >= (d)->supplytime)) +#define ring_full(d) (((d)->supply == (d)->consume) && \ + ((d)->supplytime > (d)->consumetime)) + + + + + +/* Buffer state transition routines */ + +int +ring_init(Ring *ring, unsigned char *buffer, int count) +{ + memset(ring, 0, sizeof *ring); + + ring->size = count; + + ring->supply = ring->consume = ring->bottom = buffer; + + ring->top = ring->bottom+ring->size; + +#if defined(ENCRYPTION) + ring->clearto = 0; +#endif + + return 1; +} + +/* Mark routines */ + +/* + * Mark the most recently supplied byte. + */ + +void +ring_mark(Ring *ring) +{ + ring->mark = ring_decrement(ring, ring->supply, 1); +} + +/* + * Is the ring pointing to the mark? + */ + +int +ring_at_mark(Ring *ring) +{ + if (ring->mark == ring->consume) { + return 1; + } else { + return 0; + } +} + +/* + * Clear any mark set on the ring. + */ + +void +ring_clear_mark(Ring *ring) +{ + ring->mark = 0; +} + +/* + * Add characters from current segment to ring buffer. + */ +void +ring_supplied(Ring *ring, int count) +{ + ring->supply = ring_increment(ring, ring->supply, count); + ring->supplytime = ++ring_clock; +} + +/* + * We have just consumed "c" bytes. + */ +void +ring_consumed(Ring *ring, int count) +{ + if (count == 0) /* don't update anything */ + return; + + if (ring->mark && + (ring_subtract(ring, ring->mark, ring->consume) < count)) { + ring->mark = 0; + } +#if defined(ENCRYPTION) + if (ring->consume < ring->clearto && + ring->clearto <= ring->consume + count) + ring->clearto = 0; + else if (ring->consume + count > ring->top && + ring->bottom <= ring->clearto && + ring->bottom + ((ring->consume + count) - ring->top)) + ring->clearto = 0; +#endif + ring->consume = ring_increment(ring, ring->consume, count); + ring->consumetime = ++ring_clock; + /* + * Try to encourage "ring_empty_consecutive()" to be large. + */ + if (ring_empty(ring)) { + ring->consume = ring->supply = ring->bottom; + } +} + + + +/* Buffer state query routines */ + + +/* Number of bytes that may be supplied */ +int +ring_empty_count(Ring *ring) +{ + if (ring_empty(ring)) { /* if empty */ + return ring->size; + } else { + return ring_subtract(ring, ring->consume, ring->supply); + } +} + +/* number of CONSECUTIVE bytes that may be supplied */ +int +ring_empty_consecutive(Ring *ring) +{ + if ((ring->consume < ring->supply) || ring_empty(ring)) { + /* + * if consume is "below" supply, or empty, then + * return distance to the top + */ + return ring_subtract(ring, ring->top, ring->supply); + } else { + /* + * else, return what we may. + */ + return ring_subtract(ring, ring->consume, ring->supply); + } +} + +/* Return the number of bytes that are available for consuming + * (but don't give more than enough to get to cross over set mark) + */ + +int +ring_full_count(Ring *ring) +{ + if ((ring->mark == 0) || (ring->mark == ring->consume)) { + if (ring_full(ring)) { + return ring->size; /* nothing consumed, but full */ + } else { + return ring_subtract(ring, ring->supply, ring->consume); + } + } else { + return ring_subtract(ring, ring->mark, ring->consume); + } +} + +/* + * Return the number of CONSECUTIVE bytes available for consuming. + * However, don't return more than enough to cross over set mark. + */ +int +ring_full_consecutive(Ring *ring) +{ + if ((ring->mark == 0) || (ring->mark == ring->consume)) { + if ((ring->supply < ring->consume) || ring_full(ring)) { + return ring_subtract(ring, ring->top, ring->consume); + } else { + return ring_subtract(ring, ring->supply, ring->consume); + } + } else { + if (ring->mark < ring->consume) { + return ring_subtract(ring, ring->top, ring->consume); + } else { /* Else, distance to mark */ + return ring_subtract(ring, ring->mark, ring->consume); + } + } +} + +/* + * Move data into the "supply" portion of of the ring buffer. + */ +void +ring_supply_data(Ring *ring, unsigned char *buffer, int count) +{ + int i; + + while (count) { + i = min(count, ring_empty_consecutive(ring)); + memmove(ring->supply, buffer, i); + ring_supplied(ring, i); + count -= i; + buffer += i; + } +} + +#ifdef notdef + +/* + * Move data from the "consume" portion of the ring buffer + */ +void +ring_consume_data(Ring *ring, unsigned char *buffer, int count) +{ + int i; + + while (count) { + i = min(count, ring_full_consecutive(ring)); + memmove(buffer, ring->consume, i); + ring_consumed(ring, i); + count -= i; + buffer += i; + } +} +#endif + +#if defined(ENCRYPTION) +void +ring_encrypt(Ring *ring, void (*encryptor)()) +{ + unsigned char *s, *c; + + if (ring_empty(ring) || ring->clearto == ring->supply) + return; + + if (!(c = ring->clearto)) + c = ring->consume; + + s = ring->supply; + + if (s <= c) { + (*encryptor)(c, ring->top - c); + (*encryptor)(ring->bottom, s - ring->bottom); + } else + (*encryptor)(c, s - c); + + ring->clearto = ring->supply; +} + +void +ring_clearto(Ring *ring) +{ + if (!ring_empty(ring)) + ring->clearto = ring->supply; + else + ring->clearto = 0; +} +#endif + diff --git a/crypto/kerberosIV/appl/telnet/telnet/ring.h b/crypto/kerberosIV/appl/telnet/telnet/ring.h new file mode 100644 index 0000000..fa7ad18 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/ring.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ring.h 8.1 (Berkeley) 6/6/93 + */ + +/* $Id: ring.h,v 1.3 1997/05/04 04:01:09 assar Exp $ */ + +/* + * This defines a structure for a ring buffer. + * + * The circular buffer has two parts: + *((( + * full: [consume, supply) + * empty: [supply, consume) + *]]] + * + */ +typedef struct { + unsigned char *consume, /* where data comes out of */ + *supply, /* where data comes in to */ + *bottom, /* lowest address in buffer */ + *top, /* highest address+1 in buffer */ + *mark; /* marker (user defined) */ +#if defined(ENCRYPTION) + unsigned char *clearto; /* Data to this point is clear text */ + unsigned char *encryyptedto; /* Data is encrypted to here */ +#endif + int size; /* size in bytes of buffer */ + u_long consumetime, /* help us keep straight full, empty, etc. */ + supplytime; +} Ring; + +/* Here are some functions and macros to deal with the ring buffer */ + +/* Initialization routine */ +extern int + ring_init (Ring *ring, unsigned char *buffer, int count); + +/* Data movement routines */ +extern void + ring_supply_data (Ring *ring, unsigned char *buffer, int count); +#ifdef notdef +extern void + ring_consume_data (Ring *ring, unsigned char *buffer, int count); +#endif + +/* Buffer state transition routines */ +extern void + ring_supplied (Ring *ring, int count), + ring_consumed (Ring *ring, int count); + +/* Buffer state query routines */ +extern int + ring_empty_count (Ring *ring), + ring_empty_consecutive (Ring *ring), + ring_full_count (Ring *ring), + ring_full_consecutive (Ring *ring); + +#if defined(ENCRYPTION) +extern void + ring_encrypt (Ring *ring, void (*func)()), + ring_clearto (Ring *ring); +#endif + +extern int ring_at_mark(Ring *ring); + +extern void + ring_clear_mark(Ring *ring), + ring_mark(Ring *ring); diff --git a/crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c b/crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c new file mode 100644 index 0000000..334ef04 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/sys_bsd.c @@ -0,0 +1,972 @@ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnet_locl.h" + +RCSID("$Id: sys_bsd.c,v 1.23 1998/06/09 19:24:46 joda Exp $"); + +/* + * The following routines try to encapsulate what is system dependent + * (at least between 4.x and dos) which is used in telnet.c. + */ + +int + tout, /* Output file descriptor */ + tin, /* Input file descriptor */ + net; + +struct termios old_tc = { 0 }; +extern struct termios new_tc; + +# ifndef TCSANOW +# ifdef TCSETS +# define TCSANOW TCSETS +# define TCSADRAIN TCSETSW +# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) +# else +# ifdef TCSETA +# define TCSANOW TCSETA +# define TCSADRAIN TCSETAW +# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) +# else +# define TCSANOW TIOCSETA +# define TCSADRAIN TIOCSETAW +# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) +# endif +# endif +# define tcsetattr(f, a, t) ioctl(f, a, (char *)t) +# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) +# ifdef CIBAUD +# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) +# else +# define cfgetispeed(ptr) cfgetospeed(ptr) +# endif +# endif /* TCSANOW */ + +static fd_set ibits, obits, xbits; + + +void +init_sys(void) +{ + tout = fileno(stdout); + tin = fileno(stdin); + FD_ZERO(&ibits); + FD_ZERO(&obits); + FD_ZERO(&xbits); + + errno = 0; +} + + +int +TerminalWrite(char *buf, int n) +{ + return write(tout, buf, n); +} + +int +TerminalRead(unsigned char *buf, int n) +{ + return read(tin, buf, n); +} + +/* + * + */ + +int +TerminalAutoFlush(void) +{ +#if defined(LNOFLSH) + int flush; + + ioctl(0, TIOCLGET, (char *)&flush); + return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ +#else /* LNOFLSH */ + return 1; +#endif /* LNOFLSH */ +} + +#ifdef KLUDGELINEMODE +extern int kludgelinemode; +#endif +/* + * TerminalSpecialChars() + * + * Look at an input character to see if it is a special character + * and decide what to do. + * + * Output: + * + * 0 Don't add this character. + * 1 Do add this character + */ + +int +TerminalSpecialChars(int c) +{ + if (c == termIntChar) { + intp(); + return 0; + } else if (c == termQuitChar) { +#ifdef KLUDGELINEMODE + if (kludgelinemode) + sendbrk(); + else +#endif + sendabort(); + return 0; + } else if (c == termEofChar) { + if (my_want_state_is_will(TELOPT_LINEMODE)) { + sendeof(); + return 0; + } + return 1; + } else if (c == termSuspChar) { + sendsusp(); + return(0); + } else if (c == termFlushChar) { + xmitAO(); /* Transmit Abort Output */ + return 0; + } else if (!MODE_LOCAL_CHARS(globalmode)) { + if (c == termKillChar) { + xmitEL(); + return 0; + } else if (c == termEraseChar) { + xmitEC(); /* Transmit Erase Character */ + return 0; + } + } + return 1; +} + + +/* + * Flush output to the terminal + */ + +void +TerminalFlushOutput(void) +{ +#ifdef TIOCFLUSH + ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); +#else + ioctl(fileno(stdout), TCFLSH, (char *) 0); +#endif +} + +void +TerminalSaveState(void) +{ + tcgetattr(0, &old_tc); + + new_tc = old_tc; + +#ifndef VDISCARD + termFlushChar = CONTROL('O'); +#endif +#ifndef VWERASE + termWerasChar = CONTROL('W'); +#endif +#ifndef VREPRINT + termRprntChar = CONTROL('R'); +#endif +#ifndef VLNEXT + termLiteralNextChar = CONTROL('V'); +#endif +#ifndef VSTART + termStartChar = CONTROL('Q'); +#endif +#ifndef VSTOP + termStopChar = CONTROL('S'); +#endif +#ifndef VSTATUS + termAytChar = CONTROL('T'); +#endif +} + +cc_t* +tcval(int func) +{ + switch(func) { + case SLC_IP: return(&termIntChar); + case SLC_ABORT: return(&termQuitChar); + case SLC_EOF: return(&termEofChar); + case SLC_EC: return(&termEraseChar); + case SLC_EL: return(&termKillChar); + case SLC_XON: return(&termStartChar); + case SLC_XOFF: return(&termStopChar); + case SLC_FORW1: return(&termForw1Char); + case SLC_FORW2: return(&termForw2Char); +# ifdef VDISCARD + case SLC_AO: return(&termFlushChar); +# endif +# ifdef VSUSP + case SLC_SUSP: return(&termSuspChar); +# endif +# ifdef VWERASE + case SLC_EW: return(&termWerasChar); +# endif +# ifdef VREPRINT + case SLC_RP: return(&termRprntChar); +# endif +# ifdef VLNEXT + case SLC_LNEXT: return(&termLiteralNextChar); +# endif +# ifdef VSTATUS + case SLC_AYT: return(&termAytChar); +# endif + + case SLC_SYNCH: + case SLC_BRK: + case SLC_EOR: + default: + return((cc_t *)0); + } +} + +void +TerminalDefaultChars(void) +{ + memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); +# ifndef VDISCARD + termFlushChar = CONTROL('O'); +# endif +# ifndef VWERASE + termWerasChar = CONTROL('W'); +# endif +# ifndef VREPRINT + termRprntChar = CONTROL('R'); +# endif +# ifndef VLNEXT + termLiteralNextChar = CONTROL('V'); +# endif +# ifndef VSTART + termStartChar = CONTROL('Q'); +# endif +# ifndef VSTOP + termStopChar = CONTROL('S'); +# endif +# ifndef VSTATUS + termAytChar = CONTROL('T'); +# endif +} + +#ifdef notdef +void +TerminalRestoreState() +{ +} +#endif + +/* + * TerminalNewMode - set up terminal to a specific mode. + * MODE_ECHO: do local terminal echo + * MODE_FLOW: do local flow control + * MODE_TRAPSIG: do local mapping to TELNET IAC sequences + * MODE_EDIT: do local line editing + * + * Command mode: + * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG + * local echo + * local editing + * local xon/xoff + * local signal mapping + * + * Linemode: + * local/no editing + * Both Linemode and Single Character mode: + * local/remote echo + * local/no xon/xoff + * local/no signal mapping + */ + + +#ifdef SIGTSTP +static RETSIGTYPE susp(); +#endif /* SIGTSTP */ +#ifdef SIGINFO +static RETSIGTYPE ayt(); +#endif + +void +TerminalNewMode(int f) +{ + static int prevmode = 0; + struct termios tmp_tc; + int onoff; + int old; + cc_t esc; + + globalmode = f&~MODE_FORCE; + if (prevmode == f) + return; + + /* + * Write any outstanding data before switching modes + * ttyflush() returns 0 only when there is no more data + * left to write out, it returns -1 if it couldn't do + * anything at all, otherwise it returns 1 + the number + * of characters left to write. + */ + old = ttyflush(SYNCHing|flushout); + if (old < 0 || old > 1) { + tcgetattr(tin, &tmp_tc); + do { + /* + * Wait for data to drain, then flush again. + */ + tcsetattr(tin, TCSADRAIN, &tmp_tc); + old = ttyflush(SYNCHing|flushout); + } while (old < 0 || old > 1); + } + + old = prevmode; + prevmode = f&~MODE_FORCE; + tmp_tc = new_tc; + + if (f&MODE_ECHO) { + tmp_tc.c_lflag |= ECHO; + tmp_tc.c_oflag |= ONLCR; + if (crlf) + tmp_tc.c_iflag |= ICRNL; + } else { + tmp_tc.c_lflag &= ~ECHO; + tmp_tc.c_oflag &= ~ONLCR; +# ifdef notdef + if (crlf) + tmp_tc.c_iflag &= ~ICRNL; +# endif + } + + if ((f&MODE_FLOW) == 0) { + tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ + } else { + if (restartany < 0) { + tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ + } else if (restartany > 0) { + tmp_tc.c_iflag |= IXOFF|IXON|IXANY; + } else { + tmp_tc.c_iflag |= IXOFF|IXON; + tmp_tc.c_iflag &= ~IXANY; + } + } + + if ((f&MODE_TRAPSIG) == 0) { + tmp_tc.c_lflag &= ~ISIG; + localchars = 0; + } else { + tmp_tc.c_lflag |= ISIG; + localchars = 1; + } + + if (f&MODE_EDIT) { + tmp_tc.c_lflag |= ICANON; + } else { + tmp_tc.c_lflag &= ~ICANON; + tmp_tc.c_iflag &= ~ICRNL; + tmp_tc.c_cc[VMIN] = 1; + tmp_tc.c_cc[VTIME] = 0; + } + + if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { +# ifdef VLNEXT + tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); +# endif + } + + if (f&MODE_SOFT_TAB) { +# ifdef OXTABS + tmp_tc.c_oflag |= OXTABS; +# endif +# ifdef TABDLY + tmp_tc.c_oflag &= ~TABDLY; + tmp_tc.c_oflag |= TAB3; +# endif + } else { +# ifdef OXTABS + tmp_tc.c_oflag &= ~OXTABS; +# endif +# ifdef TABDLY + tmp_tc.c_oflag &= ~TABDLY; +# endif + } + + if (f&MODE_LIT_ECHO) { +# ifdef ECHOCTL + tmp_tc.c_lflag &= ~ECHOCTL; +# endif + } else { +# ifdef ECHOCTL + tmp_tc.c_lflag |= ECHOCTL; +# endif + } + + if (f == -1) { + onoff = 0; + } else { + if (f & MODE_INBIN) + tmp_tc.c_iflag &= ~ISTRIP; + else + tmp_tc.c_iflag |= ISTRIP; + if ((f & MODE_OUTBIN) || (f & MODE_OUT8)) { + tmp_tc.c_cflag &= ~(CSIZE|PARENB); + tmp_tc.c_cflag |= CS8; + if(f & MODE_OUTBIN) + tmp_tc.c_oflag &= ~OPOST; + else + tmp_tc.c_oflag |= OPOST; + } else { + tmp_tc.c_cflag &= ~(CSIZE|PARENB); + tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); + tmp_tc.c_oflag |= OPOST; + } + onoff = 1; + } + + if (f != -1) { + +#ifdef SIGTSTP + signal(SIGTSTP, susp); +#endif /* SIGTSTP */ +#ifdef SIGINFO + signal(SIGINFO, ayt); +#endif +#ifdef NOKERNINFO + tmp_tc.c_lflag |= NOKERNINFO; +#endif + /* + * We don't want to process ^Y here. It's just another + * character that we'll pass on to the back end. It has + * to process it because it will be processed when the + * user attempts to read it, not when we send it. + */ +# ifdef VDSUSP + tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); +# endif + /* + * If the VEOL character is already set, then use VEOL2, + * otherwise use VEOL. + */ + esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; + if ((tmp_tc.c_cc[VEOL] != esc) +# ifdef VEOL2 + && (tmp_tc.c_cc[VEOL2] != esc) +# endif + ) { + if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) + tmp_tc.c_cc[VEOL] = esc; +# ifdef VEOL2 + else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) + tmp_tc.c_cc[VEOL2] = esc; +# endif + } + } else { + sigset_t sm; +#ifdef SIGINFO + RETSIGTYPE ayt_status(); + + signal(SIGINFO, ayt_status); +#endif +#ifdef SIGTSTP + signal(SIGTSTP, SIG_DFL); + sigemptyset(&sm); + sigaddset(&sm, SIGTSTP); + sigprocmask(SIG_UNBLOCK, &sm, NULL); +#endif /* SIGTSTP */ + tmp_tc = old_tc; + } + if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) + tcsetattr(tin, TCSANOW, &tmp_tc); + + ioctl(tin, FIONBIO, (char *)&onoff); + ioctl(tout, FIONBIO, (char *)&onoff); + +} + +/* + * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). + */ +#if B4800 != 4800 +#define DECODE_BAUD +#endif + +#ifdef DECODE_BAUD +#ifndef B7200 +#define B7200 B4800 +#endif + +#ifndef B14400 +#define B14400 B9600 +#endif + +#ifndef B19200 +# define B19200 B14400 +#endif + +#ifndef B28800 +#define B28800 B19200 +#endif + +#ifndef B38400 +# define B38400 B28800 +#endif + +#ifndef B57600 +#define B57600 B38400 +#endif + +#ifndef B76800 +#define B76800 B57600 +#endif + +#ifndef B115200 +#define B115200 B76800 +#endif + +#ifndef B230400 +#define B230400 B115200 +#endif + + +/* + * This code assumes that the values B0, B50, B75... + * are in ascending order. They do not have to be + * contiguous. + */ +struct termspeeds { + long speed; + long value; +} termspeeds[] = { + { 0, B0 }, { 50, B50 }, { 75, B75 }, + { 110, B110 }, { 134, B134 }, { 150, B150 }, + { 200, B200 }, { 300, B300 }, { 600, B600 }, + { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, + { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, + { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, + { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, + { 230400, B230400 }, { -1, B230400 } +}; +#endif /* DECODE_BAUD */ + +void +TerminalSpeeds(long *input_speed, long *output_speed) +{ +#ifdef DECODE_BAUD + struct termspeeds *tp; +#endif /* DECODE_BAUD */ + long in, out; + + out = cfgetospeed(&old_tc); + in = cfgetispeed(&old_tc); + if (in == 0) + in = out; + +#ifdef DECODE_BAUD + tp = termspeeds; + while ((tp->speed != -1) && (tp->value < in)) + tp++; + *input_speed = tp->speed; + + tp = termspeeds; + while ((tp->speed != -1) && (tp->value < out)) + tp++; + *output_speed = tp->speed; +#else /* DECODE_BAUD */ + *input_speed = in; + *output_speed = out; +#endif /* DECODE_BAUD */ +} + +int +TerminalWindowSize(long *rows, long *cols) +{ + struct winsize ws; + + if (get_window_size (STDIN_FILENO, &ws) == 0) { + *rows = ws.ws_row; + *cols = ws.ws_col; + return 1; + } else + return 0; +} + +int +NetClose(int fd) +{ + return close(fd); +} + + +void +NetNonblockingIO(int fd, int onoff) +{ + ioctl(fd, FIONBIO, (char *)&onoff); +} + + +/* + * Various signal handling routines. + */ + +static RETSIGTYPE deadpeer(int), + intr(int), intr2(int), susp(int), sendwin(int); +#ifdef SIGINFO +static RETSIGTYPE ayt(int); +#endif + + + /* ARGSUSED */ +static RETSIGTYPE +deadpeer(int sig) +{ + setcommandmode(); + longjmp(peerdied, -1); +} + + /* ARGSUSED */ +static RETSIGTYPE +intr(int sig) +{ + if (localchars) { + intp(); + return; + } + setcommandmode(); + longjmp(toplevel, -1); +} + + /* ARGSUSED */ +static RETSIGTYPE +intr2(int sig) +{ + if (localchars) { +#ifdef KLUDGELINEMODE + if (kludgelinemode) + sendbrk(); + else +#endif + sendabort(); + return; + } +} + +#ifdef SIGTSTP + /* ARGSUSED */ +static RETSIGTYPE +susp(int sig) +{ + if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) + return; + if (localchars) + sendsusp(); +} +#endif + +#ifdef SIGWINCH + /* ARGSUSED */ +static RETSIGTYPE +sendwin(int sig) +{ + if (connected) { + sendnaws(); + } +} +#endif + +#ifdef SIGINFO + /* ARGSUSED */ +static RETSIGTYPE +ayt(int sig) +{ + if (connected) + sendayt(); + else + ayt_status(sig); +} +#endif + + +void +sys_telnet_init(void) +{ + signal(SIGINT, intr); + signal(SIGQUIT, intr2); + signal(SIGPIPE, deadpeer); +#ifdef SIGWINCH + signal(SIGWINCH, sendwin); +#endif +#ifdef SIGTSTP + signal(SIGTSTP, susp); +#endif +#ifdef SIGINFO + signal(SIGINFO, ayt); +#endif + + setconnmode(0); + + NetNonblockingIO(net, 1); + + +#if defined(SO_OOBINLINE) + if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { + perror("SetSockOpt"); + } +#endif /* defined(SO_OOBINLINE) */ +} + +/* + * Process rings - + * + * This routine tries to fill up/empty our various rings. + * + * The parameter specifies whether this is a poll operation, + * or a block-until-something-happens operation. + * + * The return value is 1 if something happened, 0 if not. + */ + +int +process_rings(int netin, + int netout, + int netex, + int ttyin, + int ttyout, + int poll) /* If 0, then block until something to do */ +{ + int c; + /* One wants to be a bit careful about setting returnValue + * to one, since a one implies we did some useful work, + * and therefore probably won't be called to block next + * time (TN3270 mode only). + */ + int returnValue = 0; + static struct timeval TimeValue = { 0 }; + + if (netout) { + FD_SET(net, &obits); + } + if (ttyout) { + FD_SET(tout, &obits); + } + if (ttyin) { + FD_SET(tin, &ibits); + } + if (netin) { + FD_SET(net, &ibits); + } +#if !defined(SO_OOBINLINE) + if (netex) { + FD_SET(net, &xbits); + } +#endif + if ((c = select(16, &ibits, &obits, &xbits, + (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { + if (c == -1) { + /* + * we can get EINTR if we are in line mode, + * and the user does an escape (TSTP), or + * some other signal generator. + */ + if (errno == EINTR) { + return 0; + } + /* I don't like this, does it ever happen? */ + printf("sleep(5) from telnet, after select\r\n"); + sleep(5); + } + return 0; + } + + /* + * Any urgent data? + */ + if (FD_ISSET(net, &xbits)) { + FD_CLR(net, &xbits); + SYNCHing = 1; + ttyflush(1); /* flush already enqueued data */ + } + + /* + * Something to read from the network... + */ + if (FD_ISSET(net, &ibits)) { + int canread; + + FD_CLR(net, &ibits); + canread = ring_empty_consecutive(&netiring); +#if !defined(SO_OOBINLINE) + /* + * In 4.2 (and some early 4.3) systems, the + * OOB indication and data handling in the kernel + * is such that if two separate TCP Urgent requests + * come in, one byte of TCP data will be overlaid. + * This is fatal for Telnet, but we try to live + * with it. + * + * In addition, in 4.2 (and...), a special protocol + * is needed to pick up the TCP Urgent data in + * the correct sequence. + * + * What we do is: if we think we are in urgent + * mode, we look to see if we are "at the mark". + * If we are, we do an OOB receive. If we run + * this twice, we will do the OOB receive twice, + * but the second will fail, since the second + * time we were "at the mark", but there wasn't + * any data there (the kernel doesn't reset + * "at the mark" until we do a normal read). + * Once we've read the OOB data, we go ahead + * and do normal reads. + * + * There is also another problem, which is that + * since the OOB byte we read doesn't put us + * out of OOB state, and since that byte is most + * likely the TELNET DM (data mark), we would + * stay in the TELNET SYNCH (SYNCHing) state. + * So, clocks to the rescue. If we've "just" + * received a DM, then we test for the + * presence of OOB data when the receive OOB + * fails (and AFTER we did the normal mode read + * to clear "at the mark"). + */ + if (SYNCHing) { + int atmark; + static int bogus_oob = 0, first = 1; + + ioctl(net, SIOCATMARK, (char *)&atmark); + if (atmark) { + c = recv(net, netiring.supply, canread, MSG_OOB); + if ((c == -1) && (errno == EINVAL)) { + c = recv(net, netiring.supply, canread, 0); + if (clocks.didnetreceive < clocks.gotDM) { + SYNCHing = stilloob(); + } + } else if (first && c > 0) { + /* + * Bogosity check. Systems based on 4.2BSD + * do not return an error if you do a second + * recv(MSG_OOB). So, we do one. If it + * succeeds and returns exactly the same + * data, then assume that we are running + * on a broken system and set the bogus_oob + * flag. (If the data was different, then + * we probably got some valid new data, so + * increment the count...) + */ + int i; + i = recv(net, netiring.supply + c, canread - c, MSG_OOB); + if (i == c && + memcmp(netiring.supply, netiring.supply + c, i) == 0) { + bogus_oob = 1; + first = 0; + } else if (i < 0) { + bogus_oob = 0; + first = 0; + } else + c += i; + } + if (bogus_oob && c > 0) { + int i; + /* + * Bogosity. We have to do the read + * to clear the atmark to get out of + * an infinate loop. + */ + i = read(net, netiring.supply + c, canread - c); + if (i > 0) + c += i; + } + } else { + c = recv(net, netiring.supply, canread, 0); + } + } else { + c = recv(net, netiring.supply, canread, 0); + } + settimer(didnetreceive); +#else /* !defined(SO_OOBINLINE) */ + c = recv(net, (char *)netiring.supply, canread, 0); +#endif /* !defined(SO_OOBINLINE) */ + if (c < 0 && errno == EWOULDBLOCK) { + c = 0; + } else if (c <= 0) { + return -1; + } + if (netdata) { + Dump('<', netiring.supply, c); + } + if (c) + ring_supplied(&netiring, c); + returnValue = 1; + } + + /* + * Something to read from the tty... + */ + if (FD_ISSET(tin, &ibits)) { + FD_CLR(tin, &ibits); + c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); + if (c < 0 && errno == EIO) + c = 0; + if (c < 0 && errno == EWOULDBLOCK) { + c = 0; + } else { + /* EOF detection for line mode!!!! */ + if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { + /* must be an EOF... */ + *ttyiring.supply = termEofChar; + c = 1; + } + if (c <= 0) { + return -1; + } + if (termdata) { + Dump('<', ttyiring.supply, c); + } + ring_supplied(&ttyiring, c); + } + returnValue = 1; /* did something useful */ + } + + if (FD_ISSET(net, &obits)) { + FD_CLR(net, &obits); + returnValue |= netflush(); + } + if (FD_ISSET(tout, &obits)) { + FD_CLR(tout, &obits); + returnValue |= (ttyflush(SYNCHing|flushout) > 0); + } + + return returnValue; +} diff --git a/crypto/kerberosIV/appl/telnet/telnet/telnet.c b/crypto/kerberosIV/appl/telnet/telnet/telnet.c new file mode 100644 index 0000000..1df4d6e --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/telnet.c @@ -0,0 +1,2313 @@ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnet_locl.h" +#ifdef HAVE_TERMCAP_H +#include <termcap.h> +#endif + +RCSID("$Id: telnet.c,v 1.25 1999/03/11 13:49:34 joda Exp $"); + +#define strip(x) (eight ? (x) : ((x) & 0x7f)) + +static unsigned char subbuffer[SUBBUFSIZE], + *subpointer, *subend; /* buffer for sub-options */ +#define SB_CLEAR() subpointer = subbuffer; +#define SB_TERM() { subend = subpointer; SB_CLEAR(); } +#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ + *subpointer++ = (c); \ + } + +#define SB_GET() ((*subpointer++)&0xff) +#define SB_PEEK() ((*subpointer)&0xff) +#define SB_EOF() (subpointer >= subend) +#define SB_LEN() (subend - subpointer) + +char options[256]; /* The combined options */ +char do_dont_resp[256]; +char will_wont_resp[256]; + +int + eight = 3, + binary = 0, + autologin = 0, /* Autologin anyone? */ + skiprc = 0, + connected, + showoptions, + ISend, /* trying to send network data in */ + debug = 0, + crmod, + netdata, /* Print out network data flow */ + crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */ + telnetport, + SYNCHing, /* we are in TELNET SYNCH mode */ + flushout, /* flush output */ + autoflush = 0, /* flush output when interrupting? */ + autosynch, /* send interrupt characters with SYNCH? */ + localflow, /* we handle flow control locally */ + restartany, /* if flow control enabled, restart on any character */ + localchars, /* we recognize interrupt/quit */ + donelclchars, /* the user has set "localchars" */ + donebinarytoggle, /* the user has put us in binary */ + dontlecho, /* do we suppress local echoing right now? */ + globalmode; + +char *prompt = 0; + +cc_t escape; +cc_t rlogin; +#ifdef KLUDGELINEMODE +cc_t echoc; +#endif + +/* + * Telnet receiver states for fsm + */ +#define TS_DATA 0 +#define TS_IAC 1 +#define TS_WILL 2 +#define TS_WONT 3 +#define TS_DO 4 +#define TS_DONT 5 +#define TS_CR 6 +#define TS_SB 7 /* sub-option collection */ +#define TS_SE 8 /* looking for sub-option end */ + +static int telrcv_state; +#ifdef OLD_ENVIRON +unsigned char telopt_environ = TELOPT_NEW_ENVIRON; +#else +# define telopt_environ TELOPT_NEW_ENVIRON +#endif + +jmp_buf toplevel; +jmp_buf peerdied; + +int flushline; +int linemode; + +#ifdef KLUDGELINEMODE +int kludgelinemode = 1; +#endif + +/* + * The following are some clocks used to decide how to interpret + * the relationship between various variables. + */ + +Clocks clocks; + +static int is_unique(char *name, char **as, char **ae); + + +/* + * Initialize telnet environment. + */ + +void +init_telnet(void) +{ + env_init(); + + SB_CLEAR(); + memset(options, 0, sizeof options); + + connected = ISend = localflow = donebinarytoggle = 0; +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + auth_encrypt_connect(connected); +#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ + restartany = -1; + + SYNCHing = 0; + + /* Don't change NetTrace */ + + escape = CONTROL(']'); + rlogin = _POSIX_VDISABLE; +#ifdef KLUDGELINEMODE + echoc = CONTROL('E'); +#endif + + flushline = 1; + telrcv_state = TS_DATA; +} + + +/* + * These routines are in charge of sending option negotiations + * to the other side. + * + * The basic idea is that we send the negotiation if either side + * is in disagreement as to what the current state should be. + */ + +void +send_do(int c, int init) +{ + if (init) { + if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || + my_want_state_is_do(c)) + return; + set_my_want_state_do(c); + do_dont_resp[c]++; + } + NET2ADD(IAC, DO); + NETADD(c); + printoption("SENT", DO, c); +} + +void +send_dont(int c, int init) +{ + if (init) { + if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || + my_want_state_is_dont(c)) + return; + set_my_want_state_dont(c); + do_dont_resp[c]++; + } + NET2ADD(IAC, DONT); + NETADD(c); + printoption("SENT", DONT, c); +} + +void +send_will(int c, int init) +{ + if (init) { + if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || + my_want_state_is_will(c)) + return; + set_my_want_state_will(c); + will_wont_resp[c]++; + } + NET2ADD(IAC, WILL); + NETADD(c); + printoption("SENT", WILL, c); +} + +void +send_wont(int c, int init) +{ + if (init) { + if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || + my_want_state_is_wont(c)) + return; + set_my_want_state_wont(c); + will_wont_resp[c]++; + } + NET2ADD(IAC, WONT); + NETADD(c); + printoption("SENT", WONT, c); +} + + +void +willoption(int option) +{ + int new_state_ok = 0; + + if (do_dont_resp[option]) { + --do_dont_resp[option]; + if (do_dont_resp[option] && my_state_is_do(option)) + --do_dont_resp[option]; + } + + if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { + + switch (option) { + + case TELOPT_ECHO: + case TELOPT_BINARY: + case TELOPT_SGA: + settimer(modenegotiated); + /* FALL THROUGH */ + case TELOPT_STATUS: +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: +#endif +#if defined(ENCRYPTION) + case TELOPT_ENCRYPT: +#endif + new_state_ok = 1; + break; + + case TELOPT_TM: + if (flushout) + flushout = 0; + /* + * Special case for TM. If we get back a WILL, + * pretend we got back a WONT. + */ + set_my_want_state_dont(option); + set_my_state_dont(option); + return; /* Never reply to TM will's/wont's */ + + case TELOPT_LINEMODE: + default: + break; + } + + if (new_state_ok) { + set_my_want_state_do(option); + send_do(option, 0); + setconnmode(0); /* possibly set new tty mode */ + } else { + do_dont_resp[option]++; + send_dont(option, 0); + } + } + set_my_state_do(option); +#if defined(ENCRYPTION) + if (option == TELOPT_ENCRYPT) + encrypt_send_support(); +#endif +} + +void +wontoption(int option) +{ + if (do_dont_resp[option]) { + --do_dont_resp[option]; + if (do_dont_resp[option] && my_state_is_dont(option)) + --do_dont_resp[option]; + } + + if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { + + switch (option) { + +#ifdef KLUDGELINEMODE + case TELOPT_SGA: + if (!kludgelinemode) + break; + /* FALL THROUGH */ +#endif + case TELOPT_ECHO: + settimer(modenegotiated); + break; + + case TELOPT_TM: + if (flushout) + flushout = 0; + set_my_want_state_dont(option); + set_my_state_dont(option); + return; /* Never reply to TM will's/wont's */ + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + encrypt_not(); + break; +#endif + default: + break; + } + set_my_want_state_dont(option); + if (my_state_is_do(option)) + send_dont(option, 0); + setconnmode(0); /* Set new tty mode */ + } else if (option == TELOPT_TM) { + /* + * Special case for TM. + */ + if (flushout) + flushout = 0; + set_my_want_state_dont(option); + } + set_my_state_dont(option); +} + +static void +dooption(int option) +{ + int new_state_ok = 0; + + if (will_wont_resp[option]) { + --will_wont_resp[option]; + if (will_wont_resp[option] && my_state_is_will(option)) + --will_wont_resp[option]; + } + + if (will_wont_resp[option] == 0) { + if (my_want_state_is_wont(option)) { + + switch (option) { + + case TELOPT_TM: + /* + * Special case for TM. We send a WILL, but pretend + * we sent WONT. + */ + send_will(option, 0); + set_my_want_state_wont(TELOPT_TM); + set_my_state_wont(TELOPT_TM); + return; + + case TELOPT_BINARY: /* binary mode */ + case TELOPT_NAWS: /* window size */ + case TELOPT_TSPEED: /* terminal speed */ + case TELOPT_LFLOW: /* local flow control */ + case TELOPT_TTYPE: /* terminal type option */ + case TELOPT_SGA: /* no big deal */ +#if defined(ENCRYPTION) + case TELOPT_ENCRYPT: /* encryption variable option */ +#endif + new_state_ok = 1; + break; + + case TELOPT_NEW_ENVIRON: /* New environment variable option */ +#ifdef OLD_ENVIRON + if (my_state_is_will(TELOPT_OLD_ENVIRON)) + send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */ + goto env_common; + case TELOPT_OLD_ENVIRON: /* Old environment variable option */ + if (my_state_is_will(TELOPT_NEW_ENVIRON)) + break; /* Don't enable if new one is in use! */ + env_common: + telopt_environ = option; +#endif + new_state_ok = 1; + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + if (autologin) + new_state_ok = 1; + break; +#endif + + case TELOPT_XDISPLOC: /* X Display location */ + if (env_getvalue((unsigned char *)"DISPLAY")) + new_state_ok = 1; + break; + + case TELOPT_LINEMODE: +#ifdef KLUDGELINEMODE + kludgelinemode = 0; + send_do(TELOPT_SGA, 1); +#endif + set_my_want_state_will(TELOPT_LINEMODE); + send_will(option, 0); + set_my_state_will(TELOPT_LINEMODE); + slc_init(); + return; + + case TELOPT_ECHO: /* We're never going to echo... */ + default: + break; + } + + if (new_state_ok) { + set_my_want_state_will(option); + send_will(option, 0); + setconnmode(0); /* Set new tty mode */ + } else { + will_wont_resp[option]++; + send_wont(option, 0); + } + } else { + /* + * Handle options that need more things done after the + * other side has acknowledged the option. + */ + switch (option) { + case TELOPT_LINEMODE: +#ifdef KLUDGELINEMODE + kludgelinemode = 0; + send_do(TELOPT_SGA, 1); +#endif + set_my_state_will(option); + slc_init(); + send_do(TELOPT_SGA, 0); + return; + } + } + } + set_my_state_will(option); +} + +static void +dontoption(int option) +{ + + if (will_wont_resp[option]) { + --will_wont_resp[option]; + if (will_wont_resp[option] && my_state_is_wont(option)) + --will_wont_resp[option]; + } + + if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { + switch (option) { + case TELOPT_LINEMODE: + linemode = 0; /* put us back to the default state */ + break; +#ifdef OLD_ENVIRON + case TELOPT_NEW_ENVIRON: + /* + * The new environ option wasn't recognized, try + * the old one. + */ + send_will(TELOPT_OLD_ENVIRON, 1); + telopt_environ = TELOPT_OLD_ENVIRON; + break; +#endif +#if 0 +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + encrypt_not(); + break; +#endif +#endif + } + /* we always accept a DONT */ + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + setconnmode(0); /* Set new tty mode */ + } + set_my_state_wont(option); +} + +/* + * Given a buffer returned by tgetent(), this routine will turn + * the pipe seperated list of names in the buffer into an array + * of pointers to null terminated names. We toss out any bad, + * duplicate, or verbose names (names with spaces). + */ + +static char *name_unknown = "UNKNOWN"; +static char *unknown[] = { 0, 0 }; + +static char ** +mklist(char *buf, char *name) +{ + int n; + char c, *cp, **argvp, *cp2, **argv, **avt; + + if (name) { + if ((int)strlen(name) > 40) { + name = 0; + unknown[0] = name_unknown; + } else { + unknown[0] = name; + strupr(name); + } + } else + unknown[0] = name_unknown; + /* + * Count up the number of names. + */ + for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { + if (*cp == '|') + n++; + } + /* + * Allocate an array to put the name pointers into + */ + argv = (char **)malloc((n+3)*sizeof(char *)); + if (argv == 0) + return(unknown); + + /* + * Fill up the array of pointers to names. + */ + *argv = 0; + argvp = argv+1; + n = 0; + for (cp = cp2 = buf; (c = *cp); cp++) { + if (c == '|' || c == ':') { + *cp++ = '\0'; + /* + * Skip entries that have spaces or are over 40 + * characters long. If this is our environment + * name, then put it up front. Otherwise, as + * long as this is not a duplicate name (case + * insensitive) add it to the list. + */ + if (n || (cp - cp2 > 41)) + ; + else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) + *argv = cp2; + else if (is_unique(cp2, argv+1, argvp)) + *argvp++ = cp2; + if (c == ':') + break; + /* + * Skip multiple delimiters. Reset cp2 to + * the beginning of the next name. Reset n, + * the flag for names with spaces. + */ + while ((c = *cp) == '|') + cp++; + cp2 = cp; + n = 0; + } + /* + * Skip entries with spaces or non-ascii values. + * Convert lower case letters to upper case. + */ +#define ISASCII(c) (!((c)&0x80)) + if ((c == ' ') || !ISASCII(c)) + n = 1; + else if (islower(c)) + *cp = toupper(c); + } + + /* + * Check for an old V6 2 character name. If the second + * name points to the beginning of the buffer, and is + * only 2 characters long, move it to the end of the array. + */ + if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { + --argvp; + for (avt = &argv[1]; avt < argvp; avt++) + *avt = *(avt+1); + *argvp++ = buf; + } + + /* + * Duplicate last name, for TTYPE option, and null + * terminate the array. If we didn't find a match on + * our terminal name, put that name at the beginning. + */ + cp = *(argvp-1); + *argvp++ = cp; + *argvp = 0; + + if (*argv == 0) { + if (name) + *argv = name; + else { + --argvp; + for (avt = argv; avt < argvp; avt++) + *avt = *(avt+1); + } + } + if (*argv) + return(argv); + else + return(unknown); +} + +static int +is_unique(char *name, char **as, char **ae) +{ + char **ap; + int n; + + n = strlen(name) + 1; + for (ap = as; ap < ae; ap++) + if (strncasecmp(*ap, name, n) == 0) + return(0); + return (1); +} + +static char termbuf[1024]; + +static int +telnet_setupterm(const char *tname, int fd, int *errp) +{ + if (tgetent(termbuf, tname) == 1) { + termbuf[1023] = '\0'; + if (errp) + *errp = 1; + return(0); + } + if (errp) + *errp = 0; + return(-1); +} + +int resettermname = 1; + +static char * +gettermname() +{ + char *tname; + static char **tnamep = 0; + static char **next; + int err; + + if (resettermname) { + resettermname = 0; + if (tnamep && tnamep != unknown) + free(tnamep); + if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && + telnet_setupterm(tname, 1, &err) == 0) { + tnamep = mklist(termbuf, tname); + } else { + if (tname && ((int)strlen(tname) <= 40)) { + unknown[0] = tname; + strupr(tname); + } else + unknown[0] = name_unknown; + tnamep = unknown; + } + next = tnamep; + } + if (*next == 0) + next = tnamep; + return(*next++); +} +/* + * suboption() + * + * Look at the sub-option buffer, and try to be helpful to the other + * side. + * + * Currently we recognize: + * + * Terminal type, send request. + * Terminal speed (send request). + * Local flow control (is request). + * Linemode + */ + +static void +suboption() +{ + unsigned char subchar; + + printsub('<', subbuffer, SB_LEN()+2); + switch (subchar = SB_GET()) { + case TELOPT_TTYPE: + if (my_want_state_is_wont(TELOPT_TTYPE)) + return; + if (SB_EOF() || SB_GET() != TELQUAL_SEND) { + return; + } else { + char *name; + unsigned char temp[50]; + int len; + + name = gettermname(); + len = strlen(name) + 4 + 2; + if (len < NETROOM()) { + snprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, + TELQUAL_IS, name, IAC, SE); + ring_supply_data(&netoring, temp, len); + printsub('>', &temp[2], len-2); + } else { + ExitString("No room in buffer for terminal type.\n", 1); + /*NOTREACHED*/ + } + } + break; + case TELOPT_TSPEED: + if (my_want_state_is_wont(TELOPT_TSPEED)) + return; + if (SB_EOF()) + return; + if (SB_GET() == TELQUAL_SEND) { + long output_speed, input_speed; + unsigned char temp[50]; + int len; + + TerminalSpeeds(&input_speed, &output_speed); + + snprintf((char *)temp, sizeof(temp), + "%c%c%c%c%u,%u%c%c", IAC, SB, TELOPT_TSPEED, + TELQUAL_IS, + (unsigned)output_speed, + (unsigned)input_speed, IAC, SE); + len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ + + if (len < NETROOM()) { + ring_supply_data(&netoring, temp, len); + printsub('>', temp+2, len - 2); + } +/*@*/ else printf("lm_will: not enough room in buffer\n"); + } + break; + case TELOPT_LFLOW: + if (my_want_state_is_wont(TELOPT_LFLOW)) + return; + if (SB_EOF()) + return; + switch(SB_GET()) { + case LFLOW_RESTART_ANY: + restartany = 1; + break; + case LFLOW_RESTART_XON: + restartany = 0; + break; + case LFLOW_ON: + localflow = 1; + break; + case LFLOW_OFF: + localflow = 0; + break; + default: + return; + } + setcommandmode(); + setconnmode(0); + break; + + case TELOPT_LINEMODE: + if (my_want_state_is_wont(TELOPT_LINEMODE)) + return; + if (SB_EOF()) + return; + switch (SB_GET()) { + case WILL: + lm_will(subpointer, SB_LEN()); + break; + case WONT: + lm_wont(subpointer, SB_LEN()); + break; + case DO: + lm_do(subpointer, SB_LEN()); + break; + case DONT: + lm_dont(subpointer, SB_LEN()); + break; + case LM_SLC: + slc(subpointer, SB_LEN()); + break; + case LM_MODE: + lm_mode(subpointer, SB_LEN(), 0); + break; + default: + break; + } + break; + +#ifdef OLD_ENVIRON + case TELOPT_OLD_ENVIRON: +#endif + case TELOPT_NEW_ENVIRON: + if (SB_EOF()) + return; + switch(SB_PEEK()) { + case TELQUAL_IS: + case TELQUAL_INFO: + if (my_want_state_is_dont(subchar)) + return; + break; + case TELQUAL_SEND: + if (my_want_state_is_wont(subchar)) { + return; + } + break; + default: + return; + } + env_opt(subpointer, SB_LEN()); + break; + + case TELOPT_XDISPLOC: + if (my_want_state_is_wont(TELOPT_XDISPLOC)) + return; + if (SB_EOF()) + return; + if (SB_GET() == TELQUAL_SEND) { + unsigned char temp[50], *dp; + int len; + + if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) { + /* + * Something happened, we no longer have a DISPLAY + * variable. So, turn off the option. + */ + send_wont(TELOPT_XDISPLOC, 1); + break; + } + snprintf((char *)temp, sizeof(temp), + "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, + TELQUAL_IS, dp, IAC, SE); + len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ + + if (len < NETROOM()) { + ring_supply_data(&netoring, temp, len); + printsub('>', temp+2, len - 2); + } +/*@*/ else printf("lm_will: not enough room in buffer\n"); + } + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: { + if (!autologin) + break; + if (SB_EOF()) + return; + switch(SB_GET()) { + case TELQUAL_IS: + if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) + return; + auth_is(subpointer, SB_LEN()); + break; + case TELQUAL_SEND: + if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) + return; + auth_send(subpointer, SB_LEN()); + break; + case TELQUAL_REPLY: + if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) + return; + auth_reply(subpointer, SB_LEN()); + break; + case TELQUAL_NAME: + if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) + return; + auth_name(subpointer, SB_LEN()); + break; + } + } + break; +#endif +#if defined(ENCRYPTION) + case TELOPT_ENCRYPT: + if (SB_EOF()) + return; + switch(SB_GET()) { + case ENCRYPT_START: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_start(subpointer, SB_LEN()); + break; + case ENCRYPT_END: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_end(); + break; + case ENCRYPT_SUPPORT: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_support(subpointer, SB_LEN()); + break; + case ENCRYPT_REQSTART: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_request_start(subpointer, SB_LEN()); + break; + case ENCRYPT_REQEND: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + /* + * We can always send an REQEND so that we cannot + * get stuck encrypting. We should only get this + * if we have been able to get in the correct mode + * anyhow. + */ + encrypt_request_end(); + break; + case ENCRYPT_IS: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_is(subpointer, SB_LEN()); + break; + case ENCRYPT_REPLY: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_reply(subpointer, SB_LEN()); + break; + case ENCRYPT_ENC_KEYID: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_enc_keyid(subpointer, SB_LEN()); + break; + case ENCRYPT_DEC_KEYID: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_dec_keyid(subpointer, SB_LEN()); + break; + default: + break; + } + break; +#endif + default: + break; + } +} + +static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; + +void +lm_will(unsigned char *cmd, int len) +{ + if (len < 1) { +/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: /* We shouldn't ever get this... */ + default: + str_lm[3] = DONT; + str_lm[4] = cmd[0]; + if (NETROOM() > sizeof(str_lm)) { + ring_supply_data(&netoring, str_lm, sizeof(str_lm)); + printsub('>', &str_lm[2], sizeof(str_lm)-2); + } +/*@*/ else printf("lm_will: not enough room in buffer\n"); + break; + } +} + +void +lm_wont(unsigned char *cmd, int len) +{ + if (len < 1) { +/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: /* We shouldn't ever get this... */ + default: + /* We are always DONT, so don't respond */ + return; + } +} + +void +lm_do(unsigned char *cmd, int len) +{ + if (len < 1) { +/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: + default: + str_lm[3] = WONT; + str_lm[4] = cmd[0]; + if (NETROOM() > sizeof(str_lm)) { + ring_supply_data(&netoring, str_lm, sizeof(str_lm)); + printsub('>', &str_lm[2], sizeof(str_lm)-2); + } +/*@*/ else printf("lm_do: not enough room in buffer\n"); + break; + } +} + +void +lm_dont(unsigned char *cmd, int len) +{ + if (len < 1) { +/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: + default: + /* we are always WONT, so don't respond */ + break; + } +} + +static unsigned char str_lm_mode[] = { + IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE +}; + +void +lm_mode(unsigned char *cmd, int len, int init) +{ + if (len != 1) + return; + if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) + return; + if (*cmd&MODE_ACK) + return; + linemode = *cmd&(MODE_MASK&~MODE_ACK); + str_lm_mode[4] = linemode; + if (!init) + str_lm_mode[4] |= MODE_ACK; + if (NETROOM() > sizeof(str_lm_mode)) { + ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); + printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); + } +/*@*/ else printf("lm_mode: not enough room in buffer\n"); + setconnmode(0); /* set changed mode */ +} + + + +/* + * slc() + * Handle special character suboption of LINEMODE. + */ + +struct spc { + cc_t val; + cc_t *valp; + char flags; /* Current flags & level */ + char mylevel; /* Maximum level & flags */ +} spc_data[NSLC+1]; + +#define SLC_IMPORT 0 +#define SLC_EXPORT 1 +#define SLC_RVALUE 2 +static int slc_mode = SLC_EXPORT; + +void +slc_init() +{ + struct spc *spcp; + + localchars = 1; + for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { + spcp->val = 0; + spcp->valp = 0; + spcp->flags = spcp->mylevel = SLC_NOSUPPORT; + } + +#define initfunc(func, flags) { \ + spcp = &spc_data[func]; \ + if ((spcp->valp = tcval(func))) { \ + spcp->val = *spcp->valp; \ + spcp->mylevel = SLC_VARIABLE|flags; \ + } else { \ + spcp->val = 0; \ + spcp->mylevel = SLC_DEFAULT; \ + } \ + } + + initfunc(SLC_SYNCH, 0); + /* No BRK */ + initfunc(SLC_AO, 0); + initfunc(SLC_AYT, 0); + /* No EOR */ + initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); + initfunc(SLC_EOF, 0); + initfunc(SLC_SUSP, SLC_FLUSHIN); + initfunc(SLC_EC, 0); + initfunc(SLC_EL, 0); + initfunc(SLC_EW, 0); + initfunc(SLC_RP, 0); + initfunc(SLC_LNEXT, 0); + initfunc(SLC_XON, 0); + initfunc(SLC_XOFF, 0); + initfunc(SLC_FORW1, 0); + initfunc(SLC_FORW2, 0); + /* No FORW2 */ + + initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); +#undef initfunc + + if (slc_mode == SLC_EXPORT) + slc_export(); + else + slc_import(1); + +} + +void +slcstate() +{ + printf("Special characters are %s values\n", + slc_mode == SLC_IMPORT ? "remote default" : + slc_mode == SLC_EXPORT ? "local" : + "remote"); +} + +void +slc_mode_export() +{ + slc_mode = SLC_EXPORT; + if (my_state_is_will(TELOPT_LINEMODE)) + slc_export(); +} + +void +slc_mode_import(int def) +{ + slc_mode = def ? SLC_IMPORT : SLC_RVALUE; + if (my_state_is_will(TELOPT_LINEMODE)) + slc_import(def); +} + +unsigned char slc_import_val[] = { + IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE +}; +unsigned char slc_import_def[] = { + IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE +}; + +void +slc_import(int def) +{ + if (NETROOM() > sizeof(slc_import_val)) { + if (def) { + ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); + printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); + } else { + ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); + printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); + } + } +/*@*/ else printf("slc_import: not enough room\n"); +} + +void +slc_export() +{ + struct spc *spcp; + + TerminalDefaultChars(); + + slc_start_reply(); + for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { + if (spcp->mylevel != SLC_NOSUPPORT) { + if (spcp->val == (cc_t)(_POSIX_VDISABLE)) + spcp->flags = SLC_NOSUPPORT; + else + spcp->flags = spcp->mylevel; + if (spcp->valp) + spcp->val = *spcp->valp; + slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); + } + } + slc_end_reply(); + slc_update(); + setconnmode(1); /* Make sure the character values are set */ +} + +void +slc(unsigned char *cp, int len) +{ + struct spc *spcp; + int func,level; + + slc_start_reply(); + + for (; len >= 3; len -=3, cp +=3) { + + func = cp[SLC_FUNC]; + + if (func == 0) { + /* + * Client side: always ignore 0 function. + */ + continue; + } + if (func > NSLC) { + if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) + slc_add_reply(func, SLC_NOSUPPORT, 0); + continue; + } + + spcp = &spc_data[func]; + + level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); + + if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && + ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { + continue; + } + + if (level == (SLC_DEFAULT|SLC_ACK)) { + /* + * This is an error condition, the SLC_ACK + * bit should never be set for the SLC_DEFAULT + * level. Our best guess to recover is to + * ignore the SLC_ACK bit. + */ + cp[SLC_FLAGS] &= ~SLC_ACK; + } + + if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { + spcp->val = (cc_t)cp[SLC_VALUE]; + spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ + continue; + } + + level &= ~SLC_ACK; + + if (level <= (spcp->mylevel&SLC_LEVELBITS)) { + spcp->flags = cp[SLC_FLAGS]|SLC_ACK; + spcp->val = (cc_t)cp[SLC_VALUE]; + } + if (level == SLC_DEFAULT) { + if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) + spcp->flags = spcp->mylevel; + else + spcp->flags = SLC_NOSUPPORT; + } + slc_add_reply(func, spcp->flags, spcp->val); + } + slc_end_reply(); + if (slc_update()) + setconnmode(1); /* set the new character values */ +} + +void +slc_check() +{ + struct spc *spcp; + + slc_start_reply(); + for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { + if (spcp->valp && spcp->val != *spcp->valp) { + spcp->val = *spcp->valp; + if (spcp->val == (cc_t)(_POSIX_VDISABLE)) + spcp->flags = SLC_NOSUPPORT; + else + spcp->flags = spcp->mylevel; + slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); + } + } + slc_end_reply(); + setconnmode(1); +} + + +unsigned char slc_reply[128]; +unsigned char *slc_replyp; + +void +slc_start_reply() +{ + slc_replyp = slc_reply; + *slc_replyp++ = IAC; + *slc_replyp++ = SB; + *slc_replyp++ = TELOPT_LINEMODE; + *slc_replyp++ = LM_SLC; +} + +void +slc_add_reply(unsigned char func, unsigned char flags, cc_t value) +{ + if ((*slc_replyp++ = func) == IAC) + *slc_replyp++ = IAC; + if ((*slc_replyp++ = flags) == IAC) + *slc_replyp++ = IAC; + if ((*slc_replyp++ = (unsigned char)value) == IAC) + *slc_replyp++ = IAC; +} + +void +slc_end_reply() +{ + int len; + + *slc_replyp++ = IAC; + *slc_replyp++ = SE; + len = slc_replyp - slc_reply; + if (len <= 6) + return; + if (NETROOM() > len) { + ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); + printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); + } +/*@*/else printf("slc_end_reply: not enough room\n"); +} + +int +slc_update() +{ + struct spc *spcp; + int need_update = 0; + + for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { + if (!(spcp->flags&SLC_ACK)) + continue; + spcp->flags &= ~SLC_ACK; + if (spcp->valp && (*spcp->valp != spcp->val)) { + *spcp->valp = spcp->val; + need_update = 1; + } + } + return(need_update); +} + +#ifdef OLD_ENVIRON +# define old_env_var OLD_ENV_VAR +# define old_env_value OLD_ENV_VALUE +#endif + +void +env_opt(unsigned char *buf, int len) +{ + unsigned char *ep = 0, *epc = 0; + int i; + + switch(buf[0]&0xff) { + case TELQUAL_SEND: + env_opt_start(); + if (len == 1) { + env_opt_add(NULL); + } else for (i = 1; i < len; i++) { + switch (buf[i]&0xff) { +#ifdef OLD_ENVIRON + case OLD_ENV_VAR: + case OLD_ENV_VALUE: + /* + * Although OLD_ENV_VALUE is not legal, we will + * still recognize it, just in case it is an + * old server that has VAR & VALUE mixed up... + */ + /* FALL THROUGH */ +#else + case NEW_ENV_VAR: +#endif + case ENV_USERVAR: + if (ep) { + *epc = 0; + env_opt_add(ep); + } + ep = epc = &buf[i+1]; + break; + case ENV_ESC: + i++; + /*FALL THROUGH*/ + default: + if (epc) + *epc++ = buf[i]; + break; + } + } + if (ep) { + *epc = 0; + env_opt_add(ep); + } + env_opt_end(1); + break; + + case TELQUAL_IS: + case TELQUAL_INFO: + /* Ignore for now. We shouldn't get it anyway. */ + break; + + default: + break; + } +} + +#define OPT_REPLY_SIZE 256 +unsigned char *opt_reply; +unsigned char *opt_replyp; +unsigned char *opt_replyend; + +void +env_opt_start() +{ + if (opt_reply) + opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); + else + opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE); + if (opt_reply == NULL) { +/*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n"); + opt_reply = opt_replyp = opt_replyend = NULL; + return; + } + opt_replyp = opt_reply; + opt_replyend = opt_reply + OPT_REPLY_SIZE; + *opt_replyp++ = IAC; + *opt_replyp++ = SB; + *opt_replyp++ = telopt_environ; + *opt_replyp++ = TELQUAL_IS; +} + +void +env_opt_start_info() +{ + env_opt_start(); + if (opt_replyp) + opt_replyp[-1] = TELQUAL_INFO; +} + +void +env_opt_add(unsigned char *ep) +{ + unsigned char *vp, c; + + if (opt_reply == NULL) /*XXX*/ + return; /*XXX*/ + + if (ep == NULL || *ep == '\0') { + /* Send user defined variables first. */ + env_default(1, 0); + while ((ep = env_default(0, 0))) + env_opt_add(ep); + + /* Now add the list of well know variables. */ + env_default(1, 1); + while ((ep = env_default(0, 1))) + env_opt_add(ep); + return; + } + vp = env_getvalue(ep); + if (opt_replyp + (vp ? strlen((char *)vp) : 0) + + strlen((char *)ep) + 6 > opt_replyend) + { + int len; + opt_replyend += OPT_REPLY_SIZE; + len = opt_replyend - opt_reply; + opt_reply = (unsigned char *)realloc(opt_reply, len); + if (opt_reply == NULL) { +/*@*/ printf("env_opt_add: realloc() failed!!!\n"); + opt_reply = opt_replyp = opt_replyend = NULL; + return; + } + opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); + opt_replyend = opt_reply + len; + } + if (opt_welldefined((char *)ep)) { +#ifdef OLD_ENVIRON + if (telopt_environ == TELOPT_OLD_ENVIRON) + *opt_replyp++ = old_env_var; + else +#endif + *opt_replyp++ = NEW_ENV_VAR; + } else + *opt_replyp++ = ENV_USERVAR; + for (;;) { + while ((c = *ep++)) { + switch(c&0xff) { + case IAC: + *opt_replyp++ = IAC; + break; + case NEW_ENV_VAR: + case NEW_ENV_VALUE: + case ENV_ESC: + case ENV_USERVAR: + *opt_replyp++ = ENV_ESC; + break; + } + *opt_replyp++ = c; + } + if ((ep = vp)) { +#ifdef OLD_ENVIRON + if (telopt_environ == TELOPT_OLD_ENVIRON) + *opt_replyp++ = old_env_value; + else +#endif + *opt_replyp++ = NEW_ENV_VALUE; + vp = NULL; + } else + break; + } +} + +int +opt_welldefined(char *ep) +{ + if ((strcmp(ep, "USER") == 0) || + (strcmp(ep, "DISPLAY") == 0) || + (strcmp(ep, "PRINTER") == 0) || + (strcmp(ep, "SYSTEMTYPE") == 0) || + (strcmp(ep, "JOB") == 0) || + (strcmp(ep, "ACCT") == 0)) + return(1); + return(0); +} + +void +env_opt_end(int emptyok) +{ + int len; + + len = opt_replyp - opt_reply + 2; + if (emptyok || len > 6) { + *opt_replyp++ = IAC; + *opt_replyp++ = SE; + if (NETROOM() > len) { + ring_supply_data(&netoring, opt_reply, len); + printsub('>', &opt_reply[2], len - 2); + } +/*@*/ else printf("slc_end_reply: not enough room\n"); + } + if (opt_reply) { + free(opt_reply); + opt_reply = opt_replyp = opt_replyend = NULL; + } +} + + + +int +telrcv(void) +{ + int c; + int scc; + unsigned char *sbp = NULL; + int count; + int returnValue = 0; + + scc = 0; + count = 0; + while (TTYROOM() > 2) { + if (scc == 0) { + if (count) { + ring_consumed(&netiring, count); + returnValue = 1; + count = 0; + } + sbp = netiring.consume; + scc = ring_full_consecutive(&netiring); + if (scc == 0) { + /* No more data coming in */ + break; + } + } + + c = *sbp++ & 0xff, scc--; count++; +#if defined(ENCRYPTION) + if (decrypt_input) + c = (*decrypt_input)(c); +#endif + + switch (telrcv_state) { + + case TS_CR: + telrcv_state = TS_DATA; + if (c == '\0') { + break; /* Ignore \0 after CR */ + } + else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { + TTYADD(c); + break; + } + /* Else, fall through */ + + case TS_DATA: + if (c == IAC) { + telrcv_state = TS_IAC; + break; + } + /* + * The 'crmod' hack (see following) is needed + * since we can't set CRMOD on output only. + * Machines like MULTICS like to send \r without + * \n; since we must turn off CRMOD to get proper + * input, the mapping is done here (sigh). + */ + if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { + if (scc > 0) { + c = *sbp&0xff; +#if defined(ENCRYPTION) + if (decrypt_input) + c = (*decrypt_input)(c); +#endif + if (c == 0) { + sbp++, scc--; count++; + /* a "true" CR */ + TTYADD('\r'); + } else if (my_want_state_is_dont(TELOPT_ECHO) && + (c == '\n')) { + sbp++, scc--; count++; + TTYADD('\n'); + } else { +#if defined(ENCRYPTION) + if (decrypt_input) + (*decrypt_input)(-1); +#endif + + TTYADD('\r'); + if (crmod) { + TTYADD('\n'); + } + } + } else { + telrcv_state = TS_CR; + TTYADD('\r'); + if (crmod) { + TTYADD('\n'); + } + } + } else { + TTYADD(c); + } + continue; + + case TS_IAC: +process_iac: + switch (c) { + + case WILL: + telrcv_state = TS_WILL; + continue; + + case WONT: + telrcv_state = TS_WONT; + continue; + + case DO: + telrcv_state = TS_DO; + continue; + + case DONT: + telrcv_state = TS_DONT; + continue; + + case DM: + /* + * We may have missed an urgent notification, + * so make sure we flush whatever is in the + * buffer currently. + */ + printoption("RCVD", IAC, DM); + SYNCHing = 1; + ttyflush(1); + SYNCHing = stilloob(); + settimer(gotDM); + break; + + case SB: + SB_CLEAR(); + telrcv_state = TS_SB; + continue; + + + case IAC: + TTYADD(IAC); + break; + + case NOP: + case GA: + default: + printoption("RCVD", IAC, c); + break; + } + telrcv_state = TS_DATA; + continue; + + case TS_WILL: + printoption("RCVD", WILL, c); + willoption(c); + telrcv_state = TS_DATA; + continue; + + case TS_WONT: + printoption("RCVD", WONT, c); + wontoption(c); + telrcv_state = TS_DATA; + continue; + + case TS_DO: + printoption("RCVD", DO, c); + dooption(c); + if (c == TELOPT_NAWS) { + sendnaws(); + } else if (c == TELOPT_LFLOW) { + localflow = 1; + setcommandmode(); + setconnmode(0); + } + telrcv_state = TS_DATA; + continue; + + case TS_DONT: + printoption("RCVD", DONT, c); + dontoption(c); + flushline = 1; + setconnmode(0); /* set new tty mode (maybe) */ + telrcv_state = TS_DATA; + continue; + + case TS_SB: + if (c == IAC) { + telrcv_state = TS_SE; + } else { + SB_ACCUM(c); + } + continue; + + case TS_SE: + if (c != SE) { + if (c != IAC) { + /* + * This is an error. We only expect to get + * "IAC IAC" or "IAC SE". Several things may + * have happend. An IAC was not doubled, the + * IAC SE was left off, or another option got + * inserted into the suboption are all possibilities. + * If we assume that the IAC was not doubled, + * and really the IAC SE was left off, we could + * get into an infinate loop here. So, instead, + * we terminate the suboption, and process the + * partial suboption if we can. + */ + SB_ACCUM(IAC); + SB_ACCUM(c); + subpointer -= 2; + SB_TERM(); + + printoption("In SUBOPTION processing, RCVD", IAC, c); + suboption(); /* handle sub-option */ + telrcv_state = TS_IAC; + goto process_iac; + } + SB_ACCUM(c); + telrcv_state = TS_SB; + } else { + SB_ACCUM(IAC); + SB_ACCUM(SE); + subpointer -= 2; + SB_TERM(); + suboption(); /* handle sub-option */ + telrcv_state = TS_DATA; + } + } + } + if (count) + ring_consumed(&netiring, count); + return returnValue||count; +} + +static int bol = 1, local = 0; + +int +rlogin_susp(void) +{ + if (local) { + local = 0; + bol = 1; + command(0, "z\n", 2); + return(1); + } + return(0); +} + +static int +telsnd() +{ + int tcc; + int count; + int returnValue = 0; + unsigned char *tbp = NULL; + + tcc = 0; + count = 0; + while (NETROOM() > 2) { + int sc; + int c; + + if (tcc == 0) { + if (count) { + ring_consumed(&ttyiring, count); + returnValue = 1; + count = 0; + } + tbp = ttyiring.consume; + tcc = ring_full_consecutive(&ttyiring); + if (tcc == 0) { + break; + } + } + c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; + if (rlogin != _POSIX_VDISABLE) { + if (bol) { + bol = 0; + if (sc == rlogin) { + local = 1; + continue; + } + } else if (local) { + local = 0; + if (sc == '.' || c == termEofChar) { + bol = 1; + command(0, "close\n", 6); + continue; + } + if (sc == termSuspChar) { + bol = 1; + command(0, "z\n", 2); + continue; + } + if (sc == escape) { + command(0, (char *)tbp, tcc); + bol = 1; + count += tcc; + tcc = 0; + flushline = 1; + break; + } + if (sc != rlogin) { + ++tcc; + --tbp; + --count; + c = sc = rlogin; + } + } + if ((sc == '\n') || (sc == '\r')) + bol = 1; + } else if (sc == escape) { + /* + * Double escape is a pass through of a single escape character. + */ + if (tcc && strip(*tbp) == escape) { + tbp++; + tcc--; + count++; + bol = 0; + } else { + command(0, (char *)tbp, tcc); + bol = 1; + count += tcc; + tcc = 0; + flushline = 1; + break; + } + } else + bol = 0; +#ifdef KLUDGELINEMODE + if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { + if (tcc > 0 && strip(*tbp) == echoc) { + tcc--; tbp++; count++; + } else { + dontlecho = !dontlecho; + settimer(echotoggle); + setconnmode(0); + flushline = 1; + break; + } + } +#endif + if (MODE_LOCAL_CHARS(globalmode)) { + if (TerminalSpecialChars(sc) == 0) { + bol = 1; + break; + } + } + if (my_want_state_is_wont(TELOPT_BINARY)) { + switch (c) { + case '\n': + /* + * If we are in CRMOD mode (\r ==> \n) + * on our local machine, then probably + * a newline (unix) is CRLF (TELNET). + */ + if (MODE_LOCAL_CHARS(globalmode)) { + NETADD('\r'); + } + NETADD('\n'); + bol = flushline = 1; + break; + case '\r': + if (!crlf) { + NET2ADD('\r', '\0'); + } else { + NET2ADD('\r', '\n'); + } + bol = flushline = 1; + break; + case IAC: + NET2ADD(IAC, IAC); + break; + default: + NETADD(c); + break; + } + } else if (c == IAC) { + NET2ADD(IAC, IAC); + } else { + NETADD(c); + } + } + if (count) + ring_consumed(&ttyiring, count); + return returnValue||count; /* Non-zero if we did anything */ +} + +/* + * Scheduler() + * + * Try to do something. + * + * If we do something useful, return 1; else return 0. + * + */ + + +static int +Scheduler(int block) /* should we block in the select ? */ +{ + /* One wants to be a bit careful about setting returnValue + * to one, since a one implies we did some useful work, + * and therefore probably won't be called to block next + * time (TN3270 mode only). + */ + int returnValue; + int netin, netout, netex, ttyin, ttyout; + + /* Decide which rings should be processed */ + + netout = ring_full_count(&netoring) && + (flushline || + (my_want_state_is_wont(TELOPT_LINEMODE) +#ifdef KLUDGELINEMODE + && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)) +#endif + ) || + my_want_state_is_will(TELOPT_BINARY)); + ttyout = ring_full_count(&ttyoring); + + ttyin = ring_empty_count(&ttyiring); + + netin = !ISend && ring_empty_count(&netiring); + + netex = !SYNCHing; + + /* If we have seen a signal recently, reset things */ + + /* Call to system code to process rings */ + + returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); + + /* Now, look at the input rings, looking for work to do. */ + + if (ring_full_count(&ttyiring)) { + returnValue |= telsnd(); + } + + if (ring_full_count(&netiring)) { + returnValue |= telrcv(); + } + return returnValue; +} + +/* + * Select from tty and network... + */ +void +my_telnet(char *user) +{ + sys_telnet_init(); + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + { + static char local_host[256] = { 0 }; + + if (!local_host[0]) { + /* XXX - should be k_gethostname? */ + gethostname(local_host, sizeof(local_host)); + local_host[sizeof(local_host)-1] = 0; + } + auth_encrypt_init(local_host, hostname, "TELNET", 0); + auth_encrypt_user(user); + } +#endif + if (telnetport) { +#if defined(AUTHENTICATION) + if (autologin) + send_will(TELOPT_AUTHENTICATION, 1); +#endif +#if defined(ENCRYPTION) + send_do(TELOPT_ENCRYPT, 1); + send_will(TELOPT_ENCRYPT, 1); +#endif + send_do(TELOPT_SGA, 1); + send_will(TELOPT_TTYPE, 1); + send_will(TELOPT_NAWS, 1); + send_will(TELOPT_TSPEED, 1); + send_will(TELOPT_LFLOW, 1); + send_will(TELOPT_LINEMODE, 1); + send_will(TELOPT_NEW_ENVIRON, 1); + send_do(TELOPT_STATUS, 1); + if (env_getvalue((unsigned char *)"DISPLAY")) + send_will(TELOPT_XDISPLOC, 1); + if (binary) + tel_enter_binary(binary); + } + + for (;;) { + int schedValue; + + while ((schedValue = Scheduler(0)) != 0) { + if (schedValue == -1) { + setcommandmode(); + return; + } + } + + if (Scheduler(1) == -1) { + setcommandmode(); + return; + } + } +} + +/* + * netclear() + * + * We are about to do a TELNET SYNCH operation. Clear + * the path to the network. + * + * Things are a bit tricky since we may have sent the first + * byte or so of a previous TELNET command into the network. + * So, we have to scan the network buffer from the beginning + * until we are up to where we want to be. + * + * A side effect of what we do, just to keep things + * simple, is to clear the urgent data pointer. The principal + * caller should be setting the urgent data pointer AFTER calling + * us in any case. + */ + +static void +netclear() +{ +#if 0 /* XXX */ + char *thisitem, *next; + char *good; +#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ + ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) + + thisitem = netobuf; + + while ((next = nextitem(thisitem)) <= netobuf.send) { + thisitem = next; + } + + /* Now, thisitem is first before/at boundary. */ + + good = netobuf; /* where the good bytes go */ + + while (netoring.add > thisitem) { + if (wewant(thisitem)) { + int length; + + next = thisitem; + do { + next = nextitem(next); + } while (wewant(next) && (nfrontp > next)); + length = next-thisitem; + memmove(good, thisitem, length); + good += length; + thisitem = next; + } else { + thisitem = nextitem(thisitem); + } + } + +#endif /* 0 */ +} + +/* + * These routines add various telnet commands to the data stream. + */ + +static void +doflush() +{ + NET2ADD(IAC, DO); + NETADD(TELOPT_TM); + flushline = 1; + flushout = 1; + ttyflush(1); /* Flush/drop output */ + /* do printoption AFTER flush, otherwise the output gets tossed... */ + printoption("SENT", DO, TELOPT_TM); +} + +void +xmitAO(void) +{ + NET2ADD(IAC, AO); + printoption("SENT", IAC, AO); + if (autoflush) { + doflush(); + } +} + + +void +xmitEL(void) +{ + NET2ADD(IAC, EL); + printoption("SENT", IAC, EL); +} + +void +xmitEC(void) +{ + NET2ADD(IAC, EC); + printoption("SENT", IAC, EC); +} + + +int +dosynch() +{ + netclear(); /* clear the path to the network */ + NETADD(IAC); + setneturg(); + NETADD(DM); + printoption("SENT", IAC, DM); + return 1; +} + +int want_status_response = 0; + +int +get_status() +{ + unsigned char tmp[16]; + unsigned char *cp; + + if (my_want_state_is_dont(TELOPT_STATUS)) { + printf("Remote side does not support STATUS option\n"); + return 0; + } + cp = tmp; + + *cp++ = IAC; + *cp++ = SB; + *cp++ = TELOPT_STATUS; + *cp++ = TELQUAL_SEND; + *cp++ = IAC; + *cp++ = SE; + if (NETROOM() >= cp - tmp) { + ring_supply_data(&netoring, tmp, cp-tmp); + printsub('>', tmp+2, cp - tmp - 2); + } + ++want_status_response; + return 1; +} + +void +intp(void) +{ + NET2ADD(IAC, IP); + printoption("SENT", IAC, IP); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + +void +sendbrk(void) +{ + NET2ADD(IAC, BREAK); + printoption("SENT", IAC, BREAK); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + +void +sendabort(void) +{ + NET2ADD(IAC, ABORT); + printoption("SENT", IAC, ABORT); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + +void +sendsusp(void) +{ + NET2ADD(IAC, SUSP); + printoption("SENT", IAC, SUSP); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + +void +sendeof(void) +{ + NET2ADD(IAC, xEOF); + printoption("SENT", IAC, xEOF); +} + +void +sendayt(void) +{ + NET2ADD(IAC, AYT); + printoption("SENT", IAC, AYT); +} + +/* + * Send a window size update to the remote system. + */ + +void +sendnaws() +{ + long rows, cols; + unsigned char tmp[16]; + unsigned char *cp; + + if (my_state_is_wont(TELOPT_NAWS)) + return; + +#define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ + if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } + + if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ + return; + } + + cp = tmp; + + *cp++ = IAC; + *cp++ = SB; + *cp++ = TELOPT_NAWS; + PUTSHORT(cp, cols); + PUTSHORT(cp, rows); + *cp++ = IAC; + *cp++ = SE; + if (NETROOM() >= cp - tmp) { + ring_supply_data(&netoring, tmp, cp-tmp); + printsub('>', tmp+2, cp - tmp - 2); + } +} + +void +tel_enter_binary(int rw) +{ + if (rw&1) + send_do(TELOPT_BINARY, 1); + if (rw&2) + send_will(TELOPT_BINARY, 1); +} + +void +tel_leave_binary(int rw) +{ + if (rw&1) + send_dont(TELOPT_BINARY, 1); + if (rw&2) + send_wont(TELOPT_BINARY, 1); +} diff --git a/crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h b/crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h new file mode 100644 index 0000000..b4a3782 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/telnet_locl.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: telnet_locl.h,v 1.16.8.1 1999/07/22 03:22:52 assar Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif +#include <errno.h> +#include <setjmp.h> +#ifdef HAVE_BSDSETJMP_H +#include <bsdsetjmp.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +/* termios.h *must* be included before curses.h */ +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#endif + +#if defined(SOCKS) && defined(HAVE_CURSES_H) +#include <curses.h> +#endif + +#if defined(HAVE_SYS_TERMIO_H) && !defined(HAVE_TERMIOS_H) +#include <sys/termio.h> +#endif + +#if defined(HAVE_TERMCAP_H) +#include <termcap.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +/* not with SunOS 4 */ +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 +#include <sys/ioctl.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif /* HAVE_SYS_RESOURCE_H */ +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif +#ifdef HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN6_H +#include <netinet/in6.h> +#endif +#ifdef HAVE_NETINET6_IN6_H +#include <netinet6/in6.h> +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif + +#ifdef SOCKS +#include <socks.h> +#endif + +#include <roken.h> +/* krb.h? */ + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#include <libtelnet/auth.h> +#include <libtelnet/encrypt.h> +#endif +#include <libtelnet/misc.h> +#include <libtelnet/misc-proto.h> + +#define LINEMODE +#define KLUDGELINEMODE + +#include "ring.h" +#include "externs.h" +#include "defines.h" +#include "types.h" + +/* prototypes */ + diff --git a/crypto/kerberosIV/appl/telnet/telnet/terminal.c b/crypto/kerberosIV/appl/telnet/telnet/terminal.c new file mode 100644 index 0000000..4404384 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/terminal.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnet_locl.h" + +RCSID("$Id: terminal.c,v 1.10 1997/12/15 19:53:06 joda Exp $"); + +Ring ttyoring, ttyiring; +unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ]; + +int termdata; /* Debugging flag */ + +# ifndef VDISCARD +cc_t termFlushChar; +# endif +# ifndef VLNEXT +cc_t termLiteralNextChar; +# endif +# ifndef VSUSP +cc_t termSuspChar; +# endif +# ifndef VWERASE +cc_t termWerasChar; +# endif +# ifndef VREPRINT +cc_t termRprntChar; +# endif +# ifndef VSTART +cc_t termStartChar; +# endif +# ifndef VSTOP +cc_t termStopChar; +# endif +# ifndef VEOL +cc_t termForw1Char; +# endif +# ifndef VEOL2 +cc_t termForw2Char; +# endif +# ifndef VSTATUS +cc_t termAytChar; +# endif + +/* + * initialize the terminal data structures. + */ + +void +init_terminal(void) +{ + if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) { + exit(1); + } + if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) { + exit(1); + } + autoflush = TerminalAutoFlush(); +} + + +/* + * Send as much data as possible to the terminal. + * + * Return value: + * -1: No useful work done, data waiting to go out. + * 0: No data was waiting, so nothing was done. + * 1: All waiting data was written out. + * n: All data - n was written out. + */ + + +int +ttyflush(int drop) +{ + int n, n0, n1; + + n0 = ring_full_count(&ttyoring); + if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) { + if (drop) { + TerminalFlushOutput(); + /* we leave 'n' alone! */ + } else { + n = TerminalWrite((char *)ttyoring.consume, n); + } + } + if (n > 0) { + if (termdata && n) { + Dump('>', ttyoring.consume, n); + } + /* + * If we wrote everything, and the full count is + * larger than what we wrote, then write the + * rest of the buffer. + */ + if (n1 == n && n0 > n) { + n1 = n0 - n; + if (!drop) + n1 = TerminalWrite((char *)ttyoring.bottom, n1); + if (n1 > 0) + n += n1; + } + ring_consumed(&ttyoring, n); + } + if (n < 0) + return -1; + if (n == n0) { + if (n0) + return -1; + return 0; + } + return n0 - n + 1; +} + + +/* + * These routines decides on what the mode should be (based on the values + * of various global variables). + */ + + +int +getconnmode(void) +{ + extern int linemode; + int mode = 0; +#ifdef KLUDGELINEMODE + extern int kludgelinemode; +#endif + + if (my_want_state_is_dont(TELOPT_ECHO)) + mode |= MODE_ECHO; + + if (localflow) + mode |= MODE_FLOW; + + if ((eight & 1) || my_want_state_is_will(TELOPT_BINARY)) + mode |= MODE_INBIN; + + if (eight & 2) + mode |= MODE_OUT8; + if (his_want_state_is_will(TELOPT_BINARY)) + mode |= MODE_OUTBIN; + +#ifdef KLUDGELINEMODE + if (kludgelinemode) { + if (my_want_state_is_dont(TELOPT_SGA)) { + mode |= (MODE_TRAPSIG|MODE_EDIT); + if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) { + mode &= ~MODE_ECHO; + } + } + return(mode); + } +#endif + if (my_want_state_is_will(TELOPT_LINEMODE)) + mode |= linemode; + return(mode); +} + + void +setconnmode(force) + int force; +{ +#ifdef ENCRYPTION + static int enc_passwd = 0; +#endif + int newmode; + + newmode = getconnmode()|(force?MODE_FORCE:0); + + TerminalNewMode(newmode); + +#ifdef ENCRYPTION + if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) { + if (my_want_state_is_will(TELOPT_ENCRYPT) + && (enc_passwd == 0) && !encrypt_output) { + encrypt_request_start(0, 0); + enc_passwd = 1; + } + } else { + if (enc_passwd) { + encrypt_request_end(); + enc_passwd = 0; + } + } +#endif + +} + + + void +setcommandmode() +{ + TerminalNewMode(-1); +} diff --git a/crypto/kerberosIV/appl/telnet/telnet/types.h b/crypto/kerberosIV/appl/telnet/telnet/types.h new file mode 100644 index 0000000..191d311 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/types.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.1 (Berkeley) 6/6/93 + */ + +typedef struct { + char *modedescriptions; + char modetype; +} Modelist; + +extern Modelist modelist[]; + +typedef struct { + int + system, /* what the current time is */ + echotoggle, /* last time user entered echo character */ + modenegotiated, /* last time operating mode negotiated */ + didnetreceive, /* last time we read data from network */ + gotDM; /* when did we last see a data mark */ +} Clocks; + +extern Clocks clocks; diff --git a/crypto/kerberosIV/appl/telnet/telnet/utilities.c b/crypto/kerberosIV/appl/telnet/telnet/utilities.c new file mode 100644 index 0000000..5d677cf --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnet/utilities.c @@ -0,0 +1,863 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define TELOPTS +#define TELCMDS +#define SLC_NAMES + +#include "telnet_locl.h" + +RCSID("$Id: utilities.c,v 1.21 1998/06/09 19:24:47 joda Exp $"); + +FILE *NetTrace = 0; /* Not in bss, since needs to stay */ +int prettydump; + +/* + * SetSockOpt() + * + * Compensate for differences in 4.2 and 4.3 systems. + */ + +int +SetSockOpt(int fd, int level, int option, int yesno) +{ +#ifdef HAVE_SETSOCKOPT +#ifndef NOT43 + return setsockopt(fd, level, option, + (void *)&yesno, sizeof yesno); +#else /* NOT43 */ + if (yesno == 0) { /* Can't do that in 4.2! */ + fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", + option); + return -1; + } + return setsockopt(fd, level, option, 0, 0); +#endif /* NOT43 */ +#else + return -1; +#endif +} + +/* + * The following are routines used to print out debugging information. + */ + +char NetTraceFile[256] = "(standard output)"; + +void +SetNetTrace(char *file) +{ + if (NetTrace && NetTrace != stdout) + fclose(NetTrace); + if (file && (strcmp(file, "-") != 0)) { + NetTrace = fopen(file, "w"); + if (NetTrace) { + strcpy_truncate(NetTraceFile, file, sizeof(NetTraceFile)); + return; + } + fprintf(stderr, "Cannot open %s.\n", file); + } + NetTrace = stdout; + strcpy_truncate(NetTraceFile, "(standard output)", sizeof(NetTraceFile)); +} + +void +Dump(char direction, unsigned char *buffer, int length) +{ +# define BYTES_PER_LINE 32 + unsigned char *pThis; + int offset; + + offset = 0; + + while (length) { + /* print one line */ + fprintf(NetTrace, "%c 0x%x\t", direction, offset); + pThis = buffer; + if (prettydump) { + buffer = buffer + min(length, BYTES_PER_LINE/2); + while (pThis < buffer) { + fprintf(NetTrace, "%c%.2x", + (((*pThis)&0xff) == 0xff) ? '*' : ' ', + (*pThis)&0xff); + pThis++; + } + length -= BYTES_PER_LINE/2; + offset += BYTES_PER_LINE/2; + } else { + buffer = buffer + min(length, BYTES_PER_LINE); + while (pThis < buffer) { + fprintf(NetTrace, "%.2x", (*pThis)&0xff); + pThis++; + } + length -= BYTES_PER_LINE; + offset += BYTES_PER_LINE; + } + if (NetTrace == stdout) { + fprintf(NetTrace, "\r\n"); + } else { + fprintf(NetTrace, "\n"); + } + if (length < 0) { + fflush(NetTrace); + return; + } + /* find next unique line */ + } + fflush(NetTrace); +} + + +void +printoption(char *direction, int cmd, int option) +{ + if (!showoptions) + return; + if (cmd == IAC) { + if (TELCMD_OK(option)) + fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); + else + fprintf(NetTrace, "%s IAC %d", direction, option); + } else { + char *fmt; + fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : + (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; + if (fmt) { + fprintf(NetTrace, "%s %s ", direction, fmt); + if (TELOPT_OK(option)) + fprintf(NetTrace, "%s", TELOPT(option)); + else if (option == TELOPT_EXOPL) + fprintf(NetTrace, "EXOPL"); + else + fprintf(NetTrace, "%d", option); + } else + fprintf(NetTrace, "%s %d %d", direction, cmd, option); + } + if (NetTrace == stdout) { + fprintf(NetTrace, "\r\n"); + fflush(NetTrace); + } else { + fprintf(NetTrace, "\n"); + } + return; +} + +void +optionstatus(void) +{ + int i; + extern char will_wont_resp[], do_dont_resp[]; + + for (i = 0; i < 256; i++) { + if (do_dont_resp[i]) { + if (TELOPT_OK(i)) + printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); + else if (TELCMD_OK(i)) + printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); + else + printf("resp DO_DONT %d: %d\n", i, + do_dont_resp[i]); + if (my_want_state_is_do(i)) { + if (TELOPT_OK(i)) + printf("want DO %s\n", TELOPT(i)); + else if (TELCMD_OK(i)) + printf("want DO %s\n", TELCMD(i)); + else + printf("want DO %d\n", i); + } else { + if (TELOPT_OK(i)) + printf("want DONT %s\n", TELOPT(i)); + else if (TELCMD_OK(i)) + printf("want DONT %s\n", TELCMD(i)); + else + printf("want DONT %d\n", i); + } + } else { + if (my_state_is_do(i)) { + if (TELOPT_OK(i)) + printf(" DO %s\n", TELOPT(i)); + else if (TELCMD_OK(i)) + printf(" DO %s\n", TELCMD(i)); + else + printf(" DO %d\n", i); + } + } + if (will_wont_resp[i]) { + if (TELOPT_OK(i)) + printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); + else if (TELCMD_OK(i)) + printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); + else + printf("resp WILL_WONT %d: %d\n", + i, will_wont_resp[i]); + if (my_want_state_is_will(i)) { + if (TELOPT_OK(i)) + printf("want WILL %s\n", TELOPT(i)); + else if (TELCMD_OK(i)) + printf("want WILL %s\n", TELCMD(i)); + else + printf("want WILL %d\n", i); + } else { + if (TELOPT_OK(i)) + printf("want WONT %s\n", TELOPT(i)); + else if (TELCMD_OK(i)) + printf("want WONT %s\n", TELCMD(i)); + else + printf("want WONT %d\n", i); + } + } else { + if (my_state_is_will(i)) { + if (TELOPT_OK(i)) + printf(" WILL %s\n", TELOPT(i)); + else if (TELCMD_OK(i)) + printf(" WILL %s\n", TELCMD(i)); + else + printf(" WILL %d\n", i); + } + } + } + +} + +void +printsub(int direction, unsigned char *pointer, int length) +{ + int i; + unsigned char buf[512]; + extern int want_status_response; + + if (showoptions || direction == 0 || + (want_status_response && (pointer[0] == TELOPT_STATUS))) { + if (direction) { + fprintf(NetTrace, "%s IAC SB ", + (direction == '<')? "RCVD":"SENT"); + if (length >= 3) { + int j; + + i = pointer[length-2]; + j = pointer[length-1]; + + if (i != IAC || j != SE) { + fprintf(NetTrace, "(terminated by "); + if (TELOPT_OK(i)) + fprintf(NetTrace, "%s ", TELOPT(i)); + else if (TELCMD_OK(i)) + fprintf(NetTrace, "%s ", TELCMD(i)); + else + fprintf(NetTrace, "%d ", i); + if (TELOPT_OK(j)) + fprintf(NetTrace, "%s", TELOPT(j)); + else if (TELCMD_OK(j)) + fprintf(NetTrace, "%s", TELCMD(j)); + else + fprintf(NetTrace, "%d", j); + fprintf(NetTrace, ", not IAC SE!) "); + } + } + length -= 2; + } + if (length < 1) { + fprintf(NetTrace, "(Empty suboption??\?)"); + if (NetTrace == stdout) + fflush(NetTrace); + return; + } + switch (pointer[0]) { + case TELOPT_TTYPE: + fprintf(NetTrace, "TERMINAL-TYPE "); + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); + break; + case TELQUAL_SEND: + fprintf(NetTrace, "SEND"); + break; + default: + fprintf(NetTrace, + "- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + case TELOPT_TSPEED: + fprintf(NetTrace, "TERMINAL-SPEED"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, " IS "); + fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); + break; + default: + if (pointer[1] == 1) + fprintf(NetTrace, " SEND"); + else + fprintf(NetTrace, " %d (unknown)", pointer[1]); + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + } + break; + + case TELOPT_LFLOW: + fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case LFLOW_OFF: + fprintf(NetTrace, " OFF"); break; + case LFLOW_ON: + fprintf(NetTrace, " ON"); break; + case LFLOW_RESTART_ANY: + fprintf(NetTrace, " RESTART-ANY"); break; + case LFLOW_RESTART_XON: + fprintf(NetTrace, " RESTART-XON"); break; + default: + fprintf(NetTrace, " %d (unknown)", pointer[1]); + } + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + + case TELOPT_NAWS: + fprintf(NetTrace, "NAWS"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + if (length == 2) { + fprintf(NetTrace, " ?%d?", pointer[1]); + break; + } + fprintf(NetTrace, " %d %d (%d)", + pointer[1], pointer[2], + (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); + if (length == 4) { + fprintf(NetTrace, " ?%d?", pointer[3]); + break; + } + fprintf(NetTrace, " %d %d (%d)", + pointer[3], pointer[4], + (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); + for (i = 5; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + fprintf(NetTrace, "AUTHENTICATION"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case TELQUAL_REPLY: + case TELQUAL_IS: + fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? + "IS" : "REPLY"); + if (AUTHTYPE_NAME_OK(pointer[2])) + fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); + else + fprintf(NetTrace, "%d ", pointer[2]); + if (length < 3) { + fprintf(NetTrace, "(partial suboption??\?)"); + break; + } + fprintf(NetTrace, "%s|%s", + ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + + auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + fprintf(NetTrace, "%s", buf); + break; + + case TELQUAL_SEND: + i = 2; + fprintf(NetTrace, " SEND "); + while (i < length) { + if (AUTHTYPE_NAME_OK(pointer[i])) + fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); + else + fprintf(NetTrace, "%d ", pointer[i]); + if (++i >= length) { + fprintf(NetTrace, "(partial suboption??\?)"); + break; + } + fprintf(NetTrace, "%s|%s ", + ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + ++i; + } + break; + + case TELQUAL_NAME: + i = 2; + fprintf(NetTrace, " NAME \""); + while (i < length) + putc(pointer[i++], NetTrace); + putc('"', NetTrace); + break; + + default: + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + } + break; +#endif + +#if defined(ENCRYPTION) + case TELOPT_ENCRYPT: + fprintf(NetTrace, "ENCRYPT"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption?)"); + break; + } + switch (pointer[1]) { + case ENCRYPT_START: + fprintf(NetTrace, " START"); + break; + + case ENCRYPT_END: + fprintf(NetTrace, " END"); + break; + + case ENCRYPT_REQSTART: + fprintf(NetTrace, " REQUEST-START"); + break; + + case ENCRYPT_REQEND: + fprintf(NetTrace, " REQUEST-END"); + break; + + case ENCRYPT_IS: + case ENCRYPT_REPLY: + fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? + "IS" : "REPLY"); + if (length < 3) { + fprintf(NetTrace, " (partial suboption?)"); + break; + } + if (ENCTYPE_NAME_OK(pointer[2])) + fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); + else + fprintf(NetTrace, " %d (unknown)", pointer[2]); + + encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + fprintf(NetTrace, "%s", buf); + break; + + case ENCRYPT_SUPPORT: + i = 2; + fprintf(NetTrace, " SUPPORT "); + while (i < length) { + if (ENCTYPE_NAME_OK(pointer[i])) + fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); + else + fprintf(NetTrace, "%d ", pointer[i]); + i++; + } + break; + + case ENCRYPT_ENC_KEYID: + fprintf(NetTrace, " ENC_KEYID "); + goto encommon; + + case ENCRYPT_DEC_KEYID: + fprintf(NetTrace, " DEC_KEYID "); + goto encommon; + + default: + fprintf(NetTrace, " %d (unknown)", pointer[1]); + encommon: + for (i = 2; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + break; + } + break; +#endif + + case TELOPT_LINEMODE: + fprintf(NetTrace, "LINEMODE "); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case WILL: + fprintf(NetTrace, "WILL "); + goto common; + case WONT: + fprintf(NetTrace, "WONT "); + goto common; + case DO: + fprintf(NetTrace, "DO "); + goto common; + case DONT: + fprintf(NetTrace, "DONT "); + common: + if (length < 3) { + fprintf(NetTrace, "(no option??\?)"); + break; + } + switch (pointer[2]) { + case LM_FORWARDMASK: + fprintf(NetTrace, "Forward Mask"); + for (i = 3; i < length; i++) + fprintf(NetTrace, " %x", pointer[i]); + break; + default: + fprintf(NetTrace, "%d (unknown)", pointer[2]); + for (i = 3; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + break; + } + break; + + case LM_SLC: + fprintf(NetTrace, "SLC"); + for (i = 2; i < length - 2; i += 3) { + if (SLC_NAME_OK(pointer[i+SLC_FUNC])) + fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); + else + fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); + switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { + case SLC_NOSUPPORT: + fprintf(NetTrace, " NOSUPPORT"); break; + case SLC_CANTCHANGE: + fprintf(NetTrace, " CANTCHANGE"); break; + case SLC_VARIABLE: + fprintf(NetTrace, " VARIABLE"); break; + case SLC_DEFAULT: + fprintf(NetTrace, " DEFAULT"); break; + } + fprintf(NetTrace, "%s%s%s", + pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); + if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| + SLC_FLUSHOUT| SLC_LEVELBITS)) + fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); + fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); + if ((pointer[i+SLC_VALUE] == IAC) && + (pointer[i+SLC_VALUE+1] == IAC)) + i++; + } + for (; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + + case LM_MODE: + fprintf(NetTrace, "MODE "); + if (length < 3) { + fprintf(NetTrace, "(no mode??\?)"); + break; + } + { + char tbuf[64]; + snprintf(tbuf, sizeof(tbuf), + "%s%s%s%s%s", + pointer[2]&MODE_EDIT ? "|EDIT" : "", + pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", + pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", + pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", + pointer[2]&MODE_ACK ? "|ACK" : ""); + fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); + } + if (pointer[2]&~(MODE_MASK)) + fprintf(NetTrace, " (0x%x)", pointer[2]); + for (i = 3; i < length; i++) + fprintf(NetTrace, " ?0x%x?", pointer[i]); + break; + default: + fprintf(NetTrace, "%d (unknown)", pointer[1]); + for (i = 2; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + } + break; + + case TELOPT_STATUS: { + char *cp; + int j, k; + + fprintf(NetTrace, "STATUS"); + + switch (pointer[1]) { + default: + if (pointer[1] == TELQUAL_SEND) + fprintf(NetTrace, " SEND"); + else + fprintf(NetTrace, " %d (unknown)", pointer[1]); + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + case TELQUAL_IS: + if (--want_status_response < 0) + want_status_response = 0; + if (NetTrace == stdout) + fprintf(NetTrace, " IS\r\n"); + else + fprintf(NetTrace, " IS\n"); + + for (i = 2; i < length; i++) { + switch(pointer[i]) { + case DO: cp = "DO"; goto common2; + case DONT: cp = "DONT"; goto common2; + case WILL: cp = "WILL"; goto common2; + case WONT: cp = "WONT"; goto common2; + common2: + i++; + if (TELOPT_OK((int)pointer[i])) + fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); + else + fprintf(NetTrace, " %s %d", cp, pointer[i]); + + if (NetTrace == stdout) + fprintf(NetTrace, "\r\n"); + else + fprintf(NetTrace, "\n"); + break; + + case SB: + fprintf(NetTrace, " SB "); + i++; + j = k = i; + while (j < length) { + if (pointer[j] == SE) { + if (j+1 == length) + break; + if (pointer[j+1] == SE) + j++; + else + break; + } + pointer[k++] = pointer[j++]; + } + printsub(0, &pointer[i], k - i); + if (i < length) { + fprintf(NetTrace, " SE"); + i = j; + } else + i = j - 1; + + if (NetTrace == stdout) + fprintf(NetTrace, "\r\n"); + else + fprintf(NetTrace, "\n"); + + break; + + default: + fprintf(NetTrace, " %d", pointer[i]); + break; + } + } + break; + } + break; + } + + case TELOPT_XDISPLOC: + fprintf(NetTrace, "X-DISPLAY-LOCATION "); + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); + break; + case TELQUAL_SEND: + fprintf(NetTrace, "SEND"); + break; + default: + fprintf(NetTrace, "- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + + case TELOPT_NEW_ENVIRON: + fprintf(NetTrace, "NEW-ENVIRON "); +#ifdef OLD_ENVIRON + goto env_common1; + case TELOPT_OLD_ENVIRON: + fprintf(NetTrace, "OLD-ENVIRON"); + env_common1: +#endif + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, "IS "); + goto env_common; + case TELQUAL_SEND: + fprintf(NetTrace, "SEND "); + goto env_common; + case TELQUAL_INFO: + fprintf(NetTrace, "INFO "); + env_common: + { + int noquote = 2; + for (i = 2; i < length; i++ ) { + switch (pointer[i]) { + case NEW_ENV_VALUE: +#ifdef OLD_ENVIRON + /* case NEW_ENV_OVAR: */ + if (pointer[0] == TELOPT_OLD_ENVIRON) { + fprintf(NetTrace, "\" VAR " + noquote); + } else +#endif /* OLD_ENVIRON */ + fprintf(NetTrace, "\" VALUE " + noquote); + noquote = 2; + break; + + case NEW_ENV_VAR: +#ifdef OLD_ENVIRON + /* case OLD_ENV_VALUE: */ + if (pointer[0] == TELOPT_OLD_ENVIRON) { + fprintf(NetTrace, "\" VALUE " + noquote); + } else +#endif /* OLD_ENVIRON */ + fprintf(NetTrace, "\" VAR " + noquote); + noquote = 2; + break; + + case ENV_ESC: + fprintf(NetTrace, "\" ESC " + noquote); + noquote = 2; + break; + + case ENV_USERVAR: + fprintf(NetTrace, "\" USERVAR " + noquote); + noquote = 2; + break; + + default: + if (isprint(pointer[i]) && pointer[i] != '"') { + if (noquote) { + putc('"', NetTrace); + noquote = 0; + } + putc(pointer[i], NetTrace); + } else { + fprintf(NetTrace, "\" %03o " + noquote, + pointer[i]); + noquote = 2; + } + break; + } + } + if (!noquote) + putc('"', NetTrace); + break; + } + } + break; + + default: + if (TELOPT_OK(pointer[0])) + fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); + else + fprintf(NetTrace, "%d (unknown)", pointer[0]); + for (i = 1; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + break; + } + if (direction) { + if (NetTrace == stdout) + fprintf(NetTrace, "\r\n"); + else + fprintf(NetTrace, "\n"); + } + if (NetTrace == stdout) + fflush(NetTrace); + } +} + +/* EmptyTerminal - called to make sure that the terminal buffer is empty. + * Note that we consider the buffer to run all the + * way to the kernel (thus the select). + */ + +void +EmptyTerminal(void) +{ + fd_set outs; + + FD_ZERO(&outs); + + if (TTYBYTES() == 0) { + FD_SET(tout, &outs); + select(tout+1, 0, &outs, 0, + (struct timeval *) 0); /* wait for TTLOWAT */ + } else { + while (TTYBYTES()) { + ttyflush(0); + FD_SET(tout, &outs); + select(tout+1, 0, &outs, 0, + (struct timeval *) 0); /* wait for TTLOWAT */ + } + } +} + +void +SetForExit(void) +{ + setconnmode(0); + do { + telrcv(); /* Process any incoming data */ + EmptyTerminal(); + } while (ring_full_count(&netiring)); /* While there is any */ + setcommandmode(); + fflush(stdout); + fflush(stderr); + setconnmode(0); + EmptyTerminal(); /* Flush the path to the tty */ + setcommandmode(); +} + +void +Exit(int returnCode) +{ + SetForExit(); + exit(returnCode); +} + +void +ExitString(char *string, int returnCode) +{ + SetForExit(); + fwrite(string, 1, strlen(string), stderr); + exit(returnCode); +} diff --git a/crypto/kerberosIV/appl/telnet/telnetd/Makefile.am b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.am new file mode 100644 index 0000000..c228518 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.am @@ -0,0 +1,21 @@ +# $Id: Makefile.am,v 1.12 1999/04/09 18:24:38 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += -I$(srcdir)/.. $(INCLUDE_krb4) + +libexec_PROGRAMS = telnetd + +CHECK_LOCAL = + +telnetd_SOURCES = telnetd.c state.c termstat.c slc.c sys_term.c \ + utility.c global.c authenc.c defs.h ext.h telnetd.h + +LDADD = \ + ../libtelnet/libtelnet.a \ + $(LIB_krb5) \ + $(LIB_krb4) \ + $(top_builddir)/lib/des/libdes.la \ + $(LIB_tgetent) \ + $(LIB_logwtmp) \ + $(LIB_roken) diff --git a/crypto/kerberosIV/appl/telnet/telnetd/Makefile.in b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.in new file mode 100644 index 0000000..ed42d1d --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/Makefile.in @@ -0,0 +1,79 @@ +# $Id: Makefile.in,v 1.38 1999/03/11 13:50:16 joda Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +top_builddir = ../../.. + +SHELL = /bin/sh + +CC = @CC@ +LINK = @LINK@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ -DBINDIR='"$(bindir)"' +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ +LD_FLAGS = @LD_FLAGS@ +LIBS = @LIBS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +PROGS = telnetd$(EXECSUFFIX) + +SOURCES=telnetd.c state.c termstat.c slc.c sys_term.c \ + utility.c global.c authenc.c + +OBJECTS=telnetd.o state.o termstat.o slc.o sys_term.o \ + utility.o global.o authenc.o + +libtop = @libtop@ + +LIBKRB = -L../../../lib/krb -lkrb +LIBDES = -L../../../lib/des -ldes +LIBKAFS = @KRB_KAFS_LIB@ +LIBROKEN = -L../../../lib/roken -lroken + +KLIB=$(LIBKAFS) $(LIBKRB) $(LIBDES) + + +all: $(PROGS) + +.c.o: + $(CC) -c $(DEFS) -I../../../include -I.. -I$(srcdir)/.. -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $< + +telnetd$(EXECSUFFIX): $(OBJECTS) + $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS) -L../libtelnet -ltelnet $(KLIB) $(LIBROKEN) $(LIBS) @LIB_tgetent@ $(LIBROKEN) + +install: all + $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir) + for x in $(PROGS); do \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROGS); do \ + rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + +TAGS: $(SOURCES) + etags $(SOURCES) + +clean cleandir: + rm -f *.o *.a telnetd$(EXECSUFFIX) \#* *~ core + +distclean: clean + rm -f Makefile *~ + + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/telnet/telnetd/authenc.c b/crypto/kerberosIV/appl/telnet/telnetd/authenc.c new file mode 100644 index 0000000..2a95127 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/authenc.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnetd.h" + +RCSID("$Id: authenc.c,v 1.8 1998/07/09 23:16:37 assar Exp $"); + +#ifdef AUTHENTICATION + +int +telnet_net_write(unsigned char *str, int len) +{ + if (nfrontp + len < netobuf + BUFSIZ) { + memmove(nfrontp, str, len); + nfrontp += len; + return(len); + } + return(0); +} + +void +net_encrypt(void) +{ +#ifdef ENCRYPTION + char *s = (nclearto > nbackp) ? nclearto : nbackp; + if (s < nfrontp && encrypt_output) { + (*encrypt_output)((unsigned char *)s, nfrontp - s); + } + nclearto = nfrontp; +#endif +} + +int +telnet_spin(void) +{ + ttloop(); + return(0); +} + +char * +telnet_getenv(char *val) +{ + extern char *getenv(const char *); + return(getenv(val)); +} + +char * +telnet_gets(char *prompt, char *result, int length, int echo) +{ + return NULL; +} +#endif diff --git a/crypto/kerberosIV/appl/telnet/telnetd/defs.h b/crypto/kerberosIV/appl/telnet/telnetd/defs.h new file mode 100644 index 0000000..dc3f842 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/defs.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/4/93 + */ + +/* + * Telnet server defines + */ + +#ifndef __DEFS_H__ +#define __DEFS_H__ + +#ifndef BSD +# define BSD 43 +#endif + +#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS) +#define TELOPTS +#define TELCMDS +#define SLC_NAMES +#endif + +#if !defined(TIOCSCTTY) && defined(TCSETCTTY) +# define TIOCSCTTY TCSETCTTY +#endif + +#ifndef TIOCPKT_FLUSHWRITE +#define TIOCPKT_FLUSHWRITE 0x02 +#endif + +#ifndef TIOCPKT_NOSTOP +#define TIOCPKT_NOSTOP 0x10 +#endif + +#ifndef TIOCPKT_DOSTOP +#define TIOCPKT_DOSTOP 0x20 +#endif + +/* + * I/O data buffers defines + */ +#define NETSLOP 64 +#ifdef _CRAY +#undef BUFSIZ +#define BUFSIZ 2048 +#endif + +#define NIACCUM(c) { *netip++ = c; \ + ncc++; \ + } + +/* clock manipulations */ +#define settimer(x) (clocks.x = ++clocks.system) +#define sequenceIs(x,y) (clocks.x < clocks.y) + +/* + * Structures of information for each special character function. + */ +typedef struct { + unsigned char flag; /* the flags for this function */ + cc_t val; /* the value of the special character */ +} slcent, *Slcent; + +typedef struct { + slcent defset; /* the default settings */ + slcent current; /* the current settings */ + cc_t *sptr; /* a pointer to the char in */ + /* system data structures */ +} slcfun, *Slcfun; + +#ifdef DIAGNOSTICS +/* + * Diagnostics capabilities + */ +#define TD_REPORT 0x01 /* Report operations to client */ +#define TD_EXERCISE 0x02 /* Exercise client's implementation */ +#define TD_NETDATA 0x04 /* Display received data stream */ +#define TD_PTYDATA 0x08 /* Display data passed to pty */ +#define TD_OPTIONS 0x10 /* Report just telnet options */ +#endif /* DIAGNOSTICS */ + +/* + * We keep track of each side of the option negotiation. + */ + +#define MY_STATE_WILL 0x01 +#define MY_WANT_STATE_WILL 0x02 +#define MY_STATE_DO 0x04 +#define MY_WANT_STATE_DO 0x08 + +/* + * Macros to check the current state of things + */ + +#define my_state_is_do(opt) (options[opt]&MY_STATE_DO) +#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) +#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) +#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) + +#define my_state_is_dont(opt) (!my_state_is_do(opt)) +#define my_state_is_wont(opt) (!my_state_is_will(opt)) +#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) +#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) + +#define set_my_state_do(opt) (options[opt] |= MY_STATE_DO) +#define set_my_state_will(opt) (options[opt] |= MY_STATE_WILL) +#define set_my_want_state_do(opt) (options[opt] |= MY_WANT_STATE_DO) +#define set_my_want_state_will(opt) (options[opt] |= MY_WANT_STATE_WILL) + +#define set_my_state_dont(opt) (options[opt] &= ~MY_STATE_DO) +#define set_my_state_wont(opt) (options[opt] &= ~MY_STATE_WILL) +#define set_my_want_state_dont(opt) (options[opt] &= ~MY_WANT_STATE_DO) +#define set_my_want_state_wont(opt) (options[opt] &= ~MY_WANT_STATE_WILL) + +/* + * Tricky code here. What we want to know is if the MY_STATE_WILL + * and MY_WANT_STATE_WILL bits have the same value. Since the two + * bits are adjacent, a little arithmatic will show that by adding + * in the lower bit, the upper bit will be set if the two bits were + * different, and clear if they were the same. + */ +#define my_will_wont_is_changing(opt) \ + ((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL) + +#define my_do_dont_is_changing(opt) \ + ((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO) + +/* + * Make everything symetrical + */ + +#define HIS_STATE_WILL MY_STATE_DO +#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO +#define HIS_STATE_DO MY_STATE_WILL +#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL + +#define his_state_is_do my_state_is_will +#define his_state_is_will my_state_is_do +#define his_want_state_is_do my_want_state_is_will +#define his_want_state_is_will my_want_state_is_do + +#define his_state_is_dont my_state_is_wont +#define his_state_is_wont my_state_is_dont +#define his_want_state_is_dont my_want_state_is_wont +#define his_want_state_is_wont my_want_state_is_dont + +#define set_his_state_do set_my_state_will +#define set_his_state_will set_my_state_do +#define set_his_want_state_do set_my_want_state_will +#define set_his_want_state_will set_my_want_state_do + +#define set_his_state_dont set_my_state_wont +#define set_his_state_wont set_my_state_dont +#define set_his_want_state_dont set_my_want_state_wont +#define set_his_want_state_wont set_my_want_state_dont + +#define his_will_wont_is_changing my_do_dont_is_changing +#define his_do_dont_is_changing my_will_wont_is_changing + +#endif /* __DEFS_H__ */ diff --git a/crypto/kerberosIV/appl/telnet/telnetd/ext.h b/crypto/kerberosIV/appl/telnet/telnetd/ext.h new file mode 100644 index 0000000..83b7166 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/ext.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ext.h 8.2 (Berkeley) 12/15/93 + */ + +/* $Id: ext.h,v 1.17 1998/07/09 23:16:38 assar Exp $ */ + +#ifndef __EXT_H__ +#define __EXT_H__ + +/* + * Telnet server variable declarations + */ +extern char options[256]; +extern char do_dont_resp[256]; +extern char will_wont_resp[256]; +extern int flowmode; /* current flow control state */ +extern int restartany; /* restart output on any character state */ +#ifdef DIAGNOSTICS +extern int diagnostic; /* telnet diagnostic capabilities */ +#endif /* DIAGNOSTICS */ +extern int require_otp; +#ifdef AUTHENTICATION +extern int auth_level; +#endif +extern const char *new_login; + +extern slcfun slctab[NSLC + 1]; /* slc mapping table */ + +extern char *terminaltype; + +/* + * I/O data buffers, pointers, and counters. + */ +extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; + +extern char netibuf[BUFSIZ], *netip; + +extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp; +extern char *neturg; /* one past last bye of urgent data */ + +extern int pcc, ncc; + +extern int ourpty, net; +extern char *line; +extern int SYNCHing; /* we are in TELNET SYNCH mode */ + +int telnet_net_write (unsigned char *str, int len); +void net_encrypt (void); +int telnet_spin (void); +char *telnet_getenv (char *val); +char *telnet_gets (char *prompt, char *result, int length, int echo); +void get_slc_defaults (void); +void telrcv (void); +void send_do (int option, int init); +void willoption (int option); +void send_dont (int option, int init); +void wontoption (int option); +void send_will (int option, int init); +void dooption (int option); +void send_wont (int option, int init); +void dontoption (int option); +void suboption (void); +void doclientstat (void); +void send_status (void); +void init_termbuf (void); +void set_termbuf (void); +int spcset (int func, cc_t *valp, cc_t **valpp); +void set_utid (void); +int getpty (int *ptynum); +int tty_isecho (void); +int tty_flowmode (void); +int tty_restartany (void); +void tty_setecho (int on); +int tty_israw (void); +void tty_binaryin (int on); +void tty_binaryout (int on); +int tty_isbinaryin (void); +int tty_isbinaryout (void); +int tty_issofttab (void); +void tty_setsofttab (int on); +int tty_islitecho (void); +void tty_setlitecho (int on); +int tty_iscrnl (void); +void tty_tspeed (int val); +void tty_rspeed (int val); +void getptyslave (void); +int cleanopen (char *line); +void startslave (char *host, int autologin, char *autoname); +void init_env (void); +void start_login (char *host, int autologin, char *name); +void cleanup (int sig); +int main (int argc, char **argv); +void usage (void); +int getterminaltype (char *name, size_t); +void _gettermname (void); +int terminaltypeok (char *s); +void doit (struct sockaddr_in *who); +void my_telnet (int f, int p, char*, int, char*); +void interrupt (void); +void sendbrk (void); +void sendsusp (void); +void recv_ayt (void); +void doeof (void); +void flowstat (void); +void clientstat (int code, int parm1, int parm2); +void ttloop (void); +int stilloob (int s); +void ptyflush (void); +char *nextitem (char *current); +void netclear (void); +void netflush (void); +void writenet (unsigned char *ptr, int len); +void fatal (int f, char *msg); +void fatalperror (int f, const char *msg); +void edithost (char *pat, char *host); +void putstr (char *s); +void putchr (int cc); +void putf (char *cp, char *where); +void printoption (char *fmt, int option); +void printsub (int direction, unsigned char *pointer, int length); +void printdata (char *tag, char *ptr, int cnt); +int login_tty(int t); + +#ifdef ENCRYPTION +extern void (*encrypt_output) (unsigned char *, int); +extern int (*decrypt_input) (int); +extern char *nclearto; +#endif + + +/* + * The following are some clocks used to decide how to interpret + * the relationship between various variables. + */ + +struct clocks_t{ + int + system, /* what the current time is */ + echotoggle, /* last time user entered echo character */ + modenegotiated, /* last time operating mode negotiated */ + didnetreceive, /* last time we read data from network */ + ttypesubopt, /* ttype subopt is received */ + tspeedsubopt, /* tspeed subopt is received */ + environsubopt, /* environ subopt is received */ + oenvironsubopt, /* old environ subopt is received */ + xdisplocsubopt, /* xdisploc subopt is received */ + baseline, /* time started to do timed action */ + gotDM; /* when did we last see a data mark */ +}; +extern struct clocks_t clocks; + +extern int log_unauth; +extern int no_warn; + +#ifdef STREAMSPTY +extern int really_stream; +#endif + +#ifndef USE_IM +# ifdef CRAY +# define USE_IM "Cray UNICOS (%h) (%t)" +# endif +# ifdef _AIX +# define USE_IM "%s %v.%r (%h) (%t)" +# endif +# ifndef USE_IM +# define USE_IM "%s %r (%h) (%t)" +# endif +#endif + +#define DEFAULT_IM "\r\n\r\n" USE_IM "\r\n\r\n\r\n" + +#endif /* __EXT_H__ */ diff --git a/crypto/kerberosIV/appl/telnet/telnetd/global.c b/crypto/kerberosIV/appl/telnet/telnetd/global.c new file mode 100644 index 0000000..275cb45 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/global.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* a *lot* of ugly global definitions that really should be removed... + */ + +#include "telnetd.h" + +RCSID("$Id: global.c,v 1.12 1997/05/11 06:29:59 assar Exp $"); + +/* + * Telnet server variable declarations + */ +char options[256]; +char do_dont_resp[256]; +char will_wont_resp[256]; +int linemode; /* linemode on/off */ +int flowmode; /* current flow control state */ +int restartany; /* restart output on any character state */ +#ifdef DIAGNOSTICS +int diagnostic; /* telnet diagnostic capabilities */ +#endif /* DIAGNOSTICS */ +int require_otp; + +slcfun slctab[NSLC + 1]; /* slc mapping table */ + +char *terminaltype; + +/* + * I/O data buffers, pointers, and counters. + */ +char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; + +char netibuf[BUFSIZ], *netip; + +char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp; +char *neturg; /* one past last bye of urgent data */ + +int pcc, ncc; + +int ourpty, net; +int SYNCHing; /* we are in TELNET SYNCH mode */ + +/* + * The following are some clocks used to decide how to interpret + * the relationship between various variables. + */ + +struct clocks_t clocks; + + +/* whether to log unauthenticated login attempts */ +int log_unauth; + +/* do not print warning if connection is not encrypted */ +int no_warn; + +/* + * This function appends data to nfrontp and advances nfrontp. + */ + +int +output_data (const char *format, ...) +{ + va_list args; + size_t remaining, ret; + + va_start(args, format); + remaining = BUFSIZ - (nfrontp - netobuf); + ret = vsnprintf (nfrontp, + remaining, + format, + args); + nfrontp += ret; + va_end(args); + return ret; +} diff --git a/crypto/kerberosIV/appl/telnet/telnetd/slc.c b/crypto/kerberosIV/appl/telnet/telnetd/slc.c new file mode 100644 index 0000000..799d2d8 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/slc.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnetd.h" + +RCSID("$Id: slc.c,v 1.10 1997/05/11 06:30:00 assar Exp $"); + +/* + * get_slc_defaults + * + * Initialize the slc mapping table. + */ +void +get_slc_defaults(void) +{ + int i; + + init_termbuf(); + + for (i = 1; i <= NSLC; i++) { + slctab[i].defset.flag = + spcset(i, &slctab[i].defset.val, &slctab[i].sptr); + slctab[i].current.flag = SLC_NOSUPPORT; + slctab[i].current.val = 0; + } + +} diff --git a/crypto/kerberosIV/appl/telnet/telnetd/state.c b/crypto/kerberosIV/appl/telnet/telnetd/state.c new file mode 100644 index 0000000..80b90ea --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/state.c @@ -0,0 +1,1356 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnetd.h" + +RCSID("$Id: state.c,v 1.13 1999/05/13 23:12:50 assar Exp $"); + +unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; +unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; +unsigned char will[] = { IAC, WILL, '%', 'c', 0 }; +unsigned char wont[] = { IAC, WONT, '%', 'c', 0 }; +int not42 = 1; + +/* + * Buffer for sub-options, and macros + * for suboptions buffer manipulations + */ +unsigned char subbuffer[2048], *subpointer= subbuffer, *subend= subbuffer; + +#define SB_CLEAR() subpointer = subbuffer +#define SB_TERM() { subend = subpointer; SB_CLEAR(); } +#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ + *subpointer++ = (c); \ + } +#define SB_GET() ((*subpointer++)&0xff) +#define SB_EOF() (subpointer >= subend) +#define SB_LEN() (subend - subpointer) + +#ifdef ENV_HACK +unsigned char *subsave; +#define SB_SAVE() subsave = subpointer; +#define SB_RESTORE() subpointer = subsave; +#endif + + +/* + * State for recv fsm + */ +#define TS_DATA 0 /* base state */ +#define TS_IAC 1 /* look for double IAC's */ +#define TS_CR 2 /* CR-LF ->'s CR */ +#define TS_SB 3 /* throw away begin's... */ +#define TS_SE 4 /* ...end's (suboption negotiation) */ +#define TS_WILL 5 /* will option negotiation */ +#define TS_WONT 6 /* wont -''- */ +#define TS_DO 7 /* do -''- */ +#define TS_DONT 8 /* dont -''- */ + +void +telrcv(void) +{ + int c; + static int state = TS_DATA; + + while (ncc > 0) { + if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) + break; + c = *netip++ & 0377, ncc--; +#ifdef ENCRYPTION + if (decrypt_input) + c = (*decrypt_input)(c); +#endif + switch (state) { + + case TS_CR: + state = TS_DATA; + /* Strip off \n or \0 after a \r */ + if ((c == 0) || (c == '\n')) { + break; + } + /* FALL THROUGH */ + + case TS_DATA: + if (c == IAC) { + state = TS_IAC; + break; + } + /* + * We now map \r\n ==> \r for pragmatic reasons. + * Many client implementations send \r\n when + * the user hits the CarriageReturn key. + * + * We USED to map \r\n ==> \n, since \r\n says + * that we want to be in column 1 of the next + * printable line, and \n is the standard + * unix way of saying that (\r is only good + * if CRMOD is set, which it normally is). + */ + if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { + int nc = *netip; +#ifdef ENCRYPTION + if (decrypt_input) + nc = (*decrypt_input)(nc & 0xff); +#endif + { +#ifdef ENCRYPTION + if (decrypt_input) + (void)(*decrypt_input)(-1); +#endif + state = TS_CR; + } + } + *pfrontp++ = c; + break; + + case TS_IAC: + gotiac: switch (c) { + + /* + * Send the process on the pty side an + * interrupt. Do this with a NULL or + * interrupt char; depending on the tty mode. + */ + case IP: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + interrupt(); + break; + + case BREAK: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + sendbrk(); + break; + + /* + * Are You There? + */ + case AYT: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + recv_ayt(); + break; + + /* + * Abort Output + */ + case AO: + { + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + + if (slctab[SLC_AO].sptr && + *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { + *pfrontp++ = + (unsigned char)*slctab[SLC_AO].sptr; + } + + netclear(); /* clear buffer back */ + output_data ("%c%c", IAC, DM); + neturg = nfrontp-1; /* off by one XXX */ + DIAG(TD_OPTIONS, + printoption("td: send IAC", DM)); + break; + } + + /* + * Erase Character and + * Erase Line + */ + case EC: + case EL: + { + cc_t ch; + + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + if (c == EC) + ch = *slctab[SLC_EC].sptr; + else + ch = *slctab[SLC_EL].sptr; + if (ch != (cc_t)(_POSIX_VDISABLE)) + *pfrontp++ = (unsigned char)ch; + break; + } + + /* + * Check for urgent data... + */ + case DM: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + SYNCHing = stilloob(net); + settimer(gotDM); + break; + + + /* + * Begin option subnegotiation... + */ + case SB: + state = TS_SB; + SB_CLEAR(); + continue; + + case WILL: + state = TS_WILL; + continue; + + case WONT: + state = TS_WONT; + continue; + + case DO: + state = TS_DO; + continue; + + case DONT: + state = TS_DONT; + continue; + case EOR: + if (his_state_is_will(TELOPT_EOR)) + doeof(); + break; + + /* + * Handle RFC 10xx Telnet linemode option additions + * to command stream (EOF, SUSP, ABORT). + */ + case xEOF: + doeof(); + break; + + case SUSP: + sendsusp(); + break; + + case ABORT: + sendbrk(); + break; + + case IAC: + *pfrontp++ = c; + break; + } + state = TS_DATA; + break; + + case TS_SB: + if (c == IAC) { + state = TS_SE; + } else { + SB_ACCUM(c); + } + break; + + case TS_SE: + if (c != SE) { + if (c != IAC) { + /* + * bad form of suboption negotiation. + * handle it in such a way as to avoid + * damage to local state. Parse + * suboption buffer found so far, + * then treat remaining stream as + * another command sequence. + */ + + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(c); + subpointer -= 2; + + SB_TERM(); + suboption(); + state = TS_IAC; + goto gotiac; + } + SB_ACCUM(c); + state = TS_SB; + } else { + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(SE); + subpointer -= 2; + + SB_TERM(); + suboption(); /* handle sub-option */ + state = TS_DATA; + } + break; + + case TS_WILL: + willoption(c); + state = TS_DATA; + continue; + + case TS_WONT: + wontoption(c); + if (c==TELOPT_ENCRYPT && his_do_dont_is_changing(TELOPT_ENCRYPT) ) + dontoption(c); + state = TS_DATA; + continue; + + case TS_DO: + dooption(c); + state = TS_DATA; + continue; + + case TS_DONT: + dontoption(c); + state = TS_DATA; + continue; + + default: + syslog(LOG_ERR, "telnetd: panic state=%d\n", state); + printf("telnetd: panic state=%d\n", state); + exit(1); + } + } +} /* end of telrcv */ + +/* + * The will/wont/do/dont state machines are based on Dave Borman's + * Telnet option processing state machine. + * + * These correspond to the following states: + * my_state = the last negotiated state + * want_state = what I want the state to go to + * want_resp = how many requests I have sent + * All state defaults are negative, and resp defaults to 0. + * + * When initiating a request to change state to new_state: + * + * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { + * do nothing; + * } else { + * want_state = new_state; + * send new_state; + * want_resp++; + * } + * + * When receiving new_state: + * + * if (want_resp) { + * want_resp--; + * if (want_resp && (new_state == my_state)) + * want_resp--; + * } + * if ((want_resp == 0) && (new_state != want_state)) { + * if (ok_to_switch_to new_state) + * want_state = new_state; + * else + * want_resp++; + * send want_state; + * } + * my_state = new_state; + * + * Note that new_state is implied in these functions by the function itself. + * will and do imply positive new_state, wont and dont imply negative. + * + * Finally, there is one catch. If we send a negative response to a + * positive request, my_state will be the positive while want_state will + * remain negative. my_state will revert to negative when the negative + * acknowlegment arrives from the peer. Thus, my_state generally tells + * us not only the last negotiated state, but also tells us what the peer + * wants to be doing as well. It is important to understand this difference + * as we may wish to be processing data streams based on our desired state + * (want_state) or based on what the peer thinks the state is (my_state). + * + * This all works fine because if the peer sends a positive request, the data + * that we receive prior to negative acknowlegment will probably be affected + * by the positive state, and we can process it as such (if we can; if we + * can't then it really doesn't matter). If it is that important, then the + * peer probably should be buffering until this option state negotiation + * is complete. + * + */ +void +send_do(int option, int init) +{ + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || + his_want_state_is_will(option)) + return; + /* + * Special case for TELOPT_TM: We send a DO, but pretend + * that we sent a DONT, so that we can send more DOs if + * we want to. + */ + if (option == TELOPT_TM) + set_his_want_state_wont(option); + else + set_his_want_state_will(option); + do_dont_resp[option]++; + } + output_data((const char *)doopt, option); + + DIAG(TD_OPTIONS, printoption("td: send do", option)); +} + +#ifdef AUTHENTICATION +extern void auth_request(void); +#endif +#ifdef ENCRYPTION +extern void encrypt_send_support(); +#endif + +void +willoption(int option) +{ + int changeok = 0; + void (*func)() = 0; + + /* + * process input from peer. + */ + + DIAG(TD_OPTIONS, printoption("td: recv will", option)); + + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_will(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_wont(option)) { + switch (option) { + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(1); + set_termbuf(); + changeok++; + break; + + case TELOPT_ECHO: + /* + * See comments below for more info. + */ + not42 = 0; /* looks like a 4.2 system */ + break; + + case TELOPT_TM: + /* + * We never respond to a WILL TM, and + * we leave the state WONT. + */ + return; + + case TELOPT_LFLOW: + /* + * If we are going to support flow control + * option, then don't worry peer that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_DEFAULT; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; + case TELOPT_TTYPE: + case TELOPT_SGA: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_XDISPLOC: + case TELOPT_NEW_ENVIRON: + case TELOPT_OLD_ENVIRON: + changeok++; + break; + + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + func = auth_request; + changeok++; + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + func = encrypt_send_support; + changeok++; + break; +#endif + + default: + break; + } + if (changeok) { + set_his_want_state_will(option); + send_do(option, 0); + } else { + do_dont_resp[option]++; + send_dont(option, 0); + } + } else { + /* + * Option processing that should happen when + * we receive conformation of a change in + * state that we had requested. + */ + switch (option) { + case TELOPT_ECHO: + not42 = 0; /* looks like a 4.2 system */ + /* + * Egads, he responded "WILL ECHO". Turn + * it off right now! + */ + send_dont(option, 1); + /* + * "WILL ECHO". Kludge upon kludge! + * A 4.2 client is now echoing user input at + * the tty. This is probably undesireable and + * it should be stopped. The client will + * respond WONT TM to the DO TM that we send to + * check for kludge linemode. When the WONT TM + * arrives, linemode will be turned off and a + * change propogated to the pty. This change + * will cause us to process the new pty state + * in localstat(), which will notice that + * linemode is off and send a WILL ECHO + * so that we are properly in character mode and + * all is well. + */ + break; + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + func = auth_request; + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + func = encrypt_send_support; + break; +#endif + + case TELOPT_LFLOW: + func = flowstat; + break; + } + } + } + set_his_state_will(option); + if (func) + (*func)(); +} /* end of willoption */ + +void +send_dont(int option, int init) +{ + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || + his_want_state_is_wont(option)) + return; + set_his_want_state_wont(option); + do_dont_resp[option]++; + } + output_data((const char *)dont, option); + + DIAG(TD_OPTIONS, printoption("td: send dont", option)); +} + +void +wontoption(int option) +{ + /* + * Process client input. + */ + + DIAG(TD_OPTIONS, printoption("td: recv wont", option)); + + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_wont(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_will(option)) { + /* it is always ok to change to negative state */ + switch (option) { + case TELOPT_ECHO: + not42 = 1; /* doesn't seem to be a 4.2 system */ + break; + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(0); + set_termbuf(); + break; + + case TELOPT_TM: + /* + * If we get a WONT TM, and had sent a DO TM, + * don't respond with a DONT TM, just leave it + * as is. Short circut the state machine to + * achive this. + */ + set_his_want_state_wont(TELOPT_TM); + return; + + case TELOPT_LFLOW: + /* + * If we are not going to support flow control + * option, then let peer know that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; + break; + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; +#endif + + /* + * For options that we might spin waiting for + * sub-negotiation, if the client turns off the + * option rather than responding to the request, + * we have to treat it here as if we got a response + * to the sub-negotiation, (by updating the timers) + * so that we'll break out of the loop. + */ + case TELOPT_TTYPE: + settimer(ttypesubopt); + break; + + case TELOPT_TSPEED: + settimer(tspeedsubopt); + break; + + case TELOPT_XDISPLOC: + settimer(xdisplocsubopt); + break; + + case TELOPT_OLD_ENVIRON: + settimer(oenvironsubopt); + break; + + case TELOPT_NEW_ENVIRON: + settimer(environsubopt); + break; + + default: + break; + } + set_his_want_state_wont(option); + if (his_state_is_will(option)) + send_dont(option, 0); + } else { + switch (option) { + case TELOPT_TM: + break; + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; +#endif + default: + break; + } + } + } + set_his_state_wont(option); + +} /* end of wontoption */ + +void +send_will(int option, int init) +{ + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| + my_want_state_is_will(option)) + return; + set_my_want_state_will(option); + will_wont_resp[option]++; + } + output_data ((const char *)will, option); + + DIAG(TD_OPTIONS, printoption("td: send will", option)); +} + +/* + * When we get a DONT SGA, we will try once to turn it + * back on. If the other side responds DONT SGA, we + * leave it at that. This is so that when we talk to + * clients that understand KLUDGELINEMODE but not LINEMODE, + * we'll keep them in char-at-a-time mode. + */ +int turn_on_sga = 0; + +void +dooption(int option) +{ + int changeok = 0; + + /* + * Process client input. + */ + + DIAG(TD_OPTIONS, printoption("td: recv do", option)); + + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_will(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { + switch (option) { + case TELOPT_ECHO: + { + init_termbuf(); + tty_setecho(1); + set_termbuf(); + } + changeok++; + break; + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(1); + set_termbuf(); + changeok++; + break; + + case TELOPT_SGA: + turn_on_sga = 0; + changeok++; + break; + + case TELOPT_STATUS: + changeok++; + break; + + case TELOPT_TM: + /* + * Special case for TM. We send a WILL, but + * pretend we sent a WONT. + */ + send_will(option, 0); + set_my_want_state_wont(option); + set_my_state_wont(option); + return; + + case TELOPT_LOGOUT: + /* + * When we get a LOGOUT option, respond + * with a WILL LOGOUT, make sure that + * it gets written out to the network, + * and then just go away... + */ + set_my_want_state_will(TELOPT_LOGOUT); + send_will(TELOPT_LOGOUT, 0); + set_my_state_will(TELOPT_LOGOUT); + netflush(); + cleanup(0); + /* NOT REACHED */ + break; + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + changeok++; + break; +#endif + case TELOPT_LINEMODE: + case TELOPT_TTYPE: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_LFLOW: + case TELOPT_XDISPLOC: +#ifdef TELOPT_ENVIRON + case TELOPT_NEW_ENVIRON: +#endif + case TELOPT_OLD_ENVIRON: + default: + break; + } + if (changeok) { + set_my_want_state_will(option); + send_will(option, 0); + } else { + will_wont_resp[option]++; + send_wont(option, 0); + } + } + set_my_state_will(option); + +} /* end of dooption */ + +void +send_wont(int option, int init) +{ + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || + my_want_state_is_wont(option)) + return; + set_my_want_state_wont(option); + will_wont_resp[option]++; + } + output_data ((const char *)wont, option); + + DIAG(TD_OPTIONS, printoption("td: send wont", option)); +} + +void +dontoption(int option) +{ + /* + * Process client input. + */ + + + DIAG(TD_OPTIONS, printoption("td: recv dont", option)); + + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_wont(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { + switch (option) { + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(0); + set_termbuf(); + break; + + case TELOPT_ECHO: /* we should stop echoing */ + { + init_termbuf(); + tty_setecho(0); + set_termbuf(); + } + break; + + case TELOPT_SGA: + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + set_my_state_wont(option); + if (turn_on_sga ^= 1) + send_will(option, 1); + return; + + default: + break; + } + + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + } + set_my_state_wont(option); + +} /* end of dontoption */ + +#ifdef ENV_HACK +int env_ovar = -1; +int env_ovalue = -1; +#else /* ENV_HACK */ +# define env_ovar OLD_ENV_VAR +# define env_ovalue OLD_ENV_VALUE +#endif /* ENV_HACK */ + +/* + * suboption() + * + * Look at the sub-option buffer, and try to be helpful to the other + * side. + * + * Currently we recognize: + * + * Terminal type is + * Linemode + * Window size + * Terminal speed + */ +void +suboption(void) +{ + int subchar; + + DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); + + subchar = SB_GET(); + switch (subchar) { + case TELOPT_TSPEED: { + int xspeed, rspeed; + + if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ + break; + + settimer(tspeedsubopt); + + if (SB_EOF() || SB_GET() != TELQUAL_IS) + return; + + xspeed = atoi((char *)subpointer); + + while (SB_GET() != ',' && !SB_EOF()); + if (SB_EOF()) + return; + + rspeed = atoi((char *)subpointer); + clientstat(TELOPT_TSPEED, xspeed, rspeed); + + break; + + } /* end of case TELOPT_TSPEED */ + + case TELOPT_TTYPE: { /* Yaaaay! */ + static char terminalname[41]; + + if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ + break; + settimer(ttypesubopt); + + if (SB_EOF() || SB_GET() != TELQUAL_IS) { + return; /* ??? XXX but, this is the most robust */ + } + + terminaltype = terminalname; + + while ((terminaltype < (terminalname + sizeof terminalname-1)) && + !SB_EOF()) { + int c; + + c = SB_GET(); + if (isupper(c)) { + c = tolower(c); + } + *terminaltype++ = c; /* accumulate name */ + } + *terminaltype = 0; + terminaltype = terminalname; + break; + } /* end of case TELOPT_TTYPE */ + + case TELOPT_NAWS: { + int xwinsize, ywinsize; + + if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ + break; + + if (SB_EOF()) + return; + xwinsize = SB_GET() << 8; + if (SB_EOF()) + return; + xwinsize |= SB_GET(); + if (SB_EOF()) + return; + ywinsize = SB_GET() << 8; + if (SB_EOF()) + return; + ywinsize |= SB_GET(); + clientstat(TELOPT_NAWS, xwinsize, ywinsize); + + break; + + } /* end of case TELOPT_NAWS */ + + case TELOPT_STATUS: { + int mode; + + if (SB_EOF()) + break; + mode = SB_GET(); + switch (mode) { + case TELQUAL_SEND: + if (my_state_is_will(TELOPT_STATUS)) + send_status(); + break; + + case TELQUAL_IS: + break; + + default: + break; + } + break; + } /* end of case TELOPT_STATUS */ + + case TELOPT_XDISPLOC: { + if (SB_EOF() || SB_GET() != TELQUAL_IS) + return; + settimer(xdisplocsubopt); + subpointer[SB_LEN()] = '\0'; + setenv("DISPLAY", (char *)subpointer, 1); + break; + } /* end of case TELOPT_XDISPLOC */ + +#ifdef TELOPT_NEW_ENVIRON + case TELOPT_NEW_ENVIRON: +#endif + case TELOPT_OLD_ENVIRON: { + int c; + char *cp, *varp, *valp; + + if (SB_EOF()) + return; + c = SB_GET(); + if (c == TELQUAL_IS) { + if (subchar == TELOPT_OLD_ENVIRON) + settimer(oenvironsubopt); + else + settimer(environsubopt); + } else if (c != TELQUAL_INFO) { + return; + } + +#ifdef TELOPT_NEW_ENVIRON + if (subchar == TELOPT_NEW_ENVIRON) { + while (!SB_EOF()) { + c = SB_GET(); + if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) + break; + } + } else +#endif + { +#ifdef ENV_HACK + /* + * We only want to do this if we haven't already decided + * whether or not the other side has its VALUE and VAR + * reversed. + */ + if (env_ovar < 0) { + int last = -1; /* invalid value */ + int empty = 0; + int got_var = 0, got_value = 0, got_uservar = 0; + + /* + * The other side might have its VALUE and VAR values + * reversed. To be interoperable, we need to determine + * which way it is. If the first recognized character + * is a VAR or VALUE, then that will tell us what + * type of client it is. If the fist recognized + * character is a USERVAR, then we continue scanning + * the suboption looking for two consecutive + * VAR or VALUE fields. We should not get two + * consecutive VALUE fields, so finding two + * consecutive VALUE or VAR fields will tell us + * what the client is. + */ + SB_SAVE(); + while (!SB_EOF()) { + c = SB_GET(); + switch(c) { + case OLD_ENV_VAR: + if (last < 0 || last == OLD_ENV_VAR + || (empty && (last == OLD_ENV_VALUE))) + goto env_ovar_ok; + got_var++; + last = OLD_ENV_VAR; + break; + case OLD_ENV_VALUE: + if (last < 0 || last == OLD_ENV_VALUE + || (empty && (last == OLD_ENV_VAR))) + goto env_ovar_wrong; + got_value++; + last = OLD_ENV_VALUE; + break; + case ENV_USERVAR: + /* count strings of USERVAR as one */ + if (last != ENV_USERVAR) + got_uservar++; + if (empty) { + if (last == OLD_ENV_VALUE) + goto env_ovar_ok; + if (last == OLD_ENV_VAR) + goto env_ovar_wrong; + } + last = ENV_USERVAR; + break; + case ENV_ESC: + if (!SB_EOF()) + c = SB_GET(); + /* FALL THROUGH */ + default: + empty = 0; + continue; + } + empty = 1; + } + if (empty) { + if (last == OLD_ENV_VALUE) + goto env_ovar_ok; + if (last == OLD_ENV_VAR) + goto env_ovar_wrong; + } + /* + * Ok, the first thing was a USERVAR, and there + * are not two consecutive VAR or VALUE commands, + * and none of the VAR or VALUE commands are empty. + * If the client has sent us a well-formed option, + * then the number of VALUEs received should always + * be less than or equal to the number of VARs and + * USERVARs received. + * + * If we got exactly as many VALUEs as VARs and + * USERVARs, the client has the same definitions. + * + * If we got exactly as many VARs as VALUEs and + * USERVARS, the client has reversed definitions. + */ + if (got_uservar + got_var == got_value) { + env_ovar_ok: + env_ovar = OLD_ENV_VAR; + env_ovalue = OLD_ENV_VALUE; + } else if (got_uservar + got_value == got_var) { + env_ovar_wrong: + env_ovar = OLD_ENV_VALUE; + env_ovalue = OLD_ENV_VAR; + DIAG(TD_OPTIONS, { + output_data("ENVIRON VALUE and VAR are reversed!\r\n"); + }); + + } + } + SB_RESTORE(); +#endif + + while (!SB_EOF()) { + c = SB_GET(); + if ((c == env_ovar) || (c == ENV_USERVAR)) + break; + } + } + + if (SB_EOF()) + return; + + cp = varp = (char *)subpointer; + valp = 0; + + while (!SB_EOF()) { + c = SB_GET(); + if (subchar == TELOPT_OLD_ENVIRON) { + if (c == env_ovar) + c = NEW_ENV_VAR; + else if (c == env_ovalue) + c = NEW_ENV_VALUE; + } + switch (c) { + + case NEW_ENV_VALUE: + *cp = '\0'; + cp = valp = (char *)subpointer; + break; + + case NEW_ENV_VAR: + case ENV_USERVAR: + *cp = '\0'; + if (valp) + setenv(varp, valp, 1); + else + unsetenv(varp); + cp = varp = (char *)subpointer; + valp = 0; + break; + + case ENV_ESC: + if (SB_EOF()) + break; + c = SB_GET(); + /* FALL THROUGH */ + default: + *cp++ = c; + break; + } + } + *cp = '\0'; + if (valp) + setenv(varp, valp, 1); + else + unsetenv(varp); + break; + } /* end of case TELOPT_NEW_ENVIRON */ +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + if (SB_EOF()) + break; + switch(SB_GET()) { + case TELQUAL_SEND: + case TELQUAL_REPLY: + /* + * These are sent by us and cannot be sent by + * the client. + */ + break; + case TELQUAL_IS: + auth_is(subpointer, SB_LEN()); + break; + case TELQUAL_NAME: + auth_name(subpointer, SB_LEN()); + break; + } + break; +#endif +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + if (SB_EOF()) + break; + switch(SB_GET()) { + case ENCRYPT_SUPPORT: + encrypt_support(subpointer, SB_LEN()); + break; + case ENCRYPT_IS: + encrypt_is(subpointer, SB_LEN()); + break; + case ENCRYPT_REPLY: + encrypt_reply(subpointer, SB_LEN()); + break; + case ENCRYPT_START: + encrypt_start(subpointer, SB_LEN()); + break; + case ENCRYPT_END: + encrypt_end(); + break; + case ENCRYPT_REQSTART: + encrypt_request_start(subpointer, SB_LEN()); + break; + case ENCRYPT_REQEND: + /* + * We can always send an REQEND so that we cannot + * get stuck encrypting. We should only get this + * if we have been able to get in the correct mode + * anyhow. + */ + encrypt_request_end(); + break; + case ENCRYPT_ENC_KEYID: + encrypt_enc_keyid(subpointer, SB_LEN()); + break; + case ENCRYPT_DEC_KEYID: + encrypt_dec_keyid(subpointer, SB_LEN()); + break; + default: + break; + } + break; +#endif + + default: + break; + } /* end of switch */ + +} /* end of suboption */ + +void +doclientstat(void) +{ + clientstat(TELOPT_LINEMODE, WILL, 0); +} + +#define ADD(c) *ncp++ = c +#define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } + +void +send_status(void) +{ + unsigned char statusbuf[256]; + unsigned char *ncp; + unsigned char i; + + ncp = statusbuf; + + netflush(); /* get rid of anything waiting to go out */ + + ADD(IAC); + ADD(SB); + ADD(TELOPT_STATUS); + ADD(TELQUAL_IS); + + /* + * We check the want_state rather than the current state, + * because if we received a DO/WILL for an option that we + * don't support, and the other side didn't send a DONT/WONT + * in response to our WONT/DONT, then the "state" will be + * WILL/DO, and the "want_state" will be WONT/DONT. We + * need to go by the latter. + */ + for (i = 0; i < (unsigned char)NTELOPTS; i++) { + if (my_want_state_is_will(i)) { + ADD(WILL); + ADD_DATA(i); + } + if (his_want_state_is_will(i)) { + ADD(DO); + ADD_DATA(i); + } + } + + if (his_want_state_is_will(TELOPT_LFLOW)) { + ADD(SB); + ADD(TELOPT_LFLOW); + if (flowmode) { + ADD(LFLOW_ON); + } else { + ADD(LFLOW_OFF); + } + ADD(SE); + + if (restartany >= 0) { + ADD(SB); + ADD(TELOPT_LFLOW); + if (restartany) { + ADD(LFLOW_RESTART_ANY); + } else { + ADD(LFLOW_RESTART_XON); + } + ADD(SE); + } + } + + + ADD(IAC); + ADD(SE); + + writenet(statusbuf, ncp - statusbuf); + netflush(); /* Send it on its way */ + + DIAG(TD_OPTIONS, + {printsub('>', statusbuf, ncp - statusbuf); netflush();}); +} diff --git a/crypto/kerberosIV/appl/telnet/telnetd/sys_term.c b/crypto/kerberosIV/appl/telnet/telnetd/sys_term.c new file mode 100644 index 0000000..09753c0 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/sys_term.c @@ -0,0 +1,1863 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnetd.h" + +RCSID("$Id: sys_term.c,v 1.85.2.1 1999/07/22 03:23:19 assar Exp $"); + +#if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H)) +# define PARENT_DOES_UTMP +#endif + +#ifdef HAVE_UTMP_H +#include <utmp.h> +#endif + +#ifdef HAVE_UTMPX_H +#include <utmpx.h> +#endif + +#ifdef HAVE_UTMPX_H +struct utmpx wtmp; +#elif defined(HAVE_UTMP_H) +struct utmp wtmp; +#endif /* HAVE_UTMPX_H */ + +#ifdef HAVE_STRUCT_UTMP_UT_HOST +int utmp_len = sizeof(wtmp.ut_host); +#else +int utmp_len = MaxHostNameLen; +#endif + +#ifndef UTMP_FILE +#ifdef _PATH_UTMP +#define UTMP_FILE _PATH_UTMP +#else +#define UTMP_FILE "/etc/utmp" +#endif +#endif + +#if !defined(WTMP_FILE) && defined(_PATH_WTMP) +#define WTMP_FILE _PATH_WTMP +#endif + +#ifndef PARENT_DOES_UTMP +#ifdef WTMP_FILE +char wtmpf[] = WTMP_FILE; +#else +char wtmpf[] = "/usr/adm/wtmp"; +#endif +char utmpf[] = UTMP_FILE; +#else /* PARENT_DOES_UTMP */ +#ifdef WTMP_FILE +char wtmpf[] = WTMP_FILE; +#else +char wtmpf[] = "/etc/wtmp"; +#endif +#endif /* PARENT_DOES_UTMP */ + +#ifdef HAVE_TMPDIR_H +#include <tmpdir.h> +#endif /* CRAY */ + +#ifdef STREAMSPTY + +#ifdef HAVE_SAC_H +#include <sac.h> +#endif + +#ifdef HAVE_SYS_STROPTS_H +#include <sys/stropts.h> +#endif + +#endif /* STREAMSPTY */ + +#ifdef HAVE_SYS_STREAM_H +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif +#ifdef __hpux +#undef SE +#endif +#include <sys/stream.h> +#endif +#if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY) +#include <sys/tty.h> +#endif +#ifdef t_erase +#undef t_erase +#undef t_kill +#undef t_intrc +#undef t_quitc +#undef t_startc +#undef t_stopc +#undef t_eofc +#undef t_brkc +#undef t_suspc +#undef t_dsuspc +#undef t_rprntc +#undef t_flushc +#undef t_werasc +#undef t_lnextc +#endif + +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#else +#ifdef HAVE_TERMIO_H +#include <termio.h> +#endif +#endif + +#ifdef HAVE_UTIL_H +#include <util.h> +#endif + +# ifndef TCSANOW +# ifdef TCSETS +# define TCSANOW TCSETS +# define TCSADRAIN TCSETSW +# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) +# else +# ifdef TCSETA +# define TCSANOW TCSETA +# define TCSADRAIN TCSETAW +# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) +# else +# define TCSANOW TIOCSETA +# define TCSADRAIN TIOCSETAW +# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) +# endif +# endif +# define tcsetattr(f, a, t) ioctl(f, a, t) +# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ +(tp)->c_cflag |= (val) +# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) +# ifdef CIBAUD +# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ + (tp)->c_cflag |= ((val)<<IBSHIFT) +# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) +# else +# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ + (tp)->c_cflag |= (val) +# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) +# endif +# endif /* TCSANOW */ + struct termios termbuf, termbuf2; /* pty control structure */ +# ifdef STREAMSPTY + static int ttyfd = -1; + int really_stream = 0; +# endif + + const char *new_login = _PATH_LOGIN; + +/* + * init_termbuf() + * copy_termbuf(cp) + * set_termbuf() + * + * These three routines are used to get and set the "termbuf" structure + * to and from the kernel. init_termbuf() gets the current settings. + * copy_termbuf() hands in a new "termbuf" to write to the kernel, and + * set_termbuf() writes the structure into the kernel. + */ + + void + init_termbuf(void) +{ +# ifdef STREAMSPTY + if (really_stream) + tcgetattr(ttyfd, &termbuf); + else +# endif + tcgetattr(ourpty, &termbuf); + termbuf2 = termbuf; +} + +void +set_termbuf(void) +{ + /* + * Only make the necessary changes. + */ + if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) +# ifdef STREAMSPTY + if (really_stream) + tcsetattr(ttyfd, TCSANOW, &termbuf); + else +# endif + tcsetattr(ourpty, TCSANOW, &termbuf); +} + + +/* + * spcset(func, valp, valpp) + * + * This function takes various special characters (func), and + * sets *valp to the current value of that character, and + * *valpp to point to where in the "termbuf" structure that + * value is kept. + * + * It returns the SLC_ level of support for this function. + */ + + +int +spcset(int func, cc_t *valp, cc_t **valpp) +{ + +#define setval(a, b) *valp = termbuf.c_cc[a]; \ + *valpp = &termbuf.c_cc[a]; \ + return(b); +#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); + + switch(func) { + case SLC_EOF: + setval(VEOF, SLC_VARIABLE); + case SLC_EC: + setval(VERASE, SLC_VARIABLE); + case SLC_EL: + setval(VKILL, SLC_VARIABLE); + case SLC_IP: + setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_ABORT: + setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_XON: +#ifdef VSTART + setval(VSTART, SLC_VARIABLE); +#else + defval(0x13); +#endif + case SLC_XOFF: +#ifdef VSTOP + setval(VSTOP, SLC_VARIABLE); +#else + defval(0x11); +#endif + case SLC_EW: +#ifdef VWERASE + setval(VWERASE, SLC_VARIABLE); +#else + defval(0); +#endif + case SLC_RP: +#ifdef VREPRINT + setval(VREPRINT, SLC_VARIABLE); +#else + defval(0); +#endif + case SLC_LNEXT: +#ifdef VLNEXT + setval(VLNEXT, SLC_VARIABLE); +#else + defval(0); +#endif + case SLC_AO: +#if !defined(VDISCARD) && defined(VFLUSHO) +# define VDISCARD VFLUSHO +#endif +#ifdef VDISCARD + setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); +#else + defval(0); +#endif + case SLC_SUSP: +#ifdef VSUSP + setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); +#else + defval(0); +#endif +#ifdef VEOL + case SLC_FORW1: + setval(VEOL, SLC_VARIABLE); +#endif +#ifdef VEOL2 + case SLC_FORW2: + setval(VEOL2, SLC_VARIABLE); +#endif + case SLC_AYT: +#ifdef VSTATUS + setval(VSTATUS, SLC_VARIABLE); +#else + defval(0); +#endif + + case SLC_BRK: + case SLC_SYNCH: + case SLC_EOR: + defval(0); + + default: + *valp = 0; + *valpp = 0; + return(SLC_NOSUPPORT); + } +} + +#ifdef _CRAY +/* + * getnpty() + * + * Return the number of pty's configured into the system. + */ +int +getnpty() +{ +#ifdef _SC_CRAY_NPTY + int numptys; + + if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) + return numptys; + else +#endif /* _SC_CRAY_NPTY */ + return 128; +} +#endif /* CRAY */ + +/* + * getpty() + * + * Allocate a pty. As a side effect, the external character + * array "line" contains the name of the slave side. + * + * Returns the file descriptor of the opened pty. + */ + +static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +char *line = Xline; + +#ifdef _CRAY +char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +#endif /* CRAY */ + +#if !defined(HAVE_PTSNAME) && defined(STREAMSPTY) +static char *ptsname(int fd) +{ +#ifdef HAVE_TTYNAME + return ttyname(fd); +#else + return NULL; +#endif +} +#endif + +int getpty(int *ptynum) +{ +#ifdef __osf__ /* XXX */ + int master; + int slave; + if(openpty(&master, &slave, line, 0, 0) == 0){ + close(slave); + return master; + } + return -1; +#else +#ifdef HAVE__GETPTY + int master, slave; + char *p; + p = _getpty(&master, O_RDWR, 0600, 1); + if(p == NULL) + return -1; + strcpy_truncate(line, p, sizeof(Xline)); + return master; +#else + + int p; + char *cp, *p1, *p2; + int i; +#if SunOS == 40 + int dummy; +#endif +#if 0 /* && defined(HAVE_OPENPTY) */ + int master; + int slave; + if(openpty(&master, &slave, line, 0, 0) == 0){ + close(slave); + return master; + } +#else +#ifdef STREAMSPTY + char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", + "/dev/ptym/clone", 0 }; + + char **q; + for(q=clone; *q; q++){ + p=open(*q, O_RDWR); + if(p >= 0){ +#ifdef HAVE_GRANTPT + grantpt(p); +#endif +#ifdef HAVE_UNLOCKPT + unlockpt(p); +#endif + strcpy_truncate(line, ptsname(p), sizeof(Xline)); + really_stream = 1; + return p; + } + } +#endif /* STREAMSPTY */ +#ifndef _CRAY + +#ifndef __hpux + snprintf(line, sizeof(Xline), "/dev/ptyXX"); + p1 = &line[8]; + p2 = &line[9]; +#else + snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); + p1 = &line[13]; + p2 = &line[14]; +#endif + + + for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { + struct stat stb; + + *p1 = *cp; + *p2 = '0'; + /* + * This stat() check is just to keep us from + * looping through all 256 combinations if there + * aren't that many ptys available. + */ + if (stat(line, &stb) < 0) + break; + for (i = 0; i < 16; i++) { + *p2 = "0123456789abcdef"[i]; + p = open(line, O_RDWR); + if (p > 0) { +#ifndef __hpux + line[5] = 't'; +#else + for (p1 = &line[8]; *p1; p1++) + *p1 = *(p1+1); + line[9] = 't'; +#endif + chown(line, 0, 0); + chmod(line, 0600); +#if SunOS == 40 + if (ioctl(p, TIOCGPGRP, &dummy) == 0 + || errno != EIO) { + chmod(line, 0666); + close(p); + line[5] = 'p'; + } else +#endif /* SunOS == 40 */ + return(p); + } + } + } +#else /* CRAY */ + extern lowpty, highpty; + struct stat sb; + + for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { + snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); + p = open(myline, 2); + if (p < 0) + continue; + snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); + /* + * Here are some shenanigans to make sure that there + * are no listeners lurking on the line. + */ + if(stat(line, &sb) < 0) { + close(p); + continue; + } + if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { + chown(line, 0, 0); + chmod(line, 0600); + close(p); + p = open(myline, 2); + if (p < 0) + continue; + } + /* + * Now it should be safe...check for accessability. + */ + if (access(line, 6) == 0) + return(p); + else { + /* no tty side to pty so skip it */ + close(p); + } + } +#endif /* CRAY */ +#endif /* STREAMSPTY */ +#endif /* OPENPTY */ + return(-1); +#endif +} + + +int +tty_isecho(void) +{ + return (termbuf.c_lflag & ECHO); +} + +int +tty_flowmode(void) +{ + return((termbuf.c_iflag & IXON) ? 1 : 0); +} + +int +tty_restartany(void) +{ + return((termbuf.c_iflag & IXANY) ? 1 : 0); +} + +void +tty_setecho(int on) +{ + if (on) + termbuf.c_lflag |= ECHO; + else + termbuf.c_lflag &= ~ECHO; +} + +int +tty_israw(void) +{ + return(!(termbuf.c_lflag & ICANON)); +} + +void +tty_binaryin(int on) +{ + if (on) { + termbuf.c_iflag &= ~ISTRIP; + } else { + termbuf.c_iflag |= ISTRIP; + } +} + +void +tty_binaryout(int on) +{ + if (on) { + termbuf.c_cflag &= ~(CSIZE|PARENB); + termbuf.c_cflag |= CS8; + termbuf.c_oflag &= ~OPOST; + } else { + termbuf.c_cflag &= ~CSIZE; + termbuf.c_cflag |= CS7|PARENB; + termbuf.c_oflag |= OPOST; + } +} + +int +tty_isbinaryin(void) +{ + return(!(termbuf.c_iflag & ISTRIP)); +} + +int +tty_isbinaryout(void) +{ + return(!(termbuf.c_oflag&OPOST)); +} + + +int +tty_issofttab(void) +{ +# ifdef OXTABS + return (termbuf.c_oflag & OXTABS); +# endif +# ifdef TABDLY + return ((termbuf.c_oflag & TABDLY) == TAB3); +# endif +} + +void +tty_setsofttab(int on) +{ + if (on) { +# ifdef OXTABS + termbuf.c_oflag |= OXTABS; +# endif +# ifdef TABDLY + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB3; +# endif + } else { +# ifdef OXTABS + termbuf.c_oflag &= ~OXTABS; +# endif +# ifdef TABDLY + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB0; +# endif + } +} + +int +tty_islitecho(void) +{ +# ifdef ECHOCTL + return (!(termbuf.c_lflag & ECHOCTL)); +# endif +# ifdef TCTLECH + return (!(termbuf.c_lflag & TCTLECH)); +# endif +# if !defined(ECHOCTL) && !defined(TCTLECH) + return (0); /* assumes ctl chars are echoed '^x' */ +# endif +} + +void +tty_setlitecho(int on) +{ +# ifdef ECHOCTL + if (on) + termbuf.c_lflag &= ~ECHOCTL; + else + termbuf.c_lflag |= ECHOCTL; +# endif +# ifdef TCTLECH + if (on) + termbuf.c_lflag &= ~TCTLECH; + else + termbuf.c_lflag |= TCTLECH; +# endif +} + +int +tty_iscrnl(void) +{ + return (termbuf.c_iflag & ICRNL); +} + +/* + * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). + */ +#if B4800 != 4800 +#define DECODE_BAUD +#endif + +#ifdef DECODE_BAUD + +/* + * A table of available terminal speeds + */ +struct termspeeds { + int speed; + int value; +} termspeeds[] = { + { 0, B0 }, { 50, B50 }, { 75, B75 }, + { 110, B110 }, { 134, B134 }, { 150, B150 }, + { 200, B200 }, { 300, B300 }, { 600, B600 }, + { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, + { 4800, B4800 }, +#ifdef B7200 + { 7200, B7200 }, +#endif + { 9600, B9600 }, +#ifdef B14400 + { 14400, B14400 }, +#endif +#ifdef B19200 + { 19200, B19200 }, +#endif +#ifdef B28800 + { 28800, B28800 }, +#endif +#ifdef B38400 + { 38400, B38400 }, +#endif +#ifdef B57600 + { 57600, B57600 }, +#endif +#ifdef B115200 + { 115200, B115200 }, +#endif +#ifdef B230400 + { 230400, B230400 }, +#endif + { -1, 0 } +}; +#endif /* DECODE_BUAD */ + +void +tty_tspeed(int val) +{ +#ifdef DECODE_BAUD + struct termspeeds *tp; + + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetospeed(&termbuf, tp->value); +#else /* DECODE_BUAD */ + cfsetospeed(&termbuf, val); +#endif /* DECODE_BUAD */ +} + +void +tty_rspeed(int val) +{ +#ifdef DECODE_BAUD + struct termspeeds *tp; + + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetispeed(&termbuf, tp->value); +#else /* DECODE_BAUD */ + cfsetispeed(&termbuf, val); +#endif /* DECODE_BAUD */ +} + +#ifdef PARENT_DOES_UTMP +extern struct utmp wtmp; +extern char wtmpf[]; + +extern void utmp_sig_init (void); +extern void utmp_sig_reset (void); +extern void utmp_sig_wait (void); +extern void utmp_sig_notify (int); +# endif /* PARENT_DOES_UTMP */ + +#ifdef STREAMSPTY + +/* I_FIND seems to live a life of its own */ +static int my_find(int fd, char *module) +{ +#if defined(I_FIND) && defined(I_LIST) + static int flag; + static struct str_list sl; + int n; + int i; + + if(!flag){ + n = ioctl(fd, I_LIST, 0); + if(n < 0){ + perror("ioctl(fd, I_LIST, 0)"); + return -1; + } + sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist)); + sl.sl_nmods = n; + n = ioctl(fd, I_LIST, &sl); + if(n < 0){ + perror("ioctl(fd, I_LIST, n)"); + return -1; + } + flag = 1; + } + + for(i=0; i<sl.sl_nmods; i++) + if(!strcmp(sl.sl_modlist[i].l_name, module)) + return 1; +#endif + return 0; +} + +static void maybe_push_modules(int fd, char **modules) +{ + char **p; + int err; + + for(p=modules; *p; p++){ + err = my_find(fd, *p); + if(err == 1) + break; + if(err < 0 && errno != EINVAL) + fatalperror(net, "my_find()"); + /* module not pushed or does not exist */ + } + /* p points to null or to an already pushed module, now push all + modules before this one */ + + for(p--; p >= modules; p--){ + err = ioctl(fd, I_PUSH, *p); + if(err < 0 && errno != EINVAL) + fatalperror(net, "I_PUSH"); + } +} +#endif + +/* + * getptyslave() + * + * Open the slave side of the pty, and do any initialization + * that is necessary. The return value is a file descriptor + * for the slave side. + */ +void getptyslave(void) +{ + int t = -1; + + struct winsize ws; + extern int def_row, def_col; + extern int def_tspeed, def_rspeed; + /* + * Opening the slave side may cause initilization of the + * kernel tty structure. We need remember the state of + * if linemode was turned on + * terminal window size + * terminal speed + * so that we can re-set them if we need to. + */ + + + /* + * Make sure that we don't have a controlling tty, and + * that we are the session (process group) leader. + */ + +#ifdef HAVE_SETSID + if(setsid()<0) + fatalperror(net, "setsid()"); +#else +# ifdef TIOCNOTTY + t = open(_PATH_TTY, O_RDWR); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + close(t); + } +# endif +#endif + +# ifdef PARENT_DOES_UTMP + /* + * Wait for our parent to get the utmp stuff to get done. + */ + utmp_sig_wait(); +# endif + + t = cleanopen(line); + if (t < 0) + fatalperror(net, line); + +#ifdef STREAMSPTY + ttyfd = t; + + + /* + * Not all systems have (or need) modules ttcompat and pckt so + * don't flag it as a fatal error if they don't exist. + */ + + if (really_stream) + { + /* these are the streams modules that we want pushed. note + that they are in reverse order, ptem will be pushed + first. maybe_push_modules() will try to push all modules + before the first one that isn't already pushed. i.e if + ldterm is pushed, only ttcompat will be attempted. + + all this is because we don't know which modules are + available, and we don't know which modules are already + pushed (via autopush, for instance). + + */ + + char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; + char *ptymodules[] = { "pckt", NULL }; + + maybe_push_modules(t, ttymodules); + maybe_push_modules(ourpty, ptymodules); + } +#endif + /* + * set up the tty modes as we like them to be. + */ + init_termbuf(); +# ifdef TIOCSWINSZ + if (def_row || def_col) { + memset(&ws, 0, sizeof(ws)); + ws.ws_col = def_col; + ws.ws_row = def_row; + ioctl(t, TIOCSWINSZ, (char *)&ws); + } +# endif + + /* + * Settings for sgtty based systems + */ + + /* + * Settings for UNICOS (and HPUX) + */ +# if defined(_CRAY) || defined(__hpux) + termbuf.c_oflag = OPOST|ONLCR|TAB3; + termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; + termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; + termbuf.c_cflag = EXTB|HUPCL|CS8; +# endif + + /* + * Settings for all other termios/termio based + * systems, other than 4.4BSD. In 4.4BSD the + * kernel does the initial terminal setup. + */ +# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) +# ifndef OXTABS +# define OXTABS 0 +# endif + termbuf.c_lflag |= ECHO; + termbuf.c_oflag |= ONLCR|OXTABS; + termbuf.c_iflag |= ICRNL; + termbuf.c_iflag &= ~IXOFF; +# endif + tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); + tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); + + /* + * Set the tty modes, and make this our controlling tty. + */ + set_termbuf(); + if (login_tty(t) == -1) + fatalperror(net, "login_tty"); + if (net > 2) + close(net); + if (ourpty > 2) { + close(ourpty); + ourpty = -1; + } +} + +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif +/* + * Open the specified slave side of the pty, + * making sure that we have a clean tty. + */ + +int cleanopen(char *line) +{ + int t; + +#ifdef STREAMSPTY + if (!really_stream) +#endif + { + /* + * Make sure that other people can't open the + * slave side of the connection. + */ + chown(line, 0, 0); + chmod(line, 0600); + } + +#ifdef HAVE_REVOKE + revoke(line); +#endif + + t = open(line, O_RDWR|O_NOCTTY); + + if (t < 0) + return(-1); + + /* + * Hangup anybody else using this ttyp, then reopen it for + * ourselves. + */ +# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) + signal(SIGHUP, SIG_IGN); +#ifdef HAVE_VHANGUP + vhangup(); +#else +#endif + signal(SIGHUP, SIG_DFL); + t = open(line, O_RDWR|O_NOCTTY); + if (t < 0) + return(-1); +# endif +# if defined(_CRAY) && defined(TCVHUP) + { + int i; + signal(SIGHUP, SIG_IGN); + ioctl(t, TCVHUP, (char *)0); + signal(SIGHUP, SIG_DFL); + + i = open(line, O_RDWR); + + if (i < 0) + return(-1); + close(t); + t = i; + } +# endif /* defined(CRAY) && defined(TCVHUP) */ + return(t); +} + +#if !defined(BSD4_4) + +int login_tty(int t) +{ +# if defined(TIOCSCTTY) && !defined(__hpux) + if (ioctl(t, TIOCSCTTY, (char *)0) < 0) + fatalperror(net, "ioctl(sctty)"); +# ifdef _CRAY + /* + * Close the hard fd to /dev/ttypXXX, and re-open through + * the indirect /dev/tty interface. + */ + close(t); + if ((t = open("/dev/tty", O_RDWR)) < 0) + fatalperror(net, "open(/dev/tty)"); +# endif +# else + /* + * We get our controlling tty assigned as a side-effect + * of opening up a tty device. But on BSD based systems, + * this only happens if our process group is zero. The + * setsid() call above may have set our pgrp, so clear + * it out before opening the tty... + */ +#ifdef HAVE_SETPGID + setpgid(0, 0); +#else + setpgrp(0, 0); /* if setpgid isn't available, setpgrp + probably takes arguments */ +#endif + close(open(line, O_RDWR)); +# endif + if (t != 0) + dup2(t, 0); + if (t != 1) + dup2(t, 1); + if (t != 2) + dup2(t, 2); + if (t > 2) + close(t); + return(0); +} +#endif /* BSD <= 43 */ + +/* + * This comes from ../../bsd/tty.c and should not really be here. + */ + +/* + * Clean the tty name. Return a pointer to the cleaned version. + */ + +static char * +clean_ttyname (char *tty) +{ + char *res = tty; + + if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0) + res += strlen(_PATH_DEV); + if (strncmp (res, "pty/", 4) == 0) + res += 4; + if (strncmp (res, "ptym/", 5) == 0) + res += 5; + return res; +} + +/* + * Generate a name usable as an `ut_id', typically without `tty'. + */ + +#ifdef HAVE_STRUCT_UTMP_UT_ID +static char * +make_id (char *tty) +{ + char *res = tty; + + if (strncmp (res, "pts/", 4) == 0) + res += 4; + if (strncmp (res, "tty", 3) == 0) + res += 3; + return res; +} +#endif + +/* + * startslave(host) + * + * Given a hostname, do whatever + * is necessary to startup the login process on the slave side of the pty. + */ + +/* ARGSUSED */ +void +startslave(char *host, int autologin, char *autoname) +{ + int i; + +#ifdef AUTHENTICATION + if (!autoname || !autoname[0]) + autologin = 0; + + if (autologin < auth_level) { + fatal(net, "Authorization failed"); + exit(1); + } +#endif + + { + char *tbuf = + "\r\n*** Connection not encrypted! " + "Communication may be eavesdropped. ***\r\n"; +#ifdef ENCRYPTION + if (!no_warn && (encrypt_output == 0 || decrypt_input == 0)) +#endif + writenet((unsigned char*)tbuf, strlen(tbuf)); + } +# ifdef PARENT_DOES_UTMP + utmp_sig_init(); +# endif /* PARENT_DOES_UTMP */ + + if ((i = fork()) < 0) + fatalperror(net, "fork"); + if (i) { +# ifdef PARENT_DOES_UTMP + /* + * Cray parent will create utmp entry for child and send + * signal to child to tell when done. Child waits for signal + * before doing anything important. + */ + int pid = i; + void sigjob (int); + + setpgrp(); + utmp_sig_reset(); /* reset handler to default */ + /* + * Create utmp entry for child + */ + time(&wtmp.ut_time); + wtmp.ut_type = LOGIN_PROCESS; + wtmp.ut_pid = pid; + strncpy(wtmp.ut_user, "LOGIN", sizeof(wtmp.ut_user)); + strncpy(wtmp.ut_host, host, sizeof(wtmp.ut_host)); + strncpy(wtmp.ut_line, clean_ttyname(line), sizeof(wtmp.ut_line)); +#ifdef HAVE_STRUCT_UTMP_UT_ID + strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id)); +#endif + + pututline(&wtmp); + endutent(); + if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { + write(i, &wtmp, sizeof(struct utmp)); + close(i); + } +#ifdef _CRAY + signal(WJSIGNAL, sigjob); +#endif + utmp_sig_notify(pid); +# endif /* PARENT_DOES_UTMP */ + } else { + getptyslave(); + start_login(host, autologin, autoname); + /*NOTREACHED*/ + } +} + +char *envinit[3]; +extern char **environ; + +void +init_env(void) +{ + extern char *getenv(const char *); + char **envp; + + envp = envinit; + if ((*envp = getenv("TZ"))) + *envp++ -= 3; +#if defined(_CRAY) || defined(__hpux) + else + *envp++ = "TZ=GMT0"; +#endif + *envp = 0; + environ = envinit; +} + +/* + * scrub_env() + * + * Remove variables from the environment that might cause login to + * behave in a bad manner. To avoid this, login should be staticly + * linked. + */ + +static void scrub_env(void) +{ + static char *remove[] = { "LD_", "_RLD_", "LIBPATH=", "IFS=", NULL }; + + char **cpp, **cpp2; + char **p; + + for (cpp2 = cpp = environ; *cpp; cpp++) { + for(p = remove; *p; p++) + if(strncmp(*cpp, *p, strlen(*p)) == 0) + break; + if(*p == NULL) + *cpp2++ = *cpp; + } + *cpp2 = 0; +} + + +struct arg_val { + int size; + int argc; + char **argv; +}; + +static int addarg(struct arg_val*, char*); + +/* + * start_login(host) + * + * Assuming that we are now running as a child processes, this + * function will turn us into the login process. + */ + +void +start_login(char *host, int autologin, char *name) +{ + struct arg_val argv; + char *user; + +#ifdef HAVE_UTMPX_H + int pid = getpid(); + struct utmpx utmpx; + char *clean_tty; + + /* + * Create utmp entry for child + */ + + clean_tty = clean_ttyname(line); + memset(&utmpx, 0, sizeof(utmpx)); + strncpy(utmpx.ut_user, ".telnet", sizeof(utmpx.ut_user)); + strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); +#ifdef HAVE_STRUCT_UTMP_UT_ID + strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id)); +#endif + utmpx.ut_pid = pid; + + utmpx.ut_type = LOGIN_PROCESS; + + gettimeofday (&utmpx.ut_tv, NULL); + if (pututxline(&utmpx) == NULL) + fatal(net, "pututxline failed"); +#endif + + scrub_env(); + + /* + * -h : pass on name of host. + * WARNING: -h is accepted by login if and only if + * getuid() == 0. + * -p : don't clobber the environment (so terminal type stays set). + * + * -f : force this login, he has already been authenticated + */ + + /* init argv structure */ + argv.size=0; + argv.argc=0; + argv.argv=(char**)malloc(0); /*so we can call realloc later */ + addarg(&argv, "login"); + addarg(&argv, "-h"); + addarg(&argv, host); + addarg(&argv, "-p"); + if(name[0]) + user = name; + else + user = getenv("USER"); +#ifdef AUTHENTICATION + if (auth_level < 0 || autologin != AUTH_VALID) { + if(!no_warn) { + printf("User not authenticated. "); + if (require_otp) + printf("Using one-time password\r\n"); + else + printf("Using plaintext username and password\r\n"); + } + if (require_otp) { + addarg(&argv, "-a"); + addarg(&argv, "otp"); + } + if(log_unauth) + syslog(LOG_INFO, "unauthenticated access from %s (%s)", + host, user ? user : "unknown user"); + } + if (auth_level >= 0 && autologin == AUTH_VALID) + addarg(&argv, "-f"); +#endif + if(user){ + addarg(&argv, "--"); + addarg(&argv, strdup(user)); + } + if (getenv("USER")) { + /* + * Assume that login will set the USER variable + * correctly. For SysV systems, this means that + * USER will no longer be set, just LOGNAME by + * login. (The problem is that if the auto-login + * fails, and the user then specifies a different + * account name, he can get logged in with both + * LOGNAME and USER in his environment, but the + * USER value will be wrong. + */ + unsetenv("USER"); + } + closelog(); + /* + * This sleep(1) is in here so that telnetd can + * finish up with the tty. There's a race condition + * the login banner message gets lost... + */ + sleep(1); + + execv(new_login, argv.argv); + + syslog(LOG_ERR, "%s: %m\n", new_login); + fatalperror(net, new_login); + /*NOTREACHED*/ +} + + + +static int addarg(struct arg_val *argv, char *val) +{ + if(argv->size <= argv->argc+1){ + argv->argv = (char**)realloc(argv->argv, sizeof(char*) * (argv->size + 10)); + if(argv->argv == NULL) + return 1; /* this should probably be handled better */ + argv->size+=10; + } + argv->argv[argv->argc++]=val; + argv->argv[argv->argc]=NULL; + return 0; +} + + +/* + * rmut() + * + * This is the function called by cleanup() to + * remove the utmp entry for this person. + */ + +#ifdef HAVE_UTMPX_H +static void +rmut(void) +{ + struct utmpx *utxp, utmpx; + char *clean_tty = clean_ttyname(line); + + /* + * This updates the utmpx and utmp entries and make a wtmp/x entry + */ + + setutxent(); + memset(&utmpx, 0, sizeof(utmpx)); + strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); + utmpx.ut_type = LOGIN_PROCESS; + utxp = getutxline(&utmpx); + if (utxp) { + utxp->ut_user[0] = '\0'; + utxp->ut_type = DEAD_PROCESS; +#ifdef HAVE_STRUCT_UTMPX_UT_EXIT +#ifdef _STRUCT___EXIT_STATUS + utxp->ut_exit.__e_termination = 0; + utxp->ut_exit.__e_exit = 0; +#elif defined(__osf__) /* XXX */ + utxp->ut_exit.ut_termination = 0; + utxp->ut_exit.ut_exit = 0; +#else + utxp->ut_exit.e_termination = 0; + utxp->ut_exit.e_exit = 0; +#endif +#endif + gettimeofday(&utxp->ut_tv, NULL); + pututxline(utxp); +#ifdef WTMPX_FILE + updwtmpx(WTMPX_FILE, utxp); +#elif defined(WTMP_FILE) + /* This is a strange system with a utmpx and a wtmp! */ + { + int f = open(wtmpf, O_WRONLY|O_APPEND); + struct utmp wtmp; + if (f >= 0) { + strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); + strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); +#ifdef HAVE_STRUCT_UTMP_UT_HOST + strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); +#endif + time(&wtmp.ut_time); + write(f, &wtmp, sizeof(wtmp)); + close(f); + } + } +#else + +#endif + } + endutxent(); +} /* end of rmut */ +#endif + +#if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43 +static void +rmut(void) +{ + int f; + int found = 0; + struct utmp *u, *utmp; + int nutmp; + struct stat statbf; + char *clean_tty = clean_ttyname(line); + + f = open(utmpf, O_RDWR); + if (f >= 0) { + fstat(f, &statbf); + utmp = (struct utmp *)malloc((unsigned)statbf.st_size); + if (!utmp) + syslog(LOG_ERR, "utmp malloc failed"); + if (statbf.st_size && utmp) { + nutmp = read(f, utmp, (int)statbf.st_size); + nutmp /= sizeof(struct utmp); + + for (u = utmp ; u < &utmp[nutmp] ; u++) { + if (strncmp(u->ut_line, + clean_tty, + sizeof(u->ut_line)) || + u->ut_name[0]==0) + continue; + lseek(f, ((long)u)-((long)utmp), L_SET); + strncpy(u->ut_name, "", sizeof(u->ut_name)); +#ifdef HAVE_STRUCT_UTMP_UT_HOST + strncpy(u->ut_host, "", sizeof(u->ut_host)); +#endif + time(&u->ut_time); + write(f, u, sizeof(wtmp)); + found++; + } + } + close(f); + } + if (found) { + f = open(wtmpf, O_WRONLY|O_APPEND); + if (f >= 0) { + strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); + strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); +#ifdef HAVE_STRUCT_UTMP_UT_HOST + strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); +#endif + time(&wtmp.ut_time); + write(f, &wtmp, sizeof(wtmp)); + close(f); + } + } + chmod(line, 0666); + chown(line, 0, 0); + line[strlen("/dev/")] = 'p'; + chmod(line, 0666); + chown(line, 0, 0); +} /* end of rmut */ +#endif /* CRAY */ + +#if defined(__hpux) && !defined(HAVE_UTMPX_H) +static void +rmut (char *line) +{ + struct utmp utmp; + struct utmp *utptr; + int fd; /* for /etc/wtmp */ + + utmp.ut_type = USER_PROCESS; + strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line)); + setutent(); + utptr = getutline(&utmp); + /* write it out only if it exists */ + if (utptr) { + utptr->ut_type = DEAD_PROCESS; + utptr->ut_time = time(NULL); + pututline(utptr); + /* set wtmp entry if wtmp file exists */ + if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { + write(fd, utptr, sizeof(utmp)); + close(fd); + } + } + endutent(); + + chmod(line, 0666); + chown(line, 0, 0); + line[14] = line[13]; + line[13] = line[12]; + line[8] = 'm'; + line[9] = '/'; + line[10] = 'p'; + line[11] = 't'; + line[12] = 'y'; + chmod(line, 0666); + chown(line, 0, 0); +} +#endif + +/* + * cleanup() + * + * This is the routine to call when we are all through, to + * clean up anything that needs to be cleaned up. + */ + +#ifdef PARENT_DOES_UTMP + +void +cleanup(int sig) +{ +#ifdef _CRAY + static int incleanup = 0; + int t; + int child_status; /* status of child process as returned by waitpid */ + int flags = WNOHANG|WUNTRACED; + + /* + * 1: Pick up the zombie, if we are being called + * as the signal handler. + * 2: If we are a nested cleanup(), return. + * 3: Try to clean up TMPDIR. + * 4: Fill in utmp with shutdown of process. + * 5: Close down the network and pty connections. + * 6: Finish up the TMPDIR cleanup, if needed. + */ + if (sig == SIGCHLD) { + while (waitpid(-1, &child_status, flags) > 0) + ; /* VOID */ + /* Check if the child process was stopped + * rather than exited. We want cleanup only if + * the child has died. + */ + if (WIFSTOPPED(child_status)) { + return; + } + } + t = sigblock(sigmask(SIGCHLD)); + if (incleanup) { + sigsetmask(t); + return; + } + incleanup = 1; + sigsetmask(t); + + t = cleantmp(&wtmp); + setutent(); /* just to make sure */ +#endif /* CRAY */ + rmut(line); + close(ourpty); + shutdown(net, 2); +#ifdef _CRAY + if (t == 0) + cleantmp(&wtmp); +#endif /* CRAY */ + exit(1); +} + +#else /* PARENT_DOES_UTMP */ + +void +cleanup(int sig) +{ +#if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP) + rmut(); +#ifdef HAVE_VHANGUP +#ifndef __sgi + vhangup(); /* XXX */ +#endif +#endif +#else + char *p; + + p = line + sizeof("/dev/") - 1; + if (logout(p)) + logwtmp(p, "", ""); + chmod(line, 0666); + chown(line, 0, 0); + *p = 'p'; + chmod(line, 0666); + chown(line, 0, 0); +#endif + shutdown(net, 2); + exit(1); +} + +#endif /* PARENT_DOES_UTMP */ + +#ifdef PARENT_DOES_UTMP +/* + * _utmp_sig_rcv + * utmp_sig_init + * utmp_sig_wait + * These three functions are used to coordinate the handling of + * the utmp file between the server and the soon-to-be-login shell. + * The server actually creates the utmp structure, the child calls + * utmp_sig_wait(), until the server calls utmp_sig_notify() and + * signals the future-login shell to proceed. + */ +static int caught=0; /* NZ when signal intercepted */ +static void (*func)(); /* address of previous handler */ + +void +_utmp_sig_rcv(sig) + int sig; +{ + caught = 1; + signal(SIGUSR1, func); +} + +void +utmp_sig_init() +{ + /* + * register signal handler for UTMP creation + */ + if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) + fatalperror(net, "telnetd/signal"); +} + +void +utmp_sig_reset() +{ + signal(SIGUSR1, func); /* reset handler to default */ +} + +# ifdef __hpux +# define sigoff() /* do nothing */ +# define sigon() /* do nothing */ +# endif + +void +utmp_sig_wait() +{ + /* + * Wait for parent to write our utmp entry. + */ + sigoff(); + while (caught == 0) { + pause(); /* wait until we get a signal (sigon) */ + sigoff(); /* turn off signals while we check caught */ + } + sigon(); /* turn on signals again */ +} + +void +utmp_sig_notify(pid) +{ + kill(pid, SIGUSR1); +} + +#ifdef _CRAY +static int gotsigjob = 0; + + /*ARGSUSED*/ +void +sigjob(sig) + int sig; +{ + int jid; + struct jobtemp *jp; + + while ((jid = waitjob(NULL)) != -1) { + if (jid == 0) { + return; + } + gotsigjob++; + jobend(jid, NULL, NULL); + } +} + +/* + * jid_getutid: + * called by jobend() before calling cleantmp() + * to find the correct $TMPDIR to cleanup. + */ + +struct utmp * +jid_getutid(jid) + int jid; +{ + struct utmp *cur = NULL; + + setutent(); /* just to make sure */ + while (cur = getutent()) { + if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { + return(cur); + } + } + + return(0); +} + +/* + * Clean up the TMPDIR that login created. + * The first time this is called we pick up the info + * from the utmp. If the job has already gone away, + * then we'll clean up and be done. If not, then + * when this is called the second time it will wait + * for the signal that the job is done. + */ +int +cleantmp(wtp) + struct utmp *wtp; +{ + struct utmp *utp; + static int first = 1; + int mask, omask, ret; + extern struct utmp *getutid (const struct utmp *_Id); + + + mask = sigmask(WJSIGNAL); + + if (first == 0) { + omask = sigblock(mask); + while (gotsigjob == 0) + sigpause(omask); + return(1); + } + first = 0; + setutent(); /* just to make sure */ + + utp = getutid(wtp); + if (utp == 0) { + syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); + return(-1); + } + /* + * Nothing to clean up if the user shell was never started. + */ + if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) + return(1); + + /* + * Block the WJSIGNAL while we are in jobend(). + */ + omask = sigblock(mask); + ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); + sigsetmask(omask); + return(ret); +} + +int +jobend(jid, path, user) + int jid; + char *path; + char *user; +{ + static int saved_jid = 0; + static int pty_saved_jid = 0; + static char saved_path[sizeof(wtmp.ut_tpath)+1]; + static char saved_user[sizeof(wtmp.ut_user)+1]; + + /* + * this little piece of code comes into play + * only when ptyreconnect is used to reconnect + * to an previous session. + * + * this is the only time when the + * "saved_jid != jid" code is executed. + */ + + if ( saved_jid && saved_jid != jid ) { + if (!path) { /* called from signal handler */ + pty_saved_jid = jid; + } else { + pty_saved_jid = saved_jid; + } + } + + if (path) { + strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); + strncpy(saved_user, user, sizeof(wtmp.ut_user)); + saved_path[sizeof(saved_path)] = '\0'; + saved_user[sizeof(saved_user)] = '\0'; + } + if (saved_jid == 0) { + saved_jid = jid; + return(0); + } + + /* if the jid has changed, get the correct entry from the utmp file */ + + if ( saved_jid != jid ) { + struct utmp *utp = NULL; + struct utmp *jid_getutid(); + + utp = jid_getutid(pty_saved_jid); + + if (utp == 0) { + syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); + return(-1); + } + + cleantmpdir(jid, utp->ut_tpath, utp->ut_user); + return(1); + } + + cleantmpdir(jid, saved_path, saved_user); + return(1); +} + +/* + * Fork a child process to clean up the TMPDIR + */ +cleantmpdir(jid, tpath, user) + int jid; + char *tpath; + char *user; +{ + switch(fork()) { + case -1: + syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", + tpath); + break; + case 0: + execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); + syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", + tpath, CLEANTMPCMD); + exit(1); + default: + /* + * Forget about child. We will exit, and + * /etc/init will pick it up. + */ + break; + } +} +#endif /* CRAY */ +#endif /* defined(PARENT_DOES_UTMP) */ diff --git a/crypto/kerberosIV/appl/telnet/telnetd/telnetd.c b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.c new file mode 100644 index 0000000..73008a3 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.c @@ -0,0 +1,1357 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnetd.h" + +RCSID("$Id: telnetd.c,v 1.53 1999/03/15 16:40:52 joda Exp $"); + +#ifdef _SC_CRAY_SECURE_SYS +#include <sys/sysv.h> +#include <sys/secdev.h> +#include <sys/secparm.h> +#include <sys/usrv.h> +int secflag; +char tty_dev[16]; +struct secdev dv; +struct sysv sysv; +struct socksec ss; +#endif /* _SC_CRAY_SECURE_SYS */ + +#ifdef AUTHENTICATION +int auth_level = 0; +#endif + +extern int utmp_len; +int registerd_host_only = 0; + +#ifdef STREAMSPTY +# include <stropts.h> +# include <termios.h> +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif /* HAVE_SYS_UIO_H */ +#ifdef HAVE_SYS_STREAM_H +#include <sys/stream.h> +#endif +#ifdef _AIX +#include <sys/termio.h> +#endif +# ifdef HAVE_SYS_STRTTY_H +# include <sys/strtty.h> +# endif +# ifdef HAVE_SYS_STR_TTY_H +# include <sys/str_tty.h> +# endif +/* make sure we don't get the bsd version */ +/* what is this here for? solaris? /joda */ +# ifdef HAVE_SYS_TTY_H +# include "/usr/include/sys/tty.h" +# endif +# ifdef HAVE_SYS_PTYVAR_H +# include <sys/ptyvar.h> +# endif + +/* + * Because of the way ptyibuf is used with streams messages, we need + * ptyibuf+1 to be on a full-word boundary. The following wierdness + * is simply to make that happen. + */ +long ptyibufbuf[BUFSIZ/sizeof(long)+1]; +char *ptyibuf = ((char *)&ptyibufbuf[1])-1; +char *ptyip = ((char *)&ptyibufbuf[1])-1; +char ptyibuf2[BUFSIZ]; +unsigned char ctlbuf[BUFSIZ]; +struct strbuf strbufc, strbufd; + +int readstream(int, char*, int); + +#else /* ! STREAMPTY */ + +/* + * I/O data buffers, + * pointers, and counters. + */ +char ptyibuf[BUFSIZ], *ptyip = ptyibuf; +char ptyibuf2[BUFSIZ]; + +#endif /* ! STREAMPTY */ + +int hostinfo = 1; /* do we print login banner? */ + +#ifdef _CRAY +extern int newmap; /* nonzero if \n maps to ^M^J */ +int lowpty = 0, highpty; /* low, high pty numbers */ +#endif /* CRAY */ + +int debug = 0; +int keepalive = 1; +char *progname; + +extern void usage (void); + +/* + * The string to pass to getopt(). We do it this way so + * that only the actual options that we support will be + * passed off to getopt(). + */ +char valid_opts[] = "Bd:hklnS:u:UL:y" +#ifdef AUTHENTICATION + "a:X:z" +#endif +#ifdef DIAGNOSTICS + "D:" +#endif +#ifdef _CRAY + "r:" +#endif + ; + +void doit(struct sockaddr_in*); + +int main(int argc, char **argv) +{ + struct sockaddr_in from; + int on = 1, fromlen; + int ch; +#if defined(IPPROTO_IP) && defined(IP_TOS) + int tos = -1; +#endif +#ifdef ENCRYPTION + extern int des_check_key; + des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */ +#endif + pfrontp = pbackp = ptyobuf; + netip = netibuf; + nfrontp = nbackp = netobuf; + + progname = *argv; +#ifdef ENCRYPTION + nclearto = 0; +#endif + +#ifdef _CRAY + /* + * Get number of pty's before trying to process options, + * which may include changing pty range. + */ + highpty = getnpty(); +#endif /* CRAY */ + + while ((ch = getopt(argc, argv, valid_opts)) != EOF) { + switch(ch) { + +#ifdef AUTHENTICATION + case 'a': + /* + * Check for required authentication level + */ + if (strcmp(optarg, "debug") == 0) { + auth_debug_mode = 1; + } else if (strcasecmp(optarg, "none") == 0) { + auth_level = 0; + } else if (strcasecmp(optarg, "otp") == 0) { + auth_level = 0; + require_otp = 1; + } else if (strcasecmp(optarg, "other") == 0) { + auth_level = AUTH_OTHER; + } else if (strcasecmp(optarg, "user") == 0) { + auth_level = AUTH_USER; + } else if (strcasecmp(optarg, "valid") == 0) { + auth_level = AUTH_VALID; + } else if (strcasecmp(optarg, "off") == 0) { + /* + * This hack turns off authentication + */ + auth_level = -1; + } else { + fprintf(stderr, + "telnetd: unknown authorization level for -a\n"); + } + break; +#endif /* AUTHENTICATION */ + + case 'B': /* BFTP mode is not supported any more */ + break; + case 'd': + if (strcmp(optarg, "ebug") == 0) { + debug++; + break; + } + usage(); + /* NOTREACHED */ + break; + +#ifdef DIAGNOSTICS + case 'D': + /* + * Check for desired diagnostics capabilities. + */ + if (!strcmp(optarg, "report")) { + diagnostic |= TD_REPORT|TD_OPTIONS; + } else if (!strcmp(optarg, "exercise")) { + diagnostic |= TD_EXERCISE; + } else if (!strcmp(optarg, "netdata")) { + diagnostic |= TD_NETDATA; + } else if (!strcmp(optarg, "ptydata")) { + diagnostic |= TD_PTYDATA; + } else if (!strcmp(optarg, "options")) { + diagnostic |= TD_OPTIONS; + } else { + usage(); + /* NOT REACHED */ + } + break; +#endif /* DIAGNOSTICS */ + + + case 'h': + hostinfo = 0; + break; + + case 'k': /* Linemode is not supported any more */ + case 'l': + break; + + case 'n': + keepalive = 0; + break; + +#ifdef _CRAY + case 'r': + { + char *strchr(); + char *c; + + /* + * Allow the specification of alterations + * to the pty search range. It is legal to + * specify only one, and not change the + * other from its default. + */ + c = strchr(optarg, '-'); + if (c) { + *c++ = '\0'; + highpty = atoi(c); + } + if (*optarg != '\0') + lowpty = atoi(optarg); + if ((lowpty > highpty) || (lowpty < 0) || + (highpty > 32767)) { + usage(); + /* NOT REACHED */ + } + break; + } +#endif /* CRAY */ + + case 'S': +#ifdef HAVE_PARSETOS + if ((tos = parsetos(optarg, "tcp")) < 0) + fprintf(stderr, "%s%s%s\n", + "telnetd: Bad TOS argument '", optarg, + "'; will try to use default TOS"); +#else + fprintf(stderr, "%s%s\n", "TOS option unavailable; ", + "-S flag not supported\n"); +#endif + break; + + case 'u': + utmp_len = atoi(optarg); + break; + + case 'U': + registerd_host_only = 1; + break; + +#ifdef AUTHENTICATION + case 'X': + /* + * Check for invalid authentication types + */ + auth_disable_name(optarg); + break; +#endif + case 'y': + no_warn = 1; + break; +#ifdef AUTHENTICATION + case 'z': + log_unauth = 1; + break; + +#endif /* AUTHENTICATION */ + + case 'L': + new_login = optarg; + break; + + default: + fprintf(stderr, "telnetd: %c: unknown option\n", ch); + /* FALLTHROUGH */ + case '?': + usage(); + /* NOTREACHED */ + } + } + + argc -= optind; + argv += optind; + + if (debug) { + int port = 0; + struct servent *sp; + + if (argc > 1) { + usage (); + } else if (argc == 1) { + sp = roken_getservbyname (*argv, "tcp"); + if (sp) + port = sp->s_port; + else + port = htons(atoi(*argv)); + } else { +#ifdef KRB5 + port = krb5_getportbyname (NULL, "telnet", "tcp", 23); +#else + port = k_getportbyname("telnet", "tcp", htons(23)); +#endif + } + mini_inetd (port); + } else if (argc > 0) { + usage(); + /* NOT REACHED */ + } + +#ifdef _SC_CRAY_SECURE_SYS + secflag = sysconf(_SC_CRAY_SECURE_SYS); + + /* + * Get socket's security label + */ + if (secflag) { + int szss = sizeof(ss); + int sock_multi; + int szi = sizeof(int); + + memset(&dv, 0, sizeof(dv)); + + if (getsysv(&sysv, sizeof(struct sysv)) != 0) + fatalperror(net, "getsysv"); + + /* + * Get socket security label and set device values + * {security label to be set on ttyp device} + */ +#ifdef SO_SEC_MULTI /* 8.0 code */ + if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, + (void *)&ss, &szss) < 0) || + (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, + (void *)&sock_multi, &szi) < 0)) + fatalperror(net, "getsockopt"); + else { + dv.dv_actlvl = ss.ss_actlabel.lt_level; + dv.dv_actcmp = ss.ss_actlabel.lt_compart; + if (!sock_multi) { + dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; + dv.dv_valcmp = dv.dv_actcmp; + } else { + dv.dv_minlvl = ss.ss_minlabel.lt_level; + dv.dv_maxlvl = ss.ss_maxlabel.lt_level; + dv.dv_valcmp = ss.ss_maxlabel.lt_compart; + } + dv.dv_devflg = 0; + } +#else /* SO_SEC_MULTI */ /* 7.0 code */ + if (getsockopt(0, SOL_SOCKET, SO_SECURITY, + (void *)&ss, &szss) >= 0) { + dv.dv_actlvl = ss.ss_slevel; + dv.dv_actcmp = ss.ss_compart; + dv.dv_minlvl = ss.ss_minlvl; + dv.dv_maxlvl = ss.ss_maxlvl; + dv.dv_valcmp = ss.ss_maxcmp; + } +#endif /* SO_SEC_MULTI */ + } +#endif /* _SC_CRAY_SECURE_SYS */ + + roken_openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); + fromlen = sizeof (from); + if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) { + fprintf(stderr, "%s: ", progname); + perror("getpeername"); + _exit(1); + } + if (keepalive && + setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, + (void *)&on, sizeof (on)) < 0) { + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); + } + +#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + { +# ifdef HAVE_GETTOSBYNAME + struct tosent *tp; + if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) + tos = tp->t_tos; +# endif + if (tos < 0) + tos = 020; /* Low Delay bit */ + if (tos + && (setsockopt(0, IPPROTO_IP, IP_TOS, + (void *)&tos, sizeof(tos)) < 0) + && (errno != ENOPROTOOPT) ) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + } +#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ + net = 0; + doit(&from); + /* NOTREACHED */ + return 0; +} /* end of main */ + +void +usage() +{ + fprintf(stderr, "Usage: telnetd"); +#ifdef AUTHENTICATION + fprintf(stderr, " [-a (debug|other|otp|user|valid|off|none)]\n\t"); +#endif + fprintf(stderr, " [-debug]"); +#ifdef DIAGNOSTICS + fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); +#endif +#ifdef AUTHENTICATION + fprintf(stderr, " [-edebug]"); +#endif + fprintf(stderr, " [-h]"); + fprintf(stderr, " [-L login]"); + fprintf(stderr, " [-n]"); +#ifdef _CRAY + fprintf(stderr, " [-r[lowpty]-[highpty]]"); +#endif + fprintf(stderr, "\n\t"); +#ifdef HAVE_GETTOSBYNAME + fprintf(stderr, " [-S tos]"); +#endif +#ifdef AUTHENTICATION + fprintf(stderr, " [-X auth-type] [-y] [-z]"); +#endif + fprintf(stderr, " [-u utmp_hostname_length] [-U]"); + fprintf(stderr, " [port]\n"); + exit(1); +} + +/* + * getterminaltype + * + * Ask the other end to send along its terminal type and speed. + * Output is the variable terminaltype filled in. + */ +static unsigned char ttytype_sbbuf[] = { + IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE +}; + +int +getterminaltype(char *name, size_t name_sz) +{ + int retval = -1; + void _gettermname(); + + settimer(baseline); +#ifdef AUTHENTICATION + /* + * Handle the Authentication option before we do anything else. + */ + send_do(TELOPT_AUTHENTICATION, 1); + while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) + ttloop(); + if (his_state_is_will(TELOPT_AUTHENTICATION)) { + retval = auth_wait(name, name_sz); + } +#endif + +#ifdef ENCRYPTION + send_will(TELOPT_ENCRYPT, 1); + send_do(TELOPT_ENCRYPT, 1); /* esc@magic.fi */ +#endif + send_do(TELOPT_TTYPE, 1); + send_do(TELOPT_TSPEED, 1); + send_do(TELOPT_XDISPLOC, 1); + send_do(TELOPT_NEW_ENVIRON, 1); + send_do(TELOPT_OLD_ENVIRON, 1); + while ( +#ifdef ENCRYPTION + his_do_dont_is_changing(TELOPT_ENCRYPT) || +#endif + his_will_wont_is_changing(TELOPT_TTYPE) || + his_will_wont_is_changing(TELOPT_TSPEED) || + his_will_wont_is_changing(TELOPT_XDISPLOC) || + his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || + his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { + ttloop(); + } +#ifdef ENCRYPTION + /* + * Wait for the negotiation of what type of encryption we can + * send with. If autoencrypt is not set, this will just return. + */ + if (his_state_is_will(TELOPT_ENCRYPT)) { + encrypt_wait(); + } +#endif + if (his_state_is_will(TELOPT_TSPEED)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; + + telnet_net_write (sb, sizeof sb); + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + if (his_state_is_will(TELOPT_XDISPLOC)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; + + telnet_net_write (sb, sizeof sb); + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + if (his_state_is_will(TELOPT_NEW_ENVIRON)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; + + telnet_net_write (sb, sizeof sb); + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; + + telnet_net_write (sb, sizeof sb); + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + if (his_state_is_will(TELOPT_TTYPE)) { + + telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf); + DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, + sizeof ttytype_sbbuf - 2);); + } + if (his_state_is_will(TELOPT_TSPEED)) { + while (sequenceIs(tspeedsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_XDISPLOC)) { + while (sequenceIs(xdisplocsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_NEW_ENVIRON)) { + while (sequenceIs(environsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_OLD_ENVIRON)) { + while (sequenceIs(oenvironsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_TTYPE)) { + char first[256], last[256]; + + while (sequenceIs(ttypesubopt, baseline)) + ttloop(); + + /* + * If the other side has already disabled the option, then + * we have to just go with what we (might) have already gotten. + */ + if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { + strcpy_truncate(first, terminaltype, sizeof(first)); + for(;;) { + /* + * Save the unknown name, and request the next name. + */ + strcpy_truncate(last, terminaltype, sizeof(last)); + _gettermname(); + if (terminaltypeok(terminaltype)) + break; + if ((strncmp(last, terminaltype, sizeof(last)) == 0) || + his_state_is_wont(TELOPT_TTYPE)) { + /* + * We've hit the end. If this is the same as + * the first name, just go with it. + */ + if (strncmp(first, terminaltype, sizeof(first)) == 0) + break; + /* + * Get the terminal name one more time, so that + * RFC1091 compliant telnets will cycle back to + * the start of the list. + */ + _gettermname(); + if (strncmp(first, terminaltype, sizeof(first)) != 0) + strcpy(terminaltype, first); + break; + } + } + } + } + return(retval); +} /* end of getterminaltype */ + +void +_gettermname() +{ + /* + * If the client turned off the option, + * we can't send another request, so we + * just return. + */ + if (his_state_is_wont(TELOPT_TTYPE)) + return; + settimer(baseline); + telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf); + DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, + sizeof ttytype_sbbuf - 2);); + while (sequenceIs(ttypesubopt, baseline)) + ttloop(); +} + +int +terminaltypeok(char *s) +{ + return 1; +} + + +char *hostname; +char host_name[MaxHostNameLen]; +char remote_host_name[MaxHostNameLen]; + +/* + * Get a pty, scan input lines. + */ +void +doit(struct sockaddr_in *who) +{ + char *host = NULL; + struct hostent *hp; + int level; + int ptynum; + char user_name[256]; + + /* + * Find an available pty to use. + */ + ourpty = getpty(&ptynum); + if (ourpty < 0) + fatal(net, "All network ports in use"); + +#ifdef _SC_CRAY_SECURE_SYS + /* + * set ttyp line security label + */ + if (secflag) { + char slave_dev[16]; + + snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum); + if (setdevs(tty_dev, &dv) < 0) + fatal(net, "cannot set pty security"); + snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum); + if (setdevs(slave_dev, &dv) < 0) + fatal(net, "cannot set tty security"); + } +#endif /* _SC_CRAY_SECURE_SYS */ + + /* get name of connected client */ + hp = roken_gethostbyaddr((const char *)&who->sin_addr, + sizeof (struct in_addr), + who->sin_family); + + if (hp == NULL && registerd_host_only) { + fatal(net, "Couldn't resolve your address into a host name.\r\n\ +Please contact your net administrator"); + } else if (hp) { + host = hp->h_name; + } else { + host = inet_ntoa(who->sin_addr); + } + /* + * We must make a copy because Kerberos is probably going + * to also do a gethost* and overwrite the static data... + */ + strcpy_truncate(remote_host_name, host, sizeof(remote_host_name)); + host = remote_host_name; + + /* XXX - should be k_gethostname? */ + gethostname(host_name, sizeof (host_name)); + hostname = host_name; + + /* Only trim if too long (and possible) */ + if (strlen(remote_host_name) > abs(utmp_len)) { + char *domain = strchr(host_name, '.'); + char *p = strchr(remote_host_name, '.'); + if (domain && p && (strcmp(p, domain) == 0)) + *p = 0; /* remove domain part */ + } + + + /* + * If hostname still doesn't fit utmp, use ipaddr. + */ + if (strlen(remote_host_name) > abs(utmp_len)) + strcpy_truncate(remote_host_name, + inet_ntoa(who->sin_addr), + sizeof(remote_host_name)); + +#ifdef AUTHENTICATION + auth_encrypt_init(hostname, host, "TELNETD", 1); +#endif + + init_env(); + /* + * get terminal type. + */ + *user_name = 0; + level = getterminaltype(user_name, sizeof(user_name)); + setenv("TERM", terminaltype ? terminaltype : "network", 1); + +#ifdef _SC_CRAY_SECURE_SYS + if (secflag) { + if (setulvl(dv.dv_actlvl) < 0) + fatal(net,"cannot setulvl()"); + if (setucmp(dv.dv_actcmp) < 0) + fatal(net, "cannot setucmp()"); + } +#endif /* _SC_CRAY_SECURE_SYS */ + + /* begin server processing */ + my_telnet(net, ourpty, host, level, user_name); + /*NOTREACHED*/ +} /* end of doit */ + +/* output contents of /etc/issue.net, or /etc/issue */ +static void +show_issue(void) +{ + FILE *f; + char buf[128]; + f = fopen("/etc/issue.net", "r"); + if(f == NULL) + f = fopen("/etc/issue", "r"); + if(f){ + while(fgets(buf, sizeof(buf)-2, f)){ + strcpy(buf + strcspn(buf, "\r\n"), "\r\n"); + writenet((unsigned char*)buf, strlen(buf)); + } + fclose(f); + } +} + +/* + * Main loop. Select from pty and network, and + * hand data to telnet receiver finite state machine. + */ +void +my_telnet(int f, int p, char *host, int level, char *autoname) +{ + int on = 1; + char *he; + char *IM; + int nfd; + int startslave_called = 0; + time_t timeout; + + /* + * Initialize the slc mapping table. + */ + get_slc_defaults(); + + /* + * Do some tests where it is desireable to wait for a response. + * Rather than doing them slowly, one at a time, do them all + * at once. + */ + if (my_state_is_wont(TELOPT_SGA)) + send_will(TELOPT_SGA, 1); + /* + * Is the client side a 4.2 (NOT 4.3) system? We need to know this + * because 4.2 clients are unable to deal with TCP urgent data. + * + * To find out, we send out a "DO ECHO". If the remote system + * answers "WILL ECHO" it is probably a 4.2 client, and we note + * that fact ("WILL ECHO" ==> that the client will echo what + * WE, the server, sends it; it does NOT mean that the client will + * echo the terminal input). + */ + send_do(TELOPT_ECHO, 1); + + /* + * Send along a couple of other options that we wish to negotiate. + */ + send_do(TELOPT_NAWS, 1); + send_will(TELOPT_STATUS, 1); + flowmode = 1; /* default flow control state */ + restartany = -1; /* uninitialized... */ + send_do(TELOPT_LFLOW, 1); + + /* + * Spin, waiting for a response from the DO ECHO. However, + * some REALLY DUMB telnets out there might not respond + * to the DO ECHO. So, we spin looking for NAWS, (most dumb + * telnets so far seem to respond with WONT for a DO that + * they don't understand...) because by the time we get the + * response, it will already have processed the DO ECHO. + * Kludge upon kludge. + */ + while (his_will_wont_is_changing(TELOPT_NAWS)) + ttloop(); + + /* + * But... + * The client might have sent a WILL NAWS as part of its + * startup code; if so, we'll be here before we get the + * response to the DO ECHO. We'll make the assumption + * that any implementation that understands about NAWS + * is a modern enough implementation that it will respond + * to our DO ECHO request; hence we'll do another spin + * waiting for the ECHO option to settle down, which is + * what we wanted to do in the first place... + */ + if (his_want_state_is_will(TELOPT_ECHO) && + his_state_is_will(TELOPT_NAWS)) { + while (his_will_wont_is_changing(TELOPT_ECHO)) + ttloop(); + } + /* + * On the off chance that the telnet client is broken and does not + * respond to the DO ECHO we sent, (after all, we did send the + * DO NAWS negotiation after the DO ECHO, and we won't get here + * until a response to the DO NAWS comes back) simulate the + * receipt of a will echo. This will also send a WONT ECHO + * to the client, since we assume that the client failed to + * respond because it believes that it is already in DO ECHO + * mode, which we do not want. + */ + if (his_want_state_is_will(TELOPT_ECHO)) { + DIAG(TD_OPTIONS, + {output_data("td: simulating recv\r\n"); + }); + willoption(TELOPT_ECHO); + } + + /* + * Finally, to clean things up, we turn on our echo. This + * will break stupid 4.2 telnets out of local terminal echo. + */ + + if (my_state_is_wont(TELOPT_ECHO)) + send_will(TELOPT_ECHO, 1); + +#ifdef TIOCPKT +#ifdef STREAMSPTY + if (!really_stream) +#endif + /* + * Turn on packet mode + */ + ioctl(p, TIOCPKT, (char *)&on); +#endif + + + /* + * Call telrcv() once to pick up anything received during + * terminal type negotiation, 4.2/4.3 determination, and + * linemode negotiation. + */ + telrcv(); + + ioctl(f, FIONBIO, (char *)&on); + ioctl(p, FIONBIO, (char *)&on); + +#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) + setsockopt(net, SOL_SOCKET, SO_OOBINLINE, + (void *)&on, sizeof on); +#endif /* defined(SO_OOBINLINE) */ + +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); +#endif +#ifdef SIGTTOU + /* + * Ignoring SIGTTOU keeps the kernel from blocking us + * in ttioct() in /sys/tty.c. + */ + signal(SIGTTOU, SIG_IGN); +#endif + + signal(SIGCHLD, cleanup); + +#ifdef TIOCNOTTY + { + int t; + t = open(_PATH_TTY, O_RDWR); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + close(t); + } + } +#endif + + show_issue(); + /* + * Show banner that getty never gave. + * + * We put the banner in the pty input buffer. This way, it + * gets carriage return null processing, etc., just like all + * other pty --> client data. + */ + + if (getenv("USER")) + hostinfo = 0; + + IM = DEFAULT_IM; + he = 0; + edithost(he, host_name); + if (hostinfo && *IM) + putf(IM, ptyibuf2); + + if (pcc) + strncat(ptyibuf2, ptyip, pcc+1); + ptyip = ptyibuf2; + pcc = strlen(ptyip); + + DIAG(TD_REPORT, { + output_data("td: Entering processing loop\r\n"); + }); + + + nfd = ((f > p) ? f : p) + 1; + timeout = time(NULL) + 5; + for (;;) { + fd_set ibits, obits, xbits; + int c; + + /* wait for encryption to be turned on, but don't wait + indefinitely */ + if(!startslave_called && (!encrypt_delay() || timeout > time(NULL))){ + startslave_called = 1; + startslave(host, level, autoname); + } + + if (ncc < 0 && pcc < 0) + break; + + FD_ZERO(&ibits); + FD_ZERO(&obits); + FD_ZERO(&xbits); + /* + * Never look for input if there's still + * stuff in the corresponding output buffer + */ + if (nfrontp - nbackp || pcc > 0) { + FD_SET(f, &obits); + } else { + FD_SET(p, &ibits); + } + if (pfrontp - pbackp || ncc > 0) { + FD_SET(p, &obits); + } else { + FD_SET(f, &ibits); + } + if (!SYNCHing) { + FD_SET(f, &xbits); + } + if ((c = select(nfd, &ibits, &obits, &xbits, + (struct timeval *)0)) < 1) { + if (c == -1) { + if (errno == EINTR) { + continue; + } + } + sleep(5); + continue; + } + + /* + * Any urgent data? + */ + if (FD_ISSET(net, &xbits)) { + SYNCHing = 1; + } + + /* + * Something to read from the network... + */ + if (FD_ISSET(net, &ibits)) { +#ifndef SO_OOBINLINE + /* + * In 4.2 (and 4.3 beta) systems, the + * OOB indication and data handling in the kernel + * is such that if two separate TCP Urgent requests + * come in, one byte of TCP data will be overlaid. + * This is fatal for Telnet, but we try to live + * with it. + * + * In addition, in 4.2 (and...), a special protocol + * is needed to pick up the TCP Urgent data in + * the correct sequence. + * + * What we do is: if we think we are in urgent + * mode, we look to see if we are "at the mark". + * If we are, we do an OOB receive. If we run + * this twice, we will do the OOB receive twice, + * but the second will fail, since the second + * time we were "at the mark", but there wasn't + * any data there (the kernel doesn't reset + * "at the mark" until we do a normal read). + * Once we've read the OOB data, we go ahead + * and do normal reads. + * + * There is also another problem, which is that + * since the OOB byte we read doesn't put us + * out of OOB state, and since that byte is most + * likely the TELNET DM (data mark), we would + * stay in the TELNET SYNCH (SYNCHing) state. + * So, clocks to the rescue. If we've "just" + * received a DM, then we test for the + * presence of OOB data when the receive OOB + * fails (and AFTER we did the normal mode read + * to clear "at the mark"). + */ + if (SYNCHing) { + int atmark; + + ioctl(net, SIOCATMARK, (char *)&atmark); + if (atmark) { + ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); + if ((ncc == -1) && (errno == EINVAL)) { + ncc = read(net, netibuf, sizeof (netibuf)); + if (sequenceIs(didnetreceive, gotDM)) { + SYNCHing = stilloob(net); + } + } + } else { + ncc = read(net, netibuf, sizeof (netibuf)); + } + } else { + ncc = read(net, netibuf, sizeof (netibuf)); + } + settimer(didnetreceive); +#else /* !defined(SO_OOBINLINE)) */ + ncc = read(net, netibuf, sizeof (netibuf)); +#endif /* !defined(SO_OOBINLINE)) */ + if (ncc < 0 && errno == EWOULDBLOCK) + ncc = 0; + else { + if (ncc <= 0) { + break; + } + netip = netibuf; + } + DIAG((TD_REPORT | TD_NETDATA), { + output_data("td: netread %d chars\r\n", ncc); + }); + DIAG(TD_NETDATA, printdata("nd", netip, ncc)); + } + + /* + * Something to read from the pty... + */ + if (FD_ISSET(p, &ibits)) { +#ifdef STREAMSPTY + if (really_stream) + pcc = readstream(p, ptyibuf, BUFSIZ); + else +#endif + pcc = read(p, ptyibuf, BUFSIZ); + + /* + * On some systems, if we try to read something + * off the master side before the slave side is + * opened, we get EIO. + */ + if (pcc < 0 && (errno == EWOULDBLOCK || +#ifdef EAGAIN + errno == EAGAIN || +#endif + errno == EIO)) { + pcc = 0; + } else { + if (pcc <= 0) + break; + if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { + netclear(); /* clear buffer back */ +#ifndef NO_URGENT + /* + * There are client telnets on some + * operating systems get screwed up + * royally if we send them urgent + * mode data. + */ + output_data ("%c%c", IAC, DM); + + neturg = nfrontp-1; /* off by one XXX */ + DIAG(TD_OPTIONS, + printoption("td: send IAC", DM)); + +#endif + } + if (his_state_is_will(TELOPT_LFLOW) && + (ptyibuf[0] & + (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { + int newflow = + ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; + if (newflow != flowmode) { + flowmode = newflow; + output_data("%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + flowmode ? LFLOW_ON + : LFLOW_OFF, + IAC, SE); + DIAG(TD_OPTIONS, printsub('>', + (unsigned char *)nfrontp-4, + 4);); + } + } + pcc--; + ptyip = ptyibuf+1; + } + } + + while (pcc > 0) { + if ((&netobuf[BUFSIZ] - nfrontp) < 3) + break; + c = *ptyip++ & 0377, pcc--; + if (c == IAC) + *nfrontp++ = c; + *nfrontp++ = c; + if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { + if (pcc > 0 && ((*ptyip & 0377) == '\n')) { + *nfrontp++ = *ptyip++ & 0377; + pcc--; + } else + *nfrontp++ = '\0'; + } + } + + if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) + netflush(); + if (ncc > 0) + telrcv(); + if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) + ptyflush(); + } + cleanup(0); +} + +#ifndef TCSIG +# ifdef TIOCSIG +# define TCSIG TIOCSIG +# endif +#endif + +#ifdef STREAMSPTY + + int flowison = -1; /* current state of flow: -1 is unknown */ + +int +readstream(int p, char *ibuf, int bufsize) +{ + int flags = 0; + int ret = 0; + struct termios *tsp; +#if 0 + struct termio *tp; +#endif + struct iocblk *ip; + char vstop, vstart; + int ixon; + int newflow; + + strbufc.maxlen = BUFSIZ; + strbufc.buf = (char *)ctlbuf; + strbufd.maxlen = bufsize-1; + strbufd.len = 0; + strbufd.buf = ibuf+1; + ibuf[0] = 0; + + ret = getmsg(p, &strbufc, &strbufd, &flags); + if (ret < 0) /* error of some sort -- probably EAGAIN */ + return(-1); + + if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { + /* data message */ + if (strbufd.len > 0) { /* real data */ + return(strbufd.len + 1); /* count header char */ + } else { + /* nothing there */ + errno = EAGAIN; + return(-1); + } + } + + /* + * It's a control message. Return 1, to look at the flag we set + */ + + switch (ctlbuf[0]) { + case M_FLUSH: + if (ibuf[1] & FLUSHW) + ibuf[0] = TIOCPKT_FLUSHWRITE; + return(1); + + case M_IOCTL: + ip = (struct iocblk *) (ibuf+1); + + switch (ip->ioc_cmd) { +#ifdef TCSETS + case TCSETS: + case TCSETSW: + case TCSETSF: + tsp = (struct termios *) + (ibuf+1 + sizeof(struct iocblk)); + vstop = tsp->c_cc[VSTOP]; + vstart = tsp->c_cc[VSTART]; + ixon = tsp->c_iflag & IXON; + break; +#endif +#if 0 + case TCSETA: + case TCSETAW: + case TCSETAF: + tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); + vstop = tp->c_cc[VSTOP]; + vstart = tp->c_cc[VSTART]; + ixon = tp->c_iflag & IXON; + break; +#endif + default: + errno = EAGAIN; + return(-1); + } + + newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; + if (newflow != flowison) { /* it's a change */ + flowison = newflow; + ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; + return(1); + } + } + + /* nothing worth doing anything about */ + errno = EAGAIN; + return(-1); +} +#endif /* STREAMSPTY */ + +/* + * Send interrupt to process on other side of pty. + * If it is in raw mode, just write NULL; + * otherwise, write intr char. + */ +void +interrupt() +{ + ptyflush(); /* half-hearted */ + +#if defined(STREAMSPTY) && defined(TIOCSIGNAL) + /* Streams PTY style ioctl to post a signal */ + if (really_stream) + { + int sig = SIGINT; + ioctl(ourpty, TIOCSIGNAL, &sig); + ioctl(ourpty, I_FLUSH, FLUSHR); + } +#else +#ifdef TCSIG + ioctl(ourpty, TCSIG, (char *)SIGINT); +#else /* TCSIG */ + init_termbuf(); + *pfrontp++ = slctab[SLC_IP].sptr ? + (unsigned char)*slctab[SLC_IP].sptr : '\177'; +#endif /* TCSIG */ +#endif +} + +/* + * Send quit to process on other side of pty. + * If it is in raw mode, just write NULL; + * otherwise, write quit char. + */ +void +sendbrk() +{ + ptyflush(); /* half-hearted */ +#ifdef TCSIG + ioctl(ourpty, TCSIG, (char *)SIGQUIT); +#else /* TCSIG */ + init_termbuf(); + *pfrontp++ = slctab[SLC_ABORT].sptr ? + (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; +#endif /* TCSIG */ +} + +void +sendsusp() +{ +#ifdef SIGTSTP + ptyflush(); /* half-hearted */ +# ifdef TCSIG + ioctl(ourpty, TCSIG, (char *)SIGTSTP); +# else /* TCSIG */ + *pfrontp++ = slctab[SLC_SUSP].sptr ? + (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; +# endif /* TCSIG */ +#endif /* SIGTSTP */ +} + +/* + * When we get an AYT, if ^T is enabled, use that. Otherwise, + * just send back "[Yes]". + */ +void +recv_ayt() +{ +#if defined(SIGINFO) && defined(TCSIG) + if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { + ioctl(ourpty, TCSIG, (char *)SIGINFO); + return; + } +#endif + output_data("\r\n[Yes]\r\n"); +} + +void +doeof() +{ + init_termbuf(); + + *pfrontp++ = slctab[SLC_EOF].sptr ? + (unsigned char)*slctab[SLC_EOF].sptr : '\004'; +} diff --git a/crypto/kerberosIV/appl/telnet/telnetd/telnetd.h b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.h new file mode 100644 index 0000000..5ad5bd8 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/telnetd.h @@ -0,0 +1,224 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)telnetd.h 8.1 (Berkeley) 6/4/93 + */ + + +#include <config.h> + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif /* HAVE_SYS_RESOURCE_H */ + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +/* including both <sys/ioctl.h> and <termios.h> in SunOS 4 generates a + lot of warnings */ + +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 +#include <sys/ioctl.h> +#endif +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN6_H +#include <netinet/in6.h> +#endif +#ifdef HAVE_NETINET6_IN6_H +#include <netinet6/in6.h> +#endif + +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#include <signal.h> +#include <errno.h> +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif +#include <ctype.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <termios.h> + +#ifdef HAVE_PTY_H +#include <pty.h> +#endif + +#include "defs.h" + +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif + +#ifndef _POSIX_VDISABLE +# ifdef VDISABLE +# define _POSIX_VDISABLE VDISABLE +# else +# define _POSIX_VDISABLE ((unsigned char)'\377') +# endif +#endif + + +#ifdef HAVE_SYS_PTY_H +#include <sys/pty.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifdef HAVE_SYS_PTYIO_H +#include <sys/ptyio.h> +#endif + +#ifdef HAVE_SYS_UTSNAME_H +#include <sys/utsname.h> +#endif + +#include "ext.h" + +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif + +#ifdef SOCKS +#include <socks.h> +/* This doesn't belong here. */ +struct tm *localtime(const time_t *); +struct hostent *gethostbyname(const char *); +#endif + +#ifdef KRB4 +#include <des.h> +#include <krb.h> +#endif + +#ifdef AUTHENTICATION +#include <libtelnet/auth.h> +#include <libtelnet/misc.h> +#ifdef ENCRYPTION +#include <libtelnet/encrypt.h> +#endif +#endif + +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif + +#include <roken.h> + +/* Don't use the system login, use our version instead */ + +/* BINDIR should be defined somewhere else... */ + +#ifndef BINDIR +#define BINDIR "/usr/athena/bin" +#endif + +#undef _PATH_LOGIN +#define _PATH_LOGIN BINDIR "/login" + +/* fallbacks */ + +#ifndef _PATH_DEV +#define _PATH_DEV "/dev/" +#endif + +#ifndef _PATH_TTY +#define _PATH_TTY "/dev/tty" +#endif /* _PATH_TTY */ + +#ifdef DIAGNOSTICS +#define DIAG(a,b) if (diagnostic & (a)) b +#else +#define DIAG(a,b) +#endif + +/* other external variables */ +extern char **environ; + +/* prototypes */ + +/* appends data to nfrontp and advances */ +int output_data (const char *format, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; diff --git a/crypto/kerberosIV/appl/telnet/telnetd/termstat.c b/crypto/kerberosIV/appl/telnet/telnetd/termstat.c new file mode 100644 index 0000000..80ee145 --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/termstat.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "telnetd.h" + +RCSID("$Id: termstat.c,v 1.11 1997/05/11 06:30:04 assar Exp $"); + +/* + * local variables + */ +int def_tspeed = -1, def_rspeed = -1; +#ifdef TIOCSWINSZ +int def_row = 0, def_col = 0; +#endif + +/* + * flowstat + * + * Check for changes to flow control + */ +void +flowstat() +{ + if (his_state_is_will(TELOPT_LFLOW)) { + if (tty_flowmode() != flowmode) { + flowmode = tty_flowmode(); + output_data("%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + flowmode ? LFLOW_ON : LFLOW_OFF, + IAC, SE); + } + if (tty_restartany() != restartany) { + restartany = tty_restartany(); + output_data("%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + restartany ? LFLOW_RESTART_ANY + : LFLOW_RESTART_XON, + IAC, SE); + } + } +} + +/* + * clientstat + * + * Process linemode related requests from the client. + * Client can request a change to only one of linemode, editmode or slc's + * at a time, and if using kludge linemode, then only linemode may be + * affected. + */ +void +clientstat(int code, int parm1, int parm2) +{ + void netflush(); + + /* + * Get a copy of terminal characteristics. + */ + init_termbuf(); + + /* + * Process request from client. code tells what it is. + */ + switch (code) { + case TELOPT_NAWS: +#ifdef TIOCSWINSZ + { + struct winsize ws; + + def_col = parm1; + def_row = parm2; + + /* + * Change window size as requested by client. + */ + + ws.ws_col = parm1; + ws.ws_row = parm2; + ioctl(ourpty, TIOCSWINSZ, (char *)&ws); + } +#endif /* TIOCSWINSZ */ + + break; + + case TELOPT_TSPEED: + { + def_tspeed = parm1; + def_rspeed = parm2; + /* + * Change terminal speed as requested by client. + * We set the receive speed first, so that if we can't + * store seperate receive and transmit speeds, the transmit + * speed will take precedence. + */ + tty_rspeed(parm2); + tty_tspeed(parm1); + set_termbuf(); + + break; + + } /* end of case TELOPT_TSPEED */ + + default: + /* What? */ + break; + } /* end of switch */ + + netflush(); + +} diff --git a/crypto/kerberosIV/appl/telnet/telnetd/utility.c b/crypto/kerberosIV/appl/telnet/telnetd/utility.c new file mode 100644 index 0000000..cfca89a --- /dev/null +++ b/crypto/kerberosIV/appl/telnet/telnetd/utility.c @@ -0,0 +1,1157 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define PRINTOPTIONS +#include "telnetd.h" + +RCSID("$Id: utility.c,v 1.20 1998/06/13 00:06:56 assar Exp $"); + +/* + * utility functions performing io related tasks + */ + +/* + * ttloop + * + * A small subroutine to flush the network output buffer, get some + * data from the network, and pass it through the telnet state + * machine. We also flush the pty input buffer (by dropping its data) + * if it becomes too full. + */ + +void +ttloop(void) +{ + void netflush(void); + + DIAG(TD_REPORT, { + output_data("td: ttloop\r\n"); + }); + if (nfrontp-nbackp) + netflush(); + ncc = read(net, netibuf, sizeof netibuf); + if (ncc < 0) { + syslog(LOG_INFO, "ttloop: read: %m\n"); + exit(1); + } else if (ncc == 0) { + syslog(LOG_INFO, "ttloop: peer died: %m\n"); + exit(1); + } + DIAG(TD_REPORT, { + output_data("td: ttloop read %d chars\r\n", ncc); + }); + netip = netibuf; + telrcv(); /* state machine */ + if (ncc > 0) { + pfrontp = pbackp = ptyobuf; + telrcv(); + } +} /* end of ttloop */ + +/* + * Check a descriptor to see if out of band data exists on it. + */ +int +stilloob(int s) +{ + static struct timeval timeout = { 0 }; + fd_set excepts; + int value; + + do { + FD_ZERO(&excepts); + FD_SET(s, &excepts); + value = select(s+1, 0, 0, &excepts, &timeout); + } while ((value == -1) && (errno == EINTR)); + + if (value < 0) { + fatalperror(ourpty, "select"); + } + if (FD_ISSET(s, &excepts)) { + return 1; + } else { + return 0; + } +} + +void +ptyflush(void) +{ + int n; + + if ((n = pfrontp - pbackp) > 0) { + DIAG((TD_REPORT | TD_PTYDATA), { + output_data("td: ptyflush %d chars\r\n", n); + }); + DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); + n = write(ourpty, pbackp, n); + } + if (n < 0) { + if (errno == EWOULDBLOCK || errno == EINTR) + return; + cleanup(0); + } + pbackp += n; + if (pbackp == pfrontp) + pbackp = pfrontp = ptyobuf; +} + +/* + * nextitem() + * + * Return the address of the next "item" in the TELNET data + * stream. This will be the address of the next character if + * the current address is a user data character, or it will + * be the address of the character following the TELNET command + * if the current address is a TELNET IAC ("I Am a Command") + * character. + */ +char * +nextitem(char *current) +{ + if ((*current&0xff) != IAC) { + return current+1; + } + switch (*(current+1)&0xff) { + case DO: + case DONT: + case WILL: + case WONT: + return current+3; + case SB:{ + /* loop forever looking for the SE */ + char *look = current+2; + + for (;;) { + if ((*look++&0xff) == IAC) { + if ((*look++&0xff) == SE) { + return look; + } + } + } + } + default: + return current+2; + } +} + + +/* + * netclear() + * + * We are about to do a TELNET SYNCH operation. Clear + * the path to the network. + * + * Things are a bit tricky since we may have sent the first + * byte or so of a previous TELNET command into the network. + * So, we have to scan the network buffer from the beginning + * until we are up to where we want to be. + * + * A side effect of what we do, just to keep things + * simple, is to clear the urgent data pointer. The principal + * caller should be setting the urgent data pointer AFTER calling + * us in any case. + */ +void +netclear(void) +{ + char *thisitem, *next; + char *good; +#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ + ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) + +#ifdef ENCRYPTION + thisitem = nclearto > netobuf ? nclearto : netobuf; +#else + thisitem = netobuf; +#endif + + while ((next = nextitem(thisitem)) <= nbackp) { + thisitem = next; + } + + /* Now, thisitem is first before/at boundary. */ + +#ifdef ENCRYPTION + good = nclearto > netobuf ? nclearto : netobuf; +#else + good = netobuf; /* where the good bytes go */ +#endif + + while (nfrontp > thisitem) { + if (wewant(thisitem)) { + int length; + + next = thisitem; + do { + next = nextitem(next); + } while (wewant(next) && (nfrontp > next)); + length = next-thisitem; + memmove(good, thisitem, length); + good += length; + thisitem = next; + } else { + thisitem = nextitem(thisitem); + } + } + + nbackp = netobuf; + nfrontp = good; /* next byte to be sent */ + neturg = 0; +} /* end of netclear */ + +/* + * netflush + * Send as much data as possible to the network, + * handling requests for urgent data. + */ +void +netflush(void) +{ + int n; + extern int not42; + + if ((n = nfrontp - nbackp) > 0) { + DIAG(TD_REPORT, + { n += output_data("td: netflush %d chars\r\n", n); + }); +#ifdef ENCRYPTION + if (encrypt_output) { + char *s = nclearto ? nclearto : nbackp; + if (nfrontp - s > 0) { + (*encrypt_output)((unsigned char *)s, nfrontp-s); + nclearto = nfrontp; + } + } +#endif + /* + * if no urgent data, or if the other side appears to be an + * old 4.2 client (and thus unable to survive TCP urgent data), + * write the entire buffer in non-OOB mode. + */ +#if 1 /* remove this to make it work between solaris 2.6 and linux */ + if ((neturg == 0) || (not42 == 0)) { +#endif + n = write(net, nbackp, n); /* normal write */ +#if 1 /* remove this to make it work between solaris 2.6 and linux */ + } else { + n = neturg - nbackp; + /* + * In 4.2 (and 4.3) systems, there is some question about + * what byte in a sendOOB operation is the "OOB" data. + * To make ourselves compatible, we only send ONE byte + * out of band, the one WE THINK should be OOB (though + * we really have more the TCP philosophy of urgent data + * rather than the Unix philosophy of OOB data). + */ + if (n > 1) { + n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ + } else { + n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ + } + } +#endif + } + if (n < 0) { + if (errno == EWOULDBLOCK || errno == EINTR) + return; + cleanup(0); + } + nbackp += n; +#ifdef ENCRYPTION + if (nbackp > nclearto) + nclearto = 0; +#endif + if (nbackp >= neturg) { + neturg = 0; + } + if (nbackp == nfrontp) { + nbackp = nfrontp = netobuf; +#ifdef ENCRYPTION + nclearto = 0; +#endif + } + return; +} + + +/* + * writenet + * + * Just a handy little function to write a bit of raw data to the net. + * It will force a transmit of the buffer if necessary + * + * arguments + * ptr - A pointer to a character string to write + * len - How many bytes to write + */ +void +writenet(unsigned char *ptr, int len) +{ + /* flush buffer if no room for new data) */ + while ((&netobuf[BUFSIZ] - nfrontp) < len) { + /* if this fails, don't worry, buffer is a little big */ + netflush(); + } + + memmove(nfrontp, ptr, len); + nfrontp += len; +} + + +/* + * miscellaneous functions doing a variety of little jobs follow ... + */ + + +void fatal(int f, char *msg) +{ + char buf[BUFSIZ]; + + snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg); +#ifdef ENCRYPTION + if (encrypt_output) { + /* + * Better turn off encryption first.... + * Hope it flushes... + */ + encrypt_send_end(); + netflush(); + } +#endif + write(f, buf, (int)strlen(buf)); + sleep(1); /*XXX*/ + exit(1); +} + +void +fatalperror(int f, const char *msg) +{ + char buf[BUFSIZ]; + + snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno)); + fatal(f, buf); +} + +char editedhost[32]; + +void edithost(char *pat, char *host) +{ + char *res = editedhost; + + if (!pat) + pat = ""; + while (*pat) { + switch (*pat) { + + case '#': + if (*host) + host++; + break; + + case '@': + if (*host) + *res++ = *host++; + break; + + default: + *res++ = *pat; + break; + } + if (res == &editedhost[sizeof editedhost - 1]) { + *res = '\0'; + return; + } + pat++; + } + if (*host) + strcpy_truncate (res, host, + sizeof editedhost - (res - editedhost)); + else + *res = '\0'; + editedhost[sizeof editedhost - 1] = '\0'; +} + +static char *putlocation; + +void +putstr(char *s) +{ + + while (*s) + putchr(*s++); +} + +void +putchr(int cc) +{ + *putlocation++ = cc; +} + +/* + * This is split on two lines so that SCCS will not see the M + * between two % signs and expand it... + */ +static char fmtstr[] = { "%l:%M" "%P on %A, %d %B %Y" }; + +void putf(char *cp, char *where) +{ +#ifdef HAVE_UNAME + struct utsname name; +#endif + char *slash; + time_t t; + char db[100]; + + /* if we don't have uname, set these to sensible values */ + char *sysname = "Unix", + *machine = "", + *release = "", + *version = ""; + +#ifdef HAVE_UNAME + uname(&name); + sysname=name.sysname; + machine=name.machine; + release=name.release; + version=name.version; +#endif + + putlocation = where; + + while (*cp) { + if (*cp != '%') { + putchr(*cp++); + continue; + } + switch (*++cp) { + + case 't': +#ifdef STREAMSPTY + /* names are like /dev/pts/2 -- we want pts/2 */ + slash = strchr(line+1, '/'); +#else + slash = strrchr(line, '/'); +#endif + if (slash == (char *) 0) + putstr(line); + else + putstr(&slash[1]); + break; + + case 'h': + putstr(editedhost); + break; + + case 's': + putstr(sysname); + break; + + case 'm': + putstr(machine); + break; + + case 'r': + putstr(release); + break; + + case 'v': + putstr(version); + break; + + case 'd': + time(&t); + strftime(db, sizeof(db), fmtstr, localtime(&t)); + putstr(db); + break; + + case '%': + putchr('%'); + break; + } + cp++; + } +} + +#ifdef DIAGNOSTICS +/* + * Print telnet options and commands in plain text, if possible. + */ +void +printoption(char *fmt, int option) +{ + if (TELOPT_OK(option)) + output_data("%s %s\r\n", + fmt, + TELOPT(option)); + else if (TELCMD_OK(option)) + output_data("%s %s\r\n", + fmt, + TELCMD(option)); + else + output_data("%s %d\r\n", + fmt, + option); + return; +} + +void +printsub(int direction, unsigned char *pointer, int length) + /* '<' or '>' */ + /* where suboption data sits */ + /* length of suboption data */ +{ + int i = 0; + unsigned char buf[512]; + + if (!(diagnostic & TD_OPTIONS)) + return; + + if (direction) { + output_data("td: %s suboption ", + direction == '<' ? "recv" : "send"); + if (length >= 3) { + int j; + + i = pointer[length-2]; + j = pointer[length-1]; + + if (i != IAC || j != SE) { + output_data("(terminated by "); + if (TELOPT_OK(i)) + output_data("%s ", + TELOPT(i)); + else if (TELCMD_OK(i)) + output_data("%s ", + TELCMD(i)); + else + output_data("%d ", + i); + if (TELOPT_OK(j)) + output_data("%s", + TELOPT(j)); + else if (TELCMD_OK(j)) + output_data("%s", + TELCMD(j)); + else + output_data("%d", + j); + output_data(", not IAC SE!) "); + } + } + length -= 2; + } + if (length < 1) { + output_data("(Empty suboption??\?)"); + return; + } + switch (pointer[0]) { + case TELOPT_TTYPE: + output_data("TERMINAL-TYPE "); + switch (pointer[1]) { + case TELQUAL_IS: + output_data("IS \"%.*s\"", + length-2, + (char *)pointer+2); + break; + case TELQUAL_SEND: + output_data("SEND"); + break; + default: + output_data("- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + case TELOPT_TSPEED: + output_data("TERMINAL-SPEED"); + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case TELQUAL_IS: + output_data(" IS %.*s", length-2, (char *)pointer+2); + break; + default: + if (pointer[1] == 1) + output_data(" SEND"); + else + output_data(" %d (unknown)", pointer[1]); + for (i = 2; i < length; i++) { + output_data(" ?%d?", pointer[i]); + } + break; + } + break; + + case TELOPT_LFLOW: + output_data("TOGGLE-FLOW-CONTROL"); + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case LFLOW_OFF: + output_data(" OFF"); + break; + case LFLOW_ON: + output_data(" ON"); + break; + case LFLOW_RESTART_ANY: + output_data(" RESTART-ANY"); + break; + case LFLOW_RESTART_XON: + output_data(" RESTART-XON"); + break; + default: + output_data(" %d (unknown)", + pointer[1]); + } + for (i = 2; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + + case TELOPT_NAWS: + output_data("NAWS"); + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + if (length == 2) { + output_data(" ?%d?", + pointer[1]); + break; + } + output_data(" %u %u(%u)", + pointer[1], + pointer[2], + (((unsigned int)pointer[1])<<8) + pointer[2]); + if (length == 4) { + output_data(" ?%d?", + pointer[3]); + break; + } + output_data(" %u %u(%u)", + pointer[3], + pointer[4], + (((unsigned int)pointer[3])<<8) + pointer[4]); + for (i = 5; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + + case TELOPT_LINEMODE: + output_data("LINEMODE "); + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case WILL: + output_data("WILL "); + goto common; + case WONT: + output_data("WONT "); + goto common; + case DO: + output_data("DO "); + goto common; + case DONT: + output_data("DONT "); + common: + if (length < 3) { + output_data("(no option??\?)"); + break; + } + switch (pointer[2]) { + case LM_FORWARDMASK: + output_data("Forward Mask"); + for (i = 3; i < length; i++) { + output_data(" %x", pointer[i]); + } + break; + default: + output_data("%d (unknown)", + pointer[2]); + for (i = 3; i < length; i++) { + output_data(" %d", + pointer[i]); + } + break; + } + break; + + case LM_SLC: + output_data("SLC"); + for (i = 2; i < length - 2; i += 3) { + if (SLC_NAME_OK(pointer[i+SLC_FUNC])) + output_data(" %s", + SLC_NAME(pointer[i+SLC_FUNC])); + else + output_data(" %d", + pointer[i+SLC_FUNC]); + switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { + case SLC_NOSUPPORT: + output_data(" NOSUPPORT"); + break; + case SLC_CANTCHANGE: + output_data(" CANTCHANGE"); + break; + case SLC_VARIABLE: + output_data(" VARIABLE"); + break; + case SLC_DEFAULT: + output_data(" DEFAULT"); + break; + } + output_data("%s%s%s", + pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); + if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| + SLC_FLUSHOUT| SLC_LEVELBITS)) { + output_data("(0x%x)", + pointer[i+SLC_FLAGS]); + } + output_data(" %d;", + pointer[i+SLC_VALUE]); + if ((pointer[i+SLC_VALUE] == IAC) && + (pointer[i+SLC_VALUE+1] == IAC)) + i++; + } + for (; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + + case LM_MODE: + output_data("MODE "); + if (length < 3) { + output_data("(no mode??\?)"); + break; + } + { + char tbuf[32]; + snprintf(tbuf, + sizeof(tbuf), + "%s%s%s%s%s", + pointer[2]&MODE_EDIT ? "|EDIT" : "", + pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", + pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", + pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", + pointer[2]&MODE_ACK ? "|ACK" : ""); + output_data("%s", + tbuf[1] ? &tbuf[1] : "0"); + } + if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { + output_data(" (0x%x)", + pointer[2]); + } + for (i = 3; i < length; i++) { + output_data(" ?0x%x?", + pointer[i]); + } + break; + default: + output_data("%d (unknown)", + pointer[1]); + for (i = 2; i < length; i++) { + output_data(" %d", pointer[i]); + } + } + break; + + case TELOPT_STATUS: { + char *cp; + int j, k; + + output_data("STATUS"); + + switch (pointer[1]) { + default: + if (pointer[1] == TELQUAL_SEND) + output_data(" SEND"); + else + output_data(" %d (unknown)", + pointer[1]); + for (i = 2; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + case TELQUAL_IS: + output_data(" IS\r\n"); + + for (i = 2; i < length; i++) { + switch(pointer[i]) { + case DO: cp = "DO"; goto common2; + case DONT: cp = "DONT"; goto common2; + case WILL: cp = "WILL"; goto common2; + case WONT: cp = "WONT"; goto common2; + common2: + i++; + if (TELOPT_OK(pointer[i])) + output_data(" %s %s", + cp, + TELOPT(pointer[i])); + else + output_data(" %s %d", + cp, + pointer[i]); + + output_data("\r\n"); + break; + + case SB: + output_data(" SB "); + i++; + j = k = i; + while (j < length) { + if (pointer[j] == SE) { + if (j+1 == length) + break; + if (pointer[j+1] == SE) + j++; + else + break; + } + pointer[k++] = pointer[j++]; + } + printsub(0, &pointer[i], k - i); + if (i < length) { + output_data(" SE"); + i = j; + } else + i = j - 1; + + output_data("\r\n"); + + break; + + default: + output_data(" %d", + pointer[i]); + break; + } + } + break; + } + break; + } + + case TELOPT_XDISPLOC: + output_data("X-DISPLAY-LOCATION "); + switch (pointer[1]) { + case TELQUAL_IS: + output_data("IS \"%.*s\"", + length-2, + (char *)pointer+2); + break; + case TELQUAL_SEND: + output_data("SEND"); + break; + default: + output_data("- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + + case TELOPT_NEW_ENVIRON: + output_data("NEW-ENVIRON "); + goto env_common1; + case TELOPT_OLD_ENVIRON: + output_data("OLD-ENVIRON"); + env_common1: + switch (pointer[1]) { + case TELQUAL_IS: + output_data("IS "); + goto env_common; + case TELQUAL_SEND: + output_data("SEND "); + goto env_common; + case TELQUAL_INFO: + output_data("INFO "); + env_common: + { + int noquote = 2; + for (i = 2; i < length; i++ ) { + switch (pointer[i]) { + case NEW_ENV_VAR: + output_data("\" VAR " + noquote); + noquote = 2; + break; + + case NEW_ENV_VALUE: + output_data("\" VALUE " + noquote); + noquote = 2; + break; + + case ENV_ESC: + output_data("\" ESC " + noquote); + noquote = 2; + break; + + case ENV_USERVAR: + output_data("\" USERVAR " + noquote); + noquote = 2; + break; + + default: + if (isprint(pointer[i]) && pointer[i] != '"') { + if (noquote) { + output_data ("\""); + noquote = 0; + } + output_data ("%c", pointer[i]); + } else { + output_data("\" %03o " + noquote, + pointer[i]); + noquote = 2; + } + break; + } + } + if (!noquote) + output_data ("\""); + break; + } + } + break; + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + output_data("AUTHENTICATION"); + + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case TELQUAL_REPLY: + case TELQUAL_IS: + output_data(" %s ", + (pointer[1] == TELQUAL_IS) ? + "IS" : "REPLY"); + if (AUTHTYPE_NAME_OK(pointer[2])) + output_data("%s ", + AUTHTYPE_NAME(pointer[2])); + else + output_data("%d ", + pointer[2]); + if (length < 3) { + output_data("(partial suboption??\?)"); + break; + } + output_data("%s|%s", + ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + + auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + output_data("%s", + buf); + break; + + case TELQUAL_SEND: + i = 2; + output_data(" SEND "); + while (i < length) { + if (AUTHTYPE_NAME_OK(pointer[i])) + output_data("%s ", + AUTHTYPE_NAME(pointer[i])); + else + output_data("%d ", + pointer[i]); + if (++i >= length) { + output_data("(partial suboption??\?)"); + break; + } + output_data("%s|%s ", + ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + ++i; + } + break; + + case TELQUAL_NAME: + i = 2; + output_data(" NAME \"%.*s\"", + length - 2, + pointer); + break; + + default: + for (i = 2; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + } + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + output_data("ENCRYPT"); + if (length < 2) { + output_data(" (empty suboption?)"); + break; + } + switch (pointer[1]) { + case ENCRYPT_START: + output_data(" START"); + break; + + case ENCRYPT_END: + output_data(" END"); + break; + + case ENCRYPT_REQSTART: + output_data(" REQUEST-START"); + break; + + case ENCRYPT_REQEND: + output_data(" REQUEST-END"); + break; + + case ENCRYPT_IS: + case ENCRYPT_REPLY: + output_data(" %s ", + (pointer[1] == ENCRYPT_IS) ? + "IS" : "REPLY"); + if (length < 3) { + output_data(" (partial suboption?)"); + break; + } + if (ENCTYPE_NAME_OK(pointer[2])) + output_data("%s ", + ENCTYPE_NAME(pointer[2])); + else + output_data(" %d (unknown)", + pointer[2]); + + encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + output_data("%s", + buf); + break; + + case ENCRYPT_SUPPORT: + i = 2; + output_data(" SUPPORT "); + while (i < length) { + if (ENCTYPE_NAME_OK(pointer[i])) + output_data("%s ", + ENCTYPE_NAME(pointer[i])); + else + output_data("%d ", + pointer[i]); + i++; + } + break; + + case ENCRYPT_ENC_KEYID: + output_data(" ENC_KEYID %d", pointer[1]); + goto encommon; + + case ENCRYPT_DEC_KEYID: + output_data(" DEC_KEYID %d", pointer[1]); + goto encommon; + + default: + output_data(" %d (unknown)", pointer[1]); + encommon: + for (i = 2; i < length; i++) { + output_data(" %d", pointer[i]); + } + break; + } + break; +#endif + + default: + if (TELOPT_OK(pointer[0])) + output_data("%s (unknown)", + TELOPT(pointer[0])); + else + output_data("%d (unknown)", + pointer[i]); + for (i = 1; i < length; i++) { + output_data(" %d", pointer[i]); + } + break; + } + output_data("\r\n"); +} + +/* + * Dump a data buffer in hex and ascii to the output data stream. + */ +void +printdata(char *tag, char *ptr, int cnt) +{ + int i; + char xbuf[30]; + + while (cnt) { + /* flush net output buffer if no room for new data) */ + if ((&netobuf[BUFSIZ] - nfrontp) < 80) { + netflush(); + } + + /* add a line of output */ + output_data("%s: ", tag); + for (i = 0; i < 20 && cnt; i++) { + output_data("%02x", *ptr); + if (isprint(*ptr)) { + xbuf[i] = *ptr; + } else { + xbuf[i] = '.'; + } + if (i % 2) { + output_data(" "); + } + cnt--; + ptr++; + } + xbuf[i] = '\0'; + output_data(" %s\r\n", xbuf); + } +} +#endif /* DIAGNOSTICS */ |