aboutsummaryrefslogtreecommitdiff
path: root/src/appl
diff options
context:
space:
mode:
Diffstat (limited to 'src/appl')
-rw-r--r--src/appl/bsd/ChangeLog220
-rw-r--r--src/appl/bsd/Makefile.in1
-rw-r--r--src/appl/bsd/configure.in14
-rw-r--r--src/appl/bsd/defines.h44
-rw-r--r--src/appl/bsd/forward.c2
-rw-r--r--src/appl/bsd/kcmd.c197
-rw-r--r--src/appl/bsd/krcp.c131
-rw-r--r--src/appl/bsd/krlogin.c316
-rw-r--r--src/appl/bsd/krlogind.c84
-rw-r--r--src/appl/bsd/krsh.c57
-rw-r--r--src/appl/bsd/krshd.c83
-rw-r--r--src/appl/bsd/login.M2
-rw-r--r--src/appl/bsd/login.c105
-rw-r--r--src/appl/bsd/loginpaths.h2
-rw-r--r--src/appl/bsd/rcp.M12
-rw-r--r--src/appl/bsd/rlogin.M11
-rw-r--r--src/appl/bsd/rsh.M11
-rw-r--r--src/appl/bsd/v4rcp.c24
-rw-r--r--src/appl/gssftp/ChangeLog9
-rw-r--r--src/appl/gssftp/configure.in4
-rw-r--r--src/appl/gssftp/ftp/ChangeLog47
-rw-r--r--src/appl/gssftp/ftp/cmds.c23
-rw-r--r--src/appl/gssftp/ftp/domacro.c18
-rw-r--r--src/appl/gssftp/ftp/ftp.c48
-rw-r--r--src/appl/gssftp/ftp/glob.c20
-rw-r--r--src/appl/gssftp/ftp/main.c3
-rw-r--r--src/appl/gssftp/ftp/secure.c97
-rw-r--r--src/appl/gssftp/ftpd/ChangeLog65
-rw-r--r--src/appl/gssftp/ftpd/ftpcmd.y253
-rw-r--r--src/appl/gssftp/ftpd/ftpd.c198
-rw-r--r--src/appl/sample/sclient/ChangeLog6
-rw-r--r--src/appl/sample/sclient/sclient.c2
-rw-r--r--src/appl/telnet/libtelnet/ChangeLog38
-rw-r--r--src/appl/telnet/libtelnet/configure.in8
-rw-r--r--src/appl/telnet/libtelnet/gettytab.c5
-rw-r--r--src/appl/telnet/libtelnet/kerberos.c16
-rw-r--r--src/appl/telnet/libtelnet/kerberos5.c51
-rw-r--r--src/appl/telnet/libtelnet/setenv.c6
-rw-r--r--src/appl/telnet/libtelnet/spx.c20
-rw-r--r--src/appl/telnet/telnet/ChangeLog15
-rw-r--r--src/appl/telnet/telnet/commands.c15
-rw-r--r--src/appl/telnet/telnet/externs.h2
-rw-r--r--src/appl/telnet/telnet/main.c3
-rw-r--r--src/appl/telnet/telnet/tn3270.c7
-rw-r--r--src/appl/telnet/telnet/utilities.c6
-rw-r--r--src/appl/telnet/telnetd/ChangeLog67
-rw-r--r--src/appl/telnet/telnetd/authenc.c17
-rw-r--r--src/appl/telnet/telnetd/configure.in2
-rw-r--r--src/appl/telnet/telnetd/ext.h9
-rw-r--r--src/appl/telnet/telnetd/slc.c2
-rw-r--r--src/appl/telnet/telnetd/state.c39
-rw-r--r--src/appl/telnet/telnetd/sys_term.c1
-rw-r--r--src/appl/telnet/telnetd/telnetd-ktd.c53
-rw-r--r--src/appl/telnet/telnetd/telnetd.c74
-rw-r--r--src/appl/telnet/telnetd/termstat.c20
-rw-r--r--src/appl/telnet/telnetd/utility.c682
56 files changed, 2223 insertions, 1044 deletions
diff --git a/src/appl/bsd/ChangeLog b/src/appl/bsd/ChangeLog
index d3314b0..73c12dc 100644
--- a/src/appl/bsd/ChangeLog
+++ b/src/appl/bsd/ChangeLog
@@ -1,3 +1,223 @@
+2002-01-25 Ken Raeburn <raeburn@mit.edu>
+
+ * login.c (main): Fix fencepost error in last change.
+
+2001-12-21 Ken Raeburn <raeburn@mit.edu>
+
+ * loginpaths.h [_PATH_DEFPATH]: Undefine LPATH and RPATH before
+ redefining them.
+ * login.c (main): If the supplied name is longer than the utmp
+ buffer, don't bother trying it as a username.
+ (dolastlog): Don't assume lastlog.ll_time is a time_t.
+
+2001-01-13 Sam Hartman <hartmans@mit.edu>
+
+ * configure.in: Force SunOS to not use termios.
+ [pullup 5.89->5.90 from trunk]
+
+2001-01-12 Sam Hartman <hartmans@mit.edu>
+
+ * krlogin.c: Previously, we only used TIOCGLTC on systems with
+ termios. This is sort of silly since its a BSD 4.[23] IOCTL. We
+ then go out of our way not to use it on IRIX, Solaris or HPUX. I
+ think all this comes about because you really want to use BSD
+ IOCTLS on Sunos rather than termios. I propose to do that and
+ never [s/never/only/? --tlyu] use BSD IOCTLs on Sunos.
+ [pullup 5.68->5.69 from trunk]
+
+2001-09-07 Tom Yu <tlyu@mit.edu>
+
+ * krlogind.c (protocol): Don't do TIOCPKT on systems with STREAMS
+ ptys, even if there is a TIOCPKT, since it may result in hangs on
+ some systems where BSD packet mode is (presumably) not implemented
+ properly, such as AIX 4.3.3. Should get cleaned up at some later
+ point to actually I_PUSH "pckt" or equivalent and do translation
+ between STREAMS and BSD style packet mode.
+ [pullup from trunk]
+
+2001-02-16 Tom Yu <tlyu@mit.edu>
+
+ * login.M: Don't include "= 0" as part of the "accept_passwd"
+ config option.
+
+2001-01-26 Tom Yu <tlyu@mit.edu>
+
+ * krshd.c: Get path for NOLOGIN file from paths.h if present,
+ mirroring logic in login.c. [patch from David MacKenzie
+ krb5-appl/913, pulled up from trunk]
+
+2001-01-26 Tom Yu <tlyu@mit.edu>
+
+ * krlogin.c (read_wrapper): Copy from the current point and not
+ the start of the cached buffer. [pullup from trunk]
+
+2001-01-23 Tom Yu <tlyu@mit.edu>
+
+ * forward.c (rd_and_store_for_creds): Overwrite any existing value
+ of the KRB5CCNAME environment variable.
+
+2000-07-19 Peter S Litwack <plitwack@mit.edu>
+
+ * krlogin.c (writer): Improved bandwith efficiency by reading
+ and sending more than one character at a time if multiple
+ characters are available to be read from the terminal.
+ * krlogin.c (read_wrapper): Added this function as a helper
+ to writer. It facilitates checking for escape sequences
+ (~^Z etc.) when reading mulitple characters at a time.
+
+2000-06-29 Ken Raeburn <raeburn@mit.edu>
+
+ Patch from Donn Cave and Leonard Peirce from 1.1 release cycle:
+ * login.c (k_init): Call krb5_cc_set_default_name right after
+ setting the environment variable.
+ (main): Likewise.
+
+2000-06-23 Ken Raeburn <raeburn@mit.edu>
+
+ * rcp.M, rsh.M, rlogin.M: Add description of new -PO, -PN
+ options.
+
+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>
diff --git a/src/appl/bsd/Makefile.in b/src/appl/bsd/Makefile.in
index eee13ca..93a6cba 100644
--- a/src/appl/bsd/Makefile.in
+++ b/src/appl/bsd/Makefile.in
@@ -90,3 +90,4 @@ install::
getdtablesize.o: $(srcdir)/getdtablesize.c
+kcmd.o krcp.o krlogin.o krlogind.o krsh.o krshd.o : defines.h
diff --git a/src/appl/bsd/configure.in b/src/appl/bsd/configure.in
index 6d31f48..051af51 100644
--- a/src/appl/bsd/configure.in
+++ b/src/appl/bsd/configure.in
@@ -25,16 +25,20 @@ 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"
)
;;
+*-*-sunos4*)
+ ac_cv_header_termios_h=no
+ ;;
esac
dnl
dnl After beta6 this functionality will be integrated with aclocal.m4
diff --git a/src/appl/bsd/defines.h b/src/appl/bsd/defines.h
index fd9c3e1..6365d2c 100644
--- a/src/appl/bsd/defines.h
+++ b/src/appl/bsd/defines.h
@@ -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);
diff --git a/src/appl/bsd/forward.c b/src/appl/bsd/forward.c
index e22fc1d..e47b8ff 100644
--- a/src/appl/bsd/forward.c
+++ b/src/appl/bsd/forward.c
@@ -51,7 +51,7 @@ rd_and_store_for_creds(context, auth_context, inbuf, ticket, ccache)
*/
sprintf(ccname, "FILE:/tmp/krb5cc_p%d", getpid());
- setenv("KRB5CCNAME", ccname, 0);
+ setenv("KRB5CCNAME", ccname, 1);
if (retval = krb5_cc_resolve(context, ccname, ccache))
goto cleanup;
diff --git a/src/appl/bsd/kcmd.c b/src/appl/bsd/kcmd.c
index 0e68f88..3e401cc 100644
--- a/src/appl/bsd/kcmd.c
+++ b/src/appl/bsd/kcmd.c
@@ -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
diff --git a/src/appl/bsd/krcp.c b/src/appl/bsd/krcp.c
index 9670145..7292e72 100644
--- a/src/appl/bsd/krcp.c
+++ b/src/appl/bsd/krcp.c
@@ -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);
diff --git a/src/appl/bsd/krlogin.c b/src/appl/bsd/krlogin.c
index da4a889..02a8d30 100644
--- a/src/appl/bsd/krlogin.c
+++ b/src/appl/bsd/krlogin.c
@@ -138,12 +138,6 @@ char copyright[] =
#endif
#endif
-/* how do we tell apart irix 5 and irix 4? */
-#if defined(__sgi) && defined(__mips)
-/* IRIX 5: TIOCGLTC doesn't actually work */
-#undef TIOCGLTC
-#endif
-
#ifndef TIOCPKT_NOSTOP
/* These values are over-the-wire protocol, *not* local values */
#define TIOCPKT_NOSTOP 0x10
@@ -177,6 +171,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,7 +372,8 @@ 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], '/'))
argv[0] = strrchr(argv[0], '/')+1;
@@ -502,6 +498,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 +565,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 +574,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 +639,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 +662,20 @@ main(argc, argv)
try_normal(orig_argv);
#endif
} else {
- krb5_boolean similar;
-
- rcmd_stream_init_krb5(&cred->keyblock, encrypt_flag, 1);
+ krb5_keyblock *key = 0;
- 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) {
+ 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;
@@ -755,6 +768,8 @@ struct tchars {
};
#endif
+
+#ifndef POSIX_TERMIOS
#ifdef TIOCGLTC
/*
* POSIX 1003.1-1988 does not define a 'suspend' character.
@@ -768,14 +783,8 @@ struct tchars {
struct ltchars defltc;
struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
#endif
-
-#ifndef POSIX_TERMIOS
struct tchars deftc;
struct tchars notc = { -1, -1, -1, -1, -1, -1 };
-#ifndef TIOCGLTC
-struct ltchars defltc;
-struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
-#endif
#endif
doit(oldmask)
@@ -793,9 +802,6 @@ doit(oldmask)
/* there's a POSIX way of doing this, but do we need it general? */
deftty.c_cc[VLNEXT] = 0;
#endif
-#ifdef TIOCGLTC
- (void) ioctl(0, TIOCGLTC, (char *)&defltc);
-#endif
#else
#ifdef USE_TERMIO
struct termio sb;
@@ -1035,13 +1041,15 @@ int signo;
*/
writer()
{
- unsigned char c;
- register n;
- register bol = 1; /* beginning of line */
- register local = 0;
-
+ int n_read;
+ char buf[1024];
+ int got_esc; /* set to true by read_wrapper if an escape char
+ was encountered */
+ char c;
+
#ifdef ultrix
fd_set waitread;
+ register n;
/* we need to wait until the reader() has set up the terminal, else
the read() below may block and not unblock when the terminal
@@ -1062,89 +1070,169 @@ writer()
}
}
#endif /* ultrix */
+
+ /* This loop works as follows. Call read_wrapper to get data until
+ we would block or until we read a cmdchar at the beginning of a line.
+ If got_esc is false, we just send everything we got back. If got_esc
+ is true, we send everything except the cmdchar at the end and look at
+ the next char. If its a "." we break out of the loop and terminate.
+ If its ^Z or ^Y we call stop with the value of the char and continue.
+ If its none of those, we send the cmdchar and then send the char we
+ just read, unless that char is also the cmdchar (in which case we are
+ only supposed to send one of them). When this loop ends, so does the
+ program.
+ */
+
for (;;) {
- n = read(0, &c, 1);
- if (n <= 0) {
- if (n < 0 && errno == EINTR)
- continue;
+
+ /* read until we would block or we get a cmdchar */
+ n_read = read_wrapper(0,buf,sizeof(buf),&got_esc);
+
+ /* if read returns an error or 0 bytes, just quit */
+ if (n_read <= 0) {
+ break;
+ }
+
+ if (!got_esc) {
+ if (rcmd_stream_write(rem, buf, n_read, 0) == 0) {
+ prf("line gone");
+ break;
+ }
+ continue;
+ }
+ else {
+ /* This next test is necessary to avoid sending 0 bytes of data
+ in the event that we got just a cmdchar */
+ if (n_read > 1) {
+ if (rcmd_stream_write(rem, buf, n_read-1, 0) == 0) {
+ prf("line gone");
break;
+ }
}
- /*
- * If we're at the beginning of the line
- * and recognize a command character, then
- * we echo locally. Otherwise, characters
- * are echo'd remotely. If the command
- * character is doubled, this acts as a
- * force and local echo is suppressed.
- */
- if (bol) {
- bol = 0;
- if (c == cmdchar) {
- bol = 0;
- local = 1;
- continue;
- }
- } else if (local) {
- local = 0;
+ if (read_wrapper(0,&c,1,&got_esc) <= 0) {
+ break;
+ }
+
#ifdef POSIX_TERMIOS
- if (c == '.' || c == deftty.c_cc[VEOF]) {
+ if (c == '.' || c == deftty.c_cc[VEOF])
#else
- if (c == '.' || c == deftc.t_eofc) {
+ if (c == '.' || c == deftc.t_eofc)
#endif
- if (confirm_death()) {
- echo(c);
- break;
- }
- }
-#ifdef TIOCGLTC
- if ((c == defltc.t_suspc || c == defltc.t_dsuspc)
- && !no_local_escape) {
- bol = 1;
+ {
+ if (confirm_death()) {
echo(c);
- stop(c);
- continue;
+ break;
+ }
}
-#else
+
#ifdef POSIX_TERMIOS
- if ( (
- (c == deftty.c_cc[VSUSP])
+ if ( (
+ (c == deftty.c_cc[VSUSP])
#ifdef VDSUSP
- || (c == deftty.c_cc[VDSUSP])
-#endif
- )
- && !no_local_escape) {
- bol = 1;
- echo(c);
- stop(c);
- continue;
- }
+ || (c == deftty.c_cc[VDSUSP])
#endif
+ )
+ && !no_local_escape) {
+ echo(c);
+ stop(c);
+ continue;
+ }
+#else /*POSIX_TERMIOS*/
+#ifdef TIOCGLTC
+ if ((c == defltc.t_suspc || c == defltc.t_dsuspc)
+ && !no_local_escape) {
+ echo(c);
+ stop(c);
+ continue;
+ }
+#endif /*TIOCGLTC*/
#endif
- if (c != cmdchar)
- (void) rcmd_stream_write(rem, &cmdchar, 1);
+
+ if (c != cmdchar) {
+ rcmd_stream_write(rem, &cmdchar, 1, 0);
}
- if (rcmd_stream_write(rem, &c, 1) == 0) {
- prf("line gone");
- break;
+
+ if (rcmd_stream_write(rem,&c,1,0) == 0) {
+ prf("line gone");
+ break;
}
-#ifdef POSIX_TERMIOS
- bol = (c == deftty.c_cc[VKILL] ||
- c == deftty.c_cc[VINTR] ||
- c == '\r' || c == '\n');
-#ifdef TIOCGLTC
- if (!bol)
- bol = (c == defltc.t_suspc);
-#endif
-#else /* !POSIX_TERMIOS */
- bol = c == defkill || c == deftc.t_eofc ||
- c == deftc.t_intrc || c == defltc.t_suspc ||
- c == '\r' || c == '\n';
-#endif
+ }
}
}
+/* This function reads up to size bytes from file desciptor fd into buf.
+ It will copy as much data as it can without blocking, but will never
+ copy more than size bytes. In addition, if it encounters a cmdchar
+ at the beginning of a line, it will copy everything up to and including
+ the cmdchar, but nothing after that. In this instance *esc_char is set
+ to true and any remaining data is buffered and copied on a subsequent
+ call. Otherwise, *esc_char will be set to false and the minimum of size,
+ 1024, and the number of bytes that can be read without blocking will
+ be copied. In all cases, a non-negative return value indicates the number
+ of bytes actually copied and a return value of -1 indicates that there
+ was a read error (other than EINTR) and errno is set appropriately.
+*/
+
+int read_wrapper(fd,buf,size,got_esc)
+ int fd;
+ char *buf;
+ int size;
+ int *got_esc;
+{
+ static char tbuf[1024];
+ static char *data_start = tbuf;
+ static char *data_end = tbuf;
+ static int bol = 1;
+ int return_length = 0;
+ char c;
+
+ /* if we have no data buffered, get more */
+ if (data_start == data_end) {
+ int n_read;
+ while ((n_read = read(fd, tbuf, sizeof(tbuf))) <= 0) {
+ if (n_read < 0 && errno == EINTR)
+ continue;
+ return n_read;
+ }
+ data_start = tbuf;
+ data_end = tbuf+n_read;
+ }
+
+ *got_esc = 0;
+ /* We stop when we've fully checked the buffer or have checked size
+ bytes. We break out and set *got_esc if we encounter a cmdchar
+ at the beginning of a line.
+ */
+
+ while (data_start+return_length < data_end && return_length < size) {
+
+ c = *(data_start+return_length);
+ return_length++;
+
+ if (bol == 1 && c == cmdchar) {
+ bol = 0;
+ *got_esc = 1;
+ break;
+ }
+
+#ifdef POSIX_TERMIOS
+ bol = (c == deftty.c_cc[VKILL] ||
+ c == deftty.c_cc[VINTR] ||
+ c == '\r' || c == '\n');
+
+#else /* !POSIX_TERMIOS */
+ bol = c == defkill || c == deftc.t_eofc ||
+ c == deftc.t_intrc || c == defltc.t_suspc ||
+ c == '\r' || c == '\n';
+#endif
+ }
+
+ memcpy(buf, data_start, return_length);
+ data_start = data_start + return_length;
+ return return_length;
+}
echo(c)
register char c;
@@ -1187,14 +1275,13 @@ stop(cmdc)
(void) signal(SIGCHLD, SIG_IGN);
#endif
-#ifdef TIOCGLTC
- (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
-#else
#ifdef POSIX_TERMIOS
(void) kill(cmdc == deftty.c_cc[VSUSP] ? 0 : getpid(), SIGTSTP);
+#else
+#ifdef TIOCGLTC
+ (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
#endif
#endif
-
#ifdef POSIX_SIGNALS
sa.sa_handler = catchild;
(void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
@@ -1239,7 +1326,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 +1545,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)
@@ -1514,11 +1601,6 @@ mode(f)
switch(f) {
case 0:
-#ifdef TIOCGLTC
-#if !defined(sun)
- (void) ioctl(0, TIOCSLTC, (char *)&defltc);
-#endif
-#endif
(void) tcsetattr(0, TCSADRAIN, &deftty);
break;
case 1:
@@ -1555,14 +1637,6 @@ mode(f)
newtty.c_cc[VMIN] = 1;
newtty.c_cc[VTIME] = 0;
(void) tcsetattr(0, TCSADRAIN, &newtty);
-#ifdef TIOCGLTC
- /* Do this after the tcsetattr() in case this version
- * of termio supports the VSUSP or VDSUSP characters */
-#if !defined(sun)
- /* this forces ICRNL under Solaris... */
- (void) ioctl(0, TIOCSLTC, (char *)&noltc);
-#endif
-#endif
break;
default:
return;
diff --git a/src/appl/bsd/krlogind.c b/src/appl/bsd/krlogind.c
index e37b84c..9254449 100644
--- a/src/appl/bsd/krlogind.c
+++ b/src/appl/bsd/krlogind.c
@@ -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);
@@ -984,7 +986,8 @@ void protocol(f, p)
int on = 1;
#endif
-#if defined(TIOCPKT) && !defined(__svr4__) || defined(solaris20)
+#if defined(TIOCPKT) && !(defined(__svr4__) || defined(HAVE_STREAMS)) \
+ || defined(solaris20)
/* if system has TIOCPKT, try to turn it on. Some drivers
* may not support it. Save flag for later.
*/
@@ -1033,7 +1036,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 +1124,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 +1163,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 +1380,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 +1428,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 +1443,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 +1458,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 +1523,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 +1543,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");
diff --git a/src/appl/bsd/krsh.c b/src/appl/bsd/krsh.c
index 9d602b2..c1741d8 100644
--- a/src/appl/bsd/krsh.c
+++ b/src/appl/bsd/krsh.c
@@ -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);
}
diff --git a/src/appl/bsd/krshd.c b/src/appl/bsd/krshd.c
index 3844087..7bd8dbf 100644
--- a/src/appl/bsd/krshd.c
+++ b/src/appl/bsd/krshd.c
@@ -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,18 @@ char copyright[] =
Key_schedule v4_schedule;
#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#if defined(_PATH_NOLOGIN)
+#define NOLOGIN _PATH_NOLOGIN
+#else
+#define NOLOGIN "/etc/nologin"
+#endif
+
+#include "defines.h"
+
#if HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#endif
@@ -1119,7 +1129,7 @@ void doit(f, fromp)
goto signout_please;
}
- if (pwd->pw_uid && !access("/etc/nologin", F_OK)) {
+ if (pwd->pw_uid && !access(NOLOGIN, F_OK)) {
error("Logins currently disabled.\n");
goto signout_please;
}
@@ -1245,7 +1255,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 +1266,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 +1287,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 +1478,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 +1786,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 +1793,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 +1840,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 +1853,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 +1902,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 +1958,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 +2023,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);
diff --git a/src/appl/bsd/login.M b/src/appl/bsd/login.M
index f48fd0c..bcbddab 100644
--- a/src/appl/bsd/login.M
+++ b/src/appl/bsd/login.M
@@ -74,7 +74,7 @@ Attempt to run aklog. Default value true.
.IP aklog_path
Where to find it [not yet implemented.] Default value
.I $(prefix)/bin/aklog.
-.IP accept_passwd = 0
+.IP accept_passwd
Don't accept plaintext passwords [not yet implemented]. Default value false.
.SH DIAGNOSTICS
diff --git a/src/appl/bsd/login.c b/src/appl/bsd/login.c
index 40af3ce..13e8181 100644
--- a/src/appl/bsd/login.c
+++ b/src/appl/bsd/login.c
@@ -517,6 +517,7 @@ void k_init (ttyn)
if (!getenv(KRB5_ENV_CCNAME)) {
sprintf(ccfile, "FILE:/tmp/krb5cc_p%d", getpid());
setenv(KRB5_ENV_CCNAME, ccfile, 1);
+ krb5_cc_set_default_name(kcontext, ccfile);
unlink(ccfile+strlen("FILE:"));
} else {
/* note it correctly */
@@ -619,9 +620,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 +634,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 +922,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);
@@ -1145,8 +1155,13 @@ int main(argc, argv)
}
argc -= optind;
argv += optind;
- if (*argv)
- username = *argv;
+ /* Throw away too-long names, they can't be usernames. */
+ if (*argv) {
+ if (strlen (*argv) <= UT_NAMESIZE)
+ username = *argv;
+ else
+ fprintf (stderr, "login name '%s' too long\n", *argv);
+ }
#if !defined(POSIX_TERMIOS) && defined(TIOCLSET)
ioctlval = 0;
@@ -1448,7 +1463,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
@@ -1746,8 +1761,10 @@ int main(argc, argv)
#ifdef KRB5_GET_TICKETS
/* ccfile[0] is only set if we got tickets above */
- if (login_krb5_get_tickets && ccfile[0])
+ if (login_krb5_get_tickets && ccfile[0]) {
(void) setenv(KRB5_ENV_CCNAME, ccfile, 1);
+ krb5_cc_set_default_name(kcontext, ccfile);
+ }
#endif /* KRB5_GET_TICKETS */
if (tty[sizeof("tty")-1] == 'd')
@@ -2086,6 +2103,7 @@ void dolastlog(quiet, tty)
{
#if defined(HAVE_LASTLOG_H) || (defined(BSD) && (BSD >= 199103))
struct lastlog ll;
+ time_t lltime;
int fd;
if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
@@ -2094,7 +2112,9 @@ void dolastlog(quiet, tty)
if ((read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll)) &&
(ll.ll_time != 0)) {
- printf("Last login: %.*s ", 24-5, (char *)ctime(&ll.ll_time));
+ /* .ll_time may not be a time_t. */
+ lltime = ll.ll_time;
+ printf("Last login: %.*s ", 24-5, (char *)ctime(&lltime));
if (*ll.ll_host != '\0')
printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host);
@@ -2103,7 +2123,8 @@ void dolastlog(quiet, tty)
}
(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
}
- (void) time(&ll.ll_time);
+ (void) time(&lltime);
+ ll.ll_time = lltime;
(void) strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
ll.ll_line[sizeof(ll.ll_line) - 1] = '\0';
diff --git a/src/appl/bsd/loginpaths.h b/src/appl/bsd/loginpaths.h
index 41683ee..e2f759c 100644
--- a/src/appl/bsd/loginpaths.h
+++ b/src/appl/bsd/loginpaths.h
@@ -96,6 +96,8 @@
#endif
#ifdef _PATH_DEFPATH
+#undef LPATH
+#undef RPATH
#define LPATH _PATH_DEFPATH
#define RPATH _PATH_DEFPATH
#endif
diff --git a/src/appl/bsd/rcp.M b/src/appl/bsd/rcp.M
index 46267a5..e047db5 100644
--- a/src/appl/bsd/rcp.M
+++ b/src/appl/bsd/rcp.M
@@ -24,11 +24,13 @@ rcp \- remote file copy
.B rcp
[\fB\-p\fP] [\fB\-x\fP] [\fB\-k\fP \fIrealm\fP ] [\fB\-D\fP \fIport\fP]
[\fB\-N\fP]
+[\fB\-PN | \-PO\fP]
.I file1 file2
.sp
.B rcp
[\fB\-p\fB] [\fB\-x\fP] [\fP\-k\fP \fIrealm\fP] [\fB\-r\fP] [\fB\-D\fP
\fIport\fP] [\fB\-N\fP]
+[\fB\-PN | \-PO\fP]
.I file ... directory
.SH DESCRIPTION
.B Rcp
@@ -93,6 +95,16 @@ instead of the remote host's realm as determined by
if any of the source files are directories, copy each subtree rooted at
that name; in this case the destination must be a directory.
.TP
+\fB-PN\fP
+.TP
+\fB-PO\fP
+Explicitly request new or old version of the Kerberos ``rcmd''
+protocol. The new protocol avoids many security problems found in the
+old one, but is not interoperable with older servers. (An
+"input/output error" and a closed connection is the most likely result
+of attempting this combination.) If neither option is specified, some
+simple heuristics are used to guess which to try.
+.TP
\fB\-D\fP \fIport\fP
connect to port
.I port
diff --git a/src/appl/bsd/rlogin.M b/src/appl/bsd/rlogin.M
index 79ac327..601fe46 100644
--- a/src/appl/bsd/rlogin.M
+++ b/src/appl/bsd/rlogin.M
@@ -25,6 +25,7 @@ rlogin \- remote login
.I rhost
[\fB\-e\fP\fI\|c\fP] [\fB\-8\fP] [\fB\-c\fP] [ \fB\-a\fP] [\fB\-f\fP]
[\fB\-F\fP] [\fB\-t\fP \fItermtype\fP] [\fB\-n\fP] [\fB\-7\fP]
+[\fB\-PN | \-PO\fP]
[\fB\-d\fP] [\fB\-k\fP \fIrealm\fP] [\fB\-x\fP] [\fB\-L\fP] [\fB\-l\fP
\fIusername\fP]
.PP
@@ -133,6 +134,16 @@ instead of the remote host's realm as determined by
turn on DES encryption for all data passed via the rlogin session. This
significantly reduces response time and significantly increases CPU
utilization.
+.TP
+\fB-PN\fP
+.TP
+\fB-PO\fP
+Explicitly request new or old version of the Kerberos ``rcmd''
+protocol. The new protocol avoids many security problems found in the
+old one, but is not interoperable with older servers. (An
+"input/output error" and a closed connection is the most likely result
+of attempting this combination.) If neither option is specified, some
+simple heuristics are used to guess which to try.
.SH SEE ALSO
rsh(1), kerberos(3), krb_sendauth(3), krb_realmofhost(3), rlogin(1) [UCB
version]
diff --git a/src/appl/bsd/rsh.M b/src/appl/bsd/rsh.M
index 2b342c3..11a7290 100644
--- a/src/appl/bsd/rsh.M
+++ b/src/appl/bsd/rsh.M
@@ -25,6 +25,7 @@ rsh \- remote shell
.I host
[\fB\-l\fP \fIusername\fP] [\fB\-n\fP] [\fB\-d\fP] [\fB\-k\fP
\fIrealm\fP] [\fB\-f\fP | \fB\-F\fP] [\fB\-x\fP]
+[\fB\-PN | \-PO\fP]
.I command
.SH DESCRIPTION
.B Rsh
@@ -101,6 +102,16 @@ on the TCP sockets used for communication with the remote host.
redirects input from the special device
.I /dev/null
(see the BUGS section below).
+.TP
+\fB-PN\fP
+.TP
+\fB-PO\fP
+Explicitly request new or old version of the Kerberos ``rcmd''
+protocol. The new protocol avoids many security problems found in the
+old one, but is not interoperable with older servers. (An
+"input/output error" and a closed connection is the most likely result
+of attempting this combination.) If neither option is specified, some
+simple heuristics are used to guess which to try.
.PP
If you omit
.IR command ,
diff --git a/src/appl/bsd/v4rcp.c b/src/appl/bsd/v4rcp.c
index 36754de..3267783 100644
--- a/src/appl/bsd/v4rcp.c
+++ b/src/appl/bsd/v4rcp.c
@@ -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) {
diff --git a/src/appl/gssftp/ChangeLog b/src/appl/gssftp/ChangeLog
index 691a2e9..b8205e0 100644
--- a/src/appl/gssftp/ChangeLog
+++ b/src/appl/gssftp/ChangeLog
@@ -1,3 +1,12 @@
+2001-12-18 Ken Raeburn <raeburn@mit.edu>
+
+ * configure.in: Check for strerror.
+
+2000-03-24 Ken Raeburn <raeburn@mit.edu>
+
+ * configure.in: Check for alpha*-dec-osf* instead of
+ alpha-dec-osf*.
+
1999-10-26 Tom Yu <tlyu@mit.edu>
* Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
diff --git a/src/appl/gssftp/configure.in b/src/appl/gssftp/configure.in
index f0c2bff..3851949 100644
--- a/src/appl/gssftp/configure.in
+++ b/src/appl/gssftp/configure.in
@@ -20,7 +20,7 @@ AC_CHECK_HEADERS(unistd.h stdlib.h string.h sys/select.h sys/sockio.h paths.h)
CHECK_UTMP
DECLARE_SYS_ERRLIST
AC_REPLACE_FUNCS(getdtablesize)
-AC_HAVE_FUNCS(getcwd getusershell seteuid setreuid setresuid)
+AC_HAVE_FUNCS(getcwd getusershell seteuid setreuid setresuid strerror)
AC_CHECK_LIB(crypt,crypt) dnl
AC_CHECK_LIB(util,logwtmp) dnl
dnl
@@ -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"
diff --git a/src/appl/gssftp/ftp/ChangeLog b/src/appl/gssftp/ftp/ChangeLog
index 411aff7..63fe2f5 100644
--- a/src/appl/gssftp/ftp/ChangeLog
+++ b/src/appl/gssftp/ftp/ChangeLog
@@ -1,3 +1,50 @@
+2001-12-18 Ken Raeburn <raeburn@mit.edu>
+
+ * cmds.c (strerror): Only define if not HAVE_STRERROR.
+ * ftp.c (strerror): Likewise.
+ * secure.c (secure_putbuf, secure_getbyte): Use strerror.
+
+2001-11-30 Tom Yu <tlyu@mit.edu>
+
+ * glob.c (execbrc): Fix some fencepost errors. Don't copy
+ uninitialized memory past the end of the pattern string. Don't
+ increment pointer beyond string end.
+
+2001-11-02 Tom Yu <tlyu@mit.edu>
+
+ * cmds.c (setpeer): Kludge to #define unix on BSD for now.
+
+2001-10-29 Ezra Peisach <epeisach@mit.edu>
+
+ * secure.c: Instead of hard wiring the FUDGE_FACTOR, new variables
+ to keep track of the total buffer length desired and the actual
+ maximum that can be fitted. Add secure_determine_constants() to
+ determine the mechanism dependent overhead. This has a hard limit
+ for krb4 - for gssapi use gss_wrap_size_limit.
+ [pullup from trunk]
+
+2001-10-26 Ken Raeburn <raeburn@mit.edu>
+
+ * cmds.c (setpeer): Use unsigned short for port number. Patch
+ from Garry Zacheiss.
+
+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
diff --git a/src/appl/gssftp/ftp/cmds.c b/src/appl/gssftp/ftp/cmds.c
index 2a8e775..886327a 100644
--- a/src/appl/gssftp/ftp/cmds.c
+++ b/src/appl/gssftp/ftp/cmds.c
@@ -70,10 +70,12 @@ extern char **ftpglob();
extern char *home;
extern char *remglob();
extern char *getenv();
+#ifndef HAVE_STRERROR
#define strerror(error) (sys_errlist[error])
#ifdef NEED_SYS_ERRLIST
extern char *sys_errlist[];
#endif
+#endif
extern off_t restart_point;
extern char reply_string[];
@@ -126,7 +128,7 @@ setpeer(argc, argv)
char *argv[];
{
char *host, *hookup();
- short port;
+ unsigned short port;
if (connected) {
printf("Already connected to %s, use close first.\n",
@@ -182,7 +184,7 @@ setpeer(argc, argv)
(void) login(argv[1]);
}
-#ifndef unix
+#ifndef unix /* XXX */
#ifdef _AIX
#define unix
#endif
@@ -190,6 +192,10 @@ setpeer(argc, argv)
#ifdef __hpux
#define unix
#endif
+
+#ifdef BSD
+#define unix
+#endif
#endif
#if defined(unix) && (NBBY == 8 || defined(linux))
@@ -1049,7 +1055,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 +1517,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 +1710,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) {
diff --git a/src/appl/gssftp/ftp/domacro.c b/src/appl/gssftp/ftp/domacro.c
index 9bc277b..ecfe9b4 100644
--- a/src/appl/gssftp/ftp/domacro.c
+++ b/src/appl/gssftp/ftp/domacro.c
@@ -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;
diff --git a/src/appl/gssftp/ftp/ftp.c b/src/appl/gssftp/ftp/ftp.c
index 11f583a..cc84f4b 100644
--- a/src/appl/gssftp/ftp/ftp.c
+++ b/src/appl/gssftp/ftp/ftp.c
@@ -154,10 +154,12 @@ uid_t getuid();
sig_t lostpeer();
off_t restart_point = 0;
+#ifndef HAVE_STRERROR
#define strerror(error) (sys_errlist[error])
#ifdef NEED_SYS_ERRLIST
extern char *sys_errlist[];
#endif
+#endif
extern int connected;
@@ -680,9 +682,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 +709,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 +1647,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 +1861,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 +2070,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 ||
diff --git a/src/appl/gssftp/ftp/glob.c b/src/appl/gssftp/ftp/glob.c
index f92ee5e..52b9899 100644
--- a/src/appl/gssftp/ftp/glob.c
+++ b/src/appl/gssftp/ftp/glob.c
@@ -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);
}
}
@@ -283,6 +284,7 @@ execbrc(p, s)
for (lm = restbuf; *p != '{'; *lm++ = *p++)
continue;
+ /* pe starts pointing to one past the first '{'. */
for (pe = ++p; *pe; pe++)
switch (*pe) {
@@ -299,6 +301,8 @@ execbrc(p, s)
case '[':
for (pe++; *pe && *pe != ']'; pe++)
continue;
+ if (!*pe)
+ pe--;
continue;
}
pend:
@@ -311,7 +315,7 @@ pend:
continue;
case '}':
- if (brclev) {
+ if (brclev) { /* brclev = 0 is outermost brace set */
brclev--;
continue;
}
@@ -324,8 +328,12 @@ 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';
+ if (*pe) {
+ (void) strncat(restbuf, pe + 1,
+ sizeof(restbuf) - 1 - strlen(restbuf));
+ }
*pm = savec;
if (s == 0) {
sgpathp = gpathp;
@@ -700,7 +708,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);
diff --git a/src/appl/gssftp/ftp/main.c b/src/appl/gssftp/ftp/main.c
index 9c1e43a..6c7e1e9 100644
--- a/src/appl/gssftp/ftp/main.c
+++ b/src/appl/gssftp/ftp/main.c
@@ -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))
diff --git a/src/appl/gssftp/ftp/secure.c b/src/appl/gssftp/ftp/secure.c
index 48f57f9..3f5b7c1 100644
--- a/src/appl/gssftp/ftp/secure.c
+++ b/src/appl/gssftp/ftp/secure.c
@@ -3,6 +3,11 @@
* secure read(), write(), getc(), and putc().
* Only one security context, thus only work on one fd at a time!
*/
+#ifdef GSSAPI
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+extern gss_ctx_id_t gcontext;
+#endif /* GSSAPI */
#include <secure.h> /* stuff which is specific to client or server */
@@ -31,9 +36,12 @@ extern gss_ctx_id_t gcontext;
#include <netinet/in.h>
#include <errno.h>
+#ifndef HAVE_STRERROR
+#define strerror(error) (sys_errlist[error])
#ifdef NEED_SYS_ERRLIST
extern char *sys_errlist[];
#endif
+#endif
#if (SIZEOF_SHORT == 4)
typedef unsigned short ftp_uint32;
@@ -52,29 +60,29 @@ 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 */
static unsigned int nout, bufp; /* number of chars in ucbuf,
* pointer into ucbuf */
+static unsigned int smaxbuf; /* Internal saved value of maxbuf
+ in case changes on us */
+static unsigned int smaxqueue; /* Maximum allowed to queue before
+ flush buffer. < smaxbuf by fudgefactor */
#ifdef KRB5_KRB4_COMPAT
-#define FUDGE_FACTOR 32 /* Amount of growth
+#define KRB4_FUDGE_FACTOR 32 /* Amount of growth
* from cleartext to ciphertext.
* krb_mk_priv adds this # bytes.
* Must be defined for each auth type.
*/
#endif /* KRB5_KRB4_COMPAT */
-#ifdef GSSAPI
-#undef FUDGE_FACTOR
-#define FUDGE_FACTOR 64 /*It appears to add 52 byts, but I'm not usre it is a constant--hartmans*/
-#endif /*GSSAPI*/
-
-#ifndef FUDGE_FACTOR /* In case no auth types define it. */
-#define FUDGE_FACTOR 0
-#endif
-
#ifdef KRB5_KRB4_COMPAT
/* XXX - The following must be redefined if KERBEROS_V4 is not used
* but some other auth type is. They must have the same properties. */
@@ -145,20 +153,63 @@ extern secure_error();
#define ERR -2
-static
+/*
+ * Given maxbuf as a buffer size, determine how much can we
+ * really transfer given the overhead of different algorithms
+ *
+ * Sets smaxbuf and smaxqueue
+ */
+
+static int secure_determine_constants()
+{
+ smaxbuf = maxbuf;
+ smaxqueue = maxbuf;
+
+#ifdef KRB5_KRB4_COMPAT
+ /* For KRB4 - we know the fudge factor to be 32 */
+ if (strcmp(auth_type, "KERBEROS_V4") == 0) {
+ smaxqueue = smaxbuf - KRB4_FUDGE_FACTOR;
+ }
+#endif
+#ifdef GSSAPI
+ if (strcmp(auth_type, "GSSAPI") == 0) {
+ OM_uint32 maj_stat, min_stat, mlen;
+ OM_uint32 msize = maxbuf;
+ maj_stat = gss_wrap_size_limit(&min_stat, gcontext,
+ (dlevel == PROT_P),
+ GSS_C_QOP_DEFAULT,
+ msize, &mlen);
+ if (maj_stat != GSS_S_COMPLETE) {
+ secure_gss_error(maj_stat, min_stat,
+ "GSSAPI fudge determination");
+ /* Return error how? */
+ return ERR;
+ }
+ smaxqueue = mlen;
+ }
+#endif
+
+ return 0;
+}
+
+static int
secure_putbyte(fd, c)
int fd;
unsigned char c;
{
int ret;
+ if ((smaxbuf == 0) || (smaxqueue == 0) || (smaxbuf != maxbuf)) {
+ ret = secure_determine_constants();
+ if (ret) return ret;
+ }
ucbuf[nout++] = c;
- if (nout == MAX - FUDGE_FACTOR) {
+ if (nout == smaxqueue) {
nout = 0;
- ret = secure_putbuf(fd, ucbuf, MAX - FUDGE_FACTOR);
+ ret = secure_putbuf(fd, ucbuf, smaxqueue);
return(ret?ret:c);
}
-return (c);
+ return (c);
}
/* returns:
@@ -228,18 +279,20 @@ unsigned int nbyte;
static unsigned int bufsize; /* size of outbuf */
ftp_int32 length;
ftp_uint32 net_len;
+ unsigned int fudge = smaxbuf - smaxqueue; /* Difference in length
+ buffer lengths required */
/* Other auth types go here ... */
#ifdef KRB5_KRB4_COMPAT
- if (bufsize < nbyte + FUDGE_FACTOR) {
+ if (bufsize < nbyte + fudge) {
if (outbuf?
- (outbuf = realloc(outbuf, (unsigned) (nbyte + FUDGE_FACTOR))):
- (outbuf = malloc((unsigned) (nbyte + FUDGE_FACTOR)))) {
- bufsize =nbyte + FUDGE_FACTOR;
+ (outbuf = realloc(outbuf, (unsigned) (nbyte + fudge))):
+ (outbuf = malloc((unsigned) (nbyte + fudge)))) {
+ bufsize = nbyte + fudge;
} else {
bufsize = 0;
secure_error("%s (in malloc of PROT buffer)",
- sys_errlist[errno]);
+ strerror(errno));
return(ERR);
}
}
@@ -286,7 +339,7 @@ unsigned int nbyte;
} else {
bufsize = 0;
secure_error("%s (in malloc of PROT buffer)",
- sys_errlist[errno]);
+ strerror(errno));
return(ERR);
}
}
@@ -315,7 +368,7 @@ int fd;
!= sizeof(length)) {
secure_error("Couldn't read PROT buffer length: %d/%s",
kerror,
- kerror == -1 ? sys_errlist[errno]
+ kerror == -1 ? strerror(errno)
: "premature EOF");
return(ERR);
}
@@ -327,7 +380,7 @@ int fd;
if ((kerror = looping_read(fd, ucbuf, length)) != length) {
secure_error("Couldn't read %u byte PROT buffer: %s",
length, kerror == -1 ?
- sys_errlist[errno] : "premature EOF");
+ strerror(errno) : "premature EOF");
return(ERR);
}
/* Other auth types go here ... */
diff --git a/src/appl/gssftp/ftpd/ChangeLog b/src/appl/gssftp/ftpd/ChangeLog
index a459d30..274a881 100644
--- a/src/appl/gssftp/ftpd/ChangeLog
+++ b/src/appl/gssftp/ftpd/ChangeLog
@@ -1,3 +1,68 @@
+2002-11-05 Ezra Peisach <epeisach@bu.edu>
+
+ * ftpcmd.y: Bison 1.75 cleanup. Essentially remove `=' before
+ statements to be executed. (ticket 1218).
+ [pullup from trunk]
+
+2001-12-18 Ken Raeburn <raeburn@mit.edu>
+
+ * ftpd.c (strerror): Only define if not HAVE_STRERROR.
+
+2001-11-30 Tom Yu <tlyu@mit.edu>
+
+ * ftpcmd.y (pathname): Handle returns from ftpglob() better so
+ that errors get sent via reply(), while causing some match
+ failures to match to simply return $1, so the higher level can
+ deal. Previously, some failures would cause synch problems since
+ NULL would be returned and no reply was sent.
+
+2001-11-02 Tom Yu <tlyu@mit.edu>
+
+ * ftpcmd.y: Kludge to #define unix on BSD for now.
+
+2001-10-29 Ken Raeburn <raeburn@mit.edu>
+
+ * ftpd.c (login): New argument LOGINCODE, optional result code to
+ override local use of success code 230 when homedir is not
+ accessible but root directory is.
+ (user): Pass result code 232 to login.
+ (pass): Pass result code 0 to login.
+
+2001-08-28 Ezra Peisach <epeisach@mit.edu>
+
+ * ftpd.c (auth_data): Iterate over all krb4 services instead of
+ trying to examine the srvtab file for a particular key (which
+ failes when falling back on the v5 keytab for des3 services).
+ [pullup from trunk]
+
+2001-04-25 Tom Yu <tlyu@mit.edu>
+
+ * ftpcmd.y: Don't dereference a NULL pointer returned from
+ ftpglob().
+
+ * ftpd.c: Be more paranoid about return values from ftpglob().
+ Police uses of sprintf(). Account for expansion in
+ radix_encode().
+
+2000-08-25 Tom Yu <tlyu@mit.edu>
+
+ * ftpcmd.y: Fix up grammar so that single character token names
+ are no longer used; this was breaking the build using bison on
+ HP/UX because some system headers declare structures with members
+ having all-uppercase field names and bison puts the token name
+ #define statements in front of the C declarations section in the
+ output, causing them to be in force while those headers get
+ #included. There doesn't seem to be much purpose in not just
+ using character constants, anyway.
+
+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
diff --git a/src/appl/gssftp/ftpd/ftpcmd.y b/src/appl/gssftp/ftpd/ftpcmd.y
index acd1871..582b187 100644
--- a/src/appl/gssftp/ftpd/ftpcmd.y
+++ b/src/appl/gssftp/ftpd/ftpcmd.y
@@ -91,13 +91,16 @@ extern MSG_DAT msg_data;
extern gss_ctx_id_t gcontext;
#endif
-#ifndef unix
+#ifndef unix /* XXX */
#ifdef _AIX
#define unix
#endif
#ifdef __hpux
#define unix
#endif
+#ifdef BSD
+#define unix
+#endif
#endif
#ifndef NBBY
@@ -172,9 +175,6 @@ struct tab sitetab[];
%union { int num; char *str; }
%token
- A B C E F I
- L N P R S T
-
SP CRLF COMMA STRING NUMBER
USER PASS ACCT REIN QUIT PORT
@@ -204,7 +204,7 @@ struct tab sitetab[];
cmd_list: /* empty */
| cmd_list cmd
- = {
+ {
fromname = (char *) 0;
restart_point = (off_t) 0;
}
@@ -212,17 +212,17 @@ cmd_list: /* empty */
;
cmd: USER SP username CRLF
- = {
+ {
user((char *) $3);
free((char *) $3);
}
| PASS SP password CRLF
- = {
+ {
pass((char *) $3);
free((char *) $3);
}
| PORT SP host_port CRLF
- = {
+ {
/*
* Don't allow a port < 1024 if we're not
* connecting back to the original source address
@@ -241,19 +241,19 @@ cmd: USER SP username CRLF
}
}
| PASV check_login CRLF
- = {
+ {
if ($2)
passive();
}
| PROT SP prot_code CRLF
- = {
+ {
if (maxbuf)
setdlevel ($3);
else
reply(503, "Must first set PBSZ");
}
| CCC CRLF
- = {
+ {
if (!allow_ccc) {
reply(534, "CCC not supported");
}
@@ -267,7 +267,7 @@ cmd: USER SP username CRLF
}
}
| PBSZ SP STRING CRLF
- = {
+ {
/* Others may want to do something more fancy here */
if (!auth_type)
reply(503, "Must first perform authentication");
@@ -291,7 +291,7 @@ cmd: USER SP username CRLF
}
}
| TYPE SP type_code CRLF
- = {
+ {
switch (cmd_type) {
case TYPE_A:
@@ -326,7 +326,7 @@ cmd: USER SP username CRLF
}
}
| STRU SP struct_code CRLF
- = {
+ {
switch ($3) {
case STRU_F:
@@ -338,7 +338,7 @@ cmd: USER SP username CRLF
}
}
| MODE SP mode_code CRLF
- = {
+ {
switch ($3) {
case MODE_S:
@@ -350,78 +350,78 @@ cmd: USER SP username CRLF
}
}
| ALLO SP NUMBER CRLF
- = {
+ {
reply(202, "ALLO command ignored.");
}
- | ALLO SP NUMBER SP R SP NUMBER CRLF
- = {
+ | ALLO SP NUMBER SP 'R' SP NUMBER CRLF
+ {
reply(202, "ALLO command ignored.");
}
| RETR check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
retrieve((char *) 0, (char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| STOR check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
store_file((char *) $4, "w", 0);
if ($4 != NULL)
free((char *) $4);
}
| APPE check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
store_file((char *) $4, "a", 0);
if ($4 != NULL)
free((char *) $4);
}
| NLST check_login CRLF
- = {
+ {
if ($2)
send_file_list(".");
}
| NLST check_login SP STRING CRLF
- = {
+ {
if ($2 && $4 != NULL)
send_file_list((char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| LIST check_login CRLF
- = {
+ {
if ($2)
retrieve("/bin/ls -lgA", "");
}
| LIST check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
retrieve("/bin/ls -lgA %s", (char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| STAT check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
statfilecmd((char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| STAT CRLF
- = {
+ {
statcmd();
}
| DELE check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
delete_file((char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| RNTO SP pathname CRLF
- = {
+ {
if (fromname) {
renamecmd(fromname, (char *) $3);
free(fromname);
@@ -432,27 +432,27 @@ cmd: USER SP username CRLF
free((char *) $3);
}
| ABOR CRLF
- = {
+ {
reply(225, "ABOR command successful.");
}
| CWD check_login CRLF
- = {
+ {
if ($2)
cwd(pw->pw_dir);
}
| CWD check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
cwd((char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| HELP CRLF
- = {
+ {
help(cmdtab, (char *) 0);
}
| HELP SP STRING CRLF
- = {
+ {
register char *cp = (char *)$3;
if (strncasecmp(cp, "SITE", 4) == 0) {
@@ -467,43 +467,43 @@ cmd: USER SP username CRLF
help(cmdtab, (char *) $3);
}
| NOOP CRLF
- = {
+ {
reply(200, "NOOP command successful.");
}
| MKD nonguest SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
makedir((char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| RMD nonguest SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
removedir((char *) $4);
if ($4 != NULL)
free((char *) $4);
}
| PWD check_login CRLF
- = {
+ {
if ($2)
pwd();
}
| CDUP check_login CRLF
- = {
+ {
if ($2)
cwd("..");
}
| SITE SP HELP CRLF
- = {
+ {
help(sitetab, (char *) 0);
}
| SITE SP HELP SP STRING CRLF
- = {
+ {
help(sitetab, (char *) $5);
}
| SITE SP UMASK check_login CRLF
- = {
+ {
int oldmask;
if ($4) {
@@ -513,7 +513,7 @@ cmd: USER SP username CRLF
}
}
| SITE SP UMASK nonguest SP octal_number CRLF
- = {
+ {
int oldmask;
if ($4) {
@@ -528,7 +528,7 @@ cmd: USER SP username CRLF
}
}
| SITE SP CHMOD nonguest SP octal_number SP pathname CRLF
- = {
+ {
if ($4 && ($8 != NULL)) {
if ($6 > 0777)
reply(501,
@@ -542,13 +542,13 @@ cmd: USER SP username CRLF
free((char *) $8);
}
| SITE SP IDLE CRLF
- = {
+ {
reply(200,
"Current IDLE time limit is %d seconds; max %d",
timeout, maxtimeout);
}
| SITE SP IDLE SP NUMBER CRLF
- = {
+ {
if ($5 < 30 || $5 > maxtimeout) {
reply(501,
"Maximum IDLE time must be between 30 and %d seconds",
@@ -562,14 +562,14 @@ cmd: USER SP username CRLF
}
}
| STOU check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
store_file((char *) $4, "w", 1);
if ($4 != NULL)
free((char *) $4);
}
| SYST CRLF
- = {
+ {
#ifdef unix
#ifdef __svr4__
#undef BSD
@@ -593,7 +593,7 @@ cmd: USER SP username CRLF
* using with RESTART (we just count bytes).
*/
| SIZE check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL)
sizecmd((char *) $4);
if ($4 != NULL)
@@ -610,7 +610,7 @@ cmd: USER SP username CRLF
* not necessarily 3 digits)
*/
| MDTM check_login SP pathname CRLF
- = {
+ {
if ($2 && $4 != NULL) {
struct stat stbuf;
if (stat((char *) $4, &stbuf) < 0)
@@ -633,26 +633,26 @@ cmd: USER SP username CRLF
free((char *) $4);
}
| AUTH SP STRING CRLF
- = {
+ {
auth((char *) $3);
}
| ADAT SP STRING CRLF
- = {
+ {
auth_data((char *) $3);
free((char *) $3);
}
| QUIT CRLF
- = {
+ {
reply(221, "Goodbye.");
dologout(0);
}
| error CRLF
- = {
+ {
yyerrok;
}
;
rcmd: RNFR check_login SP pathname CRLF
- = {
+ {
char *renamefrom();
restart_point = (off_t) 0;
@@ -664,7 +664,7 @@ rcmd: RNFR check_login SP pathname CRLF
}
}
| REST SP byte_size CRLF
- = {
+ {
fromname = (char *) 0;
restart_point = $3;
reply(350, "Restarting at %ld. %s", restart_point,
@@ -676,7 +676,7 @@ username: STRING
;
password: /* empty */
- = {
+ {
*(char **)&($$) = (char *)calloc(1, sizeof(char));
}
| STRING
@@ -687,7 +687,7 @@ byte_size: NUMBER
host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA
NUMBER COMMA NUMBER
- = {
+ {
register char *a, *p;
a = (char *)&host_port.sin_addr;
@@ -698,122 +698,129 @@ host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA
}
;
-form_code: N
- = {
+form_code: 'N'
+ {
$$ = FORM_N;
}
- | T
- = {
+ | 'T'
+ {
$$ = FORM_T;
}
- | C
- = {
+ | 'C'
+ {
$$ = FORM_C;
}
;
-prot_code: C
- = {
+prot_code: 'C'
+ {
$$ = PROT_C;
}
- | S
- = {
+ | 'S'
+ {
$$ = PROT_S;
}
- | P
- = {
+ | 'P'
+ {
$$ = PROT_P;
}
- | E
- = {
+ | 'E'
+ {
$$ = PROT_E;
}
;
-type_code: A
- = {
+type_code: 'A'
+ {
cmd_type = TYPE_A;
cmd_form = FORM_N;
}
- | A SP form_code
- = {
+ | 'A' SP form_code
+ {
cmd_type = TYPE_A;
cmd_form = $3;
}
- | E
- = {
+ | 'E'
+ {
cmd_type = TYPE_E;
cmd_form = FORM_N;
}
- | E SP form_code
- = {
+ | 'E' SP form_code
+ {
cmd_type = TYPE_E;
cmd_form = $3;
}
- | I
- = {
+ | 'I'
+ {
cmd_type = TYPE_I;
}
- | L
- = {
+ | 'L'
+ {
cmd_type = TYPE_L;
cmd_bytesz = NBBY;
}
- | L SP byte_size
- = {
+ | 'L' SP byte_size
+ {
cmd_type = TYPE_L;
cmd_bytesz = $3;
}
/* this is for a bug in the BBN ftp */
- | L byte_size
- = {
+ | 'L' byte_size
+ {
cmd_type = TYPE_L;
cmd_bytesz = $2;
}
;
-struct_code: F
- = {
+struct_code: 'F'
+ {
$$ = STRU_F;
}
- | R
- = {
+ | 'R'
+ {
$$ = STRU_R;
}
- | P
- = {
+ | 'P'
+ {
$$ = STRU_P;
}
;
-mode_code: S
- = {
+mode_code: 'S'
+ {
$$ = MODE_S;
}
- | B
- = {
+ | 'B'
+ {
$$ = MODE_B;
}
- | C
- = {
+ | 'C'
+ {
$$ = MODE_C;
}
;
pathname: pathstring
- = {
+ {
/*
* Problem: this production is used for all pathname
* processing, but only gives a 550 error reply.
* This is a valid reply in some cases but not in others.
*/
if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) {
- *(char **)&($$) = *ftpglob((char *) $1);
- if (globerr != NULL) {
- reply(550, globerr);
- $$ = NULL;
- }
- free((char *) $1);
+ char **vv;
+
+ vv = ftpglob((char *) $1);
+ $$ = (vv != NULL) ? *vv : NULL;
+ if ($$ == NULL) {
+ if (globerr == NULL)
+ $$ = $1;
+ else {
+ reply(550, "%s", globerr);
+ free((char *) $1);
+ }
+ } else
+ free((char *) $1);
} else
$$ = $1;
}
@@ -823,7 +830,7 @@ pathstring: STRING
;
octal_number: NUMBER
- = {
+ {
register int ret, dec, multby, digit;
/*
@@ -848,7 +855,7 @@ octal_number: NUMBER
;
check_login: /* empty */
- = {
+ {
if (logged_in)
$$ = 1;
else {
@@ -859,13 +866,13 @@ check_login: /* empty */
;
nonguest: check_login
- = {
+ {
if (guest) {
reply(550, "Operation prohibited for anonymous users.");
$$ = 0;
}
else
- $$ = 1;
+ $$ = $1;
}
;
%%
@@ -1349,51 +1356,51 @@ yylex()
case 'A':
case 'a':
- return (A);
+ return ('A');
case 'B':
case 'b':
- return (B);
+ return ('B');
case 'C':
case 'c':
- return (C);
+ return ('C');
case 'E':
case 'e':
- return (E);
+ return ('E');
case 'F':
case 'f':
- return (F);
+ return ('F');
case 'I':
case 'i':
- return (I);
+ return ('I');
case 'L':
case 'l':
- return (L);
+ return ('L');
case 'N':
case 'n':
- return (N);
+ return ('N');
case 'P':
case 'p':
- return (P);
+ return ('P');
case 'R':
case 'r':
- return (R);
+ return ('R');
case 'S':
case 's':
- return (S);
+ return ('S');
case 'T':
case 't':
- return (T);
+ return ('T');
}
break;
diff --git a/src/appl/gssftp/ftpd/ftpd.c b/src/appl/gssftp/ftpd/ftpd.c
index c7dfc8a..d4ded83 100644
--- a/src/appl/gssftp/ftpd/ftpd.c
+++ b/src/appl/gssftp/ftpd/ftpd.c
@@ -109,10 +109,12 @@ static char sccsid[] = "@(#)ftpd.c 5.40 (Berkeley) 7/2/91";
#define L_INCR 1
#endif
+#ifndef HAVE_STRERROR
#define strerror(error) (sys_errlist[error])
#ifdef NEED_SYS_ERRLIST
extern char *sys_errlist[];
#endif
+#endif
extern char *mktemp ();
@@ -761,7 +763,17 @@ user(name)
int result;
#ifdef GSSAPI
if (auth_type && strcmp(auth_type, "GSSAPI") == 0) {
+ int len;
+
authorized = ftpd_gss_userok(&client_name, name) == 0;
+ len = sizeof("GSSAPI user is not authorized as "
+ "; Password required.")
+ + strlen(client_name.value)
+ + strlen(name);
+ if (len >= sizeof(buf)) {
+ syslog(LOG_ERR, "user: username too long");
+ name = "[username too long]";
+ }
sprintf(buf, "GSSAPI user %s is%s authorized as %s",
client_name.value, authorized ? "" : " not",
name);
@@ -772,7 +784,19 @@ user(name)
#endif /* GSSAPI */
#ifdef KRB5_KRB4_COMPAT
if (auth_type && strcmp(auth_type, "KERBEROS_V4") == 0) {
+ int len;
+
authorized = kuserok(&kdata,name) == 0;
+ len = sizeof("Kerberos user .@ is not authorized as "
+ "; Password required.")
+ + strlen(kdata.pname)
+ + strlen(kdata.pinst)
+ + strlen(kdata.prealm)
+ + strlen(name);
+ if (len >= sizeof(buf)) {
+ syslog(LOG_ERR, "user: username too long");
+ name = "[username too long]";
+ }
sprintf(buf, "Kerberos user %s%s%s@%s is%s authorized as %s",
kdata.pname, *kdata.pinst ? "." : "",
kdata.pinst, kdata.prealm,
@@ -796,7 +820,7 @@ user(name)
syslog(authorized ? LOG_INFO : LOG_ERR, "%s", buf);
if (result == 232)
- login(NULL);
+ login(NULL, result);
return;
}
@@ -1064,11 +1088,11 @@ pass(passwd)
}
login_attempts = 0; /* this time successful */
- login(passwd);
+ login(passwd, 0);
return;
}
-login(passwd)
+login(passwd, logincode)
char *passwd;
{
if (have_creds) {
@@ -1127,8 +1151,11 @@ login(passwd)
reply(530, "User %s: can't change directory to %s.",
pw->pw_name, pw->pw_dir);
goto bad;
- } else
- lreply(230, "No directory! Logging in with home=/");
+ } else {
+ if (!logincode)
+ logincode = 230;
+ lreply(logincode, "No directory! Logging in with home=/");
+ }
}
}
if (guest) {
@@ -1179,6 +1206,11 @@ retrieve(cmd, name)
} else {
char line[FTP_BUFSIZ];
+ if (strlen(cmd) + strlen(name) + 1 >= sizeof(line)) {
+ syslog(LOG_ERR, "retrieve: filename too long");
+ reply(501, "filename too long");
+ return;
+ }
(void) sprintf(line, cmd, name), name = line;
fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
st.st_size = -1;
@@ -1417,6 +1449,10 @@ dataconn(name, size, mode)
return (file);
}
+/*
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ
+ */
#ifdef STDARG
secure_error(char *fmt, ...)
#else
@@ -1616,13 +1652,19 @@ statfilecmd(filename)
{
char line[FTP_BUFSIZ];
FILE *fin;
- int c;
+ int c, n;
char str[FTP_BUFSIZ], *p;
+ if (strlen(filename) + sizeof("/bin/ls -lgA ")
+ >= sizeof(line)) {
+ reply(501, "filename too long");
+ return;
+ }
(void) sprintf(line, "/bin/ls -lgA %s", filename);
fin = ftpd_popen(line, "r");
lreply(211, "status of %s:", filename);
p = str;
+ n = 0;
while ((c = getc(fin)) != EOF) {
if (c == '\n') {
if (ferror(stdout)){
@@ -1639,7 +1681,16 @@ statfilecmd(filename)
*p = '\0';
reply(0, "%s", str);
p = str;
- } else *p++ = c;
+ n = 0;
+ } else {
+ *p++ = c;
+ n++;
+ if (n >= sizeof(str)) {
+ reply(551, "output line too long");
+ (void) ftpd_pclose(fin);
+ return;
+ }
+ }
}
if (p != str) {
*p = '\0';
@@ -1723,6 +1774,10 @@ fatal(s)
char cont_char = ' ';
+/*
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ bytes for now.
+ */
#ifdef STDARG
reply(int n, char *fmt, ...)
#else
@@ -1744,22 +1799,32 @@ reply(n, fmt, p0, p1, p2, p3, p4, p5)
#endif
if (auth_type) {
- char in[FTP_BUFSIZ], out[FTP_BUFSIZ];
+ /*
+ * Deal with expansion in mk_{safe,priv},
+ * radix_encode, gss_seal, plus slop.
+ */
+ char in[FTP_BUFSIZ*3/2], out[FTP_BUFSIZ*3/2];
int length, kerror;
if (n) sprintf(in, "%d%c", n, cont_char);
else in[0] = '\0';
strncat(in, buf, sizeof (in) - strlen(in) - 1);
#ifdef KRB5_KRB4_COMPAT
if (strcmp(auth_type, "KERBEROS_V4") == 0) {
- if ((length = clevel == PROT_P ?
- krb_mk_priv((unsigned char *)in,
- (unsigned char *)out,
- strlen(in), schedule, &kdata.session,
- &ctrl_addr, &his_addr)
- : krb_mk_safe((unsigned char *)in,
- (unsigned char *)out,
- strlen(in), &kdata.session,
- &ctrl_addr, &his_addr)) == -1) {
+ if (clevel == PROT_P)
+ length = krb_mk_priv((unsigned char *)in,
+ (unsigned char *)out,
+ strlen(in),
+ schedule, &kdata.session,
+ &ctrl_addr,
+ &his_addr);
+ else
+ length = krb_mk_safe((unsigned char *)in,
+ (unsigned char *)out,
+ strlen(in),
+ &kdata.session,
+ &ctrl_addr,
+ &his_addr);
+ if (length == -1) {
syslog(LOG_ERR,
"krb_mk_%s failed for KERBEROS_V4",
clevel == PROT_P ? "priv" : "safe");
@@ -1803,13 +1868,16 @@ reply(n, fmt, p0, p1, p2, p3, p4, p5)
}
#endif /* GSSAPI */
/* Other auth types go here ... */
- if (kerror = radix_encode(out, in, &length, 0)) {
+ if (length >= sizeof(in) / 4 * 3) {
+ syslog(LOG_ERR, "input to radix_encode too long");
+ fputs(in, stdout);
+ } else if (kerror = radix_encode(out, in, &length, 0)) {
syslog(LOG_ERR, "Couldn't encode reply (%s)",
radix_error(kerror));
fputs(in,stdout);
} else
- printf("%s%c%s", clevel == PROT_P ? "632" : "631",
- n ? cont_char : '-', in);
+ printf("%s%c%s", clevel == PROT_P ? "632" : "631",
+ n ? cont_char : '-', in);
} else {
if (n) printf("%d%c", n, cont_char);
fputs(buf, stdout);
@@ -1822,6 +1890,10 @@ reply(n, fmt, p0, p1, p2, p3, p4, p5)
}
}
+/*
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ
+ */
#ifdef STDARG
lreply(int n, char *fmt, ...)
#else
@@ -1866,7 +1938,8 @@ yyerror(s)
if (cp = strchr(cbuf,'\n'))
*cp = '\0';
- reply(500, "'%s': command not understood.", cbuf);
+ reply(500, "'%.*s': command not understood.",
+ FTP_BUFSIZ - sizeof("'': command not understood."), cbuf);
}
delete_file(name)
@@ -2123,7 +2196,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++) {
@@ -2142,7 +2216,23 @@ perror_reply(code, string)
int code;
char *string;
{
- reply(code, "%s: %s.", string, strerror(errno));
+ char *err_string;
+ size_t extra_len;
+
+ err_string = strerror(errno);
+ if (err_string == NULL)
+ err_string = "(unknown error)";
+ extra_len = strlen(err_string) + sizeof("(truncated): .");
+
+ /*
+ * XXX knows about FTP_BUFSIZ in reply()
+ */
+ if (strlen(string) + extra_len > FTP_BUFSIZ) {
+ reply(code, "(truncated)%.*s: %s.",
+ FTP_BUFSIZ - extra_len, string, err_string);
+ } else {
+ reply(code, "%s: %s.", string, err_string);
+ }
}
auth(type)
@@ -2173,7 +2263,7 @@ char *data;
int kerror, length;
#ifdef KRB5_KRB4_COMPAT
int i;
- static char *service;
+ static char **service=NULL;
char instance[INST_SZ];
u_long cksum;
char buf[FTP_BUFSIZ];
@@ -2199,23 +2289,22 @@ char *data;
}
(void) memcpy((char *)ticket.dat, (char *)out_buf, ticket.length = length);
strcpy(instance, "*");
- if (!service) {
- char realm[REALM_SZ];
- des_cblock key;
-
- service = "ftp";
- if (krb_get_lrealm(realm, 1) == KSUCCESS &&
- read_service_key(service, instance, realm, 0, keyfile, key))
- service = "rcmd";
- else
- (void) memset(key, 0, sizeof(key));
- }
- if (kerror = krb_rd_req(&ticket, service, instance,
- his_addr.sin_addr.s_addr, &kdata, keyfile)) {
- secure_error("ADAT: Kerberos V4 krb_rd_req: %s",
- krb_get_err_text(kerror));
- return(0);
+
+ kerror = 255;
+ for (service = krb4_services; *service; service++) {
+ kerror = krb_rd_req(&ticket, *service, instance,
+ his_addr.sin_addr.s_addr,
+ &kdata, keyfile);
+ /* Success */
+ if(!kerror) break;
+ }
+ /* rd_req failed.... */
+ if(kerror) {
+ secure_error("ADAT: Kerberos V4 krb_rd_req: %s",
+ krb_get_err_text(kerror));
+ return(0);
}
+
/* add one to the (formerly) sealed checksum, and re-seal it */
cksum = kdata.checksum + 1;
cksum = htonl(cksum);
@@ -2225,6 +2314,10 @@ char *data;
secure_error("ADAT: krb_mk_safe failed");
return(0);
}
+ if (length >= (FTP_BUFSIZ - sizeof("ADAT=")) / 4 * 3) {
+ secure_error("ADAT: reply too long");
+ return(0);
+ }
if (kerror = radix_encode(out_buf, buf, &length, 0)) {
secure_error("Couldn't encode ADAT reply (%s)",
radix_error(kerror));
@@ -2287,7 +2380,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);
@@ -2358,6 +2452,16 @@ char *data;
}
if (out_tok.length) {
+ if (out_tok.length >= ((FTP_BUFSIZ - sizeof("ADAT="))
+ / 4 * 3)) {
+ secure_error("ADAT: reply too long");
+ syslog(LOG_ERR, "ADAT: reply too long");
+ (void) gss_release_cred(&stat_min, &server_creds);
+ if (ret_flags & GSS_C_DELEG_FLAG)
+ (void) gss_release_cred(&stat_min,
+ &deleg_creds);
+ return(0);
+ }
if (kerror = radix_encode(out_tok.value, gbuf, &out_tok.length, 0)) {
secure_error("Couldn't encode ADAT reply (%s)",
radix_error(kerror));
@@ -2456,6 +2560,9 @@ static char *onefile[] = {
* n>=0 on success
* -1 on error
* -2 on security error
+ *
+ * XXX callers need to limit total length of output string to
+ * FTP_BUFSIZ
*/
#ifdef STDARG
secure_fprintf(FILE *stream, char *fmt, ...)
@@ -2573,6 +2680,15 @@ send_file_list(whichfiles)
dir->d_name[2] == '\0')
continue;
+ if (strlen(dirname) + strlen(dir->d_name)
+ + 1 /* slash */
+ + 2 /* CRLF */
+ + 1 > sizeof(nbuf)) {
+ syslog(LOG_ERR,
+ "send_file_list: pathname too long");
+ ret = -2; /* XXX */
+ goto data_err;
+ }
sprintf(nbuf, "%s/%s", dirname, dir->d_name);
/*
diff --git a/src/appl/sample/sclient/ChangeLog b/src/appl/sample/sclient/ChangeLog
index 7603506..7e9c4f4 100644
--- a/src/appl/sample/sclient/ChangeLog
+++ b/src/appl/sample/sclient/ChangeLog
@@ -1,3 +1,9 @@
+2001-01-30 Ezra Peisach <epeisach@mit.edu>
+
+ * sclient.c (main): Do not free auth_context unless
+ set. (krb5-appl/895 from tim.mann@compaq.com)
+
+
2000-02-25 Ezra Peisach <epeisach@mit.edu>
* sclient.c (main): Return type of main should by int, not void.
diff --git a/src/appl/sample/sclient/sclient.c b/src/appl/sample/sclient/sclient.c
index d2097b9..242092b 100644
--- a/src/appl/sample/sclient/sclient.c
+++ b/src/appl/sample/sclient/sclient.c
@@ -175,7 +175,7 @@ char *argv[];
krb5_free_principal(context, server); /* finished using it */
krb5_free_principal(context, client);
krb5_cc_close(context, ccdef);
- krb5_auth_con_free(context, auth_context);
+ if (auth_context) krb5_auth_con_free(context, auth_context);
if (retval && retval != KRB5_SENDAUTH_REJECTED) {
com_err(argv[0], retval, "while using sendauth");
diff --git a/src/appl/telnet/libtelnet/ChangeLog b/src/appl/telnet/libtelnet/ChangeLog
index 67877b1..95906f3 100644
--- a/src/appl/telnet/libtelnet/ChangeLog
+++ b/src/appl/telnet/libtelnet/ChangeLog
@@ -1,3 +1,41 @@
+2003-04-01 Nalin Dahyabhai <nalin@redhat.com>
+
+ * kerberos5.c (kerberos5_is): Check principal name length before
+ examining components.
+
+2002-03-29 Tom Yu <tlyu@mit.edu>
+
+ * kerberos5.c, kerberos.c (Data): Don't overflow
+ buffer. [telnet/1073] [pullup and reindent from trunk]
+
+2001-02-21 Tom Yu <tlyu@mit.edu>
+
+ * configure.in: Check for setenv, unsetenv, and getenv. Compile
+ setenv.c if at least of these is undefined.
+
+ * setenv.c: Add conditionals for compilation of setenv, unsetenv,
+ and getenv such that they only get compiled if they don't already
+ exist.
+
+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 Tom Yu <tlyu@mit.edu>
* Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
diff --git a/src/appl/telnet/libtelnet/configure.in b/src/appl/telnet/libtelnet/configure.in
index 3bae866..9040a98 100644
--- a/src/appl/telnet/libtelnet/configure.in
+++ b/src/appl/telnet/libtelnet/configure.in
@@ -3,10 +3,14 @@ CONFIG_RULES
AC_PROG_ARCHIVE
AC_PROG_ARCHIVE_ADD
AC_PROG_RANLIB
-AC_REPLACE_FUNCS([strcasecmp strdup setenv setsid strerror strftime getopt herror parsetos])
-AC_CHECK_FUNCS(gettosbyname cgetent)
+AC_REPLACE_FUNCS([strcasecmp strdup setsid strerror strftime getopt herror parsetos])
+AC_CHECK_FUNCS(setenv unsetenv getenv gettosbyname cgetent)
AC_CHECK_HEADERS(stdlib.h string.h)
LIBOBJS="$LIBOBJS getent.o"
+if test $ac_cv_func_setenv = no || test $ac_cv_func_unsetenv = no \
+ || test $ac_cv_func_getenv = no; then
+ LIBOBJS="$LIBOBJS setenv.o"
+fi
AC_CONST
if test "$KRB4_LIB" = ''; then
AC_MSG_RESULT(No Kerberos 4 authentication)
diff --git a/src/appl/telnet/libtelnet/gettytab.c b/src/appl/telnet/libtelnet/gettytab.c
index f6ffb7c..aaad43a 100644
--- a/src/appl/telnet/libtelnet/gettytab.c
+++ b/src/appl/telnet/libtelnet/gettytab.c
@@ -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) {
diff --git a/src/appl/telnet/libtelnet/kerberos.c b/src/appl/telnet/libtelnet/kerberos.c
index 734466e..0fda99b 100644
--- a/src/appl/telnet/libtelnet/kerberos.c
+++ b/src/appl/telnet/libtelnet/kerberos.c
@@ -141,6 +141,7 @@ Data(ap, type, d, c)
{
unsigned char *p = str_data + 4;
unsigned char *cd = (unsigned char *)d;
+ size_t spaceleft = sizeof(str_data) - 4;
if (c == -1)
c = strlen((char *)cd);
@@ -156,9 +157,16 @@ Data(ap, type, d, c)
*p++ = ap->type;
*p++ = ap->way;
*p++ = type;
+ spaceleft -= 3;
while (c-- > 0) {
- if ((*p++ = *cd++) == IAC)
- *p++ = IAC;
+ if ((*p++ = *cd++) == IAC) {
+ *p++ = IAC;
+ spaceleft--;
+ }
+ if ((--spaceleft < 4) && c) {
+ errno = ENOMEM;
+ return -1;
+ }
}
*p++ = IAC;
*p++ = SE;
@@ -602,7 +610,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);
diff --git a/src/appl/telnet/libtelnet/kerberos5.c b/src/appl/telnet/libtelnet/kerberos5.c
index 6a62f36..b9bbae8 100644
--- a/src/appl/telnet/libtelnet/kerberos5.c
+++ b/src/appl/telnet/libtelnet/kerberos5.c
@@ -95,7 +95,7 @@ void kerberos5_forward();
#endif /* FORWARD */
-static unsigned char str_data[2048] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+static unsigned char str_data[8192] = {IAC, SB, TELOPT_AUTHENTICATION, 0,
AUTHTYPE_KERBEROS_V5, };
/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
TELQUAL_NAME, };*/
@@ -136,6 +136,7 @@ Data(ap, type, d, c)
{
unsigned char *p = str_data + 4;
unsigned char *cd = (unsigned char *)d;
+ size_t spaceleft = sizeof(str_data) - 4;
if (c == -1)
c = strlen((char *)cd);
@@ -151,9 +152,16 @@ Data(ap, type, d, c)
*p++ = ap->type;
*p++ = ap->way;
*p++ = type;
+ spaceleft -= 3;
while (c-- > 0) {
- if ((*p++ = *cd++) == IAC)
- *p++ = IAC;
+ if ((*p++ = *cd++) == IAC) {
+ *p++ = IAC;
+ spaceleft--;
+ }
+ if ((--spaceleft < 4) && c) {
+ errno = ENOMEM;
+ return -1;
+ }
}
*p++ = IAC;
*p++ = SE;
@@ -423,7 +431,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;
}
@@ -432,6 +441,10 @@ kerberos5_is(ap, data, cnt)
* first component of a service name especially since
* the default is of length 4.
*/
+ if (krb5_princ_size(telnet_context,ticket->server) < 1) {
+ (void) strcpy(errbuf, "malformed service name");
+ goto errout;
+ }
if (krb5_princ_component(telnet_context,ticket->server,0)->length < 256) {
char princ[256];
strncpy(princ,
@@ -440,8 +453,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 +472,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 +494,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 +514,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 +526,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 +581,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 +608,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 +729,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);
diff --git a/src/appl/telnet/libtelnet/setenv.c b/src/appl/telnet/libtelnet/setenv.c
index 70695a3..bc4f22d 100644
--- a/src/appl/telnet/libtelnet/setenv.c
+++ b/src/appl/telnet/libtelnet/setenv.c
@@ -52,6 +52,7 @@ static char *__findenv __P((const char *, int *));
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
+#ifndef HAVE_SETENV
setenv(name, value, rewrite)
register const char *name;
register const char *value;
@@ -102,11 +103,13 @@ setenv(name, value, rewrite)
for (*c++ = '='; *c++ = *value++;);
return (0);
}
+#endif
/*
* unsetenv(name) --
* Delete environmental variable "name".
*/
+#ifndef HAVE_UNSETENV
void
unsetenv(name)
const char *name;
@@ -120,11 +123,13 @@ unsetenv(name)
if (!(*p = *(p + 1)))
break;
}
+#endif
/*
* getenv --
* Returns ptr to value associated with name, if any, else NULL.
*/
+#ifndef HAVE_GETENV
char *
getenv(name)
const char *name;
@@ -133,6 +138,7 @@ getenv(name)
return (__findenv(name, &offset));
}
+#endif
/*
* __findenv --
diff --git a/src/appl/telnet/libtelnet/spx.c b/src/appl/telnet/libtelnet/spx.c
index f23490f..7285d0d 100644
--- a/src/appl/telnet/libtelnet/spx.c
+++ b/src/appl/telnet/libtelnet/spx.c
@@ -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);
diff --git a/src/appl/telnet/telnet/ChangeLog b/src/appl/telnet/telnet/ChangeLog
index e3cfb63..fb7cc9394 100644
--- a/src/appl/telnet/telnet/ChangeLog
+++ b/src/appl/telnet/telnet/ChangeLog
@@ -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
diff --git a/src/appl/telnet/telnet/commands.c b/src/appl/telnet/telnet/commands.c
index 2c80b0b..8ffba2e 100644
--- a/src/appl/telnet/telnet/commands.c
+++ b/src/appl/telnet/telnet/commands.c
@@ -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;
}
diff --git a/src/appl/telnet/telnet/externs.h b/src/appl/telnet/telnet/externs.h
index e993986..f35cded 100644
--- a/src/appl/telnet/telnet/externs.h
+++ b/src/appl/telnet/telnet/externs.h
@@ -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
diff --git a/src/appl/telnet/telnet/main.c b/src/appl/telnet/telnet/main.c
index da98ae6..7696857 100644
--- a/src/appl/telnet/telnet/main.c
+++ b/src/appl/telnet/telnet/main.c
@@ -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",
diff --git a/src/appl/telnet/telnet/tn3270.c b/src/appl/telnet/telnet/tn3270.c
index 77aedaf..c46ae7e 100644
--- a/src/appl/telnet/telnet/tn3270.c
+++ b/src/appl/telnet/telnet/tn3270.c
@@ -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;
}
diff --git a/src/appl/telnet/telnet/utilities.c b/src/appl/telnet/telnet/utilities.c
index 19f503b..82ad841 100644
--- a/src/appl/telnet/telnet/utilities.c
+++ b/src/appl/telnet/telnet/utilities.c
@@ -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
diff --git a/src/appl/telnet/telnetd/ChangeLog b/src/appl/telnet/telnetd/ChangeLog
index 040a9af..5ab914a 100644
--- a/src/appl/telnet/telnetd/ChangeLog
+++ b/src/appl/telnet/telnetd/ChangeLog
@@ -1,3 +1,70 @@
+2002-01-18 Tom Yu <tlyu@mit.edu>
+
+ * ext.h: Make stdarg prototypes unconditional, to avoid annoying
+ mostly-ANSI compilers that don't define __STDC__.
+
+2001-10-15 Ken Raeburn <raeburn@mit.edu>
+
+ * telnetd.c (valid_opts): Note that 'w' takes a parameter.
+
+2001-08-02 Tom Yu <tlyu@mit.edu>
+
+ * authenc.c (net_write): Rewrite in terms of netwrite().
+
+ * configure.in: Check for vsnprintf().
+
+ * ext.h: New prototypes for netprintf, netprintf_urg,
+ netprintf_noflush, netwrite, netputs.
+
+ * slc.c: Fix to use new NETOBUF-handling functions.
+
+ * state.c: Fix to use new NETOBUF-handling functions.
+
+ * telnetd.c: Fix to use new NETOBUF-handling functions.
+
+ * termstat.c: Fix to use new NETOBUF-handling functions.
+
+ * utility.c: General rework to be more paranoid about
+ bounds-checking of NETOBUF and NFRONTP. Abstract away
+ interactions with NETOBUF to eliminate explicit references to
+ NFRONTP in many places.
+ (netwrite): New function; copies a buffer to the
+ NETOBUF "ring buffer", checking bounds and calling netflush() if
+ needed.
+ (netputs): New function; calls netwrite() with a nul-terminated
+ string.
+ (netprintf, netprintf_ext): New function; wrap sprintf() with
+ bounds checking for use with NETOBUF.
+ (netprintf_urg): New function; like netprintf() except sets neturg
+ to point at last char written.
+ (netprintf_noflush): New function; like netprintf() except
+ silently fails if NETOBUF is full.
+ (ttloop, printoption, printsub, printdata): Fix to use new
+ NETOBUF-handling functions.
+
+2001-01-25 Tom Yu <tlyu@mit.edu>
+
+ * state.c (envvarok): Disallow LC_* and NLSPATH.
+
+2000-06-19 Tom Yu <tlyu@mit.edu>
+
+ * telnetd.c (doit): Change test for "no authentication" as per
+ Jeffrey Altman's patch.
+
+2000-05-11 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-03-20 Ken Raeburn <raeburn@mit.edu>
+ Jeffrey Altman <jaltman@watsun.cc.columbia.edu>
+
+ * state.c (telrcv): Fix off-by-one error dealing with full
+ buffer.
+
2000-02-24 Ezra Peisach <epeisach@mit.edu>
* configure.in: Remove dependency on libdes425 when krb4 support
diff --git a/src/appl/telnet/telnetd/authenc.c b/src/appl/telnet/telnetd/authenc.c
index 5736698..4488954 100644
--- a/src/appl/telnet/telnetd/authenc.c
+++ b/src/appl/telnet/telnetd/authenc.c
@@ -37,20 +37,17 @@
#include "telnetd.h"
#include <libtelnet/misc.h>
- int
+int
net_write(str, len)
unsigned char *str;
int len;
{
- if (nfrontp + len < netobuf + BUFSIZ) {
- memcpy((void *)nfrontp, (void *)str, len);
- nfrontp += len;
- return(len);
- }
- return(0);
+ if (len < 0)
+ return 0;
+ return netwrite(str, len);
}
- void
+void
net_encrypt()
{
#ifdef ENCRYPTION
@@ -87,7 +84,3 @@ telnet_gets(prompt, result, length, echo)
return((char *)0);
}
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
-
-
-
-
diff --git a/src/appl/telnet/telnetd/configure.in b/src/appl/telnet/telnetd/configure.in
index e11b270..2dc6099 100644
--- a/src/appl/telnet/telnetd/configure.in
+++ b/src/appl/telnet/telnetd/configure.in
@@ -23,7 +23,7 @@ fi
fi
AC_HEADER_TIME
AC_CHECK_HEADERS(string.h arpa/nameser.h utmp.h sys/time.h sys/tty.h sac.h sys/ptyvar.h sys/filio.h sys/stream.h sys/utsname.h)
-AC_CHECK_FUNCS(gettosbyname)
+AC_CHECK_FUNCS(gettosbyname vsnprintf)
dnl Make our operating system-specific security checks and definitions for
dnl login.
dnl
diff --git a/src/appl/telnet/telnetd/ext.h b/src/appl/telnet/telnetd/ext.h
index 2ff53e3..dc9fe5a 100644
--- a/src/appl/telnet/telnetd/ext.h
+++ b/src/appl/telnet/telnetd/ext.h
@@ -187,8 +187,13 @@ extern void
tty_setsofttab P((int)),
tty_tspeed P((int)),
willoption P((int)),
- wontoption P((int)),
- writenet P((unsigned char *, int));
+ wontoption P((int));
+
+extern void netprintf(const char *, ...);
+extern void netprintf_urg(const char *fmt, ...);
+extern void netprintf_noflush(const char *fmt, ...);
+extern int netwrite(const char *, size_t);
+extern void netputs(const char *);
#ifdef ENCRYPTION
extern char *nclearto;
diff --git a/src/appl/telnet/telnetd/slc.c b/src/appl/telnet/telnetd/slc.c
index 1c68b95..613674b 100644
--- a/src/appl/telnet/telnetd/slc.c
+++ b/src/appl/telnet/telnetd/slc.c
@@ -198,7 +198,7 @@ end_slc(bufp)
(void) sprintf((char *)slcptr, "%c%c", IAC, SE);
slcptr += 2;
len = slcptr - slcbuf;
- writenet(slcbuf, len);
+ netwrite(slcbuf, len);
netflush(); /* force it out immediately */
DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2););
}
diff --git a/src/appl/telnet/telnetd/state.c b/src/appl/telnet/telnetd/state.c
index 0f3b161..d783ed6 100644
--- a/src/appl/telnet/telnetd/state.c
+++ b/src/appl/telnet/telnetd/state.c
@@ -86,7 +86,7 @@ static void sb_auth_complete()
if (!auth_negotiated) {
static char *error =
"An environment option was sent before authentication negotiation completed.\r\nThis may create a security hazard. Connection dropped.\r\n";
- writenet(error, strlen(error));
+ netputs(error);
netflush();
exit(1);
}
@@ -102,7 +102,7 @@ telrcv()
#endif
while (ncc > 0) {
- if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
+ if ((&ptyobuf[BUFSIZ] - pfrontp) < 1)
break;
c = *netip++ & 0377, ncc--;
#ifdef ENCRYPTION
@@ -209,9 +209,7 @@ gotiac: switch (c) {
}
netclear(); /* clear buffer back */
- *nfrontp++ = IAC;
- *nfrontp++ = DM;
- neturg = nfrontp-1; /* off by one XXX */
+ netprintf_urg("%c%c", IAC, DM);
DIAG(TD_OPTIONS,
printoption("td: send IAC", DM));
break;
@@ -381,9 +379,12 @@ gotiac: switch (c) {
pfrontp = opfrontp;
pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP,
xbuf2, &oc, BUFSIZ);
- for (cp = xbuf2; oc > 0; --oc)
- if ((*nfrontp++ = *cp++) == IAC)
- *nfrontp++ = IAC;
+ for (cp = xbuf2; oc > 0; --oc) {
+ if (*cp == IAC)
+ netprintf("%c%c", *cp++, IAC);
+ else
+ netprintf("%c", *cp++);
+ }
}
#endif /* defined(CRAY2) && defined(UNICOS5) */
} /* end of telrcv */
@@ -463,8 +464,7 @@ send_do(option, init)
set_his_want_state_will(option);
do_dont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)doopt, option);
- nfrontp += sizeof (dont) - 2;
+ netprintf((char *)doopt, option);
DIAG(TD_OPTIONS, printoption("td: send do", option));
}
@@ -683,8 +683,7 @@ send_dont(option, init)
set_his_want_state_wont(option);
do_dont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)dont, option);
- nfrontp += sizeof (doopt) - 2;
+ netprintf((char *)dont, option);
DIAG(TD_OPTIONS, printoption("td: send dont", option));
}
@@ -833,8 +832,7 @@ send_will(option, init)
set_my_want_state_will(option);
will_wont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)will, option);
- nfrontp += sizeof (doopt) - 2;
+ netprintf((char *)will, option);
DIAG(TD_OPTIONS, printoption("td: send will", option));
}
@@ -993,8 +991,7 @@ send_wont(option, init)
set_my_want_state_wont(option);
will_wont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)wont, option);
- nfrontp += sizeof (wont) - 2;
+ netprintf((char *)wont, option);
DIAG(TD_OPTIONS, printoption("td: send wont", option));
}
@@ -1393,10 +1390,8 @@ suboption()
env_ovar_wrong:
env_ovar = OLD_ENV_VALUE;
env_ovalue = OLD_ENV_VAR;
- DIAG(TD_OPTIONS, {sprintf(nfrontp,
- "ENVIRON VALUE and VAR are reversed!\r\n");
- nfrontp += strlen(nfrontp);});
-
+ DIAG(TD_OPTIONS,
+ netputs("ENVIRON VALUE and VAR are reversed!\r\n"));
}
}
SB_RESTORE();
@@ -1633,7 +1628,7 @@ send_status()
ADD(IAC);
ADD(SE);
- writenet(statusbuf, ncp - statusbuf);
+ netwrite(statusbuf, ncp - statusbuf);
netflush(); /* Send it on its way */
DIAG(TD_OPTIONS,
@@ -1663,6 +1658,8 @@ static int envvarok(varp)
strcmp(varp, "KRB_REALMS") && /* cns v4 */
strcmp(varp, "LIBPATH") && /* AIX */
strcmp(varp, "RESOLV_HOST_CONF") && /* linux */
+ strcmp(varp, "NLSPATH") && /* locale stuff */
+ strncmp(varp, "LC_", strlen("LC_")) && /* locale stuff */
strcmp(varp, "IFS")) {
return 1;
} else {
diff --git a/src/appl/telnet/telnetd/sys_term.c b/src/appl/telnet/telnetd/sys_term.c
index ee8d53d..b79209d 100644
--- a/src/appl/telnet/telnetd/sys_term.c
+++ b/src/appl/telnet/telnetd/sys_term.c
@@ -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);
diff --git a/src/appl/telnet/telnetd/telnetd-ktd.c b/src/appl/telnet/telnetd/telnetd-ktd.c
index 9ec608f..5936e3b 100644
--- a/src/appl/telnet/telnetd/telnetd-ktd.c
+++ b/src/appl/telnet/telnetd/telnetd-ktd.c
@@ -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
diff --git a/src/appl/telnet/telnetd/telnetd.c b/src/appl/telnet/telnetd/telnetd.c
index 7267469..5588d1a 100644
--- a/src/appl/telnet/telnetd/telnetd.c
+++ b/src/appl/telnet/telnetd/telnetd.c
@@ -153,7 +153,7 @@ extern void usage P((void));
*/
char valid_opts[] = {
'd', ':', 'h', 'k', 'L', ':', 'n', 'S', ':', 'U',
- 'w',
+ 'w', ':',
#ifdef AUTHENTICATION
'a', ':', 'X', ':',
#endif
@@ -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");
@@ -693,7 +693,7 @@ static void encrypt_failure()
char *error_message =
"Encryption was not successfully negotiated. Goodbye.\r\n\r\n";
- writenet(error_message, strlen(error_message));
+ netputs(error_message);
netflush();
exit(1);
}
@@ -780,36 +780,26 @@ getterminaltype(name)
if (his_state_is_will(TELOPT_TSPEED)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
-
- memcpy(nfrontp, sb, sizeof sb);
- nfrontp += sizeof sb;
+ netwrite(sb, sizeof(sb));
}
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;
+ netwrite(sb, sizeof(sb));
}
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;
+ netwrite(sb, sizeof(sb));
}
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;
+ netwrite(sb, sizeof(sb));
}
- if (his_state_is_will(TELOPT_TTYPE)) {
+ if (his_state_is_will(TELOPT_TTYPE))
+ netwrite(ttytype_sbbuf, sizeof(ttytype_sbbuf));
- memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
- nfrontp += sizeof ttytype_sbbuf;
- }
if (his_state_is_will(TELOPT_TSPEED)) {
while (sequenceIs(tspeedsubopt, baseline))
ttloop();
@@ -886,8 +876,7 @@ _gettermname()
if (his_state_is_wont(TELOPT_TTYPE))
return;
settimer(baseline);
- memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
- nfrontp += sizeof ttytype_sbbuf;
+ netwrite(ttytype_sbbuf, sizeof(ttytype_sbbuf));
while (sequenceIs(ttypesubopt, baseline))
ttloop();
}
@@ -1009,7 +998,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);
}
@@ -1159,9 +1148,7 @@ telnet(f, p, host)
* mode, which we do not want.
*/
if (his_want_state_is_will(TELOPT_ECHO)) {
- DIAG(TD_OPTIONS,
- {sprintf(nfrontp, "td: simulating recv\r\n");
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_OPTIONS, netputs("td: simulating recv\r\n"));
willoption(TELOPT_ECHO);
}
@@ -1205,7 +1192,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 +1253,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 {
@@ -1289,9 +1277,7 @@ telnet(f, p, host)
localstat();
#endif /* LINEMODE */
- DIAG(TD_REPORT,
- {sprintf(nfrontp, "td: Entering processing loop\r\n");
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_REPORT, netputs("td: Entering processing loop\r\n"));
#ifdef convex
startslave(host);
@@ -1416,8 +1402,7 @@ telnet(f, p, host)
netip = netibuf;
}
DIAG((TD_REPORT | TD_NETDATA),
- {sprintf(nfrontp, "td: netread %d chars\r\n", ncc);
- nfrontp += strlen(nfrontp);});
+ netprintf("td: netread %d chars\r\n", ncc));
DIAG(TD_NETDATA, printdata("nd", netip, ncc));
}
@@ -1464,9 +1449,7 @@ telnet(f, p, host)
* royally if we send them urgent
* mode data.
*/
- *nfrontp++ = IAC;
- *nfrontp++ = DM;
- neturg = nfrontp-1; /* off by one XXX */
+ netprintf_urg("%c%c", IAC, DM);
#endif
}
if (his_state_is_will(TELOPT_LFLOW) &&
@@ -1476,13 +1459,11 @@ telnet(f, p, host)
ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
if (newflow != flowmode) {
flowmode = newflow;
- (void) sprintf(nfrontp,
- "%c%c%c%c%c%c",
+ netprintf("%c%c%c%c%c%c",
IAC, SB, TELOPT_LFLOW,
flowmode ? LFLOW_ON
: LFLOW_OFF,
IAC, SE);
- nfrontp += 6;
}
}
pcc--;
@@ -1505,19 +1486,19 @@ telnet(f, p, host)
break;
c = *ptyip++ & 0377, pcc--;
if (c == IAC)
- *nfrontp++ = c;
+ netprintf("%c", c);
#if defined(CRAY2) && defined(UNICOS5)
else if (c == '\n' &&
my_state_is_wont(TELOPT_BINARY) && newmap)
- *nfrontp++ = '\r';
+ netputs("\r");
#endif /* defined(CRAY2) && defined(UNICOS5) */
- *nfrontp++ = c;
+ netprintf("%c", c);
if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
- *nfrontp++ = *ptyip++ & 0377;
+ netprintf("%c", *ptyip++ & 0377);
pcc--;
} else
- *nfrontp++ = '\0';
+ netprintf("%c", '\0');
}
}
#if defined(CRAY2) && defined(UNICOS5)
@@ -1679,7 +1660,7 @@ sendsusp()
* When we get an AYT, if ^T is enabled, use that. Otherwise,
* just send back "[Yes]".
*/
- void
+void
recv_ayt()
{
#if defined(SIGINFO) && defined(TCSIG)
@@ -1688,8 +1669,7 @@ recv_ayt()
return;
}
#endif
- (void) strcpy(nfrontp, "\r\n[Yes]\r\n");
- nfrontp += 9;
+ netputs("\r\n[Yes]\r\n");
}
void
diff --git a/src/appl/telnet/telnetd/termstat.c b/src/appl/telnet/telnetd/termstat.c
index 824a1a6..531e167 100644
--- a/src/appl/telnet/telnetd/termstat.c
+++ b/src/appl/telnet/telnetd/termstat.c
@@ -283,10 +283,9 @@ localstat()
# endif /* KLUDGELINEMODE */
send_do(TELOPT_LINEMODE, 1);
/* send along edit modes */
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
+ netprintf("%c%c%c%c%c%c%c", IAC, SB,
TELOPT_LINEMODE, LM_MODE, useeditmode,
IAC, SE);
- nfrontp += 7;
editmode = useeditmode;
# ifdef KLUDGELINEMODE
}
@@ -312,10 +311,9 @@ localstat()
/*
* Send along appropriate edit mode mask.
*/
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
+ (void) netprintf("%c%c%c%c%c%c%c", IAC, SB,
TELOPT_LINEMODE, LM_MODE, useeditmode,
IAC, SE);
- nfrontp += 7;
editmode = useeditmode;
}
@@ -359,20 +357,18 @@ flowstat()
if (his_state_is_will(TELOPT_LFLOW)) {
if (tty_flowmode() != flowmode) {
flowmode = tty_flowmode();
- (void) sprintf(nfrontp, "%c%c%c%c%c%c",
+ netprintf("%c%c%c%c%c%c",
IAC, SB, TELOPT_LFLOW,
flowmode ? LFLOW_ON : LFLOW_OFF,
IAC, SE);
- nfrontp += 6;
}
if (tty_restartany() != restartany) {
restartany = tty_restartany();
- (void) sprintf(nfrontp, "%c%c%c%c%c%c",
+ netprintf("%c%c%c%c%c%c",
IAC, SB, TELOPT_LFLOW,
restartany ? LFLOW_RESTART_ANY
: LFLOW_RESTART_XON,
IAC, SE);
- nfrontp += 6;
}
}
}
@@ -445,10 +441,9 @@ clientstat(code, parm1, parm2)
useeditmode |= MODE_SOFT_TAB;
if (tty_islitecho())
useeditmode |= MODE_LIT_ECHO;
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
+ netprintf("%c%c%c%c%c%c%c", IAC,
SB, TELOPT_LINEMODE, LM_MODE,
- useeditmode, IAC, SE);
- nfrontp += 7;
+ useeditmode, IAC, SE);
editmode = useeditmode;
}
@@ -504,11 +499,10 @@ clientstat(code, parm1, parm2)
set_termbuf();
if (!ack) {
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
+ netprintf("%c%c%c%c%c%c%c", IAC,
SB, TELOPT_LINEMODE, LM_MODE,
useeditmode|MODE_ACK,
IAC, SE);
- nfrontp += 7;
}
editmode = useeditmode;
diff --git a/src/appl/telnet/telnetd/utility.c b/src/appl/telnet/telnetd/utility.c
index 408c6f4..93a932d 100644
--- a/src/appl/telnet/telnetd/utility.c
+++ b/src/appl/telnet/telnetd/utility.c
@@ -33,6 +33,7 @@
/* based on @(#)utility.c 8.1 (Berkeley) 6/4/93 */
+#include <stdarg.h>
#define PRINTOPTIONS
#include "telnetd.h"
@@ -58,8 +59,7 @@ ttloop()
{
void netflush();
- DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n");
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_REPORT, netputs("td: ttloop\r\n"));
if (nfrontp-nbackp) {
netflush();
}
@@ -74,8 +74,7 @@ read_again:
syslog(LOG_INFO, "ttloop: peer died: %m");
exit(1);
}
- DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc);
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_REPORT, netprintf("td: ttloop read %d chars\r\n", ncc));
netip = netibuf;
telrcv(); /* state machine */
if (ncc > 0) {
@@ -118,8 +117,7 @@ ptyflush()
if ((n = pfrontp - pbackp) > 0) {
DIAG((TD_REPORT | TD_PTYDATA),
- { sprintf(nfrontp, "td: ptyflush %d chars\r\n", n);
- nfrontp += strlen(nfrontp); });
+ netprintf("td: ptyflush %d chars\r\n", n));
DIAG(TD_PTYDATA, printdata("pd", pbackp, n));
n = write(pty, pbackp, n);
}
@@ -244,18 +242,15 @@ netclear()
* Send as much data as possible to the network,
* handling requests for urgent data.
*/
- void
+void
netflush()
{
int n;
extern int not42;
if ((n = nfrontp - nbackp) > 0) {
- DIAG(TD_REPORT,
- { sprintf(nfrontp, "td: netflush %d chars\r\n", n);
- n += strlen(nfrontp); /* get count first */
- nfrontp += strlen(nfrontp); /* then move pointer */
- });
+ DIAG(TD_REPORT, {netprintf_noflush("td: netflush %d chars\r\n", n);
+ n = nfrontp - nbackp;});
#ifdef ENCRYPTION
if (encrypt_output) {
char *s = nclearto ? nclearto : nbackp;
@@ -312,33 +307,131 @@ netflush()
return;
} /* end of netflush */
+/*
+ * L8_256(x) = log8(256**x), rounded up, including sign (for decimal
+ * strings too). log8(256) = 8/3, but we use integer math to round
+ * up.
+ */
+#define L8_256(x) (((x * 8 + 2) / 3) + 1)
/*
- * writenet
+ * netprintf
*
- * Just a handy little function to write a bit of raw data to the net.
- * It will force a transmit of the buffer if necessary
+ * Do the equivalent of printf() to the NETOBUF "ring buffer",
+ * possibly calling netflush() if needed.
*
- * arguments
- * ptr - A pointer to a character string to write
- * len - How many bytes to write
+ * Thou shalt not call this with a "%s" format; use netputs instead.
+ * We also don't deal with floating point widths in here.
*/
- void
-writenet(ptr, len)
- register unsigned char *ptr;
- register int len;
+void
+netprintf_ext(int noflush, int seturg, const char *fmt, va_list args)
{
- /* flush buffer if no room for new data) */
- if ((&netobuf[BUFSIZ] - nfrontp) < len) {
- /* if this fails, don't worry, buffer is a little big */
- netflush();
+ size_t remain;
+ size_t maxoutlen;
+ char buf[BUFSIZ];
+ const char *cp;
+ int len;
+
+ buf[0] = '\0'; /* nul-terminate */
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ for (maxoutlen = 0, cp = fmt; *cp; cp++) {
+ if (*cp == '%')
+ /* Ok so this is slightly overkill... */
+ maxoutlen += L8_256(sizeof(long));
+ else
+ maxoutlen++;
}
+ if (maxoutlen >= sizeof(buf))
+ return; /* highly unlikely */
- memcpy(nfrontp, ptr, len);
+#ifdef HAVE_VSNPRINTF
+ len = vsnprintf(buf, sizeof(buf), fmt, args);
+#else
+ len = vsprintf(buf, fmt, args); /* XXX need to fix for SunOS? */
+#endif
+
+ /*
+ * The return value from sprintf()-like functions may be the
+ * number of characters that *would* have been output, not the
+ * number actually output.
+ */
+ if (len <= 0 || len > sizeof(buf))
+ return;
+ if (remain < len && !noflush) {
+ netflush();
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ }
+ if (remain < len)
+ return; /* still not enough space? */
+ memcpy(nfrontp, buf, (size_t)len);
nfrontp += len;
+ if (seturg)
+ neturg = nfrontp - 1;
+}
+
+void
+netprintf(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ netprintf_ext(0, 0, fmt, args);
+ va_end(args);
+}
+
+void
+netprintf_urg(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ netprintf_ext(0, 1, fmt, args);
+ va_end(args);
+}
+
+void
+netprintf_noflush(const char *fmt, ...)
+{
+ va_list args;
-} /* end of writenet */
+ va_start(args, fmt);
+ netprintf_ext(1, 0, fmt, args);
+ va_end(args);
+}
+
+/*
+ * netwrite
+ *
+ * Copy BUF into the NETOBUF "ring buffer", possibly calling
+ * netflush() if needed.
+ */
+int
+netwrite(const char *buf, size_t len)
+{
+ size_t remain;
+
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ if (remain < len) {
+ netflush();
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ }
+ if (remain < len)
+ return 0;
+ memcpy(nfrontp, buf, len);
+ nfrontp += len;
+ return len;
+}
+/*
+ * netputs
+ *
+ * Write S to the NETOBUF "ring buffer". Does not write a '\n'.
+ */
+void
+netputs(const char *s)
+{
+ netwrite(s, strlen(s));
+}
/*
* miscellaneous functions doing a variety of little jobs follow ...
@@ -522,22 +615,26 @@ putf(cp, where)
/*
* Print telnet options and commands in plain text, if possible.
*/
- void
+void
printoption(fmt, option)
register char *fmt;
register int option;
{
- if (TELOPT_OK(option))
- sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option));
- else if (TELCMD_OK(option))
- sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option));
- else
- sprintf(nfrontp, "%s %d\r\n", fmt, option);
- nfrontp += strlen(nfrontp);
+ netputs(fmt);
+ netputs(" ");
+ if (TELOPT_OK(option)) {
+ netputs(TELOPT(option));
+ netputs("\r\n");
+ } else if (TELCMD_OK(option)) {
+ netputs(TELCMD(option));
+ netputs("\r\n");
+ } else {
+ netprintf("%d\r\n", option);
+ }
return;
}
- void
+void
printsub(direction, pointer, length)
char direction; /* '<' or '>' */
unsigned char *pointer; /* where suboption data sits */
@@ -550,9 +647,9 @@ printsub(direction, pointer, length)
return;
if (direction) {
- sprintf(nfrontp, "td: %s suboption ",
- direction == '<' ? "recv" : "send");
- nfrontp += strlen(nfrontp);
+ netputs("td: ");
+ netputs(direction == '<' ? "recv" : "send");
+ netputs(" suboption ");
if (length >= 3) {
register int j;
@@ -560,261 +657,223 @@ printsub(direction, pointer, length)
j = pointer[length-1];
if (i != IAC || j != SE) {
- sprintf(nfrontp, "(terminated by ");
- nfrontp += strlen(nfrontp);
+ netputs("(terminated by ");
if (TELOPT_OK(i))
- sprintf(nfrontp, "%s ", TELOPT(i));
+ netputs(TELOPT(i));
else if (TELCMD_OK(i))
- sprintf(nfrontp, "%s ", TELCMD(i));
+ netputs(TELCMD(i));
else
- sprintf(nfrontp, "%d ", i);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", i);
+ netputs(" ");
if (TELOPT_OK(j))
- sprintf(nfrontp, "%s", TELOPT(j));
+ netputs(TELOPT(j));
else if (TELCMD_OK(j))
- sprintf(nfrontp, "%s", TELCMD(j));
+ netputs(TELCMD(j));
else
- sprintf(nfrontp, "%d", j);
- nfrontp += strlen(nfrontp);
- sprintf(nfrontp, ", not IAC SE!) ");
- nfrontp += strlen(nfrontp);
+ netprintf("%d", j);
+ netputs(", not IAC SE!) ");
}
}
length -= 2;
}
if (length < 1) {
- sprintf(nfrontp, "(Empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(Empty suboption??\?)");
return;
}
switch (pointer[0]) {
case TELOPT_TTYPE:
- sprintf(nfrontp, "TERMINAL-TYPE ");
- nfrontp += strlen(nfrontp);
+ netputs("TERMINAL-TYPE ");
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2);
+ netputs("IS \"");
+ netwrite((char *)pointer + 2, (size_t)(length - 2));
+ netputs("\"");
break;
case TELQUAL_SEND:
- sprintf(nfrontp, "SEND");
+ netputs("SEND");
break;
default:
- sprintf(nfrontp,
- "- unknown qualifier %d (0x%x).",
- pointer[1], pointer[1]);
+ netprintf("- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
}
- nfrontp += strlen(nfrontp);
break;
case TELOPT_TSPEED:
- sprintf(nfrontp, "TERMINAL-SPEED");
- nfrontp += strlen(nfrontp);
+ netputs("TERMINAL-SPEED ");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(empty suboption??\?)");
break;
}
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2);
- nfrontp += strlen(nfrontp);
+ netputs("IS ");
+ netwrite((char *)pointer + 2, (size_t)(length - 2));
break;
default:
if (pointer[1] == 1)
- sprintf(nfrontp, " SEND");
+ netputs("SEND");
else
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
}
break;
case TELOPT_LFLOW:
- sprintf(nfrontp, "TOGGLE-FLOW-CONTROL");
- nfrontp += strlen(nfrontp);
+ netputs("TOGGLE-FLOW-CONTROL ");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(empty suboption??\?)");
break;
}
switch (pointer[1]) {
case LFLOW_OFF:
- sprintf(nfrontp, " OFF"); break;
+ netputs("OFF"); break;
case LFLOW_ON:
- sprintf(nfrontp, " ON"); break;
+ netputs("ON"); break;
case LFLOW_RESTART_ANY:
- sprintf(nfrontp, " RESTART-ANY"); break;
+ netputs("RESTART-ANY"); break;
case LFLOW_RESTART_XON:
- sprintf(nfrontp, " RESTART-XON"); break;
+ netputs("RESTART-XON"); break;
default:
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- }
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d (unknown)", pointer[1]);
}
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case TELOPT_NAWS:
- sprintf(nfrontp, "NAWS");
- nfrontp += strlen(nfrontp);
+ netputs("NAWS");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (empty suboption??\?)");
break;
}
if (length == 2) {
- sprintf(nfrontp, " ?%d?", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netprintf(" ?%d?", pointer[1]);
break;
}
- sprintf(nfrontp, " %d %d (%d)",
+ netprintf(" %d %d (%d)",
pointer[1], pointer[2],
(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
- nfrontp += strlen(nfrontp);
if (length == 4) {
- sprintf(nfrontp, " ?%d?", pointer[3]);
- nfrontp += strlen(nfrontp);
+ netprintf(" ?%d?", pointer[3]);
break;
}
- sprintf(nfrontp, " %d %d (%d)",
+ netprintf(" %d %d (%d)",
pointer[3], pointer[4],
(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
- nfrontp += strlen(nfrontp);
- for (i = 5; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (i = 5; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case TELOPT_LINEMODE:
- sprintf(nfrontp, "LINEMODE ");
- nfrontp += strlen(nfrontp);
+ netputs("LINEMODE ");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(empty suboption??\?)");
break;
}
switch (pointer[1]) {
case WILL:
- sprintf(nfrontp, "WILL ");
+ netputs("WILL ");
goto common;
case WONT:
- sprintf(nfrontp, "WONT ");
+ netputs("WONT ");
goto common;
case DO:
- sprintf(nfrontp, "DO ");
+ netputs("DO ");
goto common;
case DONT:
- sprintf(nfrontp, "DONT ");
+ netputs("DONT ");
common:
- nfrontp += strlen(nfrontp);
if (length < 3) {
- sprintf(nfrontp, "(no option??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(no option??\?)");
break;
}
switch (pointer[2]) {
case LM_FORWARDMASK:
- sprintf(nfrontp, "Forward Mask");
- nfrontp += strlen(nfrontp);
- for (i = 3; i < length; i++) {
- sprintf(nfrontp, " %x", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netputs("Forward Mask");
+ for (i = 3; i < length; i++)
+ netprintf(" %x", pointer[i]);
break;
default:
- sprintf(nfrontp, "%d (unknown)", pointer[2]);
- nfrontp += strlen(nfrontp);
- for (i = 3; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d (unknown)", pointer[2]);
+ for (i = 3; i < length; i++)
+ netprintf(" %d", pointer[i]);
break;
}
break;
case LM_SLC:
- sprintf(nfrontp, "SLC");
- nfrontp += strlen(nfrontp);
+ netputs("SLC");
for (i = 2; i < length - 2; i += 3) {
- if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
- sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
- else
- sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]);
- nfrontp += strlen(nfrontp);
+ if (SLC_NAME_OK(pointer[i+SLC_FUNC])) {
+ netputs(" ");
+ netputs(SLC_NAME(pointer[i+SLC_FUNC]));
+ } else
+ netprintf(" %d", pointer[i+SLC_FUNC]);
switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
case SLC_NOSUPPORT:
- sprintf(nfrontp, " NOSUPPORT"); break;
+ netputs(" NOSUPPORT"); break;
case SLC_CANTCHANGE:
- sprintf(nfrontp, " CANTCHANGE"); break;
+ netputs(" CANTCHANGE"); break;
case SLC_VARIABLE:
- sprintf(nfrontp, " VARIABLE"); break;
+ netputs(" VARIABLE"); break;
case SLC_DEFAULT:
- sprintf(nfrontp, " DEFAULT"); break;
+ netputs(" DEFAULT"); break;
}
- nfrontp += strlen(nfrontp);
- sprintf(nfrontp, "%s%s%s",
- pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
- pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
- pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
- nfrontp += strlen(nfrontp);
+ netputs(pointer[i+SLC_FLAGS]&SLC_ACK
+ ? "|ACK" : "");
+ netputs(pointer[i+SLC_FLAGS]&SLC_FLUSHIN
+ ? "|FLUSHIN" : "");
+ netputs(pointer[i+SLC_FLAGS]&SLC_FLUSHOUT
+ ? "|FLUSHOUT" : "");
if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
SLC_FLUSHOUT| SLC_LEVELBITS)) {
- sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]);
- nfrontp += strlen(nfrontp);
+ netprintf("(0x%x)", pointer[i+SLC_FLAGS]);
}
- sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d;", pointer[i+SLC_VALUE]);
if ((pointer[i+SLC_VALUE] == IAC) &&
(pointer[i+SLC_VALUE+1] == IAC))
i++;
}
- for (; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case LM_MODE:
- sprintf(nfrontp, "MODE ");
- nfrontp += strlen(nfrontp);
+ netputs("MODE ");
if (length < 3) {
- sprintf(nfrontp, "(no mode??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(no mode??\?)");
break;
}
{
- char tbuf[32];
- sprintf(tbuf, "%s%s%s%s%s",
- pointer[2]&MODE_EDIT ? "|EDIT" : "",
- pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
- pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
- pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
- pointer[2]&MODE_ACK ? "|ACK" : "");
- sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0");
- nfrontp += strlen(nfrontp);
- }
- if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) {
- sprintf(nfrontp, " (0x%x)", pointer[2]);
- nfrontp += strlen(nfrontp);
- }
- for (i = 3; i < length; i++) {
- sprintf(nfrontp, " ?0x%x?", pointer[i]);
- nfrontp += strlen(nfrontp);
+ int wrotemode = 0;
+
+#define NETPUTS_MODE(x) \
+do { \
+ if (pointer[2] & (MODE_##x)) { \
+ if (wrotemode) netputs("|"); \
+ netputs(#x); \
+ wrotemode++; \
+ } \
+} while (0)
+ NETPUTS_MODE(EDIT);
+ NETPUTS_MODE(TRAPSIG);
+ NETPUTS_MODE(SOFT_TAB);
+ NETPUTS_MODE(LIT_ECHO);
+ NETPUTS_MODE(ACK);
+#undef NETPUTS_MODE
+ if (!wrotemode)
+ netputs("0");
}
+ if (pointer[2] & ~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
+ netprintf(" (0x%x)", pointer[2]);
+ for (i = 3; i < length; i++)
+ netprintf(" ?0x%x?", pointer[i]);
break;
default:
- sprintf(nfrontp, "%d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ netprintf(" %d", pointer[i]);
}
break;
@@ -822,24 +881,19 @@ printsub(direction, pointer, length)
register char *cp;
register int j, k;
- sprintf(nfrontp, "STATUS");
- nfrontp += strlen(nfrontp);
+ netputs("STATUS");
switch (pointer[1]) {
default:
if (pointer[1] == TELQUAL_SEND)
- sprintf(nfrontp, " SEND");
+ netputs(" SEND");
else
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf(" %d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case TELQUAL_IS:
- sprintf(nfrontp, " IS\r\n");
- nfrontp += strlen(nfrontp);
+ netputs(" IS\r\n");
for (i = 2; i < length; i++) {
switch(pointer[i]) {
@@ -849,19 +903,19 @@ printsub(direction, pointer, length)
case WONT: cp = "WONT"; goto common2;
common2:
i++;
+ netputs(" ");
+ netputs(cp);
+ netputs(" ");
if (TELOPT_OK(pointer[i]))
- sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i]));
+ netputs(TELOPT(pointer[i]));
else
- sprintf(nfrontp, " %s %d", cp, pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", pointer[i]);
- sprintf(nfrontp, "\r\n");
- nfrontp += strlen(nfrontp);
+ netputs("\r\n");
break;
case SB:
- sprintf(nfrontp, " SB ");
- nfrontp += strlen(nfrontp);
+ netputs(" SB ");
i++;
j = k = i;
while (j < length) {
@@ -877,20 +931,17 @@ printsub(direction, pointer, length)
}
printsub(0, &pointer[i], k - i);
if (i < length) {
- sprintf(nfrontp, " SE");
- nfrontp += strlen(nfrontp);
+ netputs(" SE");
i = j;
} else
i = j - 1;
- sprintf(nfrontp, "\r\n");
- nfrontp += strlen(nfrontp);
+ netputs("\r\n");
break;
default:
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d", pointer[i]);
break;
}
}
@@ -900,86 +951,79 @@ printsub(direction, pointer, length)
}
case TELOPT_XDISPLOC:
- sprintf(nfrontp, "X-DISPLAY-LOCATION ");
- nfrontp += strlen(nfrontp);
+ netputs("X-DISPLAY-LOCATION ");
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2);
+ netputs("IS \"");
+ netwrite((char *)pointer + 2, (size_t)(length - 2));
+ netputs("\"");
break;
case TELQUAL_SEND:
- sprintf(nfrontp, "SEND");
+ netputs("SEND");
break;
default:
- sprintf(nfrontp, "- unknown qualifier %d (0x%x).",
- pointer[1], pointer[1]);
+ netprintf("- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
}
- nfrontp += strlen(nfrontp);
break;
case TELOPT_NEW_ENVIRON:
- sprintf(nfrontp, "NEW-ENVIRON ");
+ netputs("NEW-ENVIRON ");
goto env_common1;
case TELOPT_OLD_ENVIRON:
- sprintf(nfrontp, "OLD-ENVIRON");
+ netputs("OLD-ENVIRON ");
env_common1:
- nfrontp += strlen(nfrontp);
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, "IS ");
+ netputs("IS ");
goto env_common;
case TELQUAL_SEND:
- sprintf(nfrontp, "SEND ");
+ netputs("SEND ");
goto env_common;
case TELQUAL_INFO:
- sprintf(nfrontp, "INFO ");
+ netputs("INFO ");
env_common:
- nfrontp += strlen(nfrontp);
{
register int noquote = 2;
for (i = 2; i < length; i++ ) {
switch (pointer[i]) {
case NEW_ENV_VAR:
- sprintf(nfrontp, "\" VAR " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" VAR " + noquote);
noquote = 2;
break;
case NEW_ENV_VALUE:
- sprintf(nfrontp, "\" VALUE " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" VALUE " + noquote);
noquote = 2;
break;
case ENV_ESC:
- sprintf(nfrontp, "\" ESC " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" ESC " + noquote);
noquote = 2;
break;
case ENV_USERVAR:
- sprintf(nfrontp, "\" USERVAR " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" USERVAR " + noquote);
noquote = 2;
break;
default:
if (isprint(pointer[i]) && pointer[i] != '"') {
if (noquote) {
- *nfrontp++ = '"';
+ netputs("\"");
noquote = 0;
}
- *nfrontp++ = pointer[i];
+ netprintf("%c", pointer[i]);
} else {
- sprintf(nfrontp, "\" %03o " + noquote,
- pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("\" %03o " + noquote,
+ pointer[i]);
noquote = 2;
}
break;
}
}
if (!noquote)
- *nfrontp++ = '"';
+ netputs("\"");
break;
}
}
@@ -987,91 +1031,74 @@ printsub(direction, pointer, length)
#if defined(AUTHENTICATION)
case TELOPT_AUTHENTICATION:
- sprintf(nfrontp, "AUTHENTICATION");
- nfrontp += strlen(nfrontp);
+ netputs("AUTHENTICATION");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case TELQUAL_REPLY:
case TELQUAL_IS:
- sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ?
- "IS" : "REPLY");
- nfrontp += strlen(nfrontp);
+ netputs((pointer[1] == TELQUAL_IS) ? " IS " : " REPLY ");
if (AUTHTYPE_NAME_OK(pointer[2]))
- sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2]));
+ netputs(AUTHTYPE_NAME(pointer[2]));
else
- sprintf(nfrontp, "%d ", pointer[2]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d ", pointer[2]);
if (length < 3) {
- sprintf(nfrontp, "(partial suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(partial suboption??\?)");
break;
}
- sprintf(nfrontp, "%s|%s%s",
- ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
- "CLIENT" : "SERVER",
- ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
- "MUTUAL" : "ONE-WAY",
- ((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON) ?
- "|ENCRYPT" : "");
- nfrontp += strlen(nfrontp);
+ netputs(((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT)
+ ? "CLIENT|" : "SERVER|");
+ netputs(((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+ ? "MUTUAL" : "ONE-WAY");
+ netputs(((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON)
+ ? "|ENCRYPT" : "");
auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
- sprintf(nfrontp, "%s", buf);
- nfrontp += strlen(nfrontp);
+ netputs(buf);
break;
case TELQUAL_SEND:
i = 2;
- sprintf(nfrontp, " SEND ");
- nfrontp += strlen(nfrontp);
+ netputs(" SEND ");
while (i < length) {
if (AUTHTYPE_NAME_OK(pointer[i]))
- sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i]));
+ netputs(AUTHTYPE_NAME(pointer[i]));
else
- sprintf(nfrontp, "%d ", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", pointer[i]);
+ netputs(" ");
if (++i >= length) {
- sprintf(nfrontp, "(partial suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(partial suboption??\?)");
break;
}
- sprintf(nfrontp, "%s|%s%s ",
- ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
- "CLIENT" : "SERVER",
- ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
- "MUTUAL" : "ONE-WAY",
- ((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON) ?
- "|ENCRYPT" : "");
- nfrontp += strlen(nfrontp);
+ netputs(((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT)
+ ? "CLIENT|" : "SERVER|");
+ netputs(((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+ ? "MUTUAL" : "ONE-WAY");
+ if ((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON)
+ netputs("|ENCRYPT");
++i;
}
break;
case TELQUAL_NAME:
i = 2;
- sprintf(nfrontp, " NAME \"");
- nfrontp += strlen(nfrontp);
+ netputs(" NAME \"");
while (i < length) {
if (isprint(pointer[i]))
- *nfrontp++ = pointer[i++];
+ netprintf("%c", pointer[i++]);
else {
- sprintf(nfrontp, "\"%03o",pointer[i++]);
- nfrontp += strlen(nfrontp);
+ netprintf("\\%03o", pointer[i++]);
}
}
- *nfrontp++ = '"';
+ netputs("\"");
break;
default:
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
}
break;
@@ -1079,87 +1106,72 @@ printsub(direction, pointer, length)
#ifdef ENCRYPTION
case TELOPT_ENCRYPT:
- sprintf(nfrontp, "ENCRYPT");
- nfrontp += strlen(nfrontp);
+ netputs("ENCRYPT");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case ENCRYPT_START:
- sprintf(nfrontp, " START");
- nfrontp += strlen(nfrontp);
+ netputs(" START");
break;
case ENCRYPT_END:
- sprintf(nfrontp, " END");
- nfrontp += strlen(nfrontp);
+ netputs(" END");
break;
case ENCRYPT_REQSTART:
- sprintf(nfrontp, " REQUEST-START");
- nfrontp += strlen(nfrontp);
+ netputs(" REQUEST-START");
break;
case ENCRYPT_REQEND:
- sprintf(nfrontp, " REQUEST-END");
- nfrontp += strlen(nfrontp);
+ netputs(" REQUEST-END");
break;
case ENCRYPT_IS:
case ENCRYPT_REPLY:
- sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ?
- "IS" : "REPLY");
- nfrontp += strlen(nfrontp);
+ netputs((pointer[1] == ENCRYPT_IS)
+ ? " IS " : " REPLY ");
if (length < 3) {
- sprintf(nfrontp, " (partial suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (partial suboption??\?)");
break;
}
if (ENCTYPE_NAME_OK(pointer[2]))
- sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2]));
+ netputs(ENCTYPE_NAME(pointer[2]));
else
- sprintf(nfrontp, " %d (unknown)", pointer[2]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d (unknown)", pointer[2]);
+ netputs(" ");
encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
- sprintf(nfrontp, "%s", buf);
- nfrontp += strlen(nfrontp);
+ netputs(buf);
break;
case ENCRYPT_SUPPORT:
i = 2;
- sprintf(nfrontp, " SUPPORT ");
- nfrontp += strlen(nfrontp);
+ netputs(" SUPPORT ");
while (i < length) {
if (ENCTYPE_NAME_OK(pointer[i]))
- sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i]));
+ netputs(ENCTYPE_NAME(pointer[i]));
else
- sprintf(nfrontp, "%d ", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", pointer[i]);
+ netputs(" ");
i++;
}
break;
case ENCRYPT_ENC_KEYID:
- sprintf(nfrontp, " ENC_KEYID", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netputs(" ENC_KEYID");
goto encommon;
case ENCRYPT_DEC_KEYID:
- sprintf(nfrontp, " DEC_KEYID", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netputs(" DEC_KEYID");
goto encommon;
default:
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d (unknown)", pointer[1]);
encommon:
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (i = 2; i < length; i++)
+ netprintf(" %d", pointer[i]);
break;
}
break;
@@ -1167,18 +1179,15 @@ printsub(direction, pointer, length)
default:
if (TELOPT_OK(pointer[0]))
- sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0]));
+ netputs(TELOPT(pointer[0]));
else
- sprintf(nfrontp, "%d (unknown)", pointer[i]);
- nfrontp += strlen(nfrontp);
- for (i = 1; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d", pointer[0]);
+ netputs(" (unknown)");
+ for (i = 1; i < length; i++)
+ netprintf(" %d", pointer[i]);
break;
}
- sprintf(nfrontp, "\r\n");
- nfrontp += strlen(nfrontp);
+ netputs("\r\n");
}
/*
@@ -1194,32 +1203,25 @@ printdata(tag, ptr, cnt)
char xbuf[30];
while (cnt) {
- /* flush net output buffer if no room for new data) */
- if ((&netobuf[BUFSIZ] - nfrontp) < 80) {
- netflush();
- }
-
/* add a line of output */
- sprintf(nfrontp, "%s: ", tag);
- nfrontp += strlen(nfrontp);
+ netputs(tag);
+ netputs(": ");
for (i = 0; i < 20 && cnt; i++) {
- sprintf(nfrontp, "%02x", *ptr);
- nfrontp += strlen(nfrontp);
+ netprintf("%02x", *ptr);
if (isprint(*ptr)) {
xbuf[i] = *ptr;
} else {
xbuf[i] = '.';
}
- if (i % 2) {
- *nfrontp = ' ';
- nfrontp++;
- }
+ if (i % 2)
+ netputs(" ");
cnt--;
ptr++;
}
xbuf[i] = '\0';
- sprintf(nfrontp, " %s\r\n", xbuf );
- nfrontp += strlen(nfrontp);
+ netputs(" ");
+ netputs(xbuf);
+ netputs("\r\n");
}
}
#endif /* DIAGNOSTICS */