1.2-beta4 pullup
authorKen Raeburn <raeburn@mit.edu>
Fri, 30 Jun 2000 00:16:21 +0000 (00:16 +0000)
committerKen Raeburn <raeburn@mit.edu>
Fri, 30 Jun 2000 00:16:21 +0000 (00:16 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@12470 dc483132-0cff-0310-8789-dd5450dbe970

39 files changed:
src/appl/bsd/ChangeLog
src/appl/bsd/Makefile.in
src/appl/bsd/configure.in
src/appl/bsd/defines.h
src/appl/bsd/kcmd.c
src/appl/bsd/krcp.c
src/appl/bsd/krlogin.c
src/appl/bsd/krlogind.c
src/appl/bsd/krsh.c
src/appl/bsd/krshd.c
src/appl/bsd/login.c
src/appl/bsd/v4rcp.c
src/appl/gssftp/ChangeLog
src/appl/gssftp/configure.in
src/appl/gssftp/ftp/ChangeLog
src/appl/gssftp/ftp/cmds.c
src/appl/gssftp/ftp/domacro.c
src/appl/gssftp/ftp/ftp.c
src/appl/gssftp/ftp/glob.c
src/appl/gssftp/ftp/main.c
src/appl/gssftp/ftp/secure.c
src/appl/gssftp/ftpd/ChangeLog
src/appl/gssftp/ftpd/ftpcmd.y
src/appl/gssftp/ftpd/ftpd.c
src/appl/telnet/libtelnet/ChangeLog
src/appl/telnet/libtelnet/gettytab.c
src/appl/telnet/libtelnet/kerberos.c
src/appl/telnet/libtelnet/kerberos5.c
src/appl/telnet/libtelnet/spx.c
src/appl/telnet/telnet/ChangeLog
src/appl/telnet/telnet/commands.c
src/appl/telnet/telnet/externs.h
src/appl/telnet/telnet/main.c
src/appl/telnet/telnet/tn3270.c
src/appl/telnet/telnet/utilities.c
src/appl/telnet/telnetd/ChangeLog
src/appl/telnet/telnetd/sys_term.c
src/appl/telnet/telnetd/telnetd-ktd.c
src/appl/telnet/telnetd/telnetd.c

index 9c87d9816f41eb9006b0f73afba1368d1dd0d999..0eac15d6b0b980f91771c77b74fa7bc4d1c99210 100644 (file)
@@ -1,3 +1,144 @@
+2000-06-19  Tom Yu  <tlyu@mit.edu>
+
+       * krshd.c (recvauth): Call krb5_recvauth_version() rather than
+       calling krb5_recvauth() with arguments intended for
+       krb5_recvauth_version().
+
+       * kcmd.c: Conditionalize krb_sendauth prototype based on sense of
+       KRB5_KRB4_COMPAT.
+
+2000-06-15  Tom Yu  <tlyu@mit.edu>
+
+       * login.c (try_convert524): Add use_ccache argument.  Handle case
+       where we have gotten v5 creds via password being entered and don't
+       crash in that case, since previous code was assuming that v5 creds
+       were always being provided.  Adapted from patch by Bob Basch.
+
+2000-06-10  Ken Raeburn  <raeburn@mit.edu>
+
+       * krcp.c (main): Fix logic again, this time in the "success"
+       case.  If there's a problem retrieving the new-protocol subkey,
+       print a message and exit, don't fall back.
+       * krsh.c (main): Ditto; don't look at enctype to try to guess
+       protocol version.  Delete unused variable "similar".
+
+2000-06-09  Ken Raeburn  <raeburn@mit.edu>
+
+       * krlogin.c (main): Rework fallback logic.  Fall back to k4cmd
+       unless encryption and the new protocol were both requested.
+
+       * krsh.c (main): Rework fallback logic.  Fall back to k4cmd if new
+       protocol wasn't requested.
+
+       * krcp.c (main): Revert setting of AP_OPTS_MUTUAL_REQUIRED
+       unconditionally, which was added by mistake with last set of
+       patches.  If kcmd fails and the new protocol is requested, don't
+       fall back to v4.
+
+2000-05-31  Ken Raeburn  <raeburn@mit.edu>
+
+       * Makefile.in (kcmd.o, krcp.o, krlogin.o, krlogind.o, krsh.o,
+       krshd.o): Depend on defines.h.
+       * krlogind.c: Include defines.h.
+       * krcp.c: Ditto.
+
+       * defines.h (enum kcmd_proto): New type.
+       (rcmd_stream_read, rcmd_stream_write, getport,
+       rcmd_stream_init_krb5): Add prototypes.
+
+       * kcmd.c (use_ivecs): New variable.
+       (encivec_i, encivec_o): Each is now an array of two elements.
+       (input, output, twrite, krb5_write_message, krb5_net_read,
+       krb5_net_write, krb_sendauth): Add prototypes.
+       (kcmd): New argument PROTONUMP points to enum kcmd_proto.  If
+       value is KCMD_PROTOCOL_COMPAT_HACK, set it to KCMD_NEW_PROTOCOL or
+       KCMD_OLD_PROTOCOL depending on session key type.  Use subkeys for
+       new protocol.  Callers updated.
+       (normal_read, v5_des_read, v4_des_read, twrite, v5_des_write,
+       v4_des_write, rcmd_stream_write, rcmd_stream_read): Take
+       additional argument indicating whether the fd is for the secondary
+       channel; ignored except in some v5 cases.  Callers updated.
+       (rcmd_stream_init_krb5): New argument, kcmd protocol version.  Set
+       up ivecs for secondary channel in each direction with values 0x2
+       ior primary channel value.  Callers updated.
+       (v5_des_read, v5_des_write): For new protocol, plaintext now has
+       its length prepended but not counted.
+
+       * krcp.c (main): Set kcmd protocol version based on command line,
+       not on encryption type.  Default to COMPAT_HACK.
+       * krsh.c (main): Ditto.
+       * krlogin.c (main): Ditto.
+
+       * krlogind.c (recvauth): Use new krb5_compat_recvauth_version
+       routine.  Determine client's kcmd protocol version and initialize
+       based on it.
+       * krshd.c (recvauth): Ditto.
+
+2000-05-19  Nalin Dahyabhai  <nalin@redhat.com>
+           Ken Raeburn  <raeburn@mit.edu>
+
+       * krcp.c (sink): bail if the target directory/file name is too long
+       * krlogind.c (recvauth, krb4 compat): truncate user name if the
+       principal's root would be too long to be valid
+       * v4rcp.c (sink): bail if the target directory/file name is too long
+
+2000-05-18  Tom Yu  <tlyu@mit.edu>
+
+       * krshd.c: Shuffle inclusion of defines.h so that some krb5
+       structures are declared prior to the kcmd() prototype.
+
+2000-05-16  Ken Raeburn  <raeburn@mit.edu>
+
+       * defines.h (kcmd): Add prototype.
+       * krcp.c (main): Add extra arg to a kcmd call I missed yesterday.
+
+2000-05-15  Ken Raeburn  <raeburn@mit.edu>
+
+       * krcp.c (main): Fix some conditionalizations to make proper
+       indentation easier.
+
+       * kcmd.c (encivec_i, encivec_o): New variables replace old single
+       variable encivec.
+       (rcmd_stream_init_krb5): New argument am_client, used to
+       initialize both ivec values.
+       * krcp.c (main, answer_auth): Pass new argument.
+       * krlogin.c (main): Ditto.
+       * krlogind.c (recvauth): Ditto.
+       * krsh.c (main): Ditto.
+       * krshd.c (recvauth): Ditto.
+
+       * defines.h (OPTS_FORWARD_CREDS, OPTS_FORWARDABLE_CREDS): Change
+       numbers so they don't conflict with AP_OPTS_USE_SUBKEY.
+       * kcmd.c (kcmd): New argument authconp, used to return the auth
+       context to the caller if desired.
+       * krlogin.c (auth_context): New variable.
+       (main): Request a subkey from sendauth.  Get the auth context from
+       kcmd so we can retrieve the subkey.  If non-DES session key is
+       being used, pass the subkey to rcmd_stream_init_krb5 instead of
+       the session key; fail if no subkey is found and encryption is
+       required.
+       * krlogind.c (recvauth): If a non-DES session key is being used,
+       pass the client-provided subkey to rcmd_stream_init_krb5.
+       * krcp.c (main): Set up and use subkey as above.
+       * krsh.c (main): Set up and use subkey as above.
+       * krshd.c (recvauth): Accept and use subkey as above.
+
+2000-05-08  Ken Raeburn  <raeburn@mit.edu>
+
+       * v4rcp.c (main, case 'k'): Make sure krb_realm is
+       null-terminated.
+
+2000-04-27  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * krlogin.c (main): Don't overflow buffer "term".
+       * krshd.c (doit): Don't overflow buffer "cmdbuf".
+       * login.c (afs_login): Don't overflow buffer "aklog_path".
+
+2000-03-24  Ken Raeburn  <raeburn@mit.edu>
+
+       * configure.in: Check for alpha*-dec-osf* instead of
+       alpha-dec-osf*.
+
 2000-03-15  Ken Raeburn  <raeburn@mit.edu>
            Mark D. Roth  <roth@uiuc.edu>
 
index eee13ca90f56e378cb1d3fe92fcabf21aa2bab6d..93a6cba2e998706ee287fbfe3a68e9c43bd7b866 100644 (file)
@@ -90,3 +90,4 @@ install::
 
 getdtablesize.o: $(srcdir)/getdtablesize.c
 
+kcmd.o krcp.o krlogin.o krlogind.o krsh.o krshd.o : defines.h
index 6d31f489c01f886b183b63a4558de17013cc4d33..cf6547679ebf3b526f48caaaeaa44a9d815e4a47 100644 (file)
@@ -25,11 +25,12 @@ dnl Make our operating system-specific security checks and definitions for
 dnl login.
 dnl
 case $krb5_cv_host in
-*-*-aix3*) # AIX has streams include files but not streams TTY
-# Moreover, strops.h trashes sys/ioctl.h
-krb5_cv_has_streams=no
-;;
-alpha-dec-osf*)
+*-*-aix3*)
+       # AIX has streams include files but not streams TTY
+       # Moreover, strops.h trashes sys/ioctl.h
+       krb5_cv_has_streams=no
+       ;;
+alpha*-dec-osf*)
        AC_CHECK_LIB(security,setluid,
                AC_DEFINE(HAVE_SETLUID)
                LOGINLIBS="$LOGINLIBS -lsecurity"
index fd9c3e14c8ed00e0b1f2392db9d0a3ad9220b2c3..6365d2cbed6aee25589f9603e7c51d663c587ddc 100644 (file)
@@ -1,3 +1,43 @@
-#define OPTS_FORWARD_CREDS           0x00000002
-#define OPTS_FORWARDABLE_CREDS       0x00000001
+#define OPTS_FORWARD_CREDS           0x00000020
+#define OPTS_FORWARDABLE_CREDS       0x00000010
 #define RCMD_BUFSIZ    5120
+
+enum kcmd_proto {
+  /* Old protocol: DES encryption only.  No subkeys.  No protection
+     for cleartext length.  No ivec supplied.  OOB hacks used for
+     rlogin.  Checksum may be omitted at connection startup.  */
+  KCMD_OLD_PROTOCOL = 1,
+  /* New protocol: Any encryption scheme.  Client-generated subkey
+     required.  Prepend cleartext-length to cleartext data (but don't
+     include it in count).  Starting ivec defined, chained.  In-band
+     signalling.  Checksum required.  */
+  KCMD_NEW_PROTOCOL,
+  /* Hack: Get credentials, and use the old protocol iff the session
+     key type is single-DES.  */
+  KCMD_PROTOCOL_COMPAT_HACK,
+  /* Using Kerberos version 4.  */
+  KCMD_V4_PROTOCOL,
+  /* ??? */
+  KCMD_UNKNOWN_PROTOCOL
+};
+
+extern int kcmd (int *sock, char **ahost, int /* u_short */ rport,
+                char *locuser, char *remuser, char *cmd,
+                int *fd2p, char *service, char *realm,
+                krb5_creds **cred,
+                krb5_int32 *seqno, krb5_int32 *server_seqno,
+                struct sockaddr_in *laddr,
+                struct sockaddr_in *faddr,
+                krb5_auth_context *authconp,
+                krb5_flags authopts,
+                int anyport, int suppress_err,
+                enum kcmd_proto *protonum /* input and output */
+                );
+
+extern int rcmd_stream_read (int fd, char *buf, int len, int secondary);
+extern int rcmd_stream_write (int fd, char *buf, int len, int secondary);
+extern int getport (int *);
+
+extern void rcmd_stream_init_krb5 (krb5_keyblock *in_keyblock,
+                                  int encrypt_flag, int lencheck,
+                                  int am_client, enum kcmd_proto protonum);
index 0e68f88e7c0503967783e73befb61f003c4601cf..3e401ccedb243b6018e538b74f36c1ece0622b28 100644 (file)
@@ -117,14 +117,18 @@ static char des_inbuf[2*RCMD_BUFSIZ];      /* needs to be > largest read size */
 static char des_outpkt[2*RCMD_BUFSIZ+4]; /* needs to be > largest write size */
 static krb5_data desinbuf;
 static krb5_data desoutbuf;
-static krb5_data encivec;
+
+/* XXX Overloaded: use_ivecs!=0 -> new protocol, inband signalling, etc.  */
+static int use_ivecs;
+static krb5_data encivec_i[2], encivec_o[2];
+
 static krb5_keyblock *keyblock;                 /* key for encrypt/decrypt */
-static int (*input)();
-static int (*output)();
+static int (*input)(int, char *, int, int);
+static int (*output)(int, char *, int, int);
 static char storage[2*RCMD_BUFSIZ];     /* storage for the decryption */
 static int nstored = 0;
 static char *store_ptr = storage;
-static int twrite();
+static int twrite(int, char *, int, int);
 static int v5_des_read(), v5_des_write();
 #ifdef KRB5_KRB4_COMPAT
 static int v4_des_read(), v4_des_write();
@@ -133,8 +137,29 @@ static int right_justify;
 #endif
 static int do_lencheck;
 
+/* XXX: These should be internal to krb5 library, or declared in krb5.h.  */
+extern krb5_error_code krb5_write_message (krb5_context, krb5_pointer,
+                                          krb5_data *);
+extern int krb5_net_read (krb5_context, int , char *, int);
+extern int krb5_net_write (krb5_context, int , const char *, int);
+/* XXX: And these should be declared in krb.h, or private.  */
+#ifdef KRB5_KRB4_COMPAT
+extern int
+krb_sendauth(long options, int fd, KTEXT ticket,
+            char *service, char *inst, char *realm,
+            unsigned KRB4_32 checksum,
+            MSG_DAT *msg_data,
+            CREDENTIALS *cred,
+            Key_schedule schedule,
+            struct sockaddr_in *laddr,
+            struct sockaddr_in *faddr,
+            char *version);
+#endif
+
+int
 kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
-     cred, seqno, server_seqno, laddr, faddr, authopts, anyport, suppress_err)
+     cred, seqno, server_seqno, laddr, faddr, authconp, authopts, anyport,
+     suppress_err, protonump)
      int *sock;
      char **ahost;
      u_short rport;
@@ -142,15 +167,17 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
      int *fd2p;
      char *service;
      char *realm;
-     krb5_creds **cred;
+     krb5_creds **cred; /* output only */
      krb5_int32 *seqno;
      krb5_int32 *server_seqno;
      struct sockaddr_in *laddr, *faddr;
+     krb5_auth_context *authconp;
      krb5_flags authopts;
      int anyport;
      int suppress_err;         /* Don't print if authentication fails */
+     enum kcmd_proto *protonump;
 {
-    int i, s, timo = 1, pid;
+    int s, pid;
 #ifdef POSIX_SIGNALS
     sigset_t oldmask, urgmask;
 #else
@@ -164,7 +191,6 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     int rc;
     char *host_save;
     krb5_error_code status;
-    krb5_error *err_ret;
     krb5_ap_rep_enc_part *rep_ret;
     krb5_error *error = 0;
     int sin_len;
@@ -174,6 +200,8 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     krb5_auth_context auth_context = NULL;
     char *cksumbuf;
     krb5_data cksumdat;
+    char *kcmd_version;
+    enum kcmd_proto protonum = *protonump;
 
     if ((cksumbuf = malloc(strlen(cmd)+strlen(remuser)+64)) == 0 ) {
        fprintf(stderr, "Unable to allocate memory for checksum buffer.\n");
@@ -361,12 +389,35 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
                        KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))
        goto bad2;
 
-   /* call Kerberos library routine to obtain an authenticator,
+    if (protonum == KCMD_PROTOCOL_COMPAT_HACK) {
+       krb5_boolean is_des;
+       status = krb5_c_enctype_compare (bsd_context, ENCTYPE_DES_CBC_CRC,
+                                        ret_cred->keyblock.enctype, &is_des);
+       if (status)
+           goto bad2;
+       protonum = is_des ? KCMD_OLD_PROTOCOL : KCMD_NEW_PROTOCOL;
+    }
+
+    switch (protonum) {
+    case KCMD_NEW_PROTOCOL:
+       authopts |= AP_OPTS_USE_SUBKEY;
+       kcmd_version = "KCMDV0.2";
+       break;
+    case KCMD_OLD_PROTOCOL:
+       kcmd_version = "KCMDV0.1";
+       break;
+    default:
+       status = EINVAL;
+       goto bad2;
+    }
+
+    /* Call Kerberos library routine to obtain an authenticator,
        pass it over the socket to the server, and obtain mutual
-       authentication. */
+       authentication.  */
     status = krb5_sendauth(bsd_context, &auth_context, (krb5_pointer) &s,
-                           "KCMDV0.1", ret_cred->client, ret_cred->server,
-                          authopts, &cksumdat, ret_cred, 0,    &error, &rep_ret, NULL);
+                          kcmd_version, ret_cred->client, ret_cred->server,
+                          authopts, &cksumdat, ret_cred, 0,
+                          &error, &rep_ret, NULL);
     free(cksumbuf);
     if (status) {
        if (!suppress_err)
@@ -440,10 +491,13 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
     sigsetmask(oldmask);
 #endif /* POSIX_SIGNALS */
     *sock = s;
+    *protonump = protonum;
     
     /* pass back credentials if wanted */
     if (cred) krb5_copy_creds(bsd_context, ret_cred, cred);
     krb5_free_creds(bsd_context, ret_cred);
+    if (authconp)
+       *authconp = auth_context;
     
     return (0);
   bad2:
@@ -464,6 +518,7 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm,
 
 
 #ifdef KRB5_KRB4_COMPAT
+int
 k4cmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
       cred, schedule, msg_data, laddr, faddr, authopts, anyport)
      int *sock;
@@ -701,7 +756,7 @@ reread:
 #endif /* KRB5_KRB4_COMPAT */
 
 
-
+int
 getport(alport)
      int *alport;
 {
@@ -733,16 +788,25 @@ getport(alport)
     return -1;
 }
 
+static int
+normal_read (int fd, char *buf, int len, int secondary)
+{
+    return read (fd, buf, len);
+}
+
 void rcmd_stream_init_normal()
 {
-    input = read;
+    input = normal_read;
     output = twrite;
 }
 
-void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck)
+void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client,
+                          protonum)
      krb5_keyblock *in_keyblock;
      int encrypt_flag;
      int lencheck;
+     int am_client;
+     enum kcmd_proto protonum;
 {
     krb5_error_code status;
     size_t blocksize;
@@ -760,33 +824,35 @@ void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck)
     input = v5_des_read;
     output = v5_des_write;
 
-    if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
-                                       keyblock->enctype,
-                                       &similar)) {
-       /* XXX what do I do? */
-       abort();
-    }
-
-    if (similar) {
-       encivec.length = 0;
+    if (protonum == KCMD_OLD_PROTOCOL) {
+       use_ivecs = 0;
        return;
     }
 
+    use_ivecs = 1;
+
     if (status = krb5_c_block_size(bsd_context, keyblock->enctype,
                                   &blocksize)) {
        /* XXX what do I do? */
        abort();
     }
 
-    encivec.length = blocksize;
+    encivec_i[0].length = encivec_i[1].length = encivec_o[0].length
+       = encivec_o[1].length = blocksize;
 
-    if ((encivec.data = malloc(encivec.length)) == NULL) {
+    if ((encivec_i[0].data = malloc(encivec_i[0].length * 4)) == NULL) {
        /* XXX what do I do? */
        abort();
     }
+    encivec_i[1].data = encivec_i[0].data + encivec_i[0].length;
+    encivec_o[0].data = encivec_i[1].data + encivec_i[0].length;
+    encivec_o[1].data = encivec_o[0].data + encivec_i[0].length;
 
     /* is there a better way to initialize this? */
-    memset(encivec.data, '\0', blocksize);
+    memset(encivec_i[0].data, am_client, blocksize);
+    memset(encivec_o[0].data, 1 - am_client, blocksize);
+    memset(encivec_i[1].data, 2 | am_client, blocksize);
+    memset(encivec_o[1].data, 2 | (1 - am_client), blocksize);
 }
 
 #ifdef KRB5_KRB4_COMPAT
@@ -808,35 +874,39 @@ void rcmd_stream_init_krb4(session, encrypt_flag, lencheck, justify)
 }
 #endif
 
-int rcmd_stream_read(fd, buf, len)
+int rcmd_stream_read(fd, buf, len, sec)
      int fd;
      register char *buf;
      int len;
+     int sec;
 {
-    return (*input)(fd, buf, len);
+    return (*input)(fd, buf, len, sec);
 }
 
-int rcmd_stream_write(fd, buf, len)
+int rcmd_stream_write(fd, buf, len, sec)
      int fd;
      register char *buf;
      int len;
+     int sec;
 {
-    return (*output)(fd, buf, len);
+    return (*output)(fd, buf, len, sec);
 }
 
 /* Because of rcp lossage, translate fd 0 to 1 when writing. */
-static int twrite(fd, buf, len)
+static int twrite(fd, buf, len, secondary)
      int fd;
      char *buf;
      int len;
+     int secondary;
 {
     return write((fd == 0) ? 1 : fd, buf, len);
 }
 
-static int v5_des_read(fd, buf, len)
+static int v5_des_read(fd, buf, len, secondary)
      int fd;
      char *buf;
      int len;
+     int secondary;
 {
     int nreturned = 0;
     size_t net_len,rd_len;
@@ -879,7 +949,8 @@ static int v5_des_read(fd, buf, len)
     rd_len = (rd_len << 8) | c;
 
     if (ret = krb5_c_encrypt_length(bsd_context, keyblock->enctype,
-                                 rd_len, &net_len)) {
+                                   use_ivecs ? rd_len + 4 : rd_len,
+                                   &net_len)) {
        errno = ret;
        return(-1);
     }
@@ -902,8 +973,8 @@ static int v5_des_read(fd, buf, len)
     plain.data = storage;
 
     /* decrypt info */
-    if (krb5_c_decrypt(bsd_context, keyblock, KCMD_KEYUSAGE,
-                      encivec.length?&encivec:0,
+    if (ret = krb5_c_decrypt(bsd_context, keyblock, KCMD_KEYUSAGE,
+                      use_ivecs ? encivec_i + secondary : 0,
                       &cipher, &plain)) {
        /* probably out of sync */
        errno = EIO;
@@ -911,6 +982,19 @@ static int v5_des_read(fd, buf, len)
     }
     store_ptr = storage;
     nstored = rd_len;
+    if (use_ivecs) {
+       int rd_len2;
+       rd_len2 = storage[0] & 0xff;
+       rd_len2 <<= 8; rd_len2 |= storage[1] & 0xff;
+       rd_len2 <<= 8; rd_len2 |= storage[2] & 0xff;
+       rd_len2 <<= 8; rd_len2 |= storage[3] & 0xff;
+       if (rd_len2 != rd_len) {
+           /* cleartext length trashed? */
+           errno = EIO;
+           return -1;
+       }
+       store_ptr += 4;
+    }
     if (nstored > len) {
        memcpy(buf, store_ptr, len);
        nreturned += len;
@@ -927,23 +1011,39 @@ static int v5_des_read(fd, buf, len)
 
 
 
-static int v5_des_write(fd, buf, len)
+static int v5_des_write(fd, buf, len, secondary)
      int fd;
      char *buf;
      int len;
+     int secondary;
 {
-    unsigned char *len_buf = (unsigned char *) des_outpkt;
     krb5_data plain;
     krb5_enc_data cipher;
-
-    plain.data = buf;
-    plain.length = len;
+    char tmpbuf[2*RCMD_BUFSIZ+8];
+    unsigned char *len_buf = (unsigned char *) tmpbuf;
+
+    if (use_ivecs) {
+       unsigned char *lenbuf2 = (unsigned char *) tmpbuf;
+       if (len + 4 > sizeof(tmpbuf))
+           abort ();
+       lenbuf2[0] = (len & 0xff000000) >> 24;
+       lenbuf2[1] = (len & 0xff0000) >> 16;
+       lenbuf2[2] = (len & 0xff00) >> 8;
+       lenbuf2[3] = (len & 0xff);
+       memcpy (tmpbuf + 4, buf, len);
+
+       plain.data = tmpbuf;
+       plain.length = len + 4;
+    } else {
+       plain.data = buf;
+       plain.length = len;
+    }
 
     cipher.ciphertext.length = sizeof(des_outpkt)-4;
     cipher.ciphertext.data = desoutbuf.data;
 
     if (krb5_c_encrypt(bsd_context, keyblock, KCMD_KEYUSAGE,
-                      encivec.length?&encivec:0,
+                      use_ivecs ? encivec_o + secondary : 0,
                       &plain, &cipher)) {
        errno = EIO;
        return(-1);
@@ -951,6 +1051,7 @@ static int v5_des_write(fd, buf, len)
 
     desoutbuf.length = cipher.ciphertext.length;
 
+    len_buf = (unsigned char *) des_outpkt;
     len_buf[0] = (len & 0xff000000) >> 24;
     len_buf[1] = (len & 0xff0000) >> 16;
     len_buf[2] = (len & 0xff00) >> 8;
@@ -1032,11 +1133,11 @@ int len;
                errno = EIO;
                return(-1);
        }
-       (void) pcbc_encrypt(des_inbuf,
-                           storage,
+       (void) pcbc_encrypt((des_cblock *) des_inbuf,
+                           (des_cblock *) storage,
                            (net_len < 8) ? 8 : net_len,
                            v4_schedule,
-                           v4_session,
+                           &v4_session,
                            DECRYPT);
        /* 
         * when the cleartext block is < 8 bytes, it is "right-justified"
@@ -1092,11 +1193,11 @@ int len;
                /* this "right-justifies" the data in the buffer */
                (void) memcpy(garbage_buf + 8 - len, buf, len);
        }
-       (void) pcbc_encrypt((len < 8) ? garbage_buf : buf,
-                           des_outpkt+4,
+       (void) pcbc_encrypt((des_cblock *) ((len < 8) ? garbage_buf : buf),
+                           (des_cblock *) (des_outpkt+4),
                            (len < 8) ? 8 : len,
                            v4_schedule,
-                           v4_session,
+                           &v4_session,
                            ENCRYPT);
 
        /* tell the other end the real amount, but send an 8-byte padded
index 967014579f74ad41cbd821fb3d7c49b270ff078b..7292e72fefddc1464c054b7d38dfdf20a24e173a 100644 (file)
@@ -71,6 +71,8 @@ char copyright[] =
 #include <k5-util.h>
 #include <com_err.h>
 
+#include "defines.h"
+
 #define RCP_BUFSIZ 4096
      
 int sock;
@@ -131,7 +133,7 @@ void        error KRB5_STDARG_P((char *fmt, ...));
 void   error KRB5_STDARG_P((char *, va_list));
 #endif
 
-#define        ga()            (void) rcmd_stream_write(rem, "", 1)
+#define        ga()            (void) rcmd_stream_write(rem, "", 1, 0)
 
 int main(argc, argv)
      int argc;
@@ -153,6 +155,8 @@ int main(argc, argv)
     krb5_error_code status;    
     int euid;
     char **orig_argv = save_argv(argc, argv);
+    krb5_auth_context auth_context;
+    enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
 
     status = krb5_init_context(&bsd_context);
     if (status) {
@@ -224,6 +228,14 @@ int main(argc, argv)
            }
            strcpy(krb_config, *argv);  
            goto next_arg;
+         case 'P':
+           if (!strcmp (*argv, "O"))
+               kcmd_proto = KCMD_OLD_PROTOCOL;
+           else if (!strcmp (*argv, "N"))
+               kcmd_proto = KCMD_NEW_PROTOCOL;
+           else
+               usage ();
+           goto next_arg;
 #endif /* KERBEROS */
            /* The rest of these are not for users. */
          case 'd':
@@ -376,20 +388,22 @@ int main(argc, argv)
                      suser = pwd->pw_name;
                    else if (!okname(suser))
                      continue;
+                   (void) sprintf(buf,
 #if defined(hpux) || defined(__hpux)
-                   (void) sprintf(buf, "remsh %s -l %s -n %s %s '%s%s%s:%s'",
+                                  "remsh %s -l %s -n %s %s '%s%s%s:%s'",
 #else
-                   (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s%s%s:%s'",
+                                  "rsh %s -l %s -n %s %s '%s%s%s:%s'",
 #endif
                                   host, suser, cmd, src,
                                   tuser ? tuser : "",
                                   tuser ? "@" : "",
                                   thost, targ);
               } else
+                  (void) sprintf(buf,
 #if defined(hpux) || defined(__hpux)
-                  (void) sprintf(buf, "remsh %s -n %s %s '%s%s%s:%s'",
+                                 "remsh %s -n %s %s '%s%s%s:%s'",
 #else
-                   (void) sprintf(buf, "rsh %s -n %s %s '%s%s%s:%s'",
+                                 "rsh %s -n %s %s '%s%s%s:%s'",
 #endif
                                   argv[i], cmd, src,
                                   tuser ? tuser : "",
@@ -397,7 +411,7 @@ int main(argc, argv)
                                   thost, targ);
                (void) susystem(buf);
            } else {            /* local to remote */
-krb5_creds *cred;
+               krb5_creds *cred;
                if (rem == -1) {
                    (void) sprintf(buf, "%s -t %s",
                                   cmd, targ);
@@ -418,10 +432,14 @@ krb5_creds *cred;
                                  0,  /* No server seq # */
                                  &local,
                                  &foreign,
-                                 authopts,
+                                 &auth_context, authopts,
                                  0, /* Not any port # */
-                                 0);
+                                 0,
+                                 &kcmd_proto);
                    if (status) {
+                       if (kcmd_proto == KCMD_NEW_PROTOCOL)
+                           /* Don't fall back to less safe methods.  */
+                           exit (1);
 #ifdef KRB5_KRB4_COMPAT
                        fprintf(stderr, "Trying krb4 rcp...\n");
                        if (strncmp(buf, "-x rcp", 6) == 0)
@@ -442,8 +460,29 @@ krb5_creds *cred;
                        try_normal(orig_argv);
 #endif
                    }
-                   else
-                       rcmd_stream_init_krb5(&cred->keyblock, encryptflag, 0);
+                   else {
+                       krb5_boolean similar;
+                       krb5_keyblock *key = &cred->keyblock;
+
+                       if (status = krb5_c_enctype_compare(bsd_context,
+                                                           ENCTYPE_DES_CBC_CRC,
+                                                           cred->keyblock.enctype,
+                                                           &similar))
+                           try_normal(orig_argv); /* doesn't return */
+
+                       if (!similar) {
+                           status = krb5_auth_con_getlocalsubkey (bsd_context,
+                                                                  auth_context,
+                                                                  &key);
+                           if ((status || !key) && encryptflag)
+                               try_normal(orig_argv);
+                       }
+                       if (key == 0)
+                           key = &cred->keyblock;
+
+                       rcmd_stream_init_krb5(key, encryptflag, 0, 1,
+                                             kcmd_proto);
+                   }
                    rem = sock;
 #else
                    rem = rcmd(&host, port, pwd->pw_name,
@@ -521,10 +560,14 @@ krb5_creds *cred;
                              0,  /* No server seq # */
                              (struct sockaddr_in *) 0,
                              &foreign,
-                             authopts,
+                             &auth_context, authopts,
                              0, /* Not any port # */
-                             0);
+                             0,
+                             &kcmd_proto);
                if (status) {
+                       if (kcmd_proto == KCMD_NEW_PROTOCOL)
+                           /* Don't fall back to less safe methods.  */
+                           exit (1);
 #ifdef KRB5_KRB4_COMPAT
                        fprintf(stderr, "Trying krb4 rcp...\n");
                        if (strncmp(buf, "-x rcp", 6) == 0)
@@ -543,8 +586,27 @@ krb5_creds *cred;
 #else
                        try_normal(orig_argv);
 #endif
-               } else
-                   rcmd_stream_init_krb5(&cred->keyblock, encryptflag, 0);
+               } else {
+                   krb5_keyblock *key = &cred->keyblock;
+
+                   if (kcmd_proto == KCMD_NEW_PROTOCOL) {
+                       status = krb5_auth_con_getlocalsubkey (bsd_context,
+                                                              auth_context,
+                                                              &key);
+                       if (status) {
+                           com_err (argv[0], status,
+                                    "determining subkey for session");
+                           exit (1);
+                       }
+                       if (!key) {
+                           com_err (argv[0], 0,
+                                    "no subkey negotiated for connection");
+                           exit (1);
+                       }
+                   }
+
+                   rcmd_stream_init_krb5(key, encryptflag, 0, 1, kcmd_proto);
+               }
                rem = sock; 
                                   
                euid = geteuid();
@@ -741,7 +803,7 @@ void source(argc, argv)
             */
            (void) sprintf(buf, "T%ld 0 %ld 0\n",
                           stb.st_mtime, stb.st_atime);
-           (void) rcmd_stream_write(rem, buf, strlen(buf));
+           (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
            if (response() < 0) {
                (void) close(f);
                continue;
@@ -749,7 +811,7 @@ void source(argc, argv)
        }
        (void) sprintf(buf, "C%04o %ld %s\n",
                       (int) stb.st_mode&07777, (long ) stb.st_size, last);
-       (void) rcmd_stream_write(rem, buf, strlen(buf));
+       (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
        if (response() < 0) {
            (void) close(f);
            continue;
@@ -765,7 +827,7 @@ void source(argc, argv)
              amt = stb.st_size - i;
            if (readerr == 0 && read(f, bp->buf, amt) != amt)
              readerr = errno;
-           (void) rcmd_stream_write(rem, bp->buf, amt);
+           (void) rcmd_stream_write(rem, bp->buf, amt, 0);
        }
        (void) close(f);
        if (readerr == 0)
@@ -810,14 +872,14 @@ void rsource(name, statp)
     if (pflag) {
        (void) sprintf(buf, "T%ld 0 %ld 0\n",
                       statp->st_mtime, statp->st_atime);
-       (void) rcmd_stream_write(rem, buf, strlen(buf));
+       (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
        if (response() < 0) {
            closedir(d);
            return;
        }
     }
     (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
-    (void) rcmd_stream_write(rem, buf, strlen(buf));
+    (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
     if (response() < 0) {
        closedir(d);
        return;
@@ -836,7 +898,7 @@ void rsource(name, statp)
        source(1, bufv);
     }
     closedir(d);
-    (void) rcmd_stream_write(rem, "E\n", 2);
+    (void) rcmd_stream_write(rem, "E\n", 2, 0);
     (void) response();
 }
 
@@ -845,7 +907,7 @@ void rsource(name, statp)
 int response()
 {
     char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
-    if (rcmd_stream_read(rem, &resp, 1) != 1)
+    if (rcmd_stream_read(rem, &resp, 1, 0) != 1)
       lostconn();
     switch (resp) {
        
@@ -858,7 +920,7 @@ int response()
       case 1:                          /* error, followed by err msg */
       case 2:                          /* fatal error, "" */
        do {
-           if (rcmd_stream_read(rem, &c, 1) != 1)
+           if (rcmd_stream_read(rem, &c, 1, 0) != 1)
              lostconn();
            *cp++ = c;
        } while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
@@ -941,12 +1003,12 @@ void sink(argc, argv)
       targisdir = 1;
     for (first = 1; ; first = 0) {
        cp = cmdbuf;
-       if (rcmd_stream_read(rem, cp, 1) <= 0)
+       if (rcmd_stream_read(rem, cp, 1, 0) <= 0)
          return;
        if (*cp++ == '\n')
          SCREWUP("unexpected '\\n'");
        do {
-           if (rcmd_stream_read(rem, cp, 1) != 1)
+           if (rcmd_stream_read(rem, cp, 1, 0) != 1)
              SCREWUP("lost connection");
        } while (*cp++ != '\n');
        *cp = 0;
@@ -1012,11 +1074,17 @@ void sink(argc, argv)
          size = size * 10 + (*cp++ - '0');
        if (*cp++ != ' ')
          SCREWUP("size not delimited");
-       if (targisdir)
+       if (targisdir) {
+          if(strlen(targ) + strlen(cp) + 2 >= sizeof(nambuf))
+           SCREWUP("target name too long");
          (void) sprintf(nambuf, "%s%s%s", targ,
                         *targ ? "/" : "", cp);
-       else
-         (void) strcpy(nambuf, targ);
+       } else {
+         if (strlen(targ) + 1 >= sizeof (nambuf))
+           SCREWUP("target name too long");
+         (void) strncpy(nambuf, targ, sizeof(nambuf) - 1);
+       }
+       nambuf[sizeof(nambuf) - 1] = '\0';
        exists = stat(nambuf, &stb) == 0;
        if (cmdbuf[0] == 'D') {
            if (exists) {
@@ -1064,7 +1132,7 @@ void sink(argc, argv)
              amt = size - i;
            count += amt;
            do {
-               j = rcmd_stream_read(rem, cp, amt);
+               j = rcmd_stream_read(rem, cp, amt, 0);
                if (j <= 0) {
                    if (j == 0)
                      error("rcp: dropped connection");
@@ -1159,7 +1227,7 @@ error(fmt, va_alist)
     va_end(ap);
 
     if (iamremote)
-      (void) rcmd_stream_write(rem, buf, strlen(buf));
+      (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
     else
       (void) write(2, buf+1, strlen(buf+1));
 }
@@ -1170,7 +1238,7 @@ void usage()
 {
 #ifdef KERBEROS
     fprintf(stderr,
-           "Usage: \trcp [-p] [-x] [-k realm] f1 f2; or:\n\trcp [-r] [-p] [-x] [-k realm] f1 ... fn d2\n");
+           "Usage: \trcp [-PN | -PO] [-p] [-x] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-x] [-k realm] f1 ... fn d2\n");
 #else
     fputs("usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n", stderr);
 #endif
@@ -1315,7 +1383,8 @@ void
        exit(1);
     }
     
-    rcmd_stream_init_krb5(&new_creds->keyblock, encryptflag, 0);
+    rcmd_stream_init_krb5(&new_creds->keyblock, encryptflag, 0, 0,
+                         KCMD_OLD_PROTOCOL);
     
     /* cleanup */
     krb5_free_cred_contents(bsd_context, &creds);
index da4a8898057a0161068335a5070f4359a6176b08..0039056c31e854b56954dc3196ede0a31583fe0e 100644 (file)
@@ -177,6 +177,7 @@ int fflag = 0, Fflag = 0;
 krb5_creds *cred;
 struct sockaddr_in local, foreign;
 krb5_context bsd_context;
+krb5_auth_context auth_context;
 
 #ifdef KRB5_KRB4_COMPAT
 Key_schedule v4_schedule;
@@ -377,6 +378,7 @@ main(argc, argv)
 #endif
 #endif
     int port, debug_port = 0;
+    enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
    
     memset(&defaultservent, 0, sizeof(struct servent));
     if (strrchr(argv[0], '/'))
@@ -502,6 +504,16 @@ main(argc, argv)
        argv++, argc--;
        goto another;
     }
+    if (argc > 0 && !strcmp(*argv, "-PO")) {
+       kcmd_proto = KCMD_OLD_PROTOCOL;
+       argv++, argc--;
+       goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-PN")) {
+       kcmd_proto = KCMD_NEW_PROTOCOL;
+       argv++, argc--;
+       goto another;
+    }
 #endif /* KERBEROS */
     if (host == 0)
       goto usage;
@@ -559,7 +571,8 @@ main(argc, argv)
        if (tcgetattr(0, &ttyb) == 0) {
                int ospeed = cfgetospeed (&ttyb);
 
-               (void) strcat(term, "/");
+                term[sizeof(term) - 1] = '\0';
+               (void) strncat(term, "/", sizeof(term) - 1 - strlen(term));
                if (ospeed >= 50)
                        /* On some systems, ospeed is the baud rate itself,
                           not a table index.  */
@@ -567,15 +580,16 @@ main(argc, argv)
                else if (ospeed >= sizeof(speeds)/sizeof(char*))
                        /* Past end of table, but not high enough to
                           look like a real speed.  */
-                       (void) strcat (term, speeds[sizeof(speeds)/sizeof(char*) - 1]);
+                       (void) strncat (term, speeds[sizeof(speeds)/sizeof(char*) - 1], sizeof(term) - 1 - strlen(term));
                else {
-                       (void) strcat(term, speeds[ospeed]);
+                       (void) strncat(term, speeds[ospeed], sizeof(term) - 1 - strlen(term));
                }
+                term[sizeof (term) - 1] = '\0';
        }
 #else
     if (ioctl(0, TIOCGETP, &ttyb) == 0) {
-       (void) strcat(term, "/");
-       (void) strcat(term, speeds[ttyb.sg_ospeed]);
+       (void) strncat(term, "/", sizeof(term) - 1 - strlen(term));
+       (void) strncat(term, speeds[ttyb.sg_ospeed], sizeof(term) - 1 - strlen(term));
     }
 #endif
     (void) get_window_size(0, &winsize);
@@ -631,10 +645,14 @@ main(argc, argv)
                  0,            /* No need for sequence number */
                  0,            /* No need for server seq # */
                  &local, &foreign,
-                 authopts,
+                 &auth_context, authopts,
                  0,            /* Not any port # */
-                 0);
+                 0,
+                 &kcmd_proto);
     if (status) {
+       if (kcmd_proto == KCMD_NEW_PROTOCOL && encrypt_flag)
+           /* Don't fall back to something less secure.  */
+           exit (1);
 #ifdef KRB5_KRB4_COMPAT
        fprintf(stderr, "Trying krb4 rlogin...\n");
        status = k4cmd(&sock, &host, port,
@@ -650,19 +668,20 @@ main(argc, argv)
        try_normal(orig_argv);
 #endif
     } else {
-       krb5_boolean similar;
-
-       rcmd_stream_init_krb5(&cred->keyblock, encrypt_flag, 1);
-
-       if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
-                                           cred->keyblock.enctype, &similar))
-           try_normal(orig_argv); /* doesn't return */
+       krb5_keyblock *key = 0;
 
-       if (!similar) {
+       if (kcmd_proto == KCMD_NEW_PROTOCOL) {
            do_inband = 1;
-           if (debug_port)
-               fprintf(stderr, "DEBUG: setting do_inband\n");
+
+           status = krb5_auth_con_getlocalsubkey (bsd_context, auth_context,
+                                                  &key);
+           if ((status || !key) && encrypt_flag)
+               try_normal(orig_argv);
        }
+       if (key == 0)
+           key = &cred->keyblock;
+
+       rcmd_stream_init_krb5(key, encrypt_flag, 1, 1, kcmd_proto);
     }
        
     rem = sock;
@@ -1122,9 +1141,9 @@ writer()
 #endif
 
            if (c != cmdchar)
-             (void) rcmd_stream_write(rem, &cmdchar, 1);
+             (void) rcmd_stream_write(rem, &cmdchar, 1, 0);
        }
-       if (rcmd_stream_write(rem, &c, 1) == 0) {
+       if (rcmd_stream_write(rem, &c, 1, 0) == 0) {
            prf("line gone");
            break;
        }
@@ -1239,7 +1258,7 @@ sendwindow()
     wp->ws_col = htons(winsize.ws_col);
     wp->ws_xpixel = htons(winsize.ws_xpixel);
     wp->ws_ypixel = htons(winsize.ws_ypixel);
-    (void) rcmd_stream_write(rem, obuf, sizeof(obuf));
+    (void) rcmd_stream_write(rem, obuf, sizeof(obuf), 0);
 }
 
 
@@ -1458,7 +1477,7 @@ fd_set readset, excset, writeset;
                bufp += n;
            }
            if (FD_ISSET(rem, &readset)) {
-               rcvcnt = rcmd_stream_read(rem, rcvbuf, sizeof (rcvbuf));
+               rcvcnt = rcmd_stream_read(rem, rcvbuf, sizeof (rcvbuf), 0);
                if (rcvcnt == 0)
                    return (0);
                if (rcvcnt < 0)
index e37b84cc894c306a3d7f7915be6420d060c39cdb..d2748849919840c9febab71cfaa604f0818d7226 100644 (file)
@@ -250,6 +250,7 @@ AUTH_DAT    *v4_kdata;
 Key_schedule v4_schedule;
 
 #include "com_err.h"
+#include "defines.h"
      
 #define SECURE_MESSAGE  "This rlogin session is using DES encryption for all data transmissions.\r\n"
 
@@ -815,7 +816,7 @@ void doit(f, fromp)
                                    stripdomain, always_ip,
                                    &rhost_sane);
     if (retval)
-        fatalperror(2, "failed make_sane_hostname");
+        fatalperror(f, "failed make_sane_hostname");
     if (passwd_req)
         execl(login_program, "login", "-p", "-h", rhost_sane,
           lusername, 0);
@@ -825,8 +826,9 @@ void doit(f, fromp)
 #else /* USE_LOGIN_F */
        execl(login_program, "login", "-r", rhost_sane, 0);
 #endif /* USE_LOGIN_F */
-       
-       fatalperror(2, login_program);
+       syslog(LOG_ERR, "failed exec of %s: %s",
+              login_program, error_message(errno));
+       fatalperror(f, login_program);
        /*NOTREACHED*/
     } /* if (pid == 0) */
 
@@ -850,7 +852,7 @@ void doit(f, fromp)
     
 #if defined(KERBEROS) 
     if (do_encrypt) {
-       if (rcmd_stream_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)) < 0){
+       if (rcmd_stream_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE), 0) < 0){
            sprintf(buferror, "Cannot encrypt-write network.");
            fatal(p,buferror);
        }
@@ -918,11 +920,11 @@ int sendoob(fd, byte)
        message[3] = 'o';
        message[4] = *byte;
 
-       cc = rcmd_stream_write(fd, message, sizeof(message));
+       cc = rcmd_stream_write(fd, message, sizeof(message), 0);
        while (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
            /* also shouldn't happen */
            sleep(5);
-           cc = rcmd_stream_write(fd, message, sizeof(message));
+           cc = rcmd_stream_write(fd, message, sizeof(message), 0);
        }
     } else {
        send(fd, byte, 1, MSG_OOB);
@@ -1033,7 +1035,7 @@ void protocol(f, p)
        }
 #define        pkcontrol(c)    ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
        if (FD_ISSET(f, &ibits)) {
-           fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf));
+           fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf), 0);
            if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
                fcc = 0;
            } else {
@@ -1121,7 +1123,7 @@ void protocol(f, p)
        }
 
        if (FD_ISSET(f, &obits) && pcc > 0) {
-           cc = rcmd_stream_write(f, pbp, pcc);
+           cc = rcmd_stream_write(f, pbp, pcc, 0);
            if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
                /* also shouldn't happen */
                sleep(5);
@@ -1160,7 +1162,7 @@ void fatal(f, msg)
     buf[0] = '\01';            /* error indicator */
     (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
     if ((f == netf) && (pid > 0))
-      (void) rcmd_stream_write(f, buf, strlen(buf));
+      (void) rcmd_stream_write(f, buf, strlen(buf), 0);
     else
       (void) write(f, buf, strlen(buf));
     syslog(LOG_ERR,"%s\n",msg);
@@ -1377,9 +1379,11 @@ recvauth(valid_checksum)
     int len;
     krb5_data inbuf;
     char v4_instance[INST_SZ]; /* V4 Instance */
-    char v4_version[9];
+    krb5_data version;
     krb5_authenticator *authenticator;
     krb5_rcache rcache;
+    enum kcmd_proto kcmd_proto;
+    krb5_keyblock *key;
 
     *valid_checksum = 0;
     len = sizeof(laddr);
@@ -1423,8 +1427,8 @@ recvauth(valid_checksum)
        if (status) return status;
     }
 
-    if ((status = krb5_compat_recvauth(bsd_context, &auth_context, &netf,
-                                 "KCMDV0.1",
+    if ((status = krb5_compat_recvauth_version(bsd_context, &auth_context,
+                                              &netf,
                                  NULL,         /* Specify daemon principal */
                                  0,            /* no flags */
                                  keytab, /* normally NULL to use v5srvtab */
@@ -1438,8 +1442,8 @@ recvauth(valid_checksum)
 
                                  &ticket,      /* return ticket */
                                  &auth_sys,    /* which authentication system*/
-                                 &v4_kdata, v4_schedule, v4_version))) {
-
+                                 &v4_kdata, v4_schedule,
+                                              &version))) {
        if (auth_sys == KRB5_RECVAUTH_V5) {
            /*
             * clean up before exiting
@@ -1453,7 +1457,25 @@ recvauth(valid_checksum)
 
     getstr(netf, lusername, sizeof (lusername), "locuser");
     getstr(netf, term, sizeof(term), "Terminal type");
-    if ((auth_sys == KRB5_RECVAUTH_V5) && !checksum_ignored) {
+
+    kcmd_proto = KCMD_UNKNOWN_PROTOCOL;
+    if (auth_sys == KRB5_RECVAUTH_V5) {
+       if (version.length != 9) {
+           fatal (netf, "bad application version length");
+       }
+       if (!memcmp (version.data, "KCMDV0.1", 9))
+           kcmd_proto = KCMD_OLD_PROTOCOL;
+       else if (!memcmp (version.data, "KCMDV0.2", 9))
+           kcmd_proto = KCMD_NEW_PROTOCOL;
+    }
+#ifdef KRB5_KRB4_COMPAT
+    if (auth_sys == KRB5_RECVAUTH_V4)
+       kcmd_proto = KCMD_V4_PROTOCOL;
+#endif
+
+    if ((auth_sys == KRB5_RECVAUTH_V5)
+       && !(checksum_ignored
+            && kcmd_proto == KCMD_OLD_PROTOCOL)) {
       
       if ((status = krb5_auth_con_getauthenticator(bsd_context, auth_context,
                                                   &authenticator)))
@@ -1500,7 +1522,8 @@ recvauth(valid_checksum)
          * Assume it to be the same as the first component of the
         * principal's name. 
          */
-       strcpy(rusername, v4_kdata->pname);
+       strncpy(rusername, v4_kdata->pname, sizeof(rusername) - 1);
+       rusername[sizeof(rusername) - 1] = '\0';
 
        status = krb5_425_conv_principal(bsd_context, v4_kdata->pname,
                                         v4_kdata->pinst, v4_kdata->prealm,
@@ -1519,22 +1542,20 @@ recvauth(valid_checksum)
                                      &client)))
        return status;
 
-    rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 1);
-
-    {
-       krb5_boolean similar;
-
-       if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
-                                          ticket->enc_part2->session->enctype,
-                                          &similar))
-         return(status);
+    key = 0;
+    status = krb5_auth_con_getremotesubkey (bsd_context, auth_context, &key);
+    if (status)
+       fatal (netf, "Server can't get session subkey");
+    if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL)
+       fatal (netf, "No session subkey sent");
+    if (key && kcmd_proto == KCMD_OLD_PROTOCOL)
+       fatal (netf, "Session subkey not permitted under old kcmd protocol");
+    if (key == 0)
+       key = ticket->enc_part2->session;
 
-       if (!similar) {
-         do_inband = 1;
-         syslog(LOG_DEBUG, "setting do_inband");
-       }
-    }
+    rcmd_stream_init_krb5 (key, do_encrypt, 1, 0, kcmd_proto);
 
+    do_inband = (kcmd_proto == KCMD_NEW_PROTOCOL);
 
     getstr(netf, rusername, sizeof(rusername), "remuser");
 
index 9d602b22ac85e368571bc87565cbcc8f549f9267..c1741d85620600433de0ec38fd3b3d4ddea6dc3d 100644 (file)
@@ -93,8 +93,6 @@ krb5_sigtype  sendsig();
 #define UCB_RSH "/usr/ucb/rsh"
 #endif
 
-
-
 krb5_context bsd_context;
 krb5_creds *cred;
 
@@ -137,7 +135,7 @@ main(argc, argv0)
     struct servent *sp;
     struct servent defaultservent;
     struct sockaddr_in local, foreign;
-    int suppress;
+    int suppress = 0;
 
 #ifdef POSIX_SIGNALS
     sigset_t omask, igmask;
@@ -148,6 +146,7 @@ main(argc, argv0)
 #ifdef KERBEROS
     krb5_flags authopts;
     krb5_error_code status;
+    krb5_auth_context auth_context;
     int fflag = 0, Fflag = 0;
 #ifdef KRB5_KRB4_COMPAT
     KTEXT_ST v4_ticket;
@@ -155,6 +154,7 @@ main(argc, argv0)
 #endif
 #endif  /* KERBEROS */
     int debug_port = 0;
+    enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
 
     memset(&defaultservent, 0, sizeof(struct servent));
     if (strrchr(argv[0], '/'))
@@ -239,6 +239,16 @@ main(argc, argv0)
        argv++, argc--;
        goto another;
     }
+    if (argc > 0 && !strcmp(*argv, "-PO")) {
+       argv++, argc--;
+       kcmd_proto = KCMD_OLD_PROTOCOL;
+       goto another;
+    }
+    if (argc > 0 && !strcmp(*argv, "-PN")) {
+       argv++, argc--;
+       kcmd_proto = KCMD_NEW_PROTOCOL;
+       goto another;
+    }
 #endif  /* KERBEROS */
     /*
      * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin
@@ -367,10 +377,15 @@ main(argc, argv0)
                  0,           /* No need for sequence number */
                  0,           /* No need for server seq # */
                  &local, &foreign,
-                 authopts,
+                 &auth_context, authopts,
                  1,    /* Always set anyport, there is no need not to. --proven */
-                 suppress);
+                 suppress,
+                 &kcmd_proto);
     if (status) {
+       /* If new protocol requested, don't fall back to less secure
+          ones.  */
+       if (kcmd_proto == KCMD_NEW_PROTOCOL)
+           exit (1);
 #ifdef KRB5_KRB4_COMPAT
        /* No encrypted Kerberos 4 rsh. */
        if (encrypt_flag)
@@ -391,8 +406,24 @@ main(argc, argv0)
 #else
        try_normal(argv0);
 #endif
-    } else
-       rcmd_stream_init_krb5(&cred->keyblock, encrypt_flag, 0);
+    } else {
+       krb5_keyblock *key = &cred->keyblock;
+
+       if (kcmd_proto == KCMD_NEW_PROTOCOL) {
+           status = krb5_auth_con_getlocalsubkey (bsd_context, auth_context,
+                                                  &key);
+           if (status) {
+               com_err (argv[0], status, "determining subkey for session");
+               exit (1);
+           }
+           if (!key) {
+               com_err (argv[0], 0, "no subkey negotiated for connection");
+               exit (1);
+           }
+       }
+
+       rcmd_stream_init_krb5(key, encrypt_flag, 0, 1, kcmd_proto);
+    }
 
 #ifdef HAVE_ISATTY
     if(encrypt_flag&&isatty(2)) {
@@ -489,7 +520,7 @@ main(argc, argv0)
        }
        if (FD_ISSET(rem, &rembits) == 0)
          goto rewrite;
-       wc = rcmd_stream_write(rem, bp, cc);
+       wc = rcmd_stream_write(rem, bp, cc, 0);
        if (wc < 0) {
            if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
              goto rewrite;
@@ -524,7 +555,7 @@ main(argc, argv0)
        }
        if (FD_ISSET(rfd2, &ready)) {
            errno = 0;
-           cc = rcmd_stream_read(rfd2, buf, sizeof buf);
+           cc = rcmd_stream_read(rfd2, buf, sizeof buf, 1);
            if (cc <= 0) {
                if ((errno != EWOULDBLOCK) && (errno != EAGAIN))
                    FD_CLR(rfd2, &readfrom);
@@ -533,7 +564,7 @@ main(argc, argv0)
        }
        if (FD_ISSET(rem, &ready)) {
            errno = 0;
-           cc = rcmd_stream_read(rem, buf, sizeof buf);
+           cc = rcmd_stream_read(rem, buf, sizeof buf, 0);
            if (cc <= 0) {
                if ((errno != EWOULDBLOCK) && (errno != EAGAIN))
                    FD_CLR(rem, &readfrom);
@@ -546,9 +577,9 @@ main(argc, argv0)
     exit(0);
   usage:
     fprintf(stderr,
-           "usage: \trsh host [ -l login ] [ -n ] [ -x ] [ -f / -F] command\n");
+           "usage: \trsh host [ -PN / -PO ] [ -l login ] [ -n ] [ -x ] [ -f / -F] command\n");
     fprintf(stderr,
-           "OR \trsh [ -l login ] [-n ] [ -x ] [ -f / -F ] host command\n");
+           "OR \trsh [ -PN / -PO ] [ -l login ] [-n ] [ -x ] [ -f / -F ] host command\n");
     exit(1);
 }
 
@@ -557,7 +588,7 @@ main(argc, argv0)
 krb5_sigtype sendsig(signo)
      char signo;
 {
-    (void) rcmd_stream_write(rfd2, &signo, 1);
+    (void) rcmd_stream_write(rfd2, &signo, 1, 1);
 }
 
 
index 3844087bb533b36fafef64974d4eda14a67807c8..c69729c5c98ec745bef9a92f4fc527b73896abfc 100644 (file)
@@ -48,8 +48,8 @@ char copyright[] =
  * or by the name of the daemon. If command-line arguments are present, they 
  * take priority. The options are:
  * -k means trust krb4 or krb5
-* -5 means trust krb5
-* -4 means trust krb4 (using .klogin)
+ * -5 means trust krb5
+ * -4 means trust krb4 (using .klogin)
  * 
  */
      
@@ -73,9 +73,7 @@ char copyright[] =
 #define SERVE_NON_KRB     
 #define LOG_REMOTE_REALM
 #define LOG_CMD
-#include "defines.h"
    
-  
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -162,6 +160,8 @@ char copyright[] =
 Key_schedule v4_schedule;
 #endif
 
+#include "defines.h"
+
 #if HAVE_ARPA_NAMESER_H
 #include <arpa/nameser.h>
 #endif
@@ -1245,7 +1245,7 @@ if(port)
                        shutdown(s, 1+1);
                        FD_CLR(pv[0], &readfrom);
                    } else {
-                       (void) rcmd_stream_write(s, buf, cc);
+                       (void) rcmd_stream_write(s, buf, cc, 1);
                    }
                }
                if (FD_ISSET(pw[0], &ready)) {
@@ -1256,12 +1256,12 @@ if(port)
                        shutdown(f, 1+1);
                        FD_CLR(pw[0], &readfrom);
                    } else {
-                       (void) rcmd_stream_write(f, buf, cc);
+                       (void) rcmd_stream_write(f, buf, cc, 0);
                    }
                }
                if (port&&FD_ISSET(s, &ready)) {
                    /* read from the alternate channel, signal the child */
-                   if (rcmd_stream_read(s, &sig, 1) <= 0) {
+                   if (rcmd_stream_read(s, &sig, 1, 1) <= 0) {
                        FD_CLR(s, &readfrom);
                    } else {
 #ifdef POSIX_SIGNALS
@@ -1277,7 +1277,7 @@ if(port)
                if (FD_ISSET(f, &ready)) {
                    /* read from the net, write to child stdin */
                    errno = 0;
-                   cc = rcmd_stream_read(f, buf, sizeof(buf));
+                   cc = rcmd_stream_read(f, buf, sizeof(buf), 0);
                    if (cc <= 0) {
                        (void) close(px[1]);
                        FD_CLR(f, &readfrom);
@@ -1468,15 +1468,16 @@ if(port)
         strcpy((char *) cmdbuf + offst, kprogdir);
        cp = copy + 3 + offst;
 
+       cmdbuf[sizeof(cmdbuf) - 1] = '\0';
        if (auth_sys == KRB5_RECVAUTH_V4) {
-         strcat(cmdbuf, "/v4rcp");
+         strncat(cmdbuf, "/v4rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        } else {
-         strcat(cmdbuf, "/rcp");
+         strncat(cmdbuf, "/rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        }
        if (stat((char *)cmdbuf + offst, &s) >= 0)
-         strcat(cmdbuf, cp);
+         strncat(cmdbuf, cp, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        else
-         strcpy(cmdbuf, copy);
+         strncpy(cmdbuf, copy, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        free(copy);
     }
 #endif
@@ -1775,7 +1776,6 @@ recvauth(netf, peersin, valid_checksum)
     krb5_data inbuf;
 #ifdef KRB5_KRB4_COMPAT
     char v4_instance[INST_SZ]; /* V4 Instance */
-    char v4_version[9];
 #endif
     krb5_authenticator *authenticator;
     krb5_ticket        *ticket;
@@ -1783,6 +1783,8 @@ recvauth(netf, peersin, valid_checksum)
     struct passwd *pwd;
     uid_t uid;
     gid_t gid;
+    enum kcmd_proto kcmd_proto;
+    krb5_data version;
 
     *valid_checksum = 0;
     len = sizeof(laddr);
@@ -1828,8 +1830,7 @@ recvauth(netf, peersin, valid_checksum)
     }
 
 #ifdef KRB5_KRB4_COMPAT
-    status = krb5_compat_recvauth(bsd_context, &auth_context, &netf,
-                                 "KCMDV0.1",
+    status = krb5_compat_recvauth_version(bsd_context, &auth_context, &netf,
                                  NULL,         /* Specify daemon principal */
                                  0,            /* no flags */
                                  keytab, /* normally NULL to use v5srvtab */
@@ -1842,14 +1843,14 @@ recvauth(netf, peersin, valid_checksum)
 
                                  &ticket,      /* return ticket */
                                  &auth_sys,    /* which authentication system*/
-                                 &v4_kdata, 0, v4_version);
+                                 &v4_kdata, 0, &version);
 #else
-    status = krb5_recvauth(bsd_context, &auth_context, &netf,
-                           "KCMDV0.1",
-                           NULL,        /* daemon principal */
-                           0,           /* no flags */
-                          keytab,      /* normally NULL to use v5srvtab */
-                          &ticket);    /* return ticket */
+    status = krb5_recvauth_version(bsd_context, &auth_context, &netf,
+                                  NULL,        /* daemon principal */
+                                  0,           /* no flags */
+                                  keytab,      /* normally NULL to use v5srvtab */
+                                  &ticket,    /* return ticket */
+                                  &version); /* application version string */
     auth_sys = KRB5_RECVAUTH_V5;
 #endif
 
@@ -1891,6 +1892,14 @@ recvauth(netf, peersin, valid_checksum)
 
     /* Must be V5  */
        
+    kcmd_proto = KCMD_UNKNOWN_PROTOCOL;
+    if (version.length != 9)
+       fatal (netf, "bad application version length");
+    if (!memcmp (version.data, "KCMDV0.1", 9))
+       kcmd_proto = KCMD_OLD_PROTOCOL;
+    if (!memcmp (version.data, "KCMDV0.2", 9))
+       kcmd_proto = KCMD_NEW_PROTOCOL;
+
     getstr(netf, remuser, sizeof(locuser), "remuser");
 
     if ((status = krb5_unparse_name(bsd_context, ticket->enc_part2->client, 
@@ -1939,7 +1948,21 @@ recvauth(netf, peersin, valid_checksum)
 
     if (!strncmp(cmdbuf, "-x ", 3))
        do_encrypt = 1;
-    rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 0);
+
+    {
+       krb5_keyblock *key;
+       status = krb5_auth_con_getremotesubkey (bsd_context, auth_context,
+                                               &key);
+       if (status)
+           fatal (netf, "Server can't get session subkey");
+       if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL)
+           fatal (netf, "No session subkey sent");
+       if (key && kcmd_proto == KCMD_OLD_PROTOCOL)
+           fatal (netf, "Session subkey not allowed in old kcmd protocol");
+       if (key == 0)
+           key = ticket->enc_part2->session;
+       rcmd_stream_init_krb5 (key, do_encrypt, 0, 0, kcmd_proto);
+    }
 
     /* Null out the "session" because kcmd.c references the session
      * key here, and we do not want krb5_free_ticket() to destroy it. */
@@ -1990,7 +2013,7 @@ void fatal(f, msg)
     buf[0] = '\01';             /* error indicator */
     (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
     if ((f == netf) && (pid > 0))
-      (void) rcmd_stream_write(f, buf, strlen(buf));
+      (void) rcmd_stream_write(f, buf, strlen(buf), 0);
     else
       (void) write(f, buf, strlen(buf));
     syslog(LOG_ERR,"%s\n",msg);
index 40af3ce60d3b9486df9fd81c19cb7289e33ec598..af703b3baaa7f8b1f550cc8eebbfbc63469e6e3e 100644 (file)
@@ -619,9 +619,10 @@ int have_v5_tickets (me)
 #endif /* KRB5_GET_TICKETS */
 
 #ifdef KRB4_CONVERT
-try_convert524 (kcontext, me)
-     krb5_context kcontext;
-     krb5_principal me;
+try_convert524(kcontext, me, use_ccache)
+    krb5_context kcontext;
+    krb5_principal me;
+    int use_ccache;
 {
     krb5_principal kpcserver;
     krb5_error_code kpccode;
@@ -632,38 +633,45 @@ try_convert524 (kcontext, me)
 
     /* or do this directly with krb524_convert_creds_kdc */
     krb524_init_ets(kcontext);
-    /* cc->ccache, already set up */
-    /* client->me, already set up */
-    if ((kpccode = krb5_build_principal(kcontext,
-                                       &kpcserver, 
-                                       krb5_princ_realm(kcontext, me)->length,
-                                       krb5_princ_realm(kcontext, me)->data,
-                                       "krbtgt",
-                                       krb5_princ_realm(kcontext, me)->data,
-                                       NULL))) {
-      com_err("login/v4", kpccode,
-             "while creating service principal name");
-      return 0;
-    }
 
-    memset((char *) &increds, 0, sizeof(increds));
-    increds.client = me;
-    increds.server = kpcserver;
-    increds.times.endtime = 0;
-    increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-    if ((kpccode = krb5_get_credentials(kcontext, 0, 
-                                       ccache,
-                                       &increds, 
-                                       &v5creds))) {
-       com_err("login/v4", kpccode,
-               "getting V5 credentials");
-       return 0;
-    }
-    if ((kpccode = krb524_convert_creds_kdc(kcontext, 
-                                           v5creds,
-                                           &v4creds))) {
-       com_err("login/v4", kpccode, 
-               "converting to V4 credentials");
+    /* If we have forwarded v5 tickets, retrieve the credentials from
+     * the cache; otherwise, the v5 credentials are in my_creds.
+     */
+    if (use_ccache) {
+       /* cc->ccache, already set up */
+       /* client->me, already set up */
+       kpccode = krb5_build_principal(kcontext, &kpcserver, 
+                                      krb5_princ_realm(kcontext, me)->length,
+                                      krb5_princ_realm(kcontext, me)->data,
+                                      "krbtgt",
+                                      krb5_princ_realm(kcontext, me)->data,
+                                      NULL);
+       if (kpccode) {
+           com_err("login/v4", kpccode,
+                   "while creating service principal name");
+           return 0;
+       }
+
+       memset((char *) &increds, 0, sizeof(increds));
+       increds.client = me;
+       increds.server = kpcserver;
+       increds.times.endtime = 0;
+       increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+       kpccode = krb5_get_credentials(kcontext, 0, ccache,
+                                      &increds, &v5creds);
+       krb5_free_principal(kcontext, kpcserver);
+       increds.server = NULL;
+       if (kpccode) {
+           com_err("login/v4", kpccode, "getting V5 credentials");
+           return 0;
+       }
+
+       kpccode = krb524_convert_creds_kdc(kcontext, v5creds, &v4creds);
+       krb5_free_creds(kcontext, v5creds);
+    } else
+       kpccode = krb524_convert_creds_kdc(kcontext, &my_creds, &v4creds);
+    if (kpccode) {
+       com_err("login/v4", kpccode, "converting to V4 credentials");
        return 0;
     }
     /* this is stolen from the v4 kinit */
@@ -913,8 +921,9 @@ afs_login ()
        struct stat st;
        /* construct the name */
        /* get this from profile later */
-       strcpy (aklog_path, KPROGDIR);
-       strcat (aklog_path, "/aklog");
+       aklog_path[sizeof(aklog_path) - 1] = '\0';
+       strncpy (aklog_path, KPROGDIR, sizeof(aklog_path) - 1);
+       strncat (aklog_path, "/aklog", sizeof(aklog_path) - 1 - strlen(aklog_path));
        /* only run it if we can find it */
        if (stat (aklog_path, &st) == 0) {
            system(aklog_path);
@@ -1448,7 +1457,7 @@ int main(argc, argv)
 #if defined(KRB5_GET_TICKETS) && defined(KRB4_CONVERT)
     if (login_krb4_convert && !got_v4_tickets) {
        if (got_v5_tickets||forwarded_v5_tickets)
-           try_convert524 (kcontext, me);
+           try_convert524(kcontext, me, forwarded_v5_tickets);
     }
 #endif
 
index 36754deadcb6c88e4b3b7dc74527f093277dcca4..32677835050770414c061221c62b4a8de58d6d3a 100644 (file)
@@ -208,7 +208,7 @@ int kstream_read(krem, buf, len)
       /* decrypt it */
       des_pcbc_encrypt ((des_cblock *)krem->retbuf, 
                        (des_cblock *)krem->retbuf, 
-                       sz, *krem->sched, *krem->ivec, 
+                       sz, *krem->sched, krem->ivec, 
                        DECRYPT);
 
       /* now retbuf has sz bytes, return len or x of them to the user */
@@ -265,7 +265,7 @@ int kstream_write(krem, buf, len)
       abort ();
     /* memset(outbuf+4+4, 0x42, BUFSIZ); */
     st = des_pcbc_encrypt ((des_cblock *)buf, (des_cblock *)(krem->outbuf+4+4), outlen,
-                          *krem->sched, *krem->ivec, ENCRYPT);
+                          *krem->sched, krem->ivec, ENCRYPT);
 
     if (st) abort();
     return write(krem->write_fd, krem->outbuf+4, 4+outlen);
@@ -400,6 +400,7 @@ int main(argc, argv)
                        if (argc == 0) 
                          usage();
                        strncpy(krb_realm,*argv,REALM_SZ);
+                       krb_realm[REALM_SZ-1] = 0;
                        sprintf(realmarg, " -k %s", krb_realm);
                        goto next_arg;
 #endif /* KERBEROS */
@@ -782,11 +783,20 @@ void sink(argc, argv)
                        size = size * 10 + (*cp++ - '0');
                if (*cp++ != ' ')
                        SCREWUP("size not delimited");
-               if (targisdir)
-                       (void) sprintf(nambuf, "%s%s%s", targ,
-                           *targ ? "/" : "", cp);
-               else
-                       (void) strcpy(nambuf, targ);
+               if (targisdir) {
+                       if (strlen(targ) + strlen(cp) + 1 < sizeof(nambuf)) {
+                               (void) sprintf(nambuf, "%s%s%s", targ,
+                                   *targ ? "/" : "", cp);
+                       } else {
+                               SCREWUP("target directory name too long");
+                       }
+               } else {
+                   if (strlen(targ) + 1 < sizeof(nambuf))
+                       (void) strncpy(nambuf, targ, sizeof(nambuf)-1);
+                   else
+                       SCREWUP("target pathname too long");
+               }
+               nambuf[sizeof(nambuf)-1] = '\0';
                exists = stat(nambuf, &stb) == 0;
                if (cmdbuf[0] == 'D') {
                        if (exists) {
index 7d41ff46ebf10053122e5648e2d8bb6119d71e16..ed96d063dc0369ae43ad0d960eaab485929ee639 100644 (file)
@@ -1,3 +1,8 @@
+2000-03-24  Ken Raeburn  <raeburn@mit.edu>
+
+       * configure.in: Check for alpha*-dec-osf* instead of
+       alpha-dec-osf*.
+
 1999-10-26  Wilfredo Sanchez  <tritan@mit.edu>
 
        * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
index f0c2bff166425fe1d89eed3307687309f44309df..349cc0478efa2503b2de35cdfe3ad448b932ecd8 100644 (file)
@@ -67,7 +67,7 @@ else
        FTPD_LIBS="../../../krb524/libkrb524.a"
 fi
 case $krb5_cv_host in
-alpha-dec-osf*)
+alpha*-dec-osf*)
        AC_CHECK_LIB(security,setluid,
                AC_DEFINE(HAVE_SETLUID)
                FTPD_LIBS="$FTPD_LIBS -lsecurity"
index 22a29c356486b639cf9215094a25ae05f3d359a7..a5d22653b21755910dde6e37d2fc70f6551ca7b5 100644 (file)
@@ -1,3 +1,20 @@
+2000-05-11  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * domacro.c (domacro): Don't overflow "line2"
+       * ftp.c (getreply, krb4 compat): Bail if message data too big for buffer
+       (getreply, gssapi): Ditto.
+       (pswitch): Don't overflow "ntin", "ntout", "mapin", "mapout".
+       (do_auth, krb4 compat): Don't overflow "realm".
+
+2000-04-27  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * cmds.c (remglob): Don't overflow buffer "temp".
+       (shell): Don't overflow buffer "shellnam".
+       (quote1): "buf"
+       * glob.c (ftpglob): Fix boundary in buffer "agpath".
+       (expand): Don't overflow buffer pointed to by "gpath".
+       (execbrc): Don't overflow buffer "restbuf".
+
 2000-02-18  Ken Raeburn  <raeburn@mit.edu>
 
        * cmds.c (mls): Declare some variables volatile to protect against
index 2a8e7755002c0cf2826e3161042ad9976a1b99ca..0006e4fc5da0a4484897789446f9705b4943b95e 100644 (file)
@@ -1049,7 +1049,8 @@ remglob(argv,doswitch)
                return (cp);
        }
        if (ftemp == NULL) {
-               (void) strcpy(temp, _PATH_TMP);
+               (void) strncpy(temp, _PATH_TMP, sizeof(temp) - 1);
+               temp[sizeof(temp) - 1] = '\0';
                (void) mktemp(temp);
                oldverbose = verbose, verbose = 0;
                oldhash = hash, hash = 0;
@@ -1510,7 +1511,8 @@ shell(argc, argv)
                if (namep == NULL)
                        namep = shell;
                (void) strcpy(shellnam,"-");
-               (void) strcat(shellnam, ++namep);
+               (void) strncat(shellnam, ++namep, sizeof(shellnam) - 1 - strlen(shellnam));
+               shellnam[sizeof(shellnam) - 1] = '\0';
                if (strcmp(namep, "sh") != 0)
                        shellnam[0] = '+';
                if (debug) {
@@ -1702,13 +1704,14 @@ quote1(initial, argc, argv)
        register int i, len;
        char buf[FTP_BUFSIZ];           /* must be >= sizeof(line) */
 
-       (void) strcpy(buf, initial);
+       (void) strncpy(buf, initial, sizeof(buf) - 1);
+       buf[sizeof(buf) - 1] = '\0';
        if (argc > 1) {
                len = strlen(buf);
-               len += strlen(strcpy(&buf[len], argv[1]));
+               len += strlen(strncpy(&buf[len], argv[1], sizeof(buf) - 1 - len));
                for (i = 2; i < argc; i++) {
                        buf[len++] = ' ';
-                       len += strlen(strcpy(&buf[len], argv[i]));
+                       len += strlen(strncpy(&buf[len], argv[i], sizeof(buf) - 1 - len));
                }
        }
        if (command(buf) == PRELIM) {
index 9bc277b0f8a87a7bb8a8581d06cf5ed390746ed6..ecfe9b4adfa70f6a90c6c2dd591461718a35c1b7 100644 (file)
@@ -71,7 +71,8 @@ domacro(argc, argv)
                code = -1;
                return;
        }
-       (void) strcpy(line2, line);
+       (void) strncpy(line2, line, sizeof(line2) - 1);
+       line2[sizeof(line2) - 1] = '\0';
 TOP:
        cp1 = macros[i].mac_start;
        while (cp1 != macros[i].mac_end) {
@@ -92,7 +93,11 @@ TOP:
                                    }
                                    cp1--;
                                    if (argc - 2 >= j) {
-                                       (void) strcpy(cp2, argv[j+1]);
+                                        if(cp2 + strlen(argv[j+1]) - line < sizeof(line))
+                                       (void) strncpy(cp2, argv[j+1],
+                                                      sizeof(line) - 1 -
+                                                      (cp2 - line));
+                                       line[sizeof(line) - 1] = '\0';
                                        cp2 += strlen(argv[j+1]);
                                    }
                                    break;
@@ -101,7 +106,11 @@ TOP:
                                        loopflg = 1;
                                        cp1++;
                                        if (count < argc) {
-                                          (void) strcpy(cp2, argv[count]);
+                                           if(cp2 + strlen(argv[j+1]) - line < sizeof(line))
+                                          (void) strncpy(cp2, argv[count],
+                                                         sizeof(line) - 1 -
+                                                         (cp2 - line));
+                                          line[sizeof(line) - 1] = '\0';
                                           cp2 += strlen(argv[count]);
                                        }
                                        break;
@@ -138,7 +147,8 @@ TOP:
                        if (bell && c->c_bell) {
                                (void) putchar('\007');
                        }
-                       (void) strcpy(line, line2);
+                       (void) strncpy(line, line2, sizeof(line) - 1);
+                       line[sizeof(line) - 1] = '\0';
                        makeargv();
                        argc = margc;
                        argv = margv;
index 11f583a6c893b6dc7b2451b15ae83827fe290000..a00850d95d9730571bc7b3d88efaeffa39f98c00 100644 (file)
@@ -680,9 +680,13 @@ getreply(expecteof)
                                  n = '5';
                                } else {
                                  if (debug) printf("%c:", safe ? 'S' : 'P');
-                                 memcpy(ibuf, msg_data.app_data,
-                                       msg_data.app_length);
-                                 strcpy(&ibuf[msg_data.app_length], "\r\n");
+                                 if(msg_data.app_length < sizeof(ibuf) - 2) {
+                                   memcpy(ibuf, msg_data.app_data,
+                                          msg_data.app_length);
+                                   strcpy(&ibuf[msg_data.app_length], "\r\n");
+                                 } else {
+                                   printf("Message too long!");
+                                 }
                                  continue;
                                }
 #endif
@@ -703,9 +707,14 @@ getreply(expecteof)
                                                 "failed unsealing reply");
                                  n = '5';
                                } else {
-                                 memcpy(ibuf, msg_buf.value, 
-                                        msg_buf.length);
-                                 strcpy(&ibuf[msg_buf.length], "\r\n");
+                                 if(msg_buf.length < sizeof(ibuf) - 2 - 1) {
+                                   memcpy(ibuf, msg_buf.value, 
+                                          msg_buf.length);
+                                   strcpy(&ibuf[msg_buf.length], "\r\n");
+                                 } else {
+                                   user_gss_error(maj_stat, min_stat, 
+                                                  "reply was too long");
+                                 }
                                  gss_release_buffer(&min_stat,&msg_buf);
                                  continue;
                                }
@@ -1636,20 +1645,24 @@ pswitch(flag)
        mcase = op->mcse;
        ip->ntflg = ntflag;
        ntflag = op->ntflg;
-       (void) strncpy(ip->nti, ntin, 16);
+       (void) strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
        (ip->nti)[strlen(ip->nti)] = '\0';
-       (void) strcpy(ntin, op->nti);
-       (void) strncpy(ip->nto, ntout, 16);
+       (void) strncpy(ntin, op->nti, sizeof(ntin) - 1);
+       ntin[sizeof(ntin) - 1] = '\0';
+       (void) strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
        (ip->nto)[strlen(ip->nto)] = '\0';
-       (void) strcpy(ntout, op->nto);
+       (void) strncpy(ntout, op->nto, sizeof(ntout) - 1);
+       ntout[sizeof(ntout) - 1] = '\0';
        ip->mapflg = mapflag;
        mapflag = op->mapflg;
        (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
        (ip->mi)[strlen(ip->mi)] = '\0';
-       (void) strcpy(mapin, op->mi);
+       (void) strncpy(mapin, op->mi, sizeof(mapin) - 1);
+       mapin[sizeof(mapin) - 1] = '\0';
        (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
        (ip->mo)[strlen(ip->mo)] = '\0';
-       (void) strcpy(mapout, op->mo);
+       (void) strncpy(mapout, op->mo, sizeof(mapout) - 1);
+       mapout[sizeof(mapout) - 1] = '\0';
        ip->authtype = auth_type;
        auth_type = op->authtype;
        ip->clvl = clevel;
@@ -1846,7 +1859,8 @@ gunique(local)
                fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
                return((char *) 0);
        }
-       (void) strcpy(new, local);
+       (void) strncpy(new, local, sizeof(new) - 3);
+       new[sizeof(new) - 1] = '\0';
        cp = new + strlen(new);
        *cp++ = '.';
        while (!d) {
@@ -2054,9 +2068,11 @@ do_auth()
            if (verbose)
                printf("%s accepted as authentication type\n", "KERBEROS_V4");
 
-           strcpy(inst, (char *) krb_get_phost(hostname));
+           strncpy(inst, (char *) krb_get_phost(hostname), sizeof(inst) - 1);
+           inst[sizeof(inst) - 1] = '\0';
            if (realm[0] == '\0')
-               strcpy(realm, (char *) krb_realmofhost(hostname));
+               strncpy(realm, (char *) krb_realmofhost(hostname), sizeof(realm) - 1);
+           realm[sizeof(realm) - 1] = '\0';
            if ((kerror = krb_mk_req(&ticket, service = "ftp",
                                        inst, realm, checksum))
                && (kerror != KDC_PR_UNKNOWN ||
index f92ee5e079785ed36eb631e9fcf3a9a00e8da77d..a5a6bf746d91c40fba817245fcd7ad5da9c598d4 100644 (file)
@@ -118,7 +118,7 @@ ftpglob(v)
 
        globerr = 0;
        gpath = agpath; gpathp = gpath; *gpathp = 0;
-       lastgpathp = &gpath[sizeof agpath - 2];
+       lastgpathp = &gpath[sizeof(agpath) - 1];
        ginit(agargv); globcnt = 0;
        collect(v);
        if (globcnt == 0 && (gflag&1)) {
@@ -198,7 +198,8 @@ expand(as)
                                        globerr = "Unknown user name after ~";
                                (void) strcpy(gpath, gpath + 1);
                        } else
-                               (void) strcpy(gpath, home);
+                               (void) strncpy(gpath, home, FTP_BUFSIZ - 1);
+                       gpath[FTP_BUFSIZ - 1] = '\0';
                        gpathp = strend(gpath);
                }
        }
@@ -324,8 +325,9 @@ pend:
 doit:
                savec = *pm;
                *pm = 0;
-               (void) strcpy(lm, pl);
-               (void) strcat(restbuf, pe + 1);
+               (void) strncpy(lm, pl, sizeof(restbuf) - 1 - (lm - restbuf));
+               restbuf[sizeof(restbuf) - 1] = '\0';
+               (void) strncat(restbuf, pe + 1, sizeof(restbuf) - 1 - strlen(restbuf));
                *pm = savec;
                if (s == 0) {
                        sgpathp = gpathp;
@@ -700,7 +702,7 @@ gethdir(home)
 {
        register struct passwd *pp = getpwnam(home);
 
-       if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
+       if (!pp || ((home + strlen(pp->pw_dir)) >= lastgpathp))
                return (1);
        (void) strcpy(home, pp->pw_dir);
        return (0);
index 9c1e43a863aa0e887bb2cbdede0112b628052e26..6c7e1e91b077e3d6275b7ee8de384f598b21590a 100644 (file)
@@ -193,7 +193,8 @@ main(argc, argv)
                pw = getpwuid(getuid());
        if (pw != NULL) {
                home = homedir;
-               (void) strcpy(home, pw->pw_dir);
+               (void) strncpy(home, pw->pw_dir, sizeof(homedir) - 1);
+               homedir[sizeof(homedir) - 1] = '\0';
        }
        if (argc > 0) {
                if (setjmp(toplevel))
index 48f57f93f94fecb5d77a64a4d8e07af38d15d6c9..e1f69b084abb37e95d4557d15fea00f0675d5f45 100644 (file)
@@ -52,6 +52,11 @@ extern struct        sockaddr_in myaddr;
 extern int     dlevel;
 extern char    *auth_type;
 
+/* Some libc's (GNU libc, at least) define MAX as a macro. Forget that. */
+#ifdef MAX
+#undef MAX
+#endif
+
 #define MAX maxbuf
 extern unsigned int maxbuf;    /* maximum output buffer size */
 extern unsigned char *ucbuf;   /* cleartext buffer */
index 388b4b270153ee969ea6d0ad6d33a2ab221bfff6..70f2112ce15b1d0f056183dab0f071eee5a3d628 100644 (file)
@@ -1,3 +1,11 @@
+2000-06-14  Tom Yu  <tlyu@mit.edu>
+
+       * ftpcmd.y (nonguest): Return $1, not 1, if (!guest).
+
+2000-05-11  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * ftpd.c (gunique): Make sure that path stored in "new" isn't too long.
+
 2000-02-18  Ken Raeburn  <raeburn@mit.edu>
 
        * ftpd.c (reply, lreply): Declare with format attribute under
index acd187112e729be7eabdc6c847afd5a7cc54e41c..bc252190ea2e229f9a50b6d9bd66dc5a7d5a6832 100644 (file)
@@ -865,7 +865,7 @@ nonguest: check_login
                        $$ = 0;
                }
                else
-                       $$ = 1;
+                       $$ = $1;
        }
        ;
 %%
index c7dfc8ad2766b5634810854be28ef8c6056e56aa..047be3562dfc64406a0de4de71360eec130e9a76 100644 (file)
@@ -2123,7 +2123,8 @@ gunique(local)
        }
        if (cp)
                *cp = '/';
-       (void) strcpy(new, local);
+       (void) strncpy(new, local, sizeof(new) - 1);
+       new[sizeof(new) - 1] = '\0';
        cp = new + strlen(new);
        *cp++ = '.';
        for (count = 1; count < 100; count++) {
@@ -2287,7 +2288,8 @@ char *data;
                        syslog(LOG_ERR, "Couldn't canonicalize local hostname");
                        return 0;
                }
-               strcpy(localname, hp->h_name);
+               strncpy(localname, hp->h_name, sizeof(localname) - 1);
+               localname[sizeof(localname) - 1] = '\0';
 
                for (service = gss_services; *service; service++) {
                        sprintf(service_name, "%s@%s", *service, localname);
index 03cb924fa5bd621b981df4114859a09155606769..8b71835eb29bda876a38938e133f77acdca20234 100644 (file)
@@ -1,3 +1,22 @@
+2000-05-11  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * gettytab.c (nchktc): Don't overflow tcname if tty type name is too
+       long
+       * kerberos.c (kerberos4_status): Make sure "UserNameRequested" is
+       always properly terminated.
+       * kerberos5.c (kerberos5_is): If bad principal name is too long to fit
+       in "errbuf", don't print it.
+       (kerberos5_status): Make sure "UserNameRequested" is always properly
+       terminated.
+       * spx.c (spx_status): Ditto.
+
+2000-04-28  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * kerberos5.c (kerberos5_is): Don't overflow buffer "errbuf".
+       * spx.c (spx_init, spx_send, spx_is): Don't overflow buffer
+       "targ_printable".
+       (spx_status): Don't overflow buffer "acl_file".
+
 1999-10-26  Wilfredo Sanchez  <tritan@mit.edu>
 
        * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
index f6ffb7c591ce7c359daf5c42218a97a5091a6a7f..aaad43aad7b8a7634493e1cddedda9338c3b3770 100644 (file)
@@ -98,9 +98,10 @@ nchktc()
        /* p now points to beginning of last field */
        if (p[0] != 't' || p[1] != 'c')
                return(1);
-       strcpy(tcname,p+3);
+       strncpy(tcname, p + 3, sizeof(tcname) - 1);
+       tcname[sizeof(tcname) - 1] = '\0';
        q = tcname;
-       while (q && *q != ':')
+       while (*q && *q != ':')
                q++;
        *q = 0;
        if (++hopcount > MAXHOP) {
index 734466e86c296f1198a4a56389c2f6854cec908d..eb657aee6135fe1634a830974dddd0e25b8fb0ad 100644 (file)
@@ -602,7 +602,9 @@ kerberos4_status(ap, name, level)
                return(level);
 
        if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
-               strcpy(name, UserNameRequested);
+               /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+               strncpy(name, UserNameRequested, 255);
+               name[255] = '\0';
                return(AUTH_VALID);
        } else
                return(AUTH_USER);
index 6a62f36a3d826143607e554cc890e39a3f96d95d..b4c73980b48135924754c655e92b9c7e92ff9d31 100644 (file)
@@ -423,7 +423,8 @@ kerberos5_is(ap, data, cnt)
                                    NULL, keytabid, NULL, &ticket);
                if (r) {
                        (void) strcpy(errbuf, "krb5_rd_req failed: ");
-                       (void) strcat(errbuf, error_message(r));
+                       errbuf[sizeof(errbuf) - 1] = '\0';
+                       (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
                        goto errout;
                }
 
@@ -440,8 +441,12 @@ kerberos5_is(ap, data, cnt)
                    princ[krb5_princ_component(telnet_context, 
                                               ticket->server,0)->length] = '\0';
                    if (strcmp("host", princ)) {
-                       (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"%s\"",
-                                      princ, "host");
+                        if(strlen(princ) < sizeof(errbuf) - 39) {
+                            (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"host\"",
+                                           princ);
+                        } else {
+                            (void) sprintf(errbuf, "incorrect service name: principal != \"host\"");
+                        }
                        goto errout;
                    }
                } else {
@@ -455,7 +460,8 @@ kerberos5_is(ap, data, cnt)
                if (r) {
                    (void) strcpy(errbuf,
                                  "krb5_auth_con_getauthenticator failed: ");
-                   (void) strcat(errbuf, error_message(r));
+                   errbuf[sizeof(errbuf) - 1] = '\0';
+                   (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
                    goto errout;
                }
                if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
@@ -476,7 +482,8 @@ kerberos5_is(ap, data, cnt)
                                             &key);
                    if (r) {
                        (void) strcpy(errbuf, "krb5_auth_con_getkey failed: ");
-                       (void) strcat(errbuf, error_message(r));
+                       errbuf[sizeof(errbuf) - 1] = '\0';
+                       (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
                        goto errout;
                    }
                    r = krb5_verify_checksum(telnet_context,
@@ -495,7 +502,8 @@ kerberos5_is(ap, data, cnt)
                    if (r) {
                        (void) strcpy(errbuf,
                                      "checksum verification failed: ");
-                       (void) strcat(errbuf, error_message(r));
+                       errbuf[sizeof(errbuf) - 1] = '\0';
+                       (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
                        goto errout;
                    }
                    krb5_free_keyblock(telnet_context, key);
@@ -506,7 +514,8 @@ kerberos5_is(ap, data, cnt)
                    if ((r = krb5_mk_rep(telnet_context, auth_context,
                                         &outbuf))) {
                        (void) strcpy(errbuf, "Make reply failed: ");
-                       (void) strcat(errbuf, error_message(r));
+                       errbuf[sizeof(errbuf) - 1] = '\0';
+                       (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
                        goto errout;
                    }
 
@@ -560,7 +569,8 @@ kerberos5_is(ap, data, cnt)
                    char errbuf[128];
                    
                    (void) strcpy(errbuf, "Read forwarded creds failed: ");
-                   (void) strcat(errbuf, error_message(r));
+                   errbuf[sizeof(errbuf) - 1] = '\0';
+                   (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
                    Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
                    if (auth_debug_mode)
                      printf(
@@ -586,7 +596,8 @@ kerberos5_is(ap, data, cnt)
            char eerrbuf[329];
 
            strcpy(eerrbuf, "telnetd: ");
-           strcat(eerrbuf, errbuf);
+           eerrbuf[sizeof(eerrbuf) - 1] = '\0';
+           strncat(eerrbuf, errbuf, sizeof(eerrbuf) - 1 - strlen(eerrbuf));
            Data(ap, KRB_REJECT, eerrbuf, -1);
        }
        if (auth_debug_mode)
@@ -706,7 +717,9 @@ kerberos5_status(ap, name, level)
            krb5_kuserok(telnet_context, ticket->enc_part2->client, 
                         UserNameRequested))
        {
-               strcpy(name, UserNameRequested);
+               /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+               strncpy(name, UserNameRequested, 255);
+               name[255] = '\0';
                return(AUTH_VALID);
        } else
                return(AUTH_USER);
index f23490f962695d29a6d7aef8ae5fb3f47c912467..7285d0dd39d1071a7154e58ff52f9c58a25fee60 100644 (file)
@@ -173,7 +173,8 @@ spx_init(ap, server)
                str_data[3] = TELQUAL_REPLY;
                gethostname(lhostname, sizeof(lhostname));
                strcpy(targ_printable, "SERVICE:rcmd@");
-               strcat(targ_printable, lhostname);
+               strncat(targ_printable, lhostname, sizeof(targ_printable) - 1 - 13);
+               targ_printable[sizeof(targ_printable) - 1] = '\0';
                input_name_buffer.length = strlen(targ_printable);
                input_name_buffer.value = targ_printable;
                major_status = gss_import_name(&status,
@@ -216,7 +217,8 @@ spx_send(ap)
 
        printf("[ Trying SPX ... ]\n");
        strcpy(targ_printable, "SERVICE:rcmd@");
-       strcat(targ_printable, RemoteHostName);
+       strncat(targ_printable, RemoteHostName, sizeof(targ_printable) - 1 - 13);
+       targ_printable[sizeof(targ_printable) - 1] = '\0';
 
        input_name_buffer.length = strlen(targ_printable);
        input_name_buffer.value = targ_printable;
@@ -324,7 +326,8 @@ spx_is(ap, data, cnt)
                gethostname(lhostname, sizeof(lhostname));
 
                strcpy(targ_printable, "SERVICE:rcmd@");
-               strcat(targ_printable, lhostname);
+               strncat(targ_printable, lhostname, sizeof(targ_printable) - 1 - 13);
+               targ_printable[sizeof(targ_printable) - 1] = '\0';
 
                input_name_buffer.length = strlen(targ_printable);
                input_name_buffer.value = targ_printable;
@@ -479,7 +482,7 @@ spx_status(ap, name, level)
 
        gss_buffer_desc  fullname_buffer, acl_file_buffer;
        gss_OID          fullname_type;
-        char acl_file[160], fullname[160];
+        char acl_file[MAXPATHLEN], fullname[160];
         int major_status, status = 0;
        struct passwd  *pwd;
 
@@ -494,8 +497,9 @@ spx_status(ap, name, level)
           return(AUTH_USER);   /*  not authenticated  */
         }
 
-       strcpy(acl_file, pwd->pw_dir);
-       strcat(acl_file, "/.sphinx");
+       acl_file[sizeof(acl_file) - 1] = '\0';
+       strncpy(acl_file, pwd->pw_dir, sizeof(acl_file) - 1);
+       strncat(acl_file, "/.sphinx", sizeof(acl_file) - 1 - strlen(acl_file));
         acl_file_buffer.value = acl_file;
         acl_file_buffer.length = strlen(acl_file);
 
@@ -511,7 +515,9 @@ spx_status(ap, name, level)
                                       &acl_file_buffer);
 
         if (major_status == GSS_S_COMPLETE) {
-         strcpy(name, UserNameRequested);
+          /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+         strncpy(name, UserNameRequested, 255);
+         name[255] = '\0';
          return(AUTH_VALID);
         } else {
            return(AUTH_USER);
index d8a341e9c0545067dce3bd70ea5a02dcce2bf4c4..b8f209c30b373575b510d23e5c3cebc7a541ad5f 100644 (file)
@@ -1,3 +1,18 @@
+2000-05-11  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * commands.c (makeargv): Don't overflow buffer "saveline".
+       (tn): Don't overflow buffer "_hostname".
+       (cmdrc): Don't overflow buffer "m1save".
+       * externs.h: Include the size of "tline", so that we can check for
+       overflows elsewhere.
+       * main.c(main, tn370): Don't overflow buffer "tline".
+       * utilities.c (SetNetTrace): Don't overflow buffer "NetTraceFile".
+
+2000-04-28  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * commands.c (cmdrc): Don't overflow buffer "rcbuf".
+       * tn3270.c (settranscom): Don't overflow buffer "transcom".
+
 2000-02-24  Ezra Peisach  <epeisach@mit.edu>
 
        * configure.in: Remove dependency on libdes425 when krb4 support
index 2c80b0b25dea3aa577c641915ee4efdec867f180..8ffba2e32239e78770c2d352e9bc7b4d3ba621e2 100644 (file)
@@ -138,7 +138,9 @@ makeargv()
     margc = 0;
     cp = line;
     if (*cp == '!') {          /* Special case shell escape */
-       strcpy(saveline, line); /* save for shell command */
+       strncpy(saveline, line, sizeof(saveline) - 1);
+                               /* save for shell command */
+       saveline[sizeof(saveline)  - 1] = '\0';
        *argp++ = "!";          /* No room in string to get this */
        margc++;
        cp++;
@@ -2450,7 +2452,8 @@ tn(argc, argv)
        if (temp & 0xffffffff != INADDR_NONE) {
            sin.sin_addr.s_addr = temp;
            sin.sin_family = AF_INET;
-           (void) strcpy(_hostname, hostp);  
+           (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);  
+           _hostname[sizeof(_hostname) - 1] = '\0';
            hostname = _hostname;
        } else {
            host = gethostbyname(hostp);
@@ -2855,16 +2858,18 @@ cmdrc(m1, m2)
     if (skiprc)
        return;
 
-    strcpy(m1save, m1);
+    strncpy(m1save, m1, sizeof(m1save) - 1);
+    m1save[sizeof(m1save) - 1] = '\0';
     m1 = m1save;
 
     if (rcname == 0) {
        rcname = getenv("HOME");
        if (rcname)
-           strcpy(rcbuf, rcname);
+           strncpy(rcbuf, rcname, sizeof(rcbuf) - 1);
        else
            rcbuf[0] = '\0';
-       strcat(rcbuf, "/.telnetrc");
+       rcbuf[sizeof(rcbuf) - 1] = '\0';
+       strncat(rcbuf, "/.telnetrc", sizeof(rcbuf) - 1 - strlen(rcbuf));
        rcname = rcbuf;
     }
 
index e9939865ef24ea9497e106aa84c9e49b6455f946..f35cdedaf837701f0d29ac126a9a9b99176c552c 100644 (file)
@@ -486,7 +486,7 @@ extern char
     *Ibackp,           /* Oldest byte of 3270 data */
     Ibuf[],            /* 3270 buffer */
     *Ifrontp,          /* Where next 3270 byte goes */
-    tline[],
+    tline[200],
     *transcom;         /* Transparent command */
 
 extern int
index da98ae6df825835809cc977779c6e0e2f1e15ea7..7696857c7bfeb82901c9706d54ea5005e99cae0b 100644 (file)
@@ -274,7 +274,8 @@ main(argc, argv)
                case 't':
 #if defined(TN3270) && defined(unix)
                        transcom = tline;
-                       (void)strcpy(transcom, optarg);
+                       (void)strncpy(transcom, optarg, sizeof(tline) - 1);
+                       tline[sizeof(tline) - 1] = '\0';
 #else
                        fprintf(stderr,
                           "%s: Warning: -t ignored, no TN3270 support.\n",
index 77aedaf8993f5018634e7b8af2b08f8c7d183cba..c46ae7eb8a7310d11a5d5c4c9af9caa878f36761 100644 (file)
@@ -397,10 +397,11 @@ settranscom(argc, argv)
           return 1;
        }
        transcom = tline;
-       (void) strcpy(transcom, argv[1]);
+       (void) strncpy(transcom, argv[1], sizeof(tline) - 1);
+       tline[sizeof(tline) - 1] = '\0';
        for (i = 2; i < argc; ++i) {
-           (void) strcat(transcom, " ");
-           (void) strcat(transcom, argv[i]);
+           (void) strncat(transcom, " ", sizeof(tline) - 1 - (transcom - tline));
+           (void) strncat(transcom, argv[i], sizeof(tline) - 1 - (transcom - tline));
        }
        return 1;
 }
index 19f503bd44146a58b085f3056116f93cdc429467..82ad8417821ff0db70c55f20d13c5ecac93af1d8 100644 (file)
@@ -113,13 +113,15 @@ SetNetTrace(file)
     if (file  && (strcmp(file, "-") != 0)) {
        NetTrace = fopen(file, "w");
        if (NetTrace) {
-           strcpy((char *)NetTraceFile, file);
+           strncpy((char *)NetTraceFile, file, sizeof(NetTraceFile) - 1);
+           NetTraceFile[sizeof(NetTraceFile) - 1] = '\0';
            return;
        }
        fprintf(stderr, "Cannot open %s.\n", file);
     }
     NetTrace = stdout;
-    strcpy((char *)NetTraceFile, "(standard output)");
+    strncpy((char *)NetTraceFile, "(standard output)", sizeof(NetTraceFile) - 1);
+    NetTraceFile[sizeof(NetTraceFile) - 1] = '\0';
 }
 
     void
index 800c9f87ad920481f1f4fde9f1f7ddfea2bb51f0..ce2686f53ce7b2c2422826e125b9890f3298e1e8 100644 (file)
@@ -1,3 +1,16 @@
+2000-06-29  Tom Yu  <tlyu@mit.edu>
+
+       * telnetd.c (doit): Change test for "no authentication" as per
+       Jeffrey Altman's patch.
+
+2000-06-29  Nalin Dahyabhai  <nalin@redhat.com>
+
+       * sys_term.c (start_login, Solaris): forcefully terminate "termbuf"
+       in case the "TERM" environment variable isn't.
+       * telnet-ktd.c (getterminaltype): Don't overflow buffers "first" and
+       "netobuf".
+       (recv_ayt): Forcibly terminate buffer "netobuf".
+
 2000-05-31  Wilfredo Sanchez  <tritan@mit.edu>
 
        * configure.in, defs.h: Check for existance of <memory.h>.
index ee8d53d4695d1a6a98f92fab716f8750dd5e838f..b79209d57a07b909930691b60d103b82f4a4584f 100644 (file)
@@ -1257,6 +1257,7 @@ start_login(host, autologin, name)
                } else {
                        strcpy(termbuf, "TERM=");
                        strncat(termbuf, term, sizeof(termbuf) - 6);
+                       termbuf[sizeof(termbuf) - 1] = '\0';
                        term = termbuf;
                }
                argv = addarg(argv, term);
index 9ec608fcdb8c239961fa6a9bac73bbd7ed12c27a..5936e3b5aef619fa066c7b20af94610d8d457103 100644 (file)
@@ -360,7 +360,7 @@ main(argc, argv)
            }
            (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                                (char *)&on, sizeof(on));
-           if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
+           if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
                perror("bind");
                exit(1);
            }
@@ -368,7 +368,7 @@ main(argc, argv)
                perror("listen");
                exit(1);
            }
-           foo = sizeof sin;
+           foo = sizeof(sin);
            ns = accept(s, (struct sockaddr *)&sin, &foo);
            if (ns < 0) {
                perror("accept");
@@ -548,25 +548,33 @@ getterminaltype(name)
     if (his_state_is_will(TELOPT_TSPEED)) {
        static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
 
-       memcpy(nfrontp, sbbuf, sizeof sbbuf);
-       nfrontp += sizeof sbbuf;
+       if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+               memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+               nfrontp += sizeof(sbbuf);
+       }
     }
     if (his_state_is_will(TELOPT_XDISPLOC)) {
        static char sbbuf[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
 
-       memcpy(nfrontp, sbbuf, sizeof sbbuf);
-       nfrontp += sizeof sbbuf;
+       if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+               memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+               nfrontp += sizeof(sbbuf);
+       }
     }
     if (his_state_is_will(TELOPT_ENVIRON)) {
        static char sbbuf[] = { IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE };
 
-       memcpy(nfrontp, sbbuf, sizeof sbbuf);
-       nfrontp += sizeof sbbuf;
+       if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+               memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+               nfrontp += sizeof(sbbuf);
+       }
     }
     if (his_state_is_will(TELOPT_TTYPE)) {
 
-       memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
-       nfrontp += sizeof ttytype_sbbuf;
+       if(nfrontp - netobuf + sizeof(ttytype_sbbuf) < sizeof(netobuf)) {
+               memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+               nfrontp += sizeof(ttytype_sbbuf);
+       }
     }
     if (his_state_is_will(TELOPT_TSPEED)) {
        while (sequenceIs(tspeedsubopt, baseline))
@@ -591,12 +599,14 @@ getterminaltype(name)
         * we have to just go with what we (might) have already gotten.
         */
        if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
-           (void) strncpy(first, terminaltype, sizeof(first));
+           (void) strncpy(first, terminaltype, sizeof(first) - 1);
+           first[sizeof(first) - 1] = '\0';
            for(;;) {
                /*
                 * Save the unknown name, and request the next name.
                 */
-               (void) strncpy(last, terminaltype, sizeof(last));
+               (void) strncpy(last, terminaltype, sizeof(last) - 1);
+               last[sizeof(last) - 1] = '\0';
                _gettermname();
                if (terminaltypeok(terminaltype))
                    break;
@@ -615,7 +625,8 @@ getterminaltype(name)
                     */
                     _gettermname();
                    if (strncmp(first, terminaltype, sizeof(first)) != 0)
-                       (void) strncpy(terminaltype, first, sizeof(first));
+                       (void) strncpy(terminaltype, first, sizeof(terminaltype) - 1);
+                   terminaltype[sizeof(terminaltype) - 1] = '\0';
                    break;
                }
            }
@@ -635,8 +646,8 @@ _gettermname()
     if (his_state_is_wont(TELOPT_TTYPE))
        return;
     settimer(baseline);
-    memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
-    nfrontp += sizeof ttytype_sbbuf;
+    memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+    nfrontp += sizeof(ttytype_sbbuf);
     while (sequenceIs(ttypesubopt, baseline))
        ttloop();
 }
@@ -922,7 +933,7 @@ telnet(f, p, host)
 
 #if    defined(SO_OOBINLINE)
        (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
-                               (char *)&on, sizeof on);
+                               (char *)&on, sizeof(on));
 #endif /* defined(SO_OOBINLINE) */
 
 #ifdef SIGTSTP
@@ -989,8 +1000,10 @@ telnet(f, p, host)
                HE = getstr("he", &cp);
                HN = getstr("hn", &cp);
                IM = getstr("im", &cp);
-               if (HN && *HN)
-                       (void) strcpy(host_name, HN);
+               if (HN && *HN) {
+                       (void) strncpy(host_name, HN, sizeof(host_name) - 1);
+                       host_name[sizeof(host_name) - 1] = '\0';
+               }
                if (IM == 0)
                        IM = "";
        } else {
@@ -1426,8 +1439,10 @@ recv_ayt()
                return;
        }
 #endif
-       (void) strcpy(nfrontp, "\r\n[Yes]\r\n");
+       (void) strncpy(nfrontp, "\r\n[Yes]\r\n",
+                      sizeof(netobuf) - 1 - (nfrontp - netobuf));
        nfrontp += 9;
+       *nfrontp = '\0';
 }
 
        void
index 726746967bf76fe79f36e62cf32f89be7d629364..f103488cb82a3bd22df654a1c425017500b19ccc 100644 (file)
@@ -522,7 +522,7 @@ main(argc, argv)
            }
            (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                                (char *)&on, sizeof(on));
-           if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
+           if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
                perror("bind");
                exit(1);
            }
@@ -530,7 +530,7 @@ main(argc, argv)
                perror("listen");
                exit(1);
            }
-           foo = sizeof sin;
+           foo = sizeof(sin);
            ns = accept(s, (struct sockaddr *)&sin, &foo);
            if (ns < 0) {
                perror("accept");
@@ -781,34 +781,49 @@ getterminaltype(name)
        static unsigned char sb[] =
                        { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
 
-       memcpy(nfrontp, sb, sizeof sb);
-       nfrontp += sizeof sb;
+       if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) {
+           memcpy(nfrontp, sb, sizeof(sb));
+           nfrontp += sizeof(sb);
+           *nfrontp = '\0';
+       }
     }
     if (his_state_is_will(TELOPT_XDISPLOC)) {
        static unsigned char sb[] =
                        { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
 
-       memcpy(nfrontp, sb, sizeof sb);
-       nfrontp += sizeof sb;
+       if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) {
+           memcpy(nfrontp, sb, sizeof(sb));
+           nfrontp += sizeof(sb);
+           *nfrontp = '\0';
+       }
     }
     if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
        static unsigned char sb[] =
                        { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
 
-       memcpy(nfrontp, sb, sizeof sb);
-       nfrontp += sizeof sb;
+       if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) {
+           memcpy(nfrontp, sb, sizeof(sb));
+           nfrontp += sizeof(sb);
+           *nfrontp = '\0';
+       }
     }
     else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
        static unsigned char sb[] =
                        { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
 
-       memcpy(nfrontp, sb, sizeof sb);
-       nfrontp += sizeof sb;
+       if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) {
+           memcpy(nfrontp, sb, sizeof(sb));
+           nfrontp += sizeof(sb);
+           *nfrontp = '\0';
+       }
     }
     if (his_state_is_will(TELOPT_TTYPE)) {
 
-       memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
-       nfrontp += sizeof ttytype_sbbuf;
+       if(nfrontp - netobuf + sizeof(ttytype_sbbuf) < sizeof(netobuf)) {
+           memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+           nfrontp += sizeof(ttytype_sbbuf);
+           *nfrontp = '\0';
+       }
     }
     if (his_state_is_will(TELOPT_TSPEED)) {
        while (sequenceIs(tspeedsubopt, baseline))
@@ -886,8 +901,11 @@ _gettermname()
     if (his_state_is_wont(TELOPT_TTYPE))
        return;
     settimer(baseline);
-    memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
-    nfrontp += sizeof ttytype_sbbuf;
+    if(nfrontp - netobuf + sizeof(ttytype_sbbuf)) {
+       memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+       nfrontp += sizeof(ttytype_sbbuf);
+       *nfrontp = '\0';
+    }
     while (sequenceIs(ttypesubopt, baseline))
        ttloop();
 }
@@ -1009,7 +1027,7 @@ pty_init();
        setenv("TERM", *terminaltype ? terminaltype : "network", 1);
 
 #if defined (AUTHENTICATION)
-       if (user_name[0] == '\0') {
+       if (level < 0 && auth_level > 0) {
                fatal (net, "No authentication provided");
                exit (-1);
        }
@@ -1205,7 +1223,7 @@ telnet(f, p, host)
 
 #if    defined(SO_OOBINLINE)
        (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
-                               (char *)&on, sizeof on);
+                               (char *)&on, sizeof(on));
 #endif /* defined(SO_OOBINLINE) */
 
 #ifdef SIGTSTP
@@ -1266,7 +1284,8 @@ telnet(f, p, host)
                HN = getstr("hn", &cp);
                IM = getstr("im", &cp);
                if (HN && *HN)
-                       (void) strcpy(host_name, HN);
+                       (void) strncpy(host_name, HN, sizeof(host_name) - 1);
+               host_name[sizeof(host_name) - 1] = '\0';
                if (IM == 0)
                        IM = "";
        } else {
@@ -1688,8 +1707,10 @@ recv_ayt()
                return;
        }
 #endif
-       (void) strcpy(nfrontp, "\r\n[Yes]\r\n");
+       (void) strncpy(nfrontp, "\r\n[Yes]\r\n",
+                      sizeof(netobuf) - 1 - (nfrontp - netobuf));
        nfrontp += 9;
+       *nfrontp = '\0';
 }
 
        void