diff --exclude CVS -ur inetutils/acinclude.m4 feg-inetutils/acinclude.m4 --- inetutils/acinclude.m4 2004-02-03 20:43:10.000000000 +0100 +++ feg-inetutils/acinclude.m4 2004-05-25 16:11:14.000000000 +0200 @@ -22,6 +22,8 @@ dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. dnl +sinclude(libgnutls-extra.m4) + dnl IU_FLUSHLEFT -- remove all whitespace at the beginning of lines dnl This is useful for c-code which may include cpp statements dnl Only in feg-inetutils/: ChangeLog.feg diff --exclude CVS -ur inetutils/configure.ac feg-inetutils/configure.ac --- inetutils/configure.ac 2004-02-03 20:43:10.000000000 +0100 +++ feg-inetutils/configure.ac 2004-05-25 16:21:59.000000000 +0200 @@ -1,6 +1,6 @@ # Configuration for inetutils # -# Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. +# Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. # # Written by Miles Bader # @@ -21,7 +21,7 @@ AC_PREREQ(2.54) -AC_INIT([GNU inetutils], [1.4.2], [bug-inetutils@gnu.org]) +AC_INIT([FEG inetutils], [2.0.0], [feg-inetutils@josefsson.org]) AC_CONFIG_SRCDIR([inetd/inetd.c]) AM_CONFIG_HEADER([config.h:config.hin]) @@ -33,7 +33,7 @@ # Include files that we link into our own include directory from headers. # Initialize it with the things we always want to use. IU_CONFIG_LINKS([crypt.h, arpa/telnet.h, arpa/ftp.h, arpa/tftp.h, - protocols/talkd.h, tftpsubs.h]) + protocols/talkd.h, tftpsubs.h, shishi_def.h]) dnl For now, we always use libexecdir; later we may want to vary where the dnl daemons go. @@ -58,6 +58,16 @@ AC_ARG_WITH(krb5, [ --with-krb5[[=PATH]] Compile with Kerberos V], [KERBEROS_VERSION=5 KERBEROS_DIR=$withval]) +AC_ARG_WITH(shishi, AC_HELP_STRING([--with-shishi[[=PATH]]], + [Compile with Shishi (Kerberos 5)]), + [KERBEROS_VERSION=Shishi + KERBEROS_DIR=$withval]) + +check_gnutls=no +AC_ARG_WITH(tls, AC_HELP_STRING([--with-tls], + [Compile with GnuTLS support]), + check_gnutls=yes) + AC_ARG_WITH(wrap, [ --with-wrap add tcp wrapper support]) AC_ARG_WITH(pam, [ --with-pam add support for PAM]) @@ -99,6 +109,16 @@ AC_PROG_RANLIB AC_PROG_YACC +if test $check_gnutls != no; then +AM_PATH_LIBGNUTLS_EXTRA( 1.0.11, +AC_DEFINE(TLS, 1, [Use AUTH TLS]) +, AC_MSG_ERROR([[ +*** +*** libgnutls was not found. You may want to get it from +*** ftp://ftp.gnutls.org/pub/gnutls/ +]])) +fi + dnl __P is the standard name for the ansi-or-not-ansi arg-decl macro. dnl We define our own version in if the system doesn't supply one. dnl NOTE: This check has to be done pretty early because we use __P in @@ -236,6 +256,7 @@ AH_TEMPLATE(KERBEROS, [Define to one if you have Kerberos]) AH_TEMPLATE(KRB4, [Define to one if you have Kerberos IV]) AH_TEMPLATE(KRB5, [Define to one if you have Kerberos V]) + AH_TEMPLATE(SHISHI, [Define to 1 if you have Shishi]) AH_TEMPLATE(DES_ENCRYPTION, [FIXME]) if test "$KERBEROS_VERSION" = 4; then @@ -255,7 +276,7 @@ test "$enable_encryption" = yes -a "$ac_cv_lib_des_des_key_sched" = yes \ && AC_DEFINE(DES_ENCRYPTION) fi - else + elif test "$KERBEROS_VERSION" = 5; then IU_CHECK_KRB5($KERBEROS_VERSION,$KERBEROS_DIR) LIBAUTH=$KRB5_LIBS INCAUTH=$KRB_CFLAGS @@ -269,6 +290,22 @@ ;; esac fi + else + if test x$KERBEROS_DIR != x; then + LIBAUTH=-L$KERBEROS_DIR/lib + INCAUTH=-I$KERBEROS_DIR/include + fi + LIBAUTH="$LIBAUTH -lshishi" + save_LIBS=$LIBS + LIBS="$LIBS $LIBAUTH" + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $INCAUTH" + AC_CHECK_HEADER(shishi.h, + AC_CHECK_LIB(shishi, shishi_check_version, + AC_DEFINE(SHISHI), + [INCAUTH= LIBAUTH=])) + LIBS=$save_LIBS + CPPFLAGS=$save_CPPFLAGS fi fi AC_SUBST(LIBAUTH) diff --exclude CVS -ur inetutils/.cvsignore feg-inetutils/.cvsignore --- inetutils/.cvsignore 2002-07-31 23:51:19.000000000 +0200 +++ feg-inetutils/.cvsignore 2004-05-25 20:48:49.000000000 +0200 @@ -12,3 +12,5 @@ stamp-h.in config.hin autom4te.cache +config.h +stamp* Only in feg-inetutils/: .cvsusers diff --exclude CVS -ur inetutils/ftp/ChangeLog feg-inetutils/ftp/ChangeLog --- inetutils/ftp/ChangeLog 2002-04-29 22:41:25.000000000 +0200 +++ feg-inetutils/ftp/ChangeLog 2004-05-28 19:45:44.000000000 +0200 @@ -1,3 +1,24 @@ +2004-05-27 Nikos Mavroyanopoulos + + * ruserpass.c, ftp.1: Added support for .ftprc + file to be used instead of the .netrc. This is because + we use some extra TLS options that may confuse other programs. + The .netrc file is read as a fallback. + +2004-05-25 Nikos Mavroyanopoulos + + * ftp.c: Fixed the data connection abort with + some servers. + * main.c: Passive mode is enabled by default. + +2004-05-24 Nikos Mavroyanopoulos + + * session.h: added + * tlsutil.h: added + * tlsutil.c: added + * ftp.c: Added support for AUTH TLS using GnuTLS, + based on the code of Peter Runestig's ftp-tls. + 2002-04-29 Alfred M. Szmidt * main.c : Include removed. diff --exclude CVS -ur inetutils/ftp/cmds.c feg-inetutils/ftp/cmds.c --- inetutils/ftp/cmds.c 2001-12-25 19:05:16.000000000 +0100 +++ feg-inetutils/ftp/cmds.c 2004-05-26 19:49:53.000000000 +0200 @@ -50,6 +50,9 @@ #include #include +#include +#include + #include #include #include @@ -73,6 +76,7 @@ system headers on some platforms. */ #include +#include "session.h" #include "ftp_var.h" /* Returns true if STR is entirely lower case. */ @@ -121,6 +125,7 @@ return str; } + jmp_buf jabort; char *mname; char *home = "/"; @@ -197,6 +202,16 @@ port = htons(port); } host = hookup(argv[1], port); +#ifdef TLS + tls_hostname = strdup(argv[1]); + + if (tls_init()) { + warnx("tls_init() error"); + exit(1); /* exit on TLS init error */ + } + +#endif /* TLS */ + if (host) { int overbose; @@ -210,6 +225,35 @@ (void) strcpy(modename, "stream"), mode = MODE_S; (void) strcpy(structname, "file"), stru = STRU_F; (void) strcpy(bytename, "8"), bytesize = 8; + +#ifdef TLS + if (tls_on_ctrl || require_tls) { + if (command("AUTH TLS") == COMPLETE) { + extern FILE *cout, *cin; + extern int tls_private(int on); + /* if SSL_connect() fails, we might get SIGPIPE within it */ + my_sig_t oldsig = signal(SIGPIPE, SIG_IGN); + /* disconnect if tls_connect_ctrl() fails */ + if (tls_connect_ctrl(fileno(cin), fileno(cout))) { + /* keep ignoring SIGPIPE over disconnect() */ + disconnect(0, NULL); + fprintf(stdout, + "Failed TLS negotiation on control channel, disconnected\n"); + signal(SIGPIPE, oldsig); + return; + } + signal(SIGPIPE, oldsig); + if (tls_on_data) + tls_on_data = tls_private(tls_on_data); + } else { + warnx("Host does not support TLS authentication"); + if (require_tls) + quit(0,0); + tls_on_data = 0; + } + } +#endif /* TLS */ + if (autologin) (void) login(argv[1]); @@ -269,6 +313,102 @@ } } +/* Functions to retrieve the username and the password from the + * user. + */ +/* If authenticated with TLS SRP then this should be non-null. + */ + +const char* get_username( const char* host) +{ +char *myname = getlogin(); +static char tmp[80], *ruser = 0; +const char* user; + +#ifdef TLS + if (srp_username) + return srp_username; +#endif + + if (ruserpass((char*)host, &ruser, NULL, NULL) < 0) { + return NULL; + } + if (ruser) return ruser; + + if (myname == NULL) { + struct passwd *pp = getpwuid(getuid()); + + if (pp != NULL) + myname = pp->pw_name; + } + + + if (myname) + printf("Name (%s:%s): ", host, myname); + else + printf("Name (%s): ", host); + + if (fgets(tmp, sizeof(tmp) - 1, stdin)) { + /* If they press Ctrl-d immediately, it's empty. */ + tmp[strlen(tmp) - 1] = '\0'; + } else + *tmp = '\0'; + if (*tmp == '\0') + user = myname; + else + user = tmp; + + return user; +} + +/* srp should be non zero if this function is called + * for SRP authentication. + */ +char* get_password( const char* host, int srp) +{ +char* pass = 0; +static char xxx[] = "XXXX"; + /* we shouldn't need that in real TLS-SRP + * servers, but anyway. + */ +#ifdef TLS + /* If SRP has been negotiated then it's no good + * giving our password to the server. SRP was used + * to avoid sending it, anyway. + */ + if (srp_username && srp == 0) + return xxx; +#endif + + if (ruserpass((char*)host, NULL, &pass, NULL) < 0) { + return NULL; + } + if (pass) return pass; + + return getpass("Password:"); +} + +/* Overwrites the given password. + */ +void delete_password( char* pass) +{ + if (pass != NULL) + memset( pass, 'X', strlen(pass)); +} + +const char* get_account( const char* host, const char* msg) +{ +char* acct = 0; + + if (ruserpass((char*)host, NULL, NULL, &acct) < 0) { + return NULL; + } + if (acct) return acct; + + return getpass(msg); +} + + struct types { char *t_name; char *t_mode; @@ -1016,6 +1156,15 @@ else { printf("Nmap: off\n"); } +#ifdef TLS + { + char c[60] = "not connected"; + extern FILE *cin; + if (connected && cin) + snprintf(c, sizeof(c), "%s", tls_get_cipher_info_string(fileno(cin))); + fprintf(stdout, "Private: %s, control connection %s\n", onoff(tls_on_data), c); + } +#endif /* TLS */ printf("Hash mark printing: %s; Use of PORT cmds: %s\n", onoff(hash), onoff(sendport)); if (macnum > 0) { @@ -1093,6 +1242,83 @@ code = verbose; } +#ifdef TLS +/* + * Toggle a variable + */ +static int +togglevar(argc, argv, var, mesg) + int argc; + char *argv[]; + int *var; + const char *mesg; +{ + if (argc < 2) { + *var = !*var; + } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) { + *var = 1; + } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) { + *var = 0; + } else { + fprintf(stdout, "usage: %s [ on | off ]\n", argv[0]); + return (-1); + } + if (mesg) + fprintf(stdout, "%s %s.\n", mesg, onoff(*var)); + return (*var); +} + +int tls_private(int on) +{ + int r = on; + + if (command("PBSZ 0") == COMPLETE) { + if (on) { + if (command("PROT P") != COMPLETE) + r = 0; + } + else + command("PROT C"); + } else + r = 0; + return r; +} + +/* + * Turn on TLS on data channel + */ +/*VARARGS*/ +void +setprivate(argc, argv) + int argc; + char *argv[]; +{ + extern FILE *cin; + + if (connected && cin && !tls_active(fileno(cin)) && !tls_on_data) + fprintf(stdout, "Can't set Private, control channel is clear.\n"); + else { + int r; + r = code = togglevar(argc, argv, &tls_on_data, "Private mode"); + /* toggle it again if PBSZ/PROT fails */ + if (connected && r != tls_private(tls_on_data)) + code = togglevar(argc, argv, &tls_on_data, "Private mode"); + } +} + +/* + * Turn on TLS on control channel + */ +/*VARARGS*/ +void +setprotect(argc, argv) + int argc; + char *argv[]; +{ + code = togglevar(argc, argv, &tls_on_ctrl, "TLS mode"); +} +#endif /* TLS */ + /* * Toggle PORT cmd use before each data connection. */ @@ -1720,6 +1946,9 @@ if (connected) { disconnect(0, 0); } +#ifdef TLS + tls_cleanup(); +#endif /* TLS */ exit(0); } @@ -1736,8 +1965,11 @@ return; (void) command("QUIT"); if (cout) { - (void) fclose(cout); + (void) session_fclose(cout); } +#ifdef TLS + tls_shutdown(-1, 0); +#endif /* TLS */ cout = NULL; connected = 0; data = -1; diff --exclude CVS -ur inetutils/ftp/cmdtab.c feg-inetutils/ftp/cmdtab.c --- inetutils/ftp/cmdtab.c 2000-07-06 06:21:07.000000000 +0200 +++ feg-inetutils/ftp/cmdtab.c 2004-05-24 22:57:07.000000000 +0200 @@ -79,7 +79,13 @@ char nmaphelp[] = "set templates for default file name mapping"; char ntranshelp[] = "set translation table for default file name mapping"; char porthelp[] = "toggle use of PORT cmd for each data connection"; +#ifdef TLS +char privatehelp[] = "toggle use of TLS on data channel"; +#endif /* TLS */ char prompthelp[] = "force interactive prompting on multiple commands"; +#ifdef TLS +char protecthelp[] = "toggle use of TLS on control channel"; +#endif /* TLS */ char proxyhelp[] = "issue command on alternate connection"; char pwdhelp[] = "print working directory on remote machine"; char quithelp[] = "terminate ftp session and exit"; @@ -152,7 +158,13 @@ { "ntrans", ntranshelp, 0, 0, 1, setntrans }, { "open", connecthelp, 0, 0, 1, setpeer }, { "passive", passivehelp, 0, 0, 0, setpassive }, +#ifdef TLS + { "private", privatehelp, 0, 0, 0, setprivate }, +#endif /* TLS */ { "prompt", prompthelp, 0, 0, 0, setprompt }, +#ifdef TLS + { "protect", protecthelp, 0, 0, 0, setprotect }, +#endif /* TLS */ { "proxy", proxyhelp, 0, 0, 1, doproxy }, { "sendport", porthelp, 0, 0, 0, setport }, { "put", sendhelp, 1, 1, 1, put }, diff --exclude CVS -ur inetutils/ftp/extern.h feg-inetutils/ftp/extern.h --- inetutils/ftp/extern.h 2000-08-09 07:44:23.000000000 +0200 +++ feg-inetutils/ftp/extern.h 2004-05-26 19:49:53.000000000 +0200 @@ -32,7 +32,7 @@ struct timeval; struct fd_set; -void abort_remote __P((FILE *)); +void abort_remote __P((FILE *, int)); void abortpt __P(()); void abortrecv __P(()); void abortsend __P(()); @@ -118,6 +118,10 @@ void setpassive __P((int, char **)); void setpeer __P((int, char **)); void setport __P((int, char **)); +#ifdef TLS +void setprivate(int, char **); +void setprotect(int, char **); +#endif /* TLS */ void setprompt __P((int, char **)); void setrunique __P((int, char **)); void setstruct __P((int, char **)); @@ -134,7 +138,14 @@ void syst __P((int, char **)); void tvsub __P((struct timeval *, struct timeval *, struct timeval *)); void user __P((int, char **)); +char* get_password( const char* host, int srp); +void delete_password( char* pass); +const char* get_account( const char* host, const char* msg); +const char* get_username( const char* host); +#ifdef TLS +extern char* srp_username; +#endif extern jmp_buf abortprox; extern int abrtflag; extern struct cmd cmdtab[]; diff --exclude CVS -ur inetutils/ftp/ftp.1 feg-inetutils/ftp/ftp.1 --- inetutils/ftp/ftp.1 2000-07-08 03:00:53.000000000 +0200 +++ feg-inetutils/ftp/ftp.1 2004-05-28 19:45:53.000000000 +0200 @@ -27,7 +27,7 @@ .\" .\" @(#)ftp.1 8.3 (Berkeley) 10/9/94 .\" -.Dd October 9, 1994 +.Dd May 25, 2004 .Dt FTP 1 .Os BSD 4.2 .Sh NAME @@ -42,6 +42,8 @@ .Op Fl i .Op Fl n .Op Fl g +.Op Fl A +.Op Fl z tlsoption .Op Ar host .Sh DESCRIPTION .Nm Ftp @@ -59,6 +61,8 @@ .Nm ftp to show all responses from the remote server, as well as report on data transfer statistics. +.It Fl A +will use active mode ftp (passive is the default) .It Fl n Restrains .Nm ftp @@ -66,8 +70,8 @@ If auto-login is enabled, .Nm ftp will check the -.Pa .netrc -(see below) file in the user's home directory for an entry describing +.Pa .ftprc or .netrc +(see below) files in the user's home directory for an entry describing an account on the remote machine. If no entry exists, .Nm ftp @@ -81,6 +85,32 @@ Enables debugging. .It Fl g Disables file name globbing. + +.It Fl z Ic noprotect +Disable AUTH TLS by default. +.It Fl z Ic private +Use TLS on data channel by default. +.It Fl z Ic certsok +Don't do any verification on the server's certificate. +.It Fl z Ic nosrp +Disable the TLS SRP ciphersuites. +.It Fl z Ic requiretls +Fail if TLS cannot be negotiated. +.It Fl z Ic CAfile=\fIFILE\fR +Use CA certificate(s) in \fIFILE\fR. +.It Fl z Ic crlfile=\fIFILE\fR +Use Certificate Revocation List in \fIFILE\fR. +.It Fl z Ic cert=\fIFILE\fR +Use certificate in \fIFILE\fR. +.It Fl z Ic key=\fIFILE\fR +Use private key in \fIFILE\fR. +.It Fl z Ic pgpring=\fIFILE\fR +Use OpenPGP keyring in \fIFILE\fR. +.It Fl z Ic pgpcert=\fIFILE\fR +Use OpenPGP certificate in \fIFILE\fR. +.It Fl z Ic pgpkey=\fIFILE\fR +Use OpenPGP private key in \fIFILE\fR. + .El .Pp The client host with which @@ -140,14 +170,13 @@ .Ic type to network .Tn ASCII . -This is the default type. .It Ic bell Arrange that a bell be sounded after each file transfer command is completed. .It Ic binary Set the file transfer .Ic type -to support binary image transfer. +to support binary transfer. This is the default type. .It Ic bye Terminate the .Tn FTP @@ -601,7 +630,7 @@ server (see below). .It Ic passive Toggle passive mode. If passive mode is turned on -(default is off), the ftp client will +(default is on), the ftp client will send a .Dv PASV command for all data connections instead of the usual @@ -620,6 +649,8 @@ (Note that though ftp servers are required to support the .Dv PASV command by RFC 1123, some do not.) +.It Ic private +Toggle TLS use on the data channel with the \fBPBSZ\fR / \fBPROT\fR command sequence. .It Ic prompt Toggle interactive prompting. Interactive prompting @@ -632,6 +663,10 @@ will transfer all files, and any .Ic mdelete will delete all files. +.It Ic protect +Toggle use of TLS on the control channel by the \fBAUTH TLS\fR command. Note +that this doesn't change the TLS status on any current connected control +channel. .It Ic proxy Ar ftp-command Execute an ftp command on a secondary control connection. This command allows simultaneous connection to two remote ftp @@ -1005,14 +1040,14 @@ affect a file transfer. The .Ic type -may be one of \*(Lqascii\*(Rq, \*(Lqimage\*(Rq (binary), +may be one of \*(Lqascii\*(Rq, \*(Lqbinary\*(Rq (image), \*(Lqebcdic\*(Rq, and \*(Lqlocal byte size\*(Rq (for .Tn PDP Ns -10's and .Tn PDP Ns -20's mostly). .Nm Ftp -supports the ascii and image types of file transfer, +supports the ascii and binary types of file transfer, plus local byte size 8 for .Ic tenex mode transfers. @@ -1024,12 +1059,16 @@ .Ic form , and .Ic struct . -.Sh THE .netrc FILE +.Sh THE .ftprc and .netrc FILES The -.Pa .netrc -file contains login and initialization information +.Pa .ftprc and .netrc +files contains login and initialization information used by the auto-login process. -It resides in the user's home directory. +It resides in the user's home directory. This client will prefer +.Pa .ftprc +if present and read the +.Pa .netrc +as a fallback. The following tokens are recognized; they may be separated by spaces, tabs, or new-lines: .Bl -tag -width password @@ -1037,7 +1076,7 @@ Identify a remote machine .Ar name . The auto-login process searches the -.Pa .netrc +.Pa .ftprc file for a .Ic machine token that matches the remote machine specified on the @@ -1046,7 +1085,7 @@ .Ic open command argument. Once a match is made, the subsequent -.Pa .netrc +.Pa .ftprc tokens are processed, stopping when the end of file is reached or another .Ic machine @@ -1073,7 +1112,7 @@ .Ar automatic anonymous ftp login to machines not specified in -.Pa .netrc . +.Pa .ftprc . This can be overridden by using the .Fl n @@ -1089,13 +1128,13 @@ specified string if the remote server requires a password as part of the login process. Note that if this token is present in the -.Pa .netrc +.Pa .ftprc file for any user other than .Ar anonymous , .Nm ftp will abort the auto-login process if the -.Pa .netrc +.Pa .ftprc is readable by anyone besides the user. .It Ic account Ar string @@ -1113,13 +1152,31 @@ command functions. A macro is defined with the specified name; its contents begin with the next -.Pa .netrc +.Pa .ftprc line and continue until a null line (consecutive new-line characters) is encountered. If a macro named .Ic init is defined, it is automatically executed as the last step in the auto-login process. +.It Ic private +Use TLS on data channel by default. +.It Ic requiretls +Use TLS on control channel or fail. +.It Ic ca Ar file +Defines a file to be used to read X.509 trusted authorities from. +.It Ic crl Ar file +Defines a file to be used to read X.509 certificate revocation lists from. +.It Ic certificate Ar file +Defines a file to be used to read the user's X.509 certificate. +.It Ic key Ar file +Defines a file to be used to read the user's X.509 key. +.It Ic pgpcertificate Ar file +Defines a file to be used to read the user's OpenPGP certificate. +.It Ic pgpkey Ar file +Defines a file to be used to read the user's OpenPGP key. +.It Ic pgpring Ar file +Defines a file to be used to read the user's OpenPGP trusted key ring. .El .Sh ENVIRONMENT .Nm Ftp @@ -1127,8 +1184,8 @@ .Bl -tag -width Fl .It Ev HOME For default location of a -.Pa .netrc -file, if one exists. +.Pa .ftprc or .netrc +files, if they exist. .It Ev SHELL For default shell. .El @@ -1152,4 +1209,4 @@ to and from .Bx 4.2 servers using the ascii type. -Avoid this problem by using the binary image type. +Avoid this problem by using the binary type. diff --exclude CVS -ur inetutils/ftp/ftp.c feg-inetutils/ftp/ftp.c --- inetutils/ftp/ftp.c 2002-05-14 17:13:56.000000000 +0200 +++ feg-inetutils/ftp/ftp.c 2004-05-26 19:49:53.000000000 +0200 @@ -83,6 +83,7 @@ #endif #include "ftp_var.h" +#include "session.h" #if !HAVE_DECL_FCLOSE /* Some systems don't declare fclose in , so do it ourselves. */ @@ -106,7 +107,6 @@ struct sockaddr_in myctladdr; off_t restart_point = 0; - FILE *cin, *cout; char * @@ -236,50 +236,27 @@ } int -login(host) - char *host; +login(char *host) { char tmp[80]; char *user, *pass, *acct; int n, aflag = 0; user = pass = acct = 0; - if (ruserpass(host, &user, &pass, &acct) < 0) { - code = -1; - return (0); - } - while (user == NULL) { - char *myname = getlogin(); - - if (myname == NULL) { - struct passwd *pp = getpwuid(getuid()); - if (pp != NULL) - myname = pp->pw_name; - } - if (myname) - printf("Name (%s:%s): ", host, myname); - else - printf("Name (%s): ", host); - if (fgets(tmp, sizeof(tmp) - 1, stdin)) { - /* If they press Ctrl-d immediately, it's empty. */ - tmp[strlen(tmp) - 1] = '\0'; - } else - *tmp = '\0'; - if (*tmp == '\0') - user = myname; - else - user = tmp; + while (user == NULL) { + user = (char*) get_username( host); } n = command("USER %s", user); if (n == CONTINUE) { if (pass == NULL) - pass = getpass("Password:"); + pass = get_password(host, 0); n = command("PASS %s", pass); + delete_password( pass); } if (n == CONTINUE) { aflag++; - acct = getpass("Account:"); + acct = (char*) get_account(host, "Account:"); n = command("ACCT %s", acct); } if (n != COMPLETE) { @@ -365,10 +342,10 @@ va_start(ap); fmt = va_arg(ap, char *); #endif - vfprintf(cout, fmt, ap); + session_vfprintf(cout, fmt, ap); va_end(ap); - fprintf(cout, "\r\n"); - (void) fflush(cout); + session_fprintf(cout, "\r\n"); + (void) session_fflush(cout); cpend = 1; r = getreply(!strcmp(fmt, "QUIT")); if (abrtflag && oldintr != SIG_IGN) @@ -380,8 +357,7 @@ char reply_string[BUFSIZ]; /* last line of previous reply */ int -getreply(expecteof) - int expecteof; +getreply(int expecteof) { int c, n; int dig; @@ -394,20 +370,20 @@ for (;;) { dig = n = code = 0; cp = reply_string; - while ((c = getc(cin)) != '\n') { + while ((c = session_fgetc(cin)) != '\n') { if (c == IAC) { /* handle telnet commands */ - switch (c = getc(cin)) { + switch (c = session_fgetc(cin)) { case WILL: case WONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, DONT, c); - (void) fflush(cout); + c = session_fgetc(cin); + session_fprintf(cout, "%c%c%c", IAC, DONT, c); + (void) session_fflush(cout); break; case DO: case DONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, WONT, c); - (void) fflush(cout); + c = session_fgetc(cin); + session_fprintf(cout, "%c%c%c", IAC, WONT, c); + (void) session_fflush(cout); break; default: break; @@ -542,7 +518,7 @@ (void) getreply(0); } if (data >= 0) { - (void) close(data); + (void) session_close(data); data = -1; } if (oldintr) @@ -657,7 +633,7 @@ while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { bytes += c; for (bufp = buf; c > 0; c -= d, bufp += d) - if ((d = write(fileno(dout), bufp, c)) <= 0) + if ((d = session_write(fileno(dout), bufp, c)) <= 0) break; if (hash) { while (bytes >= local_hashbytes) { @@ -683,7 +659,7 @@ break; case TYPE_A: - while ((c = getc(fin)) != EOF) { + while ((c = fgetc(fin)) != EOF) { if (c == '\n') { while (hash && (bytes >= local_hashbytes)) { (void) putchar('#'); @@ -692,10 +668,10 @@ } if (ferror(dout)) break; - (void) putc('\r', dout); + (void) session_putc('\r', dout); bytes++; } - (void) putc(c, dout); + (void) session_putc(c, dout); bytes++; /* if (c == '\r') { */ /* (void) putc('\0', dout); // this violates rfc */ @@ -719,7 +695,7 @@ } if (closefunc != NULL) (*closefunc)(fin); - (void) fclose(dout); + (void) session_fclose(dout); (void) gettimeofday(&stop, (struct timezone *)0); (void) getreply(0); (void) signal(SIGINT, oldintr); @@ -737,11 +713,11 @@ return; } if (data >= 0) { - (void) close(data); + (void) session_close(data); data = -1; } if (dout) - (void) fclose(dout); + (void) session_fclose(dout); (void) getreply(0); code = -1; if (closefunc != NULL && fin != NULL) @@ -800,7 +776,7 @@ (void) getreply(0); } if (data >= 0) { - (void) close(data); + (void) session_close(data); data = -1; } if (oldintr) @@ -891,7 +867,7 @@ return; } errno = d = 0; - while ((c = read(fileno(din), buf, bufsize)) > 0) { + while ((c = session_read(fileno(din), buf, bufsize)) > 0) { if ((d = write(fileno(fout), buf, c)) != c) break; bytes += c; @@ -930,7 +906,7 @@ goto done; n = restart_point; for (i = 0; i++ < n;) { - if ((ch = getc(fout)) == EOF) + if ((ch = fgetc(fout)) == EOF) goto done; if (ch == '\n') i++; @@ -943,7 +919,7 @@ return; } } - while ((c = getc(din)) != EOF) { + while ((c = session_fgetc(din)) != EOF) { if (c == '\n') bare_lfs++; while (c == '\r') { @@ -953,7 +929,7 @@ local_hashbytes += hashbytes; } bytes++; - if ((c = getc(din)) != '\n' || tcrflag) { + if ((c = session_fgetc(din)) != '\n' || tcrflag) { if (ferror(fout)) goto break2; (void) putc('\r', fout); @@ -994,7 +970,7 @@ (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); - (void) fclose(din); + (void) session_fclose(din); (void) gettimeofday(&stop, (struct timezone *)0); (void) getreply(0); if (bytes > 0 && is_retr) @@ -1013,16 +989,13 @@ return; } - abort_remote(din); + abort_remote(din, 1); code = -1; - if (data >= 0) { - (void) close(data); - data = -1; - } + if (closefunc != NULL && fout != NULL) (*closefunc)(fout); if (din) - (void) fclose(din); + (void) session_fclose(din); (void) gettimeofday(&stop, (struct timezone *)0); if (bytes > 0) ptransfer("received", bytes, &start, &stop); @@ -1100,7 +1073,7 @@ if (sendport) data_addr.sin_port = 0; /* let system pick one */ if (data != -1) - (void) close(data); + (void) session_close(data); data = socket(AF_INET, SOCK_STREAM, 0); if (data < 0) { warn("socket"); @@ -1151,7 +1124,7 @@ #endif return (0); bad: - (void) close(data), data = -1; + (void) session_close(data), data = -1; if (tmpno) sendport = 1; return (1); @@ -1164,22 +1137,51 @@ struct sockaddr_in from; int s, fromlen = sizeof (from), tos; - if (passivemode) + if (passivemode) { +#ifdef TLS + if (tls_on_data) { + /* disconnect if tls_connect_data() fails */ + if (tls_connect_data(data)) { + my_sig_t oldsig = signal(SIGPIPE, SIG_IGN); + disconnect(0, NULL); + fprintf(stdout, + "Failed TLS negotiation on data channel, disconnected\n"); + signal(SIGPIPE, oldsig); + return NULL; + } + } +#endif /* TLS */ return (fdopen(data, lmode)); + } s = accept(data, (struct sockaddr *) &from, &fromlen); if (s < 0) { warn("accept"); - (void) close(data), data = -1; + (void) session_close(data), data = -1; return (NULL); } - (void) close(data); + (void) session_close(data); data = s; #if defined (IP_TOS) && defined (IPPROTO_IP) && defined (IPTOS_THROUGHPUT) tos = IPTOS_THROUGHPUT; if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) warn("setsockopt TOS (ignored)"); #endif + +#ifdef TLS + if (tls_on_data) { + /* disconnect if tls_connect_data() fails */ + if (tls_connect_data(data)) { + my_sig_t oldsig = signal(SIGPIPE, SIG_IGN); + disconnect(0, NULL); + fprintf(stdout, + "Failed TLS negotiation on data channel, disconnected\n"); + signal(SIGPIPE, oldsig); + return NULL; + } + } +#endif /* TLS */ + return (fdopen(data, lmode)); } @@ -1420,7 +1422,7 @@ if (command("%s %s", cmd2, local) != PRELIM) { pswitch(0); if (cpend) - abort_remote((FILE *) NULL); + abort_remote((FILE *) NULL, 0); } pswitch(1); if (ptabflg) @@ -1429,13 +1431,13 @@ return; } if (cpend) - abort_remote((FILE *) NULL); + abort_remote((FILE *) NULL, 0); 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); + abort_remote((FILE *) NULL, 0); pswitch(1); if (ptabflg) code = -1; @@ -1444,7 +1446,7 @@ } } if (cpend) - abort_remote((FILE *) NULL); + abort_remote((FILE *) NULL, 0); pswitch(!proxy); if (cpend) { FD_ZERO(&mask); @@ -1542,8 +1544,7 @@ } void -abort_remote(din) - FILE *din; +abort_remote( FILE *din, int close_data) { char buf[BUFSIZ]; int nfnd; @@ -1554,10 +1555,10 @@ * after urgent byte rather than before as is protocol now */ sprintf(buf, "%c%c%c", IAC, IP, IAC); - if (send(fileno(cout), buf, 3, MSG_OOB) != 3) + if (session_send(fileno(cout), buf, 3, MSG_OOB) != 3) warn("abort"); - fprintf(cout,"%cABOR\r\n", DM); - (void) fflush(cout); + session_fprintf(cout,"%cABOR\r\n", DM); + (void) session_fflush(cout); FD_ZERO(&mask); FD_SET(fileno(cin), &mask); if (din) { @@ -1571,10 +1572,19 @@ code = -1; lostpeer(); } + if (din && FD_ISSET(fileno(din), &mask)) { - while (read(fileno(din), buf, BUFSIZ) > 0) + while (session_read(fileno(din), buf, BUFSIZ) > 0) /* LOOP */; } + + if (close_data && data >= 0) { + /* close the data connection. + */ + (void) session_close(data); + data = -1; + } + if (getreply(0) == ERROR && code == 552) { /* 552 needed for nic style abort */ (void) getreply(0); diff --exclude CVS -ur inetutils/ftp/ftp_var.h feg-inetutils/ftp/ftp_var.h --- inetutils/ftp/ftp_var.h 2000-07-08 03:00:53.000000000 +0200 +++ feg-inetutils/ftp/ftp_var.h 2004-05-28 19:45:53.000000000 +0200 @@ -33,6 +33,7 @@ * FTP global variables. */ +#include #include #include @@ -129,3 +130,13 @@ FTP_EXTERN int macnum; /* number of defined macros */ FTP_EXTERN struct macel macros[16]; FTP_EXTERN char macbuf[4096]; + +FTP_EXTERN char* netrc_file; + +#ifdef TLS +FTP_EXTERN int require_tls; +FTP_EXTERN int tls_on_data; +#endif + +/* sig_t isn't what we expect on all platforms so we use a custom one */ +typedef void (*my_sig_t)__P((int)); diff --exclude CVS -ur inetutils/ftp/main.c feg-inetutils/ftp/main.c --- inetutils/ftp/main.c 2002-04-29 22:40:30.000000000 +0200 +++ feg-inetutils/ftp/main.c 2004-05-28 19:45:54.000000000 +0200 @@ -58,6 +58,7 @@ /* Define macro to nothing so declarations in ftp_var.h become definitions. */ #define FTP_EXTERN #include "ftp_var.h" +#include "session.h" /* basename (argv[0]). NetBSD, linux, & gnu libc all define it. */ extern char *__progname; @@ -78,6 +79,7 @@ fprintf (stdout, "Usage: %s [OPTION...] [HOST [PORT]]\n", __progname); puts ("Remote file transfer.\n\n\ -d, --debug Turn on debugging mode\n\ + -A, --active Turn on active mode ftp\n\ -g, --no-glob Turn off file name globbing\n\ -i, --no-prompt Don't prompt during multiple-file transfers\n\ -n, --no-login Don't automatically login to the remove system\n\ @@ -85,26 +87,48 @@ -p, --prompt[=PROMPT] Print a command-line prompt (optionally PROMPT),\n\ even if not on a tty\n\ -v, --verbose Be verbose\n\ - --help Give this help list\n\ - -V, --version Print program version"); + -h, --help Give this help list\n\ + -V, --version Print program version" +#ifdef TLS +"\n\nTLS options:\n" +" -z noprotect Don't use AUTH TLS by default\n" +" -z private Use TLS on data channel by default\n" +" -z requiretls Use TLS on control channel or fail\n" +" -z compress Use compression on the TLS channel\n" +" -z nosrp Don't use the SRP ciphersuites\n" +" -z certsok Don't do any verification on the server's cert\n" +" -z cert=FILE Use certificate in FILE\n" +" -z key=FILE Use private key in FILE\n" +" -z ca=FILE Use CA certificate(s) in FILE\n" +" -z crl=FILE Use Certificate Revocation List in FILE\n" +" -z pgpcert=FILE Use OpenPGP key in FILE\n" +" -z pgpkey=FILE Use OpenPGP private key in FILE\n" +" -z pgpring=FILE Use an OpenPGP keyring in FILE\n" +#endif /* !TLS */ + +); fprintf (stdout, "\nSubmit bug reports to %s.\n", PACKAGE_BUGREPORT); } exit (err); } -static const char *short_options = "dginp::tv"; +static const char *short_options = "dginp::thvz:"; static struct option long_options[] = { { "trace", no_argument, 0, 't' }, { "verbose", no_argument, 0, 'v' }, { "no-login", no_argument, 0, 'n' }, { "no-prompt", no_argument, 0, 'i' }, + { "active", no_argument, 0, 'A' }, { "debug", no_argument, 0, 'd' }, { "no-glob", no_argument, 0, 'g' }, - { "help", no_argument, 0, '&' }, + { "help", no_argument, 0, 'h' }, { "prompt", optional_argument, 0, 'p' }, { "version", no_argument, 0, 'V' }, +#ifdef TLS + { "tlsopt", 1, 0, 'z' }, +#endif { 0 } }; @@ -125,6 +149,12 @@ doglob = 1; interactive = 1; autologin = 1; + passivemode = 1; /* passive mode is activated by default */ +#ifdef TLS + require_tls = -1; /* uninitialized */ + tls_on_data = -1; +#endif + netrc_file = NULL; /* auto detect which file to use */ while ((ch = getopt_long (argc, argv, short_options, long_options, 0)) != EOF) @@ -143,6 +173,10 @@ interactive = 0; break; + case 'A': /* No passive mode. */ + passivemode = 0; + break; + case 'n': /* No automatic login. */ autologin = 0; break; @@ -159,13 +193,19 @@ prompt = optarg ? optarg : DEFAULT_PROMPT; break; - case '&': /* Usage. */ + case 'h': /* Usage. */ usage (0); /* Not reached. */ case 'V': /* Version. */ printf ("ftp (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); exit (0); +#ifdef TLS + case 'z': + if (tls_optarg(optarg)) + usage(0); + break; +#endif /* TLS */ case '?': default: @@ -187,7 +227,6 @@ 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 */ /* @@ -207,6 +246,7 @@ home = buf; } } + if (argc > 0) { char *xargv[5]; @@ -248,29 +288,59 @@ { if (cout != NULL) { - (void) shutdown (fileno (cout), 1+1); - (void) fclose (cout); + if (sig) { + /* we do not use the tls functions if we are called as a signal + * handler. + */ + (void) shutdown (fileno (cout), 1+1); + (void) fclose (cout); + } else { + (void) session_shutdown (fileno (cout), 1+1); + (void) session_fclose (cout); + } cout = NULL; } if (data >= 0) { - (void) shutdown (data, 1+1); - (void) close (data); + if (sig) { + (void) shutdown (data, 1+1); + (void) close (data); + } else { + (void) session_shutdown (data, 1+1); + (void) session_close (data); + } data = -1; } connected = 0; } + /* we must be sure the SSL struct pointers are free'd and cleared, + * so we might connect again */ +#ifdef TLS + else if (sig == 0) + tls_free_ssls(); +#endif + pswitch (1); if (connected) { if (cout != NULL) { - (void) shutdown (fileno(cout), 1+1); - (void) fclose (cout); + if (sig) { + (void) shutdown (fileno(cout), 1+1); + (void) fclose (cout); + } else { + (void) session_shutdown (fileno(cout), 1+1); + (void) session_fclose (cout); + } cout = NULL; } connected = 0; } +#ifdef TLS + else if (sig == 0) + tls_free_ssls(); +#endif /* TLS */ + proxflag = 0; pswitch (0); } @@ -314,7 +384,7 @@ free (line); line = 0; } - line = readline (prompt); + line = (char*) readline (prompt); if (!line) quit (0, 0); if (line && *line) diff --exclude CVS -ur inetutils/ftp/Makefile.am feg-inetutils/ftp/Makefile.am --- inetutils/ftp/Makefile.am 2002-04-28 18:55:32.000000000 +0200 +++ feg-inetutils/ftp/Makefile.am 2004-06-12 23:31:43.000000000 +0200 @@ -4,17 +4,18 @@ EXTRA_PROGRAMS = ftp -ftp_SOURCES = cmds.c cmdtab.c domacro.c ftp.c main.c ruserpass.c +ftp_SOURCES = cmds.c cmdtab.c domacro.c ftp.c main.c ruserpass.c \ + tlsutil.h tlsutil.c tlsnetrc.c -noinst_HEADERS = extern.h ftp_var.h +noinst_HEADERS = extern.h ftp_var.h session.h tlsnetrc.h man_MANS = ftp.1 @PATHDEFS_MAKE@ INCLUDES = $(PATHDEF_TMP) $(PATHDEF_BSHELL) -I$(top_builddir)/include - +AM_CFLAGS = $(LIBGNUTLS_EXTRA_CFLAGS) READLINE=@LIBREADLINE@ @LIBTERMCAP@ -LDADD = -L../libinetutils -linetutils $(LIBGLOB) $(READLINE) +LDADD = -L../libinetutils -linetutils $(LIBGLOB) $(READLINE) $(LIBGNUTLS_EXTRA_LIBS) EXTRA_DIST = $(man_MANS) diff --exclude CVS -ur inetutils/ftp/ruserpass.c feg-inetutils/ftp/ruserpass.c --- inetutils/ftp/ruserpass.c 2000-08-07 08:17:46.000000000 +0200 +++ feg-inetutils/ftp/ruserpass.c 2004-05-28 19:45:54.000000000 +0200 @@ -52,36 +52,17 @@ #include #include "ftp_var.h" +#include "tlsnetrc.h" extern char *localhost __P((void)); extern char *xstrdup __P((const char *)); extern char *xmalloc __P((size_t)); -static int token __P((void)); -static FILE *cfile; - /* protect agains os headers */ -#undef DEFAULT -#define DEFAULT 1 -#undef LOGIN -#define LOGIN 2 -#undef PASSWD -#define PASSWD 3 -#undef ACCOUNT -#define ACCOUNT 4 -#undef MACDEF -#define MACDEF 5 -#undef ID -#define ID 10 -#undef MACHINE -#define MACHINE 11 - -static char tokval[100]; - -static struct toktab { - char *tokstr; - int tval; -} toktab[]= { + +char tokval[100]; + +toktab_st toktab[]= { { "default", DEFAULT }, { "login", LOGIN }, { "password", PASSWD }, @@ -89,38 +70,90 @@ { "account", ACCOUNT }, { "machine", MACHINE }, { "macdef", MACDEF }, + { "ca", CAFILE }, + { "crl", CRLFILE}, + { "key", KEY }, + { "certificate", CERT }, + { "pgpcertificate", PGPCERT }, + { "pgpkey", PGPKEY }, + { "pgpring", PGPRING }, + { "requiretls", REQUIRETLS }, + { "private", PRIVATE }, { NULL, 0 } }; -int -ruserpass(char *host, char **aname, char **apass, char **aacct) +/* returns true if the given token is in toktab + */ +int token_in_tab( const char* token) { - char *hdir, buf[BUFSIZ], *tmp; - char *myname = 0, *mydomain; - int t, i, c, usedefault = 0; - struct stat stb; +toktab_st * t; + + for (t = toktab; t->tokstr; t++) + if (!strcmp(t->tokstr, token)) + return 1; + + return 0; +} + +FILE* netrc_open( char** myname, char** mydomain) +{ +char *hdir, buf[BUFSIZ]; +FILE* cfile; + + if (netrc_file == NULL) + netrc_file = ".ftprc"; hdir = getenv("HOME"); if (hdir == NULL) hdir = "."; - snprintf (buf, sizeof buf, "%s/.netrc", hdir); + snprintf (buf, sizeof buf, "%s/%s", hdir, netrc_file); + cfile = fopen(buf, "r"); if (cfile == NULL) { + if (errno != ENOENT) - warn("%s", buf); - return (0); + warn("%s", buf); + + netrc_file = ".netrc"; + snprintf (buf, sizeof buf, "%s/%s", hdir, netrc_file); + cfile = fopen(buf, "r"); + + if (cfile == NULL) { + if (errno != ENOENT) + warn("%s", buf); + return (0); + } } + if (cfile != NULL && verbose > 1) + printf("Reading %s file\n", netrc_file); + + *myname = localhost (); + if (*myname == NULL) + *myname = xstrdup (""); + + *mydomain = strchr(*myname, '.'); + if (*mydomain == NULL) + *mydomain = xstrdup (""); + + return cfile; + +} + +int +ruserpass(char *host, char **aname, char **apass, char **aacct) +{ + char *tmp; + char *myname = 0, *mydomain = 0; + int t, i, c, usedefault = 0; + struct stat stb; + FILE* cfile; + + cfile = netrc_open( &myname, &mydomain); + if (!cfile) goto bad; - myname = localhost (); - if (! myname) - myname = xstrdup (""); - - mydomain = strchr(myname, '.'); - if (mydomain == NULL) - mydomain = xstrdup (""); next: - while ((t = token())) + while ((t = token(cfile))) { switch(t) { case DEFAULT: @@ -130,7 +163,7 @@ case MACHINE: if (!usedefault) { - if (token() != ID) + if (token(cfile) != ID) continue; /* * Allow match either for user's input host name @@ -153,32 +186,32 @@ continue; } match: - while ((t = token()) && t != MACHINE && t != DEFAULT) + while ((t = token(cfile)) && t != MACHINE && t != DEFAULT) { switch(t) { case LOGIN: - if (token()) - if (*aname == 0) + if (token(cfile)) + if (aname != NULL && *aname == 0) { *aname = xmalloc((unsigned) strlen(tokval) + 1); (void) strcpy(*aname, tokval); } else { - if (strcmp(*aname, tokval)) + if (aname != NULL && 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) + if ((aname == NULL || *aname == NULL || strcmp(*aname, "anonymous")) + && fstat(fileno(cfile), &stb) >= 0 + && (stb.st_mode & 077) != 0) + { + warnx("Error: %s file is readable by others.", netrc_file); + warnx("Remove password or make file unreadable by others."); + goto bad; + } + if (token(cfile) && apass != NULL && *apass == 0) { *apass = xmalloc((unsigned) strlen(tokval) + 1); (void) strcpy(*apass, tokval); @@ -188,11 +221,11 @@ if (fstat(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { - warnx("Error: .netrc file is readable by others."); + warnx("Error: %s file is readable by others.", netrc_file); warnx("Remove account or make file unreadable by others."); goto bad; } - if (token() && *aacct == 0) + if (token(cfile) && aacct != NULL && *aacct == 0) { *aacct = xmalloc((unsigned) strlen(tokval) + 1); (void) strcpy(*aacct, tokval); @@ -270,29 +303,34 @@ } break; default: - warnx("Unknown .netrc keyword %s", tokval); + if (token_in_tab( tokval)==0) + warnx("Unknown %s keyword %s", tokval, netrc_file); + else + token(cfile); /* read the value and ignore it */ + break; } + } goto done; } + } done: (void) fclose(cfile); if (myname) free (myname); return (0); bad: - (void) fclose(cfile); + if (cfile) fclose(cfile); if (myname) free (myname); return (-1); } -static int -token(void) +int token(FILE* cfile) { char *cp; int c; - struct toktab *t; + toktab_st *t; if (feof(cfile) || ferror(cfile)) return (0); Only in feg-inetutils/ftp: session.h Only in feg-inetutils/ftp: tlsnetrc.c Only in feg-inetutils/ftp: tlsnetrc.h Only in feg-inetutils/ftp: tlsutil.c Only in feg-inetutils/ftp: tlsutil.h diff --exclude CVS -ur inetutils/headers/Makefile.am feg-inetutils/headers/Makefile.am --- inetutils/headers/Makefile.am 2004-02-03 20:43:24.000000000 +0100 +++ feg-inetutils/headers/Makefile.am 2004-05-24 22:50:06.000000000 +0200 @@ -1,5 +1,5 @@ EXTRA_DIST = crypt.h err.h getopt.h obstack.h osockaddr.h paths.h poll.h \ - syslog-int.h tftpsubs.h confpaths.h.in stamp-h.in + syslog-int.h tftpsubs.h confpaths.h.in stamp-h.in shishi_def.h header_dirs = arpa protocols Only in feg-inetutils/headers: shishi_def.h Only in feg-inetutils/: libgnutls-extra.m4 diff --exclude CVS -ur inetutils/libinetutils/kcmd.c feg-inetutils/libinetutils/kcmd.c --- inetutils/libinetutils/kcmd.c 2000-07-06 06:21:07.000000000 +0200 +++ feg-inetutils/libinetutils/kcmd.c 2004-05-24 22:50:06.000000000 +0200 @@ -36,7 +36,7 @@ #include #endif -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) #include #include @@ -46,9 +46,14 @@ #include #include +#if defined(KERBEROS) #include #include #include +#elif defined(SHISHI) +#include +#include "shishi_def.h" +#endif #include #include @@ -66,22 +71,44 @@ #define START_PORT 5120 /* arbitrary */ +#ifdef SHISHI +#endif + int getport __P((int *)); +#if defined (KERBEROS) int kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm, cred, schedule, msg_data, laddr, faddr, authopts) +#elif defined(SHISHI) +int +kcmd(h,sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm, + key, laddr, faddr, authopts) + Shishi **h; +#endif int *sock; char **ahost; u_short rport; - char *locuser, *remuser, *cmd; + char *locuser; +#if defined (SHISHI) + char **remuser; +#else + char *remuser; +#endif + char *cmd; int *fd2p; +#if defined(KERBEROS) KTEXT ticket; +#endif char *service; char *realm; +#if defined(KERBEROS) CREDENTIALS *cred; Key_schedule schedule; MSG_DAT *msg_data; +#elif defined(SHISHI) + Shishi_key **key; +#endif struct sockaddr_in *laddr, *faddr; long authopts; { @@ -98,6 +125,9 @@ int rc; char *host_save; int status; +#if defined(SHISHI) + int zero = 0; +#endif pid = getpid(); hp = gethostbyname(*ahost); @@ -136,6 +166,7 @@ bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); #endif sin.sin_port = rport; + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) break; (void) close(s); @@ -171,6 +202,7 @@ if (errno != ECONNREFUSED) perror(hp->h_name); sigsetmask(oldmask); + return (-1); } lport--; @@ -220,6 +252,7 @@ /* (void) write(s, locuser, strlen(locuser)+1); */ /* set up the needed stuff for mutual auth, but only if necessary */ +#ifdef KERBEROS if (authopts & KOPT_DO_MUTUAL) { int sin_len; *faddr = sin; @@ -231,7 +264,7 @@ goto bad2; } } -#ifdef KERBEROS + if ((status = krb_sendauth(authopts, s, ticket, service, *ahost, realm, (unsigned long) getpid(), msg_data, cred, schedule, @@ -239,11 +272,32 @@ faddr, "KCMDV0.1")) != KSUCCESS) goto bad2; -#endif /* KERBEROS */ +#elif defined(SHISHI) + if (authopts & SHISHI_APOPTIONS_MUTUAL_REQUIRED) { + int sin_len; + *faddr = sin; + + sin_len = sizeof(struct sockaddr_in); + if (getsockname(s, (struct sockaddr *)laddr, &sin_len) < 0) { + perror("kcmd(getsockname)"); + status = -1; + goto bad2; + } + } + + if ((status = shishi_auth(h, 0, remuser, *ahost, s, cmd, rport, key, realm)) != SHISHI_OK) + goto bad2; - (void) write(s, remuser, strlen(remuser)+1); +#endif /* SHISHI */ + + (void) write(s, *remuser, strlen(*remuser)+1); (void) write(s, cmd, strlen(cmd)+1); +#ifdef SHISHI + (void) write(s, *remuser, strlen(*remuser)+1); + (void) write(s, &zero, sizeof (int)); +#endif + if ((rc = read(s, &c, 1)) != 1) { if (rc == -1) perror(*ahost); @@ -263,7 +317,11 @@ } sigsetmask(oldmask); *sock = s; +#if defined(KERBEROS) return (KSUCCESS); +#elif defined(SHISHI) + return (SHISHI_OK); +#endif bad2: if (lport) (void) close(*fd2p); diff --exclude CVS -ur inetutils/libinetutils/krcmd.c feg-inetutils/libinetutils/krcmd.c --- inetutils/libinetutils/krcmd.c 2000-07-06 06:21:07.000000000 +0200 +++ feg-inetutils/libinetutils/krcmd.c 2004-05-24 22:50:06.000000000 +0200 @@ -44,7 +44,7 @@ #include #endif -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) #include #ifdef ENCRYPTION #include @@ -52,16 +52,27 @@ #include +#ifdef KERBEROS #include #include +#elif defined(SHISHI) +#include +#include "shishi_def.h" +#endif #include #define SERVICE_NAME "rcmd" +#if defined(SHISHI) +int kcmd __P((Shishi **,int *, char **, u_short, char *, char **, char *, int *, + char *, char *, Shishi_key **, struct sockaddr_in *, + struct sockaddr_in *, long)); +#else int kcmd __P((int *, char **, u_short, char *, char *, char *, int *, KTEXT, char *, char *, CREDENTIALS *, Key_schedule, MSG_DAT *, struct sockaddr_in *, struct sockaddr_in *, long)); +#endif /* * krcmd: simplified version of Athena's "kcmd" @@ -69,6 +80,46 @@ * if fd2p is non-NULL, another socket is filled in for it */ +#if defined(SHISHI) +int +krcmd(h, ahost, rport, remuser, cmd, fd2p, realm) + Shishi **h; + char **ahost; + u_short rport; + char **remuser, *cmd; + int *fd2p; + char *realm; +{ + int sock = -1, err = 0; + long authopts = 0L; + + err = kcmd( + h, + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + SERVICE_NAME, + realm, + (Shishi_key **) NULL, /* key schedule not used */ + (struct sockaddr_in *) NULL, /* local addr not used */ + (struct sockaddr_in *) NULL, /* foreign addr not used */ + authopts + ); + + if (err > SHISHI_OK) { + fprintf(stderr, "krcmd: %s\n", "error"); + return(-1); + } + if (err < 0) + return(-1); + return(sock); +} + +#elif defined(KERBEROS) int krcmd(ahost, rport, remuser, cmd, fd2p, realm) char **ahost; @@ -108,8 +159,53 @@ return(-1); return(sock); } +#endif #ifdef ENCRYPTION + +#if defined(SHISHI) +int +krcmd_mutual(h, ahost, rport, remuser, cmd, fd2p, realm, key) + Shishi **h; + char **ahost; + u_short rport; + char **remuser, *cmd; + int *fd2p; + char *realm; + Shishi_key **key; +{ + int sock = -1, err = 0; + struct sockaddr_in laddr, faddr; + long authopts = SHISHI_APOPTIONS_MUTUAL_REQUIRED; + + err = kcmd( + h, + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + SERVICE_NAME, + realm, + key, /* filled in */ + &laddr, /* filled in */ + &faddr, /* filled in */ + authopts + ); + + if (err > SHISHI_OK) { + fprintf(stderr, "krcmd_mutual: %s\n", "error"); + return(-1); + } + + if (err < 0) + return (-1); + return(sock); +} + +#elif defined(KERBEROS) int krcmd_mutual(ahost, rport, remuser, cmd, fd2p, realm, cred, sched) char **ahost; @@ -156,3 +252,4 @@ } #endif /* CRYPT */ #endif /* KERBEROS */ +#endif /* KERBEROS */ diff --exclude CVS -ur inetutils/libinetutils/Makefile.am feg-inetutils/libinetutils/Makefile.am --- inetutils/libinetutils/Makefile.am 2003-04-05 18:43:08.000000000 +0200 +++ feg-inetutils/libinetutils/Makefile.am 2004-05-24 22:50:06.000000000 +0200 @@ -4,7 +4,7 @@ libinetutils_a_SOURCES = argcv.c cleansess.c daemon.c des_rw.c kcmd.c \ krcmd.c localhost.c logwtmpko.c setsig.c tftpsubs.c ttymsg.c \ - xmalloc.c xstrdup.c xgetcwd.c utmp_init.c utmp_logout.c + xmalloc.c xstrdup.c xgetcwd.c utmp_init.c utmp_logout.c shishi.c # memcmp.c memcpy.c memmove.c memset.c Only in feg-inetutils/libinetutils: shishi.c diff --exclude CVS -ur inetutils/libtelnet/auth.c feg-inetutils/libtelnet/auth.c --- inetutils/libtelnet/auth.c 2002-12-06 17:10:07.000000000 +0100 +++ feg-inetutils/libtelnet/auth.c 2004-05-21 21:24:25.000000000 +0200 @@ -126,6 +126,24 @@ spx_status, spx_printsub }, #endif +#ifdef SHISHI + { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, + krb5shishi_init, + krb5shishi_send, + krb5shishi_is, + krb5shishi_reply, + krb5shishi_status, + krb5shishi_printsub, + krb5shishi_cleanup }, + { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + krb5shishi_init, + krb5shishi_send, + krb5shishi_is, + krb5shishi_reply, + krb5shishi_status, + krb5shishi_printsub, + krb5shishi_cleanup }, +#endif #ifdef KRB5 # ifdef ENCRYPTION { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, @@ -610,6 +628,8 @@ TN_Authenticator *ap; int result; { + if (ap && ap->cleanup) + (*ap->cleanup) (ap); if (!(authenticated = ap)) authenticated = &NoAuth; validuser = result; diff --exclude CVS -ur inetutils/libtelnet/auth.h feg-inetutils/libtelnet/auth.h --- inetutils/libtelnet/auth.h 2002-12-06 17:09:06.000000000 +0100 +++ feg-inetutils/libtelnet/auth.h 2004-05-21 21:24:16.000000000 +0200 @@ -75,6 +75,7 @@ void (*reply) P((struct XauthP *, unsigned char *, int)); int (*status) P((struct XauthP *, char *, int)); void (*printsub) P((unsigned char *, int, unsigned char *, int)); + void (*cleanup) P((struct XauthP *)); } TN_Authenticator; #include "auth-proto.h" diff --exclude CVS -ur inetutils/libtelnet/auth-proto.h feg-inetutils/libtelnet/auth-proto.h --- inetutils/libtelnet/auth-proto.h 2002-12-06 17:09:06.000000000 +0100 +++ feg-inetutils/libtelnet/auth-proto.h 2004-05-21 21:24:10.000000000 +0200 @@ -89,4 +89,14 @@ int kerberos5_status P((TN_Authenticator *, char *, int)); void kerberos5_printsub P((unsigned char *, int, unsigned char *, int)); #endif + +#ifdef SHISHI +int krb5shishi_init P((TN_Authenticator *, int)); +int krb5shishi_send P((TN_Authenticator *)); +void krb5shishi_is P((TN_Authenticator *, unsigned char *, int)); +void krb5shishi_reply P((TN_Authenticator *, unsigned char *, int)); +int krb5shishi_status P((TN_Authenticator *, char *, int)); +void krb5shishi_printsub P((unsigned char *, int, unsigned char *, int)); +void krb5shishi_cleanup P((TN_Authenticator *)); +#endif #endif diff --exclude CVS -ur inetutils/libtelnet/enc_des.c feg-inetutils/libtelnet/enc_des.c --- inetutils/libtelnet/enc_des.c 2000-07-06 06:21:08.000000000 +0200 +++ feg-inetutils/libtelnet/enc_des.c 2004-05-24 22:50:06.000000000 +0200 @@ -37,7 +37,11 @@ #ifdef ENCRYPTION # ifdef AUTHENTICATION -# ifdef DES_ENCRYPTION +# if defined (DES_ENCRYPTION) || defined (SHISHI) +#ifdef SHISHI +#include +extern Shishi * shishi_handle; +#endif #include #include #ifdef HAVE_STDLIB_H @@ -74,7 +78,7 @@ Block str_output; Block str_feed; Block str_iv; - Block str_ikey; + Block str_ikey; Schedule str_sched; int str_index; int str_flagshift; @@ -119,7 +123,18 @@ void fb64_stream_key P((Block, struct stinfo *)); int fb64_keyid P((int, unsigned char *, int *, struct fb *)); - void +#ifdef SHISHI +void shishi_des_ecb_encrypt (Shishi * h, const char key[8], const char * in, char * out) +{ + char * tmp; + + shishi_des (h, 0, key, NULL, NULL, in, 8, &tmp); + memcpy (out, tmp, 8); + free (tmp); +} +#endif + +void cfb64_init(server) int server; { @@ -215,9 +230,16 @@ /* * Create a random feed and send it over. */ +#ifdef SHISHI + if (shishi_randomize (shishi_handle, 0, + fbp->temp_feed, 8) != SHISHI_OK) + return(FAILED); + +#else des_new_random_key(fbp->temp_feed); des_ecb_encrypt(fbp->temp_feed, fbp->temp_feed, fbp->krbdes_sched, 1); +#endif p = fbp->fb_feed + 3; *p++ = ENCRYPT_IS; p++; @@ -417,6 +439,7 @@ { if (!key || key->type != SK_DES) { + /* FIXME: Support RFC 2952 approach instead of giving up here. */ if (encrypt_debug_mode) printf("Can't set krbdes's session key (%d != %d)\r\n", key ? key->type : -1, SK_DES); @@ -428,10 +451,14 @@ fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); if (fbp->once == 0) { +#ifndef SHISHI des_set_random_generator_seed(fbp->krbdes_key); +#endif fbp->once = 1; } +#ifndef SHISHI des_key_sched(fbp->krbdes_key, fbp->krbdes_sched); +#endif /* * Now look to see if krbdes_start() was was waiting for * the key to show up. If so, go ahead an call it now @@ -552,7 +579,9 @@ memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); +#ifndef SHISHI des_key_sched(stp->str_ikey, stp->str_sched); +#endif stp->str_index = sizeof(Block); } @@ -563,8 +592,9 @@ register struct stinfo *stp; { memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); +#ifndef SHISHI des_key_sched(key, stp->str_sched); - +#endif memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); stp->str_index = sizeof(Block); @@ -604,7 +634,12 @@ while (c-- > 0) { if (index == sizeof(Block)) { Block b; +#ifdef SHISHI + shishi_des_ecb_encrypt (shishi_handle, fb[CFB].krbdes_key, + stp->str_output, b); +#else des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1); +#endif memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); index = 0; } @@ -638,7 +673,12 @@ index = stp->str_index++; if (index == sizeof(Block)) { Block b; +#ifdef SHISHI + shishi_des_ecb_encrypt (shishi_handle, fb[CFB].krbdes_key, + stp->str_output, b); +#else des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1); +#endif memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); stp->str_index = 1; /* Next time will be 1 */ index = 0; /* But now use 0 */ @@ -680,7 +720,12 @@ while (c-- > 0) { if (index == sizeof(Block)) { Block b; +#ifdef SHISHI + shishi_des_ecb_encrypt (shishi_handle, fb[OFB].krbdes_key, + stp->str_feed, b); +#else des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1); +#endif memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); index = 0; } @@ -711,7 +756,12 @@ index = stp->str_index++; if (index == sizeof(Block)) { Block b; +#ifdef SHISHI + shishi_des_ecb_encrypt (shishi_handle, fb[OFB].krbdes_key, + stp->str_feed, b); +#else des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1); +#endif memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); stp->str_index = 1; /* Next time will be 1 */ index = 0; /* But now use 0 */ diff --exclude CVS -ur inetutils/libtelnet/encrypt.c feg-inetutils/libtelnet/encrypt.c --- inetutils/libtelnet/encrypt.c 2000-07-06 06:21:08.000000000 +0200 +++ feg-inetutils/libtelnet/encrypt.c 2004-05-21 21:23:46.000000000 +0200 @@ -104,7 +104,7 @@ static long remote_supports_decrypt = 0; static Encryptions encryptions[] = { -#ifdef DES_ENCRYPTION +#if defined (DES_ENCRYPTION) || defined (SHISHI) { "DES_CFB64", ENCTYPE_DES_CFB64, cfb64_encrypt, cfb64_decrypt, diff --exclude CVS -ur inetutils/libtelnet/encrypt.h feg-inetutils/libtelnet/encrypt.h --- inetutils/libtelnet/encrypt.h 2000-07-06 06:21:08.000000000 +0200 +++ feg-inetutils/libtelnet/encrypt.h 2004-05-21 21:23:38.000000000 +0200 @@ -94,6 +94,7 @@ } Encryptions; #define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */ +#define SK_OTHER 2 /* Non-DES key. */ #include "enc-proto.h" diff --exclude CVS -ur inetutils/libtelnet/Makefile.am feg-inetutils/libtelnet/Makefile.am --- inetutils/libtelnet/Makefile.am 2002-04-08 16:02:39.000000000 +0200 +++ feg-inetutils/libtelnet/Makefile.am 2004-05-21 21:21:46.000000000 +0200 @@ -4,6 +4,6 @@ noinst_LIBRARIES = libtelnet.a -libtelnet_a_SOURCES = auth.c enc_des.c encrypt.c forward.c genget.c getent.c kerberos.c kerberos5.c misc.c read_passwd.c +libtelnet_a_SOURCES = auth.c enc_des.c encrypt.c forward.c genget.c getent.c kerberos.c kerberos5.c misc.c read_passwd.c shishi.c noinst_HEADERS = auth-proto.h auth.h enc-proto.h encrypt.h key-proto.h misc-proto.h misc.h Only in feg-inetutils/libtelnet: shishi.c diff --exclude CVS -ur inetutils/Makefile.am feg-inetutils/Makefile.am --- inetutils/Makefile.am 2004-02-03 20:43:09.000000000 +0100 +++ feg-inetutils/Makefile.am 2004-06-12 23:31:56.000000000 +0200 @@ -1,6 +1,7 @@ AUTOMAKE_OPTIONS = 1.8 -EXTRA_DIST = README-alpha paths ChangeLog.0 +EXTRA_DIST = README-alpha paths ChangeLog.0 \ + README.feg NEWS.feg ChangeLog.feg SUBDIRS = headers libinetutils libtelnet glob \ inetd telnetd libls ftpd rshd rlogind uucpd rexecd syslogd tftpd \ Only in feg-inetutils/: Makefile.feg Only in feg-inetutils/: NEWS.feg Only in feg-inetutils/: README.feg diff --exclude CVS -ur inetutils/rlogin/rlogin.c feg-inetutils/rlogin/rlogin.c --- inetutils/rlogin/rlogin.c 2003-04-05 18:58:47.000000000 +0200 +++ feg-inetutils/rlogin/rlogin.c 2004-05-24 22:50:06.000000000 +0200 @@ -96,15 +96,35 @@ #include #endif -#ifdef KERBEROS -#include -#include +#ifdef SHISHI +#define REALM_SZ 1040 +#endif +#if defined(KERBEROS) || defined(SHISHI) +int use_kerberos = 1, doencrypt; +# ifdef KERBEROS +# include +# include +char dest_realm_buf[REALM_SZ], *dest_realm = NULL; CREDENTIALS cred; Key_schedule schedule; -int use_kerberos = 1, doencrypt; + +# elif defined(SHISHI) +# include +# include "shishi_def.h" char dest_realm_buf[REALM_SZ], *dest_realm = NULL; + +Shishi * handle; +Shishi_key * key; +shishi_ivector iv1, iv2; +shishi_ivector * ivtab[2]; + +int keytype; +int keylen; +int rc; +int wlen; #endif +#endif /* KERBEROS */ /* The TIOCPKT_* macros may not be implemented in the pty driver. @@ -140,7 +160,7 @@ terminal. */ #define SPEED_NOTATTY (-1) -int eight, rem; +int eight=0, rem; int noescape; u_char escapechar = '~'; @@ -170,7 +190,11 @@ void lostpeer __P ((int)); void mode __P ((int)); void msg __P ((const char *)); +#ifdef SHISHI +void oob __P ((char)); +#else void oob __P ((int)); +#endif int reader __P ((sigset_t *)); void sendwindow __P ((void)); void setsignal __P ((int)); @@ -182,13 +206,13 @@ void writer __P ((void)); void writeroob __P ((int)); -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) void warning __P ((const char *, ...)); #endif extern sig_t setsig __P ((int, sig_t)); -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) #define OPTIONS "8EKde:k:l:xhV" #else #define OPTIONS "8EKde:l:hV" @@ -202,7 +226,7 @@ { "no-escape", no_argument, 0, 'E' }, { "8-bit", no_argument, 0, '8' }, { "kerberos", no_argument, 0, 'K' }, -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) { "realm", required_argument, 0, 'k' }, { "encrypt", no_argument, 0, 'x' }, #endif @@ -261,7 +285,7 @@ break; case 'K': -#ifdef KERBEROS +#if defined (KERBEROS) || defined(SHISHI) use_kerberos = 0; #endif break; @@ -277,7 +301,7 @@ escapechar = getescape (optarg); break; -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) case 'k': strncpy (dest_realm_buf, optarg, sizeof dest_realm_buf); /* Make sure it's null termintated. */ @@ -293,10 +317,12 @@ break; #ifdef ENCRYPTION -# ifdef KERBEROS +# if defined(KERBEROS) || defined (SHISHI) case 'x': doencrypt = 1; +# if defined(KERBEROS) des_set_key (cred.session, schedule); +#endif break; # endif #endif @@ -344,12 +370,10 @@ if (*host == '\0') usage (1); } - if (!user) - user = pw->pw_name; } sp = NULL; -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (use_kerberos) { sp = getservbyname ((doencrypt ? "eklogin" : "klogin"), "tcp"); @@ -361,7 +385,7 @@ } } #endif - + /* Get the port number for the rlogin service. */ if (sp == NULL) sp = getservbyname ("login", "tcp"); @@ -405,8 +429,8 @@ */ setsig (SIGURG, copytochild); setsig (SIGUSR1, writeroob); - -#ifdef KERBEROS + +#if defined (KERBEROS) || defined(SHISHI) try_connect: if (use_kerberos) { @@ -417,18 +441,80 @@ if (hp != NULL && !(host = strdup (hp->h_name))) errx (1, "%s", strerror (ENOMEM)); +#if defined (KERBEROS) rem = KSUCCESS; errno = 0; if (dest_realm == NULL) dest_realm = krb_realmofhost (host); +#elif defined (SHISHI) + rem = SHISHI_OK; + errno = 0; +#endif # ifdef ENCRYPTION if (doencrypt) +#if defined(SHISHI) + { + int i; + + rem = krcmd_mutual (&handle, &host, sp->s_port, &user, term, 0, + dest_realm, &key); + if (rem > 0) + { + keytype = shishi_key_type (key); + keylen = shishi_cipher_blocksize (keytype); + + ivtab[0] = &iv1; + ivtab[1] = &iv2; + + for (i=0; i<2; i++) + { + ivtab[i]->ivlen = keylen; + + switch (keytype) + { + case SHISHI_DES_CBC_CRC: + case SHISHI_DES_CBC_MD4: + case SHISHI_DES_CBC_MD5: + case SHISHI_DES_CBC_NONE: + case SHISHI_DES3_CBC_HMAC_SHA1_KD: + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; + ivtab[i]->iv = malloc (ivtab[i]->ivlen); + memset (ivtab[i]->iv, !i, ivtab[i]->ivlen); + ivtab[i]->ctx = shishi_crypto (handle, key, ivtab[i]->keyusage, shishi_key_type (key), + ivtab[i]->iv, ivtab[i]->ivlen); + break; + case SHISHI_ARCFOUR_HMAC: + case SHISHI_ARCFOUR_HMAC_EXP: + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4*i; + ivtab[i]->ctx = shishi_crypto (handle, key, ivtab[i]->keyusage, shishi_key_type (key), + NULL, 0); + break; + default : + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4*i; + ivtab[i]->iv = malloc (ivtab[i]->ivlen); + memset (ivtab[i]->iv, 0, ivtab[i]->ivlen); + ivtab[i]->ctx = shishi_crypto (handle, key, ivtab[i]->keyusage, shishi_key_type (key), + ivtab[i]->iv, ivtab[i]->ivlen); + } + } + } + } + + else +#else rem = krcmd_mutual (&host, sp->s_port, user, term, 0, dest_realm, &cred, schedule); else +#endif #endif /* CRYPT */ - rem = krcmd (&host, sp->s_port, user, term, 0, dest_realm); + + rem = krcmd ( +#if defined (SHISHI) + &handle, &host, sp->s_port, &user, term, 0, dest_realm); +#else + &host, sp->s_port, user, term, 0, dest_realm); +#endif if (rem < 0) { use_kerberos = 0; @@ -442,16 +528,22 @@ goto try_connect; } } + else { # ifdef ENCRYPTION if (doencrypt) errx (1, "the -x flag requires Kerberos authentication."); #endif /* CRYPT */ + if (!user) + user = pw->pw_name; + rem = rcmd (&host, sp->s_port, pw->pw_name, user, term, 0); } #else - + if (!user) + user = pw->pw_name; + rem = rcmd (&host, sp->s_port, pw->pw_name, user, term, 0); #endif /* KERBEROS */ @@ -598,7 +690,7 @@ } if (child == 0) { - mode (1); + mode (1); if (reader (smask) == 0) { /* If the reader () return 0, the socket to the server returned an @@ -635,6 +727,24 @@ on its end of the network connection. This should cause the server to log you out on the remote system. */ msg ("closed connection."); + +#ifdef SHISHI + if (use_kerberos) + { + shishi_done (handle); +#ifdef ENCRYPTION + if (doencrypt) + { + shishi_key_done (key); + shishi_crypto_close (iv1.ctx); + shishi_crypto_close (iv2.ctx); + free (iv1.iv); + free (iv2.iv); + } +#endif + } +#endif + done (0); } @@ -783,6 +893,10 @@ if (doencrypt) des_write (rem, (char *)&escapechar, 1); else +#elif defined(SHISHI) + if (doencrypt) + writeenc (handle, rem, (char *)&escapechar, 1, &wlen, &iv2, key, 2); + else #endif #endif write (rem, &escapechar, 1); @@ -798,6 +912,16 @@ break; } } else +#elif defined(SHISHI) + if (doencrypt) + { + writeenc (handle, rem, &c, 1, &wlen, &iv2, key, 2); + if (wlen == 0) + { + msg ("line gone"); + break; + } + } else #endif #endif if (write (rem, &c, 1) == 0) @@ -886,6 +1010,10 @@ if(doencrypt) des_write (rem, obuf, sizeof obuf); else +#elif defined(SHISHI) + if(doencrypt) + writeenc (handle, rem, obuf, sizeof obuf, &wlen, &iv2, key, 2); + else #endif #endif write (rem, obuf, sizeof obuf); @@ -902,16 +1030,26 @@ int rcvcnt, rcvstate; char rcvbuf[8 * 1024]; +#if defined(SHISHI) +void +oob (char mark) +{ + int signo; +#else void oob (int signo) { + char mark; +#endif struct termios tt; int atmark, n, out, rcvd; - char waste[BUFSIZ], mark; + char waste[BUFSIZ]; (void)signo; out = O_RDWR; rcvd = 0; + +#ifndef SHISHI while (recv (rem, &mark, 1, MSG_OOB) < 0) { switch (errno) @@ -940,6 +1078,7 @@ return; } } +#endif if (mark & TIOCPKT_WINDOW) { /* Let server know about window size changes */ @@ -1016,17 +1155,26 @@ setsig (SIGTTOU, SIG_IGN); setsig (SIGURG, oob); - + ppid = getppid (); fcntl (rem, F_SETOWN, pid); setjmp (rcvtop); sigprocmask (SIG_SETMASK, smask, (sigset_t *) 0); bufp = rcvbuf; + for (;;) { +#ifdef SHISHI + if ((rcvcnt >= 5) && (bufp[0] == '\377') && (bufp[1] == '\377')) + if ((bufp[2] == 'o') && (bufp[3] == 'o')) + { + oob (bufp[4]); + bufp += 5; + } +#endif while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { - rcvstate = WRITING; + rcvstate = WRITING; n = write (STDOUT_FILENO, bufp, remaining); if (n < 0) { @@ -1045,6 +1193,10 @@ if (doencrypt) rcvcnt = des_read (rem, rcvbuf, sizeof rcvbuf); else +#elif defined(SHISHI) + if (doencrypt) + readenc (handle, rem, rcvbuf, &rcvcnt, &iv1, key, 2); + else #endif #endif rcvcnt = read (rem, rcvbuf, sizeof rcvbuf); @@ -1058,9 +1210,7 @@ return -1; } } -} - -void +}void mode (int f) { struct termios tt; @@ -1114,7 +1264,7 @@ fprintf (stderr, "rlogin: %s\r\n", str); } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) /* VARARGS */ void #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ @@ -1146,7 +1296,7 @@ { fprintf (stderr, "Usage: rlogin [ -%s]%s[-e char] [ -l username ] [username@]host\n", -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) # ifdef ENCRYPTION "8EKx", " [-k realm] " # else @@ -1174,7 +1324,7 @@ which is ``~'' by default"); puts ("\ -l, --user USER run as USER on the remote system"); -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) puts ("\ -K, --kerberos turns off all Kerberos authentication"); puts ("\ diff --exclude CVS -ur inetutils/rlogind/rlogind.c feg-inetutils/rlogind/rlogind.c --- inetutils/rlogind/rlogind.c 2003-04-05 19:03:39.000000000 +0200 +++ feg-inetutils/rlogind/rlogind.c 2004-05-24 22:50:06.000000000 +0200 @@ -101,21 +101,28 @@ #define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL) #endif +#define AUTH_KERBEROS_SHISHI 1 #define AUTH_KERBEROS_4 4 #define AUTH_KERBEROS_5 5 -#ifdef KERBEROS -# define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" +#if defined(KERBEROS) || defined(SHISHI) # ifdef KRB4 +# define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" # include # include # define kerberos_error_string(c) krb_err_txt[c] # define AUTH_KERBEROS_DEFAULT AUTH_KERBEROS_4 # elif defined(KRB5) +# define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" # include # include # define kerberos_error_string(c) error_message (c) # define AUTH_KERBEROS_DEFAULT AUTH_KERBEROS_5 +# elif defined(SHISHI) +# define SECURE_MESSAGE "This rlogin session is using encryption for all transmissions.\r\n" +# include +# include "shishi_def.h" +# define AUTH_KERBEROS_DEFAULT AUTH_KERBEROS_SHISHI # endif #endif /* KERBEROS */ @@ -130,6 +137,7 @@ extern int __check_rhosts_file; +#ifndef SHISHI struct auth_data { struct sockaddr_in from; @@ -148,6 +156,7 @@ #endif #endif }; +#endif static const char *short_options = "aD::d::hk::L:lnp:orxV"; static struct option long_options[] = @@ -171,7 +180,7 @@ int allow_root = 0; int verify_hostname = 0; int keepalive = 1; -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) int kerberos = 0; #ifdef ENCRYPTION int encrypt_io = 0; @@ -199,7 +208,7 @@ int do_rlogin __P ((int infd, struct auth_data *ap)); int do_krb_login __P ((int infd, struct auth_data *ap, const char **msg)); void getstr __P ((int infd, char **ptr, const char *prefix)); -void protocol __P ((int f, int p)); +void protocol __P ((int f, int p, struct auth_data *ap)); int control __P ((int pty, char *cp, size_t n)); RETSIGTYPE cleanup __P ((int signo)); void fatal __P ((int f, const char *msg, int syserr)); @@ -220,26 +229,40 @@ #define MODE_INETD 0 #define MODE_DAEMON 1 -#if defined(KERBEROS) && defined(ENCRYPTION) +#if defined(KERBEROS) && defined (ENCRYPTION) # define ENCRYPT_IO encrypt_io # define IF_ENCRYPT(stmt) if (encrypt_io) stmt # define IF_NOT_ENCRYPT(stmt) if (!encrypt_io) stmt -# define ENC_READ(c, fd, buf, size) \ +# define ENC_READ(c, fd, buf, size, ap) \ if (encrypt_io) \ c = des_read(fd, buf, size); \ else \ c = read(fd, buf, size); -# define ENC_WRITE(c, fd, buf, size) \ +# define EN_WRITE(c, fd, buf, size, ap) \ if (encrypt_io) \ c = des_write(fd, buf, size); \ else \ c = write(fd, buf, size); +#elif defined(SHISHI) && defined (ENCRYPTION) +# define ENCRYPT_IO encrypt_io +# define IF_ENCRYPT(stmt) if (encrypt_io) stmt +# define IF_NOT_ENCRYPT(stmt) if (!encrypt_io) stmt +# define ENC_READ(c, fd, buf, size, ap) \ + if (encrypt_io) \ + readenc (ap->h, fd, buf, &c, &ap->iv1, ap->enckey, ap->protocol); \ + else \ + c = read(fd, buf, size); +# define ENC_WRITE(c, fd, buf, size, ap) \ + if (encrypt_io) \ + writeenc (ap->h, fd, buf, size, &c, &ap->iv2, ap->enckey, ap->protocol); \ + else \ + c = write(fd, buf, size); #else # define ENCRYPT_IO 0 # define IF_ENCRYPT(stmt) # define IF_NOT_ENCRYPT(stmt) stmt -# define ENC_READ(c, fd, buf, size) c = read (fd, buf, size) -# define ENC_WRITE(c, fd, buf, size) c = write (fd, buf, size) +# define ENC_READ(c, fd, buf, size, ap) c = read (fd, buf, size) +# define ENC_WRITE(c, fd, buf, size, ap) c = write (fd, buf, size) #endif int @@ -284,7 +307,7 @@ keepalive = 0; break; -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) case 'k': if (optarg) { @@ -339,7 +362,7 @@ if (!local_domain_name) { - char *p = localhost (); + char *p = (char *)localhost (); if (!p) { @@ -363,6 +386,7 @@ else exit (rlogind_mainloop (fileno (stdin), fileno (stdout))); + /* To pacify lint */ return 0; } @@ -470,6 +494,9 @@ struct hostent *hp; char *hostname; int authenticated = 0; +#ifdef SHISHI + int len, c; +#endif confirmed = 0; @@ -506,7 +533,7 @@ } } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (kerberos) { const char *err_msg; @@ -566,9 +593,12 @@ write (fd, "", 1); confirmed = 1; /* we sent the null! */ } - +#ifdef SHISHI + len = sizeof (SECURE_MESSAGE) - 1; + IF_ENCRYPT (writeenc (ap->h, fd, SECURE_MESSAGE, len, &c, &ap->iv2, ap->enckey, ap->protocol)); +#else IF_ENCRYPT (des_write (fd, SECURE_MESSAGE, sizeof (SECURE_MESSAGE) - 1)); - +#endif return authenticated; } @@ -728,9 +758,30 @@ ioctl (master, TIOCPKT, &true); netf = infd; /* Needed for cleanup() */ signal (SIGCHLD, cleanup); - protocol (infd, master); + protocol (infd, master, &auth_data); signal (SIGCHLD, SIG_IGN); cleanup (0); + +#ifdef SHISHI + if (kerberos) + { + int i; + + shishi_done (auth_data.h); +#ifdef ENCRYPTION + if (encrypt_io) + { + shishi_key_done (auth_data.enckey); + for (i = 0; i < 2; i++) + { + shishi_crypto_close (auth_data.ivtab[i]->ctx); + free (auth_data.ivtab[i]->iv); + } + } +#endif + } +#endif + return 0; } @@ -765,7 +816,7 @@ return rc; } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) int do_krb_login (int infd, struct auth_data *ap, const char **err_msg) { @@ -776,14 +827,24 @@ if (kerberos == AUTH_KERBEROS_5) rc = do_krb5_login (infd, ap, err_msg); else +#elif defined(SHISHI) + if (kerberos == AUTH_KERBEROS_SHISHI) + rc = do_shishi_login (infd, ap, err_msg); + else +#else + rc = do_krb4_login (infd, ap, err_msg); #endif - rc = do_krb4_login (infd, ap, err_msg); - + if (rc && !err_msg) +#if defined(SHISHI) + *err_msg = shishi_strerror (rc); +#else *err_msg = kerberos_error_string (rc); +#endif return rc; } +#ifdef KRB4 int do_krb4_login (int infd, struct auth_data *ap, const char **err_msg) { @@ -859,6 +920,7 @@ return 0; } +#endif #ifdef KRB5 int @@ -958,6 +1020,151 @@ } #endif + +#ifdef SHISHI +int +do_shishi_login (int infd, struct auth_data *ad, const char **err_msg) +{ + int rc; + int error = 0; + int keylen, keytype; + struct passwd *pwd = NULL; + int cksumtype, cksumlen = 30; + char cksum[30]; + char * compcksum; + size_t compcksumlen; + char cksumdata[100]; + struct sockaddr_in sock; + size_t socklen = sizeof (struct sockaddr_in); + +#ifdef ENCRYPTION + rc = get_auth (infd, &ad->h, &ad->ap, &ad->enckey, err_msg, &ad->protocol, + &cksumtype, cksum, &cksumlen); +#else + rc = get_auth (infd, &ad->h, &ad->ap, NULL, err_msg, &ad->protocol, + &cksumtype, cksum, &cksumlen); +#endif + if (rc != SHISHI_OK) + return rc; + +#ifdef ENCRYPTION + /* init IV */ + if (encrypt_io) + { + int i; + char *iv; + + ad->ivtab[0] = &ad->iv1; + ad->ivtab[1] = &ad->iv2; + + keytype = shishi_key_type (ad->enckey); + keylen = shishi_cipher_blocksize (keytype); + + for (i=0; i<2; i++) + { + ad->ivtab[i]->ivlen = keylen; + + switch (keytype) + { + case SHISHI_DES_CBC_CRC: + case SHISHI_DES_CBC_MD4: + case SHISHI_DES_CBC_MD5: + case SHISHI_DES_CBC_NONE: + case SHISHI_DES3_CBC_HMAC_SHA1_KD: + ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; + ad->ivtab[i]->iv = malloc (ad->ivtab[i]->ivlen); + memset (ad->ivtab[i]->iv, i, ad->ivtab[i]->ivlen); + ad->ivtab[i]->ctx = shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage, shishi_key_type (ad->enckey), + ad->ivtab[i]->iv, ad->ivtab[i]->ivlen); + break; + case SHISHI_ARCFOUR_HMAC: + case SHISHI_ARCFOUR_HMAC_EXP: + ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 6 - 4*i; + ad->ivtab[i]->ctx = shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage, shishi_key_type (ad->enckey), + NULL, 0); + break; + default : + ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 6 - 4*i; + ad->ivtab[i]->iv = malloc (ad->ivtab[i]->ivlen); + memset (ad->ivtab[i]->iv, 0, ad->ivtab[i]->ivlen); + if (ad->protocol == 2) + ad->ivtab[i]->ctx = shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage, shishi_key_type (ad->enckey), + ad->ivtab[i]->iv, ad->ivtab[i]->ivlen); + } + } + } +#endif + + getstr (infd, &ad->lusername, NULL); + getstr (infd, &ad->term, "TERM="); + getstr (infd, &ad->rusername, NULL); + + rc = read (infd, &error, sizeof (int)); + if ((rc != sizeof (int)) && rc) + { + free (pwd); + return 1; + } + + /* + getpwnam crash !!!! + + pwd = getpwnam (ad->lusername); + if (pwd == NULL) + { + *err_msg = "getpwnam failed"; + syslog (LOG_ERR, "getpwnam failed: %m"); + return 1; + } + + syslog (LOG_INFO | LOG_AUTH, + "%sKerberos V login from %s on %s\n", + (pwd->pw_uid == 0) ? "ROOT " : "", + ad->lusername, ad->hostname); + + */ + + free (pwd); + + syslog (LOG_INFO | LOG_AUTH, + "Kerberos V login from %s on %s\n", + ad->lusername, ad->hostname); + + /* verify checksum */ + + if (getsockname (infd, (struct sockaddr *)&sock, &socklen) < 0) + { + syslog (LOG_ERR, "Can't get sock name"); + fatal (infd, "Can't get sockname", 1); + } + + snprintf (cksumdata, 100, "%u:%s%s", ntohs(sock.sin_port), ad->term + 5, ad->lusername); + rc = shishi_checksum (ad->h, ad->enckey, 0, cksumtype, cksumdata, + strlen (cksumdata), &compcksum, &compcksumlen); + if ((rc != SHISHI_OK) || (compcksumlen != cksumlen) || (memcmp (compcksum, cksum, cksumlen) != 0)) + { + /* err_msg crash ? */ + /* *err_msg = "checksum verify failed"; */ + syslog (LOG_ERR, "checksum verify failed: %s", shishi_error (ad->h)); + free (compcksum); + return 1; + } + + free (compcksum); + + rc = shishi_authorized_p (ad->h, shishi_ap_tkt (ad->ap), ad->lusername); + if (!rc) + { + syslog (LOG_ERR, "User is not authorized to log in as: %s", ad->lusername); + shishi_ap_done (ad->ap); + return 1; + } + + shishi_ap_done (ad->ap); + + return SHISHI_OK; +} +#endif #endif #define BUFFER_SIZE 128 @@ -1018,9 +1225,12 @@ char magic[2] = {0377, 0377}; char oobdata[] = {TIOCPKT_WINDOW}; /* May be modified by protocol/control */ +#ifdef SHISHI +char oobdata_new[] = {0377, 0377, 'o', 'o', TIOCPKT_WINDOW}; +#endif void -protocol (int f, int p) +protocol (int f, int p, struct auth_data *ap) { char fibuf[1024], *pbp = NULL, *fbp = NULL; int pcc = 0, fcc = 0; @@ -1036,6 +1246,13 @@ * (our controlling tty is the master pty). */ signal (SIGTTOU, SIG_IGN); +#ifdef SHISHI + if (kerberos && (ap->protocol == 2)) + { + ENC_WRITE (n, f, oobdata_new, 5, ap); + } + else +#endif send (f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ if (f > p) nfd = f + 1; @@ -1107,7 +1324,7 @@ if (FD_ISSET (f, &ibits)) { - ENC_READ (fcc, f, fibuf, sizeof (fibuf)); + ENC_READ (fcc, f, fibuf, sizeof (fibuf), ap); if (fcc < 0 && errno == EWOULDBLOCK) fcc = 0; @@ -1115,7 +1332,7 @@ { register char *cp; int left; - + if (fcc <= 0) break; fbp = fibuf; @@ -1186,7 +1403,7 @@ if ((FD_ISSET (f, &obits)) && pcc > 0) { - ENC_WRITE (cc, f, pbp, pcc); + ENC_WRITE (cc, f, pbp, pcc, ap); if (cc < 0 && errno == EWOULDBLOCK) { @@ -1304,8 +1521,8 @@ " -l, --no-rhosts Ignore .rhosts file\n" " -L, --local-domain=NAME Set local domain name\n" " -n, --no-keepalive Do not set SO_KEEPALIVE\n" -#ifdef KERBEROS -" -k, --kerberos Use kerberos IV authentication\n" +#if defined(KERBEROS) || defined(SHISHI) +" -k, --kerberos Use kerberos IV/V authentication\n" #ifdef ENCRYPTION " -x, --encrypt Use DES encryption\n" #endif /* ENCRYPTION */ diff --exclude CVS -ur inetutils/rsh/rsh.c feg-inetutils/rsh/rsh.c --- inetutils/rsh/rsh.c 2003-04-05 18:58:47.000000000 +0200 +++ feg-inetutils/rsh/rsh.c 2004-05-24 22:50:06.000000000 +0200 @@ -70,16 +70,36 @@ # include #endif -#ifdef KERBEROS -#include -#include +#ifdef SHISHI +#define REALM_SZ 1040 +#endif +#if defined(KERBEROS) || defined(SHISHI) +int use_kerberos = 1, doencrypt; +# ifdef KERBEROS +# include +# include +char dest_realm_buf[REALM_SZ], *dest_realm = NULL; CREDENTIALS cred; Key_schedule schedule; -int use_kerberos = 1, doencrypt; -char dest_realm_buf[REALM_SZ], *dest_realm; extern char *krb_realmofhost(); + +# elif defined(SHISHI) +# include +# include "shishi_def.h" +char dest_realm_buf[REALM_SZ], *dest_realm = NULL; + +Shishi * h; +Shishi_key * enckey; +shishi_ivector iv1, iv2, iv3, iv4; +shishi_ivector * ivtab[4]; + +int keytype; +int keylen; +int rc; +int wlen; #endif +#endif /* KERBEROS */ /* * rsh - remote shell @@ -95,7 +115,7 @@ /* basename (argv[0]). NetBSD, linux, & gnu libc all define it. */ extern char *__progname; -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) #ifdef ENCRYPTION #define OPTIONS "8Kdek:l:nxVh" #else @@ -113,7 +133,7 @@ { "8-bit", no_argument, 0, '8' }, { "kerberos", no_argument, 0, 'K' }, { "no-input", no_argument, 0, 'n' }, -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) { "realm", required_argument, 0, 'k' }, { "encrypt", no_argument, 0, 'x' }, #endif @@ -128,7 +148,7 @@ fprintf (stream, "Usage: %s [-nd%s]%s[-l USER] [USER@]HOST [COMMAND [ARG...]]\n", __progname, -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) #ifdef ENCRYPTION "x", " [-k REALM] " #else @@ -160,7 +180,7 @@ which is ``~'' by default"); puts ("\ -l, --user USER run as USER on the remote system"); -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) puts ("\ -K, --kerberos turns off all Kerberos authentication"); puts ("\ @@ -250,12 +270,12 @@ break; case 'K': -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) use_kerberos = 0; #endif break; -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) case 'k': strncpy (dest_realm_buf, optarg, sizeof dest_realm_buf); dest_realm_buf [REALM_SZ - 1] = '\0'; @@ -265,7 +285,9 @@ # ifdef ENCRYPTION case 'x': doencrypt = 1; +#ifdef KERBEROS des_set_key (cred.session, schedule); +#endif break; # endif #endif @@ -329,11 +351,9 @@ if (*host == '\0') usage (); } - if (!user) - user = pw->pw_name; } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) #ifdef ENCRYPTION /* -x turns off -n */ if (doencrypt) @@ -355,13 +375,24 @@ doencrypt ? "ekshell" : "kshell"); } } +#elif defined(SHISHI) + if (use_kerberos) + { + sp = getservbyname ("kshell", "tcp"); + if (sp == NULL) + { + use_kerberos = 0; + warning ("can't get entry for %s/tcp service", + "kshell"); + } + } #endif if (sp == NULL) sp = getservbyname("shell", "tcp"); if (sp == NULL) errx (1, "shell/tcp: unknown service"); -#ifdef KERBEROS +#if defined (KERBEROS) || defined(SHISHI) try_connect: if (use_kerberos) { @@ -372,19 +403,86 @@ if (hp != NULL && !(host = strdup (hp->h_name))) err (1, NULL); +#if defined (KERBEROS) rem = KSUCCESS; errno = 0; if (dest_realm == NULL) dest_realm = krb_realmofhost (host); +#elif defined (SHISHI) + rem = SHISHI_OK; + errno = 0; +#endif #ifdef ENCRYPTION if (doencrypt) - rem = krcmd_mutual (&host, sp->s_port, user, args, - &rfd2, dest_realm, &cred, schedule); +#if defined(SHISHI) + { + int i; + char * term; + + term = (char *)xmalloc (strlen(args)+4); + strcpy (term, "-x "); + strcat (term, args); + + rem = krcmd_mutual (&h, &host, sp->s_port, &user, term, &rfd2, + dest_realm, &enckey); + if (rem > 0) + { + keytype = shishi_key_type (enckey); + keylen = shishi_cipher_blocksize (keytype); + + ivtab[0] = &iv1; + ivtab[1] = &iv2; + ivtab[2] = &iv3; + ivtab[3] = &iv4; + + for (i=0; i<4; i++) + { + ivtab[i]->ivlen = keylen; + + switch (keytype) + { + case SHISHI_DES_CBC_CRC: + case SHISHI_DES_CBC_MD4: + case SHISHI_DES_CBC_MD5: + case SHISHI_DES_CBC_NONE: + case SHISHI_DES3_CBC_HMAC_SHA1_KD: + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; + ivtab[i]->iv = malloc (ivtab[i]->ivlen); + memset (ivtab[i]->iv, 2*i + 1*(i<2) - 4*(i>=2), ivtab[i]->ivlen); + ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), + ivtab[i]->iv, ivtab[i]->ivlen); + break; + case SHISHI_ARCFOUR_HMAC: + case SHISHI_ARCFOUR_HMAC_EXP: + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4*i; + ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), + NULL, 0); + break; + default : + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4*i; + ivtab[i]->iv = malloc (ivtab[i]->ivlen); + memset (ivtab[i]->iv, 0, ivtab[i]->ivlen); + ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), + ivtab[i]->iv, ivtab[i]->ivlen); + } + } + } + free (term); + } + else +#else + rem = krcmd_mutual (&host, sp->s_port, user, args, &rfd2, + dest_realm, &cred, schedule); else #endif - rem = krcmd (&host, sp->s_port, user, args, &rfd2, - dest_realm); +#endif + rem = krcmd ( +#if defined (SHISHI) + &h, &host, sp->s_port, &user, args, &rfd2, dest_realm); +#else + &host, sp->s_port, user, args, &rfd2, dest_realm); +#endif if (rem < 0) { use_kerberos = 0; @@ -400,11 +498,15 @@ } else { + if (!user) + user = pw->pw_name; if (doencrypt) errx (1, "the -x flag requires Kerberos authentication"); rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2); } #else + if (!user) + user = pw->pw_name; rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2); #endif @@ -451,7 +553,7 @@ err (1, "fork"); } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) #ifdef ENCRYPTION if (!doencrypt) #endif @@ -464,6 +566,27 @@ talk (nflag, &osigs, pid, rem); + +#ifdef SHISHI + if (use_kerberos) + { + int i; + + shishi_done (h); +#ifdef ENCRYPTION + if (doencrypt) + { + shishi_key_done (enckey); + for (i = 0; i < 4; i++) + { + shishi_crypto_close (ivtab[i]->ctx); + free (ivtab[i]->iv); + } + } +#endif + } +#endif + if (!nflag) kill (pid, SIGKILL); return 0; @@ -497,11 +620,15 @@ } if (!FD_ISSET (rem, &rembits)) goto rewrite; -#ifdef KERBEROS #ifdef ENCRYPTION +#ifdef KERBEROS if (doencrypt) wc = des_write (rem, bp, cc); - else + else +#elif defined(SHISHI) + if (doencrypt) + writeenc (h, rem, bp, cc, &wc, &iv3, enckey, 2); + else #endif #endif wc = write (rem, bp, cc); @@ -550,6 +677,10 @@ cc = des_read (rfd2, buf, sizeof buf); else #endif +#elif defined(SHISHI) && defined(ENCRYPTION) + if (doencrypt) + readenc (h, rfd2, buf, &cc, &iv2, enckey, 2); + else #endif cc = read (rfd2, buf, sizeof buf); if (cc <= 0) @@ -569,6 +700,10 @@ cc = des_read (rem, buf, sizeof buf); else #endif +#elif defined(SHISHI) && defined(ENCRYPTION) + if (doencrypt) + readenc (h, rem, buf, &cc, &iv1, enckey, 2); + else #endif cc = read (rem, buf, sizeof buf); if (cc <= 0) @@ -586,6 +721,7 @@ sendsig (int sig) { char signo; + int n; signo = sig; #ifdef KERBEROS @@ -594,11 +730,16 @@ des_write (rfd2, &signo, 1); else #endif +#elif defined(SHISHI) && defined (ENCRYPTION) + if (doencrypt) + writeenc (h, rfd2, &signo, 1, &n, &iv4, enckey, 2); + else #endif + write (rfd2, &signo, 1); } -#ifdef KERBEROS +#if defined (KERBEROS) || defined(SHISHI) /* VARARGS */ void #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ diff --exclude CVS -ur inetutils/rshd/rshd.c feg-inetutils/rshd/rshd.c --- inetutils/rshd/rshd.c 2002-09-09 11:31:55.000000000 +0200 +++ feg-inetutils/rshd/rshd.c 2004-05-24 22:50:06.000000000 +0200 @@ -111,16 +111,27 @@ void usage __P ((void)); void help __P ((void)); -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) +#ifdef KERBEROS # include # include +Key_schedule schedule; +char authbuf[sizeof(AUTH_DAT)]; +char tickbuf[sizeof(KTEXT_ST)]; +#elif defined(SHISHI) +# include +# include "shishi_def.h" +Shishi * h; +Shishi_ap * ap; +Shishi_key * enckey; +shishi_ivector iv1, iv2, iv3, iv4; +shishi_ivector *ivtab[4]; +int protocol; +#endif # define VERSION_SIZE 9 # define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n" # define OPTIONS "alnkvxLVh" -char authbuf[sizeof(AUTH_DAT)]; -char tickbuf[sizeof(KTEXT_ST)]; int doencrypt, use_kerberos, vacuous; -Key_schedule schedule; #else # define OPTIONS "alnLVh" #endif @@ -167,7 +178,7 @@ keepalive = 0; /* don't enable SO_KEEPALIVE */ break; -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) case 'k': use_kerberos = 1; break; @@ -211,7 +222,7 @@ exit (1); } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (use_kerberos && vacuous) { syslog (LOG_ERR, "only one of -k and -v allowed"); @@ -293,6 +304,13 @@ fd_set wready, writeto; fromaddr = *fromp; +#elif defined SHISHI + int n; + int pv1[2], pv2[2]; + fd_set wready, writeto; + int keytype, keylen; + int cksumtype, cksumlen = 30; + char cksum[30]; #endif signal(SIGINT, SIG_DFL); @@ -353,7 +371,7 @@ /* Need host byte ordered port# to compare */ fromp->sin_port = ntohs((u_short)fromp->sin_port); /* Verify that the client's address was bound to a reserved port */ -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (!use_kerberos) #endif if (fromp->sin_port >= IPPORT_RESERVED @@ -406,7 +424,7 @@ syslog (LOG_ERR, "can't get stderr port: %m"); exit (1); } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (!use_kerberos) #endif if (port >= IPPORT_RESERVED || port < IPPORT_RESERVED/2) @@ -419,6 +437,8 @@ * client's, just change the port# to the one specified * by the clent as the secondary port. */ + syslog (LOG_ERR, "2nd port not reserved %d\n", port); + fromp->sin_port = htons (port); if (connect (s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { @@ -427,7 +447,7 @@ } } -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (vacuous) { error ("rshd: remote host requires Kerberos authentication\n"); @@ -458,7 +478,7 @@ * address corresponds to the name. */ hostname = strdup (hp->h_name); -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (!use_kerberos) #endif if (check_all || local_domain (hp->h_name)) @@ -544,13 +564,134 @@ } } else +#elif defined (SHISHI) + if (use_kerberos) + { + int rc; + char * err_msg = NULL; + + rc = get_auth (STDIN_FILENO, &h, &ap, &enckey, &err_msg, &protocol, + &cksumtype, cksum, &cksumlen); + if (rc != SHISHI_OK) + { + error ("Kerberos authentication failure: %s\n", err_msg); + free (err_msg); + exit (1); + } + } + else #endif - remuser = getstr ("remuser"); + remuser = getstr ("remuser"); /* Read three strings from the client. */ locuser = getstr ("locuser"); cmdbuf = getstr ("command"); +#ifdef SHISHI + { + int error; + int rc; + char * compcksum; + size_t compcksumlen; + char cksumdata[100]; + struct sockaddr_in sock; + size_t socklen; + +#ifdef ENCRYPTION + if (strlen (cmdbuf) >= 3) + if (!strncmp (cmdbuf, "-x ", 3)) + { + doencrypt = 1; + int i; + + ivtab[0] = &iv1; + ivtab[1] = &iv2; + ivtab[2] = &iv3; + ivtab[3] = &iv4; + + keytype = shishi_key_type (enckey); + keylen = shishi_cipher_blocksize (keytype); + + for (i=0; i<4; i++) + { + ivtab[i]->ivlen = keylen; + + switch (keytype) + { + case SHISHI_DES_CBC_CRC: + case SHISHI_DES_CBC_MD4: + case SHISHI_DES_CBC_MD5: + case SHISHI_DES_CBC_NONE: + case SHISHI_DES3_CBC_HMAC_SHA1_KD: + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; + ivtab[i]->iv = malloc (ivtab[i]->ivlen); + memset (ivtab[i]->iv, 2*i -3*(i>=2), ivtab[i]->ivlen); + ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), + ivtab[i]->iv, ivtab[i]->ivlen); + break; + case SHISHI_ARCFOUR_HMAC: + case SHISHI_ARCFOUR_HMAC_EXP: + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 4*(i<2) + 2 + 2*(i%2); + ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), + NULL, 0); + break; + default : + ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 4*(i<2) + 2 + 2*(i%2); + ivtab[i]->iv = malloc (ivtab[i]->ivlen); + memset (ivtab[i]->iv, 0, ivtab[i]->ivlen); + if (protocol == 2) + ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), + ivtab[i]->iv, ivtab[i]->ivlen); + } + } + + } +#endif + + remuser = getstr ("remuser"); + rc = read (STDIN_FILENO, &error, sizeof (int)); + if ((rc != sizeof (int)) && rc) + { + //error ("Kerberos authentication failure: %s\n", err_msg); + exit (1); + } + + /* verify checksum */ + + /* Doesn't give socket port ? + if (getsockname (STDIN_FILENO, (struct sockaddr *)&sock, &socklen) < 0) + { + syslog (LOG_ERR, "Can't get sock name"); + exit (1); + } + */ + snprintf (cksumdata, 100, "544:%s%s", /*ntohs(sock.sin_port),*/ cmdbuf, locuser); + rc = shishi_checksum (h, enckey, 0, cksumtype, cksumdata, + strlen (cksumdata), &compcksum, &compcksumlen); + if ((rc != SHISHI_OK) || (compcksumlen != cksumlen) || (memcmp (compcksum, cksum, cksumlen) != 0)) + { + /* err_msg crash ? */ + /* *err_msg = "checksum verify failed"; */ + syslog (LOG_ERR, "checksum verify failed: %s", shishi_error (h)); + free (compcksum); + exit (1); + } + + rc = shishi_authorized_p (h, shishi_ap_tkt (ap), locuser); + if (!rc) + { + syslog (LOG_ERR, "User is not authorized to log in as: %s", locuser); + shishi_ap_done (ap); + exit (1); + } + + free (compcksum); + + shishi_ap_done (ap); + + } +#endif + /* Look up locuser in the passerd file. The locuser has\* to be a * valid account on this system. */ @@ -580,6 +721,21 @@ } } else +#elif defined(SHISHI) + if (use_kerberos) + {/* + if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') + { + if (kuserok (kdata, locuser) != 0) + { + syslog (LOG_INFO|LOG_AUTH, "Kerberos rsh denied to %s.%s@%s", + kdata->pname, kdata->pinst, kdata->prealm); + error ("Permission denied.\n"); + exit (1); + } + }*/ + } + else #endif if (errorstr || pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && (iruserok (fromp->sin_addr.s_addr, pwd->pw_uid == 0, @@ -635,7 +791,7 @@ exit (1); } #ifdef ENCRYPTION -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) { if (pipe (pv1) < 0) @@ -665,7 +821,7 @@ * signal. */ #ifdef ENCRYPTION -#ifdef KERBEROS +#if defined(KERBEROS) if (doencrypt) { static char msg[] = SECURE_MESSAGE; @@ -674,6 +830,13 @@ des_write (s, msg, sizeof(msg) - 1); } else +#elif defined(SHISHI) + if (doencrypt) + { + close (pv1[1]); + close (pv2[1]); + } + else #endif #endif { @@ -694,7 +857,7 @@ else nfd = s; #ifdef ENCRYPTION -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) { FD_ZERO (&writeto); @@ -714,10 +877,14 @@ { ready = readfrom; #ifdef ENCRYPTION -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) { - wready = writeto; +#ifdef SHISHI + wready = readfrom; +#else + wready = writeto; +#endif if (select (nfd, &ready, &wready, (fd_set *) 0, (struct timeval *) 0) < 0) break; @@ -737,6 +904,10 @@ if (doencrypt) ret = des_read (s, &sig, 1); else +#elif defined(SHISHI) + if (doencrypt) + readenc (h, s, &sig, &ret, &iv2, enckey, protocol); + else #endif #endif ret = read (s, &sig, 1); @@ -761,13 +932,17 @@ if (doencrypt) des_write (s, buf, cc); else +#elif defined(SHISHI) + if (doencrypt) + writeenc (h, s, buf, cc, &n, &iv4, enckey, protocol); + else #endif #endif write (s, buf, cc); } } #ifdef ENCRYPTION -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (doencrypt && FD_ISSET(pv1[0], &ready)) { errno = 0; @@ -778,13 +953,21 @@ FD_CLR (pv1[0], &readfrom); } else +#ifdef SHISHI + writeenc (h, STDOUT_FILENO, buf, cc, &n, &iv3, enckey, protocol); +#else des_write (STDOUT_FILENO, buf, cc); +#endif } if (doencrypt && FD_ISSET(pv2[0], &wready)) { errno = 0; +#ifdef SHISHI + readenc (h, STDIN_FILENO, buf, &cc, &iv1, enckey, protocol); +#else cc = des_read (STDIN_FILENO, buf, sizeof buf); +#endif if (cc <= 0) { shutdown (pv2[0], 1+1); @@ -797,7 +980,7 @@ #endif } while (FD_ISSET (s, &readfrom) || #ifdef ENCRYPTION -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) (doencrypt && FD_ISSET (pv1[0], &readfrom)) || #endif #endif @@ -819,7 +1002,7 @@ close(s); /* control process handles this fd */ close (pv[0]); /* close read end of pipe */ #ifdef ENCRYPTION -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) if (doencrypt) { close (pv1[0]); close (pv2[0]); @@ -830,6 +1013,28 @@ } #endif #endif + +#if defined(SHISHI) + if (use_kerberos) + { + int i; + + shishi_done (h); +#ifdef ENCRYPTION + if (doencrypt) + { + shishi_key_done (enckey); + for (i = 0; i < 4; i++) + { + shishi_crypto_close (ivtab[i]->ctx); + free (ivtab[i]->iv); + } + } +#endif + } + +#endif + dup2 (pv[1], STDERR_FILENO); /* stderr of shell has to go pipe to control process */ close (pv[1]); @@ -891,7 +1096,12 @@ syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", remuser, hostname, locuser, cmdbuf); } - execl (pwd->pw_shell, cp, "-c", cmdbuf, 0); +#ifdef SHISHI + if (doencrypt) + execl (pwd->pw_shell, cp, "-c", cmdbuf+3, 0); + else +#endif + execl (pwd->pw_shell, cp, "-c", cmdbuf, 0); perror (pwd->pw_shell); exit (1); } @@ -1042,7 +1252,7 @@ -L, --log-session Set local domain name"); puts ("\ -n, --no-keepalive Do not set SO_KEEPALIVE"); -#ifdef KERBEROS +#if defined(KERBEROS) || defined(SHISHI) puts ("\ -k, --kerberos Use kerberos IV authentication"); #ifdef ENCRYPTION