From: Ken Raeburn Date: Fri, 30 Jun 2000 00:16:21 +0000 (+0000) Subject: 1.2-beta4 pullup X-Git-Tag: krb5-1.3-alpha1~2067 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=5115426fe6ca5bd63cf8e3997fbaf8277792c024;p=krb5.git 1.2-beta4 pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@12470 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/appl/bsd/ChangeLog b/src/appl/bsd/ChangeLog index 9c87d9816..0eac15d6b 100644 --- a/src/appl/bsd/ChangeLog +++ b/src/appl/bsd/ChangeLog @@ -1,3 +1,144 @@ +2000-06-19 Tom Yu + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + Ken Raeburn + + * 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 + + * krshd.c: Shuffle inclusion of defines.h so that some krb5 + structures are declared prior to the kcmd() prototype. + +2000-05-16 Ken Raeburn + + * defines.h (kcmd): Add prototype. + * krcp.c (main): Add extra arg to a kcmd call I missed yesterday. + +2000-05-15 Ken Raeburn + + * 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 + + * v4rcp.c (main, case 'k'): Make sure krb_realm is + null-terminated. + +2000-04-27 Nalin Dahyabhai + + * 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 + + * configure.in: Check for alpha*-dec-osf* instead of + alpha-dec-osf*. + 2000-03-15 Ken Raeburn Mark D. Roth diff --git a/src/appl/bsd/Makefile.in b/src/appl/bsd/Makefile.in index eee13ca90..93a6cba2e 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 6d31f489c..cf6547679 100644 --- a/src/appl/bsd/configure.in +++ b/src/appl/bsd/configure.in @@ -25,11 +25,12 @@ dnl Make our operating system-specific security checks and definitions for dnl login. dnl case $krb5_cv_host in -*-*-aix3*) # AIX has streams include files but not streams TTY -# Moreover, strops.h trashes sys/ioctl.h -krb5_cv_has_streams=no -;; -alpha-dec-osf*) +*-*-aix3*) + # AIX has streams include files but not streams TTY + # Moreover, strops.h trashes sys/ioctl.h + krb5_cv_has_streams=no + ;; +alpha*-dec-osf*) AC_CHECK_LIB(security,setluid, AC_DEFINE(HAVE_SETLUID) LOGINLIBS="$LOGINLIBS -lsecurity" diff --git a/src/appl/bsd/defines.h b/src/appl/bsd/defines.h index fd9c3e14c..6365d2cbe 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/kcmd.c b/src/appl/bsd/kcmd.c index 0e68f88e7..3e401cced 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 967014579..7292e72fe 100644 --- a/src/appl/bsd/krcp.c +++ b/src/appl/bsd/krcp.c @@ -71,6 +71,8 @@ char copyright[] = #include #include +#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 da4a88980..0039056c3 100644 --- a/src/appl/bsd/krlogin.c +++ b/src/appl/bsd/krlogin.c @@ -177,6 +177,7 @@ int fflag = 0, Fflag = 0; krb5_creds *cred; struct sockaddr_in local, foreign; krb5_context bsd_context; +krb5_auth_context auth_context; #ifdef KRB5_KRB4_COMPAT Key_schedule v4_schedule; @@ -377,6 +378,7 @@ main(argc, argv) #endif #endif int port, debug_port = 0; + enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK; memset(&defaultservent, 0, sizeof(struct servent)); if (strrchr(argv[0], '/')) @@ -502,6 +504,16 @@ main(argc, argv) argv++, argc--; goto another; } + if (argc > 0 && !strcmp(*argv, "-PO")) { + kcmd_proto = KCMD_OLD_PROTOCOL; + argv++, argc--; + goto another; + } + if (argc > 0 && !strcmp(*argv, "-PN")) { + kcmd_proto = KCMD_NEW_PROTOCOL; + argv++, argc--; + goto another; + } #endif /* KERBEROS */ if (host == 0) goto usage; @@ -559,7 +571,8 @@ main(argc, argv) if (tcgetattr(0, &ttyb) == 0) { int ospeed = cfgetospeed (&ttyb); - (void) strcat(term, "/"); + term[sizeof(term) - 1] = '\0'; + (void) strncat(term, "/", sizeof(term) - 1 - strlen(term)); if (ospeed >= 50) /* On some systems, ospeed is the baud rate itself, not a table index. */ @@ -567,15 +580,16 @@ main(argc, argv) else if (ospeed >= sizeof(speeds)/sizeof(char*)) /* Past end of table, but not high enough to look like a real speed. */ - (void) strcat (term, speeds[sizeof(speeds)/sizeof(char*) - 1]); + (void) strncat (term, speeds[sizeof(speeds)/sizeof(char*) - 1], sizeof(term) - 1 - strlen(term)); else { - (void) strcat(term, speeds[ospeed]); + (void) strncat(term, speeds[ospeed], sizeof(term) - 1 - strlen(term)); } + term[sizeof (term) - 1] = '\0'; } #else if (ioctl(0, TIOCGETP, &ttyb) == 0) { - (void) strcat(term, "/"); - (void) strcat(term, speeds[ttyb.sg_ospeed]); + (void) strncat(term, "/", sizeof(term) - 1 - strlen(term)); + (void) strncat(term, speeds[ttyb.sg_ospeed], sizeof(term) - 1 - strlen(term)); } #endif (void) get_window_size(0, &winsize); @@ -631,10 +645,14 @@ main(argc, argv) 0, /* No need for sequence number */ 0, /* No need for server seq # */ &local, &foreign, - authopts, + &auth_context, authopts, 0, /* Not any port # */ - 0); + 0, + &kcmd_proto); if (status) { + if (kcmd_proto == KCMD_NEW_PROTOCOL && encrypt_flag) + /* Don't fall back to something less secure. */ + exit (1); #ifdef KRB5_KRB4_COMPAT fprintf(stderr, "Trying krb4 rlogin...\n"); status = k4cmd(&sock, &host, port, @@ -650,19 +668,20 @@ main(argc, argv) try_normal(orig_argv); #endif } else { - krb5_boolean similar; - - rcmd_stream_init_krb5(&cred->keyblock, encrypt_flag, 1); - - if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC, - cred->keyblock.enctype, &similar)) - try_normal(orig_argv); /* doesn't return */ + krb5_keyblock *key = 0; - if (!similar) { + if (kcmd_proto == KCMD_NEW_PROTOCOL) { do_inband = 1; - if (debug_port) - fprintf(stderr, "DEBUG: setting do_inband\n"); + + status = krb5_auth_con_getlocalsubkey (bsd_context, auth_context, + &key); + if ((status || !key) && encrypt_flag) + try_normal(orig_argv); } + if (key == 0) + key = &cred->keyblock; + + rcmd_stream_init_krb5(key, encrypt_flag, 1, 1, kcmd_proto); } rem = sock; @@ -1122,9 +1141,9 @@ writer() #endif if (c != cmdchar) - (void) rcmd_stream_write(rem, &cmdchar, 1); + (void) rcmd_stream_write(rem, &cmdchar, 1, 0); } - if (rcmd_stream_write(rem, &c, 1) == 0) { + if (rcmd_stream_write(rem, &c, 1, 0) == 0) { prf("line gone"); break; } @@ -1239,7 +1258,7 @@ sendwindow() wp->ws_col = htons(winsize.ws_col); wp->ws_xpixel = htons(winsize.ws_xpixel); wp->ws_ypixel = htons(winsize.ws_ypixel); - (void) rcmd_stream_write(rem, obuf, sizeof(obuf)); + (void) rcmd_stream_write(rem, obuf, sizeof(obuf), 0); } @@ -1458,7 +1477,7 @@ fd_set readset, excset, writeset; bufp += n; } if (FD_ISSET(rem, &readset)) { - rcvcnt = rcmd_stream_read(rem, rcvbuf, sizeof (rcvbuf)); + rcvcnt = rcmd_stream_read(rem, rcvbuf, sizeof (rcvbuf), 0); if (rcvcnt == 0) return (0); if (rcvcnt < 0) diff --git a/src/appl/bsd/krlogind.c b/src/appl/bsd/krlogind.c index e37b84cc8..d27488499 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); @@ -1033,7 +1035,7 @@ void protocol(f, p) } #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) if (FD_ISSET(f, &ibits)) { - fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf)); + fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf), 0); if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) { fcc = 0; } else { @@ -1121,7 +1123,7 @@ void protocol(f, p) } if (FD_ISSET(f, &obits) && pcc > 0) { - cc = rcmd_stream_write(f, pbp, pcc); + cc = rcmd_stream_write(f, pbp, pcc, 0); if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) { /* also shouldn't happen */ sleep(5); @@ -1160,7 +1162,7 @@ void fatal(f, msg) buf[0] = '\01'; /* error indicator */ (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg); if ((f == netf) && (pid > 0)) - (void) rcmd_stream_write(f, buf, strlen(buf)); + (void) rcmd_stream_write(f, buf, strlen(buf), 0); else (void) write(f, buf, strlen(buf)); syslog(LOG_ERR,"%s\n",msg); @@ -1377,9 +1379,11 @@ recvauth(valid_checksum) int len; krb5_data inbuf; char v4_instance[INST_SZ]; /* V4 Instance */ - char v4_version[9]; + krb5_data version; krb5_authenticator *authenticator; krb5_rcache rcache; + enum kcmd_proto kcmd_proto; + krb5_keyblock *key; *valid_checksum = 0; len = sizeof(laddr); @@ -1423,8 +1427,8 @@ recvauth(valid_checksum) if (status) return status; } - if ((status = krb5_compat_recvauth(bsd_context, &auth_context, &netf, - "KCMDV0.1", + if ((status = krb5_compat_recvauth_version(bsd_context, &auth_context, + &netf, NULL, /* Specify daemon principal */ 0, /* no flags */ keytab, /* normally NULL to use v5srvtab */ @@ -1438,8 +1442,8 @@ recvauth(valid_checksum) &ticket, /* return ticket */ &auth_sys, /* which authentication system*/ - &v4_kdata, v4_schedule, v4_version))) { - + &v4_kdata, v4_schedule, + &version))) { if (auth_sys == KRB5_RECVAUTH_V5) { /* * clean up before exiting @@ -1453,7 +1457,25 @@ recvauth(valid_checksum) getstr(netf, lusername, sizeof (lusername), "locuser"); getstr(netf, term, sizeof(term), "Terminal type"); - if ((auth_sys == KRB5_RECVAUTH_V5) && !checksum_ignored) { + + kcmd_proto = KCMD_UNKNOWN_PROTOCOL; + if (auth_sys == KRB5_RECVAUTH_V5) { + if (version.length != 9) { + fatal (netf, "bad application version length"); + } + if (!memcmp (version.data, "KCMDV0.1", 9)) + kcmd_proto = KCMD_OLD_PROTOCOL; + else if (!memcmp (version.data, "KCMDV0.2", 9)) + kcmd_proto = KCMD_NEW_PROTOCOL; + } +#ifdef KRB5_KRB4_COMPAT + if (auth_sys == KRB5_RECVAUTH_V4) + kcmd_proto = KCMD_V4_PROTOCOL; +#endif + + if ((auth_sys == KRB5_RECVAUTH_V5) + && !(checksum_ignored + && kcmd_proto == KCMD_OLD_PROTOCOL)) { if ((status = krb5_auth_con_getauthenticator(bsd_context, auth_context, &authenticator))) @@ -1500,7 +1522,8 @@ recvauth(valid_checksum) * Assume it to be the same as the first component of the * principal's name. */ - strcpy(rusername, v4_kdata->pname); + strncpy(rusername, v4_kdata->pname, sizeof(rusername) - 1); + rusername[sizeof(rusername) - 1] = '\0'; status = krb5_425_conv_principal(bsd_context, v4_kdata->pname, v4_kdata->pinst, v4_kdata->prealm, @@ -1519,22 +1542,20 @@ recvauth(valid_checksum) &client))) return status; - rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 1); - - { - krb5_boolean similar; - - if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC, - ticket->enc_part2->session->enctype, - &similar)) - return(status); + key = 0; + status = krb5_auth_con_getremotesubkey (bsd_context, auth_context, &key); + if (status) + fatal (netf, "Server can't get session subkey"); + if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL) + fatal (netf, "No session subkey sent"); + if (key && kcmd_proto == KCMD_OLD_PROTOCOL) + fatal (netf, "Session subkey not permitted under old kcmd protocol"); + if (key == 0) + key = ticket->enc_part2->session; - if (!similar) { - do_inband = 1; - syslog(LOG_DEBUG, "setting do_inband"); - } - } + rcmd_stream_init_krb5 (key, do_encrypt, 1, 0, kcmd_proto); + do_inband = (kcmd_proto == KCMD_NEW_PROTOCOL); getstr(netf, rusername, sizeof(rusername), "remuser"); diff --git a/src/appl/bsd/krsh.c b/src/appl/bsd/krsh.c index 9d602b22a..c1741d856 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 3844087bb..c69729c5c 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 #endif @@ -162,6 +160,8 @@ char copyright[] = Key_schedule v4_schedule; #endif +#include "defines.h" + #if HAVE_ARPA_NAMESER_H #include #endif @@ -1245,7 +1245,7 @@ if(port) shutdown(s, 1+1); FD_CLR(pv[0], &readfrom); } else { - (void) rcmd_stream_write(s, buf, cc); + (void) rcmd_stream_write(s, buf, cc, 1); } } if (FD_ISSET(pw[0], &ready)) { @@ -1256,12 +1256,12 @@ if(port) shutdown(f, 1+1); FD_CLR(pw[0], &readfrom); } else { - (void) rcmd_stream_write(f, buf, cc); + (void) rcmd_stream_write(f, buf, cc, 0); } } if (port&&FD_ISSET(s, &ready)) { /* read from the alternate channel, signal the child */ - if (rcmd_stream_read(s, &sig, 1) <= 0) { + if (rcmd_stream_read(s, &sig, 1, 1) <= 0) { FD_CLR(s, &readfrom); } else { #ifdef POSIX_SIGNALS @@ -1277,7 +1277,7 @@ if(port) if (FD_ISSET(f, &ready)) { /* read from the net, write to child stdin */ errno = 0; - cc = rcmd_stream_read(f, buf, sizeof(buf)); + cc = rcmd_stream_read(f, buf, sizeof(buf), 0); if (cc <= 0) { (void) close(px[1]); FD_CLR(f, &readfrom); @@ -1468,15 +1468,16 @@ if(port) strcpy((char *) cmdbuf + offst, kprogdir); cp = copy + 3 + offst; + cmdbuf[sizeof(cmdbuf) - 1] = '\0'; if (auth_sys == KRB5_RECVAUTH_V4) { - strcat(cmdbuf, "/v4rcp"); + strncat(cmdbuf, "/v4rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf)); } else { - strcat(cmdbuf, "/rcp"); + strncat(cmdbuf, "/rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf)); } if (stat((char *)cmdbuf + offst, &s) >= 0) - strcat(cmdbuf, cp); + strncat(cmdbuf, cp, sizeof(cmdbuf) - 1 - strlen(cmdbuf)); else - strcpy(cmdbuf, copy); + strncpy(cmdbuf, copy, sizeof(cmdbuf) - 1 - strlen(cmdbuf)); free(copy); } #endif @@ -1775,7 +1776,6 @@ recvauth(netf, peersin, valid_checksum) krb5_data inbuf; #ifdef KRB5_KRB4_COMPAT char v4_instance[INST_SZ]; /* V4 Instance */ - char v4_version[9]; #endif krb5_authenticator *authenticator; krb5_ticket *ticket; @@ -1783,6 +1783,8 @@ recvauth(netf, peersin, valid_checksum) struct passwd *pwd; uid_t uid; gid_t gid; + enum kcmd_proto kcmd_proto; + krb5_data version; *valid_checksum = 0; len = sizeof(laddr); @@ -1828,8 +1830,7 @@ recvauth(netf, peersin, valid_checksum) } #ifdef KRB5_KRB4_COMPAT - status = krb5_compat_recvauth(bsd_context, &auth_context, &netf, - "KCMDV0.1", + status = krb5_compat_recvauth_version(bsd_context, &auth_context, &netf, NULL, /* Specify daemon principal */ 0, /* no flags */ keytab, /* normally NULL to use v5srvtab */ @@ -1842,14 +1843,14 @@ recvauth(netf, peersin, valid_checksum) &ticket, /* return ticket */ &auth_sys, /* which authentication system*/ - &v4_kdata, 0, v4_version); + &v4_kdata, 0, &version); #else - status = krb5_recvauth(bsd_context, &auth_context, &netf, - "KCMDV0.1", - NULL, /* daemon principal */ - 0, /* no flags */ - keytab, /* normally NULL to use v5srvtab */ - &ticket); /* return ticket */ + status = krb5_recvauth_version(bsd_context, &auth_context, &netf, + NULL, /* daemon principal */ + 0, /* no flags */ + keytab, /* normally NULL to use v5srvtab */ + &ticket, /* return ticket */ + &version); /* application version string */ auth_sys = KRB5_RECVAUTH_V5; #endif @@ -1891,6 +1892,14 @@ recvauth(netf, peersin, valid_checksum) /* Must be V5 */ + kcmd_proto = KCMD_UNKNOWN_PROTOCOL; + if (version.length != 9) + fatal (netf, "bad application version length"); + if (!memcmp (version.data, "KCMDV0.1", 9)) + kcmd_proto = KCMD_OLD_PROTOCOL; + if (!memcmp (version.data, "KCMDV0.2", 9)) + kcmd_proto = KCMD_NEW_PROTOCOL; + getstr(netf, remuser, sizeof(locuser), "remuser"); if ((status = krb5_unparse_name(bsd_context, ticket->enc_part2->client, @@ -1939,7 +1948,21 @@ recvauth(netf, peersin, valid_checksum) if (!strncmp(cmdbuf, "-x ", 3)) do_encrypt = 1; - rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 0); + + { + krb5_keyblock *key; + status = krb5_auth_con_getremotesubkey (bsd_context, auth_context, + &key); + if (status) + fatal (netf, "Server can't get session subkey"); + if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL) + fatal (netf, "No session subkey sent"); + if (key && kcmd_proto == KCMD_OLD_PROTOCOL) + fatal (netf, "Session subkey not allowed in old kcmd protocol"); + if (key == 0) + key = ticket->enc_part2->session; + rcmd_stream_init_krb5 (key, do_encrypt, 0, 0, kcmd_proto); + } /* Null out the "session" because kcmd.c references the session * key here, and we do not want krb5_free_ticket() to destroy it. */ @@ -1990,7 +2013,7 @@ void fatal(f, msg) buf[0] = '\01'; /* error indicator */ (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg); if ((f == netf) && (pid > 0)) - (void) rcmd_stream_write(f, buf, strlen(buf)); + (void) rcmd_stream_write(f, buf, strlen(buf), 0); else (void) write(f, buf, strlen(buf)); syslog(LOG_ERR,"%s\n",msg); diff --git a/src/appl/bsd/login.c b/src/appl/bsd/login.c index 40af3ce60..af703b3ba 100644 --- a/src/appl/bsd/login.c +++ b/src/appl/bsd/login.c @@ -619,9 +619,10 @@ int have_v5_tickets (me) #endif /* KRB5_GET_TICKETS */ #ifdef KRB4_CONVERT -try_convert524 (kcontext, me) - krb5_context kcontext; - krb5_principal me; +try_convert524(kcontext, me, use_ccache) + krb5_context kcontext; + krb5_principal me; + int use_ccache; { krb5_principal kpcserver; krb5_error_code kpccode; @@ -632,38 +633,45 @@ try_convert524 (kcontext, me) /* or do this directly with krb524_convert_creds_kdc */ krb524_init_ets(kcontext); - /* cc->ccache, already set up */ - /* client->me, already set up */ - if ((kpccode = krb5_build_principal(kcontext, - &kpcserver, - krb5_princ_realm(kcontext, me)->length, - krb5_princ_realm(kcontext, me)->data, - "krbtgt", - krb5_princ_realm(kcontext, me)->data, - NULL))) { - com_err("login/v4", kpccode, - "while creating service principal name"); - return 0; - } - memset((char *) &increds, 0, sizeof(increds)); - increds.client = me; - increds.server = kpcserver; - increds.times.endtime = 0; - increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; - if ((kpccode = krb5_get_credentials(kcontext, 0, - ccache, - &increds, - &v5creds))) { - com_err("login/v4", kpccode, - "getting V5 credentials"); - return 0; - } - if ((kpccode = krb524_convert_creds_kdc(kcontext, - v5creds, - &v4creds))) { - com_err("login/v4", kpccode, - "converting to V4 credentials"); + /* If we have forwarded v5 tickets, retrieve the credentials from + * the cache; otherwise, the v5 credentials are in my_creds. + */ + if (use_ccache) { + /* cc->ccache, already set up */ + /* client->me, already set up */ + kpccode = krb5_build_principal(kcontext, &kpcserver, + krb5_princ_realm(kcontext, me)->length, + krb5_princ_realm(kcontext, me)->data, + "krbtgt", + krb5_princ_realm(kcontext, me)->data, + NULL); + if (kpccode) { + com_err("login/v4", kpccode, + "while creating service principal name"); + return 0; + } + + memset((char *) &increds, 0, sizeof(increds)); + increds.client = me; + increds.server = kpcserver; + increds.times.endtime = 0; + increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + kpccode = krb5_get_credentials(kcontext, 0, ccache, + &increds, &v5creds); + krb5_free_principal(kcontext, kpcserver); + increds.server = NULL; + if (kpccode) { + com_err("login/v4", kpccode, "getting V5 credentials"); + return 0; + } + + kpccode = krb524_convert_creds_kdc(kcontext, v5creds, &v4creds); + krb5_free_creds(kcontext, v5creds); + } else + kpccode = krb524_convert_creds_kdc(kcontext, &my_creds, &v4creds); + if (kpccode) { + com_err("login/v4", kpccode, "converting to V4 credentials"); return 0; } /* this is stolen from the v4 kinit */ @@ -913,8 +921,9 @@ afs_login () struct stat st; /* construct the name */ /* get this from profile later */ - strcpy (aklog_path, KPROGDIR); - strcat (aklog_path, "/aklog"); + aklog_path[sizeof(aklog_path) - 1] = '\0'; + strncpy (aklog_path, KPROGDIR, sizeof(aklog_path) - 1); + strncat (aklog_path, "/aklog", sizeof(aklog_path) - 1 - strlen(aklog_path)); /* only run it if we can find it */ if (stat (aklog_path, &st) == 0) { system(aklog_path); @@ -1448,7 +1457,7 @@ int main(argc, argv) #if defined(KRB5_GET_TICKETS) && defined(KRB4_CONVERT) if (login_krb4_convert && !got_v4_tickets) { if (got_v5_tickets||forwarded_v5_tickets) - try_convert524 (kcontext, me); + try_convert524(kcontext, me, forwarded_v5_tickets); } #endif diff --git a/src/appl/bsd/v4rcp.c b/src/appl/bsd/v4rcp.c index 36754dead..326778350 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 7d41ff46e..ed96d063d 100644 --- a/src/appl/gssftp/ChangeLog +++ b/src/appl/gssftp/ChangeLog @@ -1,3 +1,8 @@ +2000-03-24 Ken Raeburn + + * configure.in: Check for alpha*-dec-osf* instead of + alpha-dec-osf*. + 1999-10-26 Wilfredo Sanchez * 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 f0c2bff16..349cc0478 100644 --- a/src/appl/gssftp/configure.in +++ b/src/appl/gssftp/configure.in @@ -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 22a29c356..a5d22653b 100644 --- a/src/appl/gssftp/ftp/ChangeLog +++ b/src/appl/gssftp/ftp/ChangeLog @@ -1,3 +1,20 @@ +2000-05-11 Nalin Dahyabhai + + * 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 + + * 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 * 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 2a8e77550..0006e4fc5 100644 --- a/src/appl/gssftp/ftp/cmds.c +++ b/src/appl/gssftp/ftp/cmds.c @@ -1049,7 +1049,8 @@ remglob(argv,doswitch) return (cp); } if (ftemp == NULL) { - (void) strcpy(temp, _PATH_TMP); + (void) strncpy(temp, _PATH_TMP, sizeof(temp) - 1); + temp[sizeof(temp) - 1] = '\0'; (void) mktemp(temp); oldverbose = verbose, verbose = 0; oldhash = hash, hash = 0; @@ -1510,7 +1511,8 @@ shell(argc, argv) if (namep == NULL) namep = shell; (void) strcpy(shellnam,"-"); - (void) strcat(shellnam, ++namep); + (void) strncat(shellnam, ++namep, sizeof(shellnam) - 1 - strlen(shellnam)); + shellnam[sizeof(shellnam) - 1] = '\0'; if (strcmp(namep, "sh") != 0) shellnam[0] = '+'; if (debug) { @@ -1702,13 +1704,14 @@ quote1(initial, argc, argv) register int i, len; char buf[FTP_BUFSIZ]; /* must be >= sizeof(line) */ - (void) strcpy(buf, initial); + (void) strncpy(buf, initial, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; if (argc > 1) { len = strlen(buf); - len += strlen(strcpy(&buf[len], argv[1])); + len += strlen(strncpy(&buf[len], argv[1], sizeof(buf) - 1 - len)); for (i = 2; i < argc; i++) { buf[len++] = ' '; - len += strlen(strcpy(&buf[len], argv[i])); + len += strlen(strncpy(&buf[len], argv[i], sizeof(buf) - 1 - len)); } } if (command(buf) == PRELIM) { diff --git a/src/appl/gssftp/ftp/domacro.c b/src/appl/gssftp/ftp/domacro.c index 9bc277b0f..ecfe9b4ad 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 11f583a6c..a00850d95 100644 --- a/src/appl/gssftp/ftp/ftp.c +++ b/src/appl/gssftp/ftp/ftp.c @@ -680,9 +680,13 @@ getreply(expecteof) n = '5'; } else { if (debug) printf("%c:", safe ? 'S' : 'P'); - memcpy(ibuf, msg_data.app_data, - msg_data.app_length); - strcpy(&ibuf[msg_data.app_length], "\r\n"); + if(msg_data.app_length < sizeof(ibuf) - 2) { + memcpy(ibuf, msg_data.app_data, + msg_data.app_length); + strcpy(&ibuf[msg_data.app_length], "\r\n"); + } else { + printf("Message too long!"); + } continue; } #endif @@ -703,9 +707,14 @@ getreply(expecteof) "failed unsealing reply"); n = '5'; } else { - memcpy(ibuf, msg_buf.value, - msg_buf.length); - strcpy(&ibuf[msg_buf.length], "\r\n"); + if(msg_buf.length < sizeof(ibuf) - 2 - 1) { + memcpy(ibuf, msg_buf.value, + msg_buf.length); + strcpy(&ibuf[msg_buf.length], "\r\n"); + } else { + user_gss_error(maj_stat, min_stat, + "reply was too long"); + } gss_release_buffer(&min_stat,&msg_buf); continue; } @@ -1636,20 +1645,24 @@ pswitch(flag) mcase = op->mcse; ip->ntflg = ntflag; ntflag = op->ntflg; - (void) strncpy(ip->nti, ntin, 16); + (void) strncpy(ip->nti, ntin, sizeof(ip->nti) - 1); (ip->nti)[strlen(ip->nti)] = '\0'; - (void) strcpy(ntin, op->nti); - (void) strncpy(ip->nto, ntout, 16); + (void) strncpy(ntin, op->nti, sizeof(ntin) - 1); + ntin[sizeof(ntin) - 1] = '\0'; + (void) strncpy(ip->nto, ntout, sizeof(ip->nto) - 1); (ip->nto)[strlen(ip->nto)] = '\0'; - (void) strcpy(ntout, op->nto); + (void) strncpy(ntout, op->nto, sizeof(ntout) - 1); + ntout[sizeof(ntout) - 1] = '\0'; ip->mapflg = mapflag; mapflag = op->mapflg; (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); (ip->mi)[strlen(ip->mi)] = '\0'; - (void) strcpy(mapin, op->mi); + (void) strncpy(mapin, op->mi, sizeof(mapin) - 1); + mapin[sizeof(mapin) - 1] = '\0'; (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); (ip->mo)[strlen(ip->mo)] = '\0'; - (void) strcpy(mapout, op->mo); + (void) strncpy(mapout, op->mo, sizeof(mapout) - 1); + mapout[sizeof(mapout) - 1] = '\0'; ip->authtype = auth_type; auth_type = op->authtype; ip->clvl = clevel; @@ -1846,7 +1859,8 @@ gunique(local) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); return((char *) 0); } - (void) strcpy(new, local); + (void) strncpy(new, local, sizeof(new) - 3); + new[sizeof(new) - 1] = '\0'; cp = new + strlen(new); *cp++ = '.'; while (!d) { @@ -2054,9 +2068,11 @@ do_auth() if (verbose) printf("%s accepted as authentication type\n", "KERBEROS_V4"); - strcpy(inst, (char *) krb_get_phost(hostname)); + strncpy(inst, (char *) krb_get_phost(hostname), sizeof(inst) - 1); + inst[sizeof(inst) - 1] = '\0'; if (realm[0] == '\0') - strcpy(realm, (char *) krb_realmofhost(hostname)); + strncpy(realm, (char *) krb_realmofhost(hostname), sizeof(realm) - 1); + realm[sizeof(realm) - 1] = '\0'; if ((kerror = krb_mk_req(&ticket, service = "ftp", inst, realm, checksum)) && (kerror != KDC_PR_UNKNOWN || diff --git a/src/appl/gssftp/ftp/glob.c b/src/appl/gssftp/ftp/glob.c index f92ee5e07..a5a6bf746 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); } } @@ -324,8 +325,9 @@ pend: doit: savec = *pm; *pm = 0; - (void) strcpy(lm, pl); - (void) strcat(restbuf, pe + 1); + (void) strncpy(lm, pl, sizeof(restbuf) - 1 - (lm - restbuf)); + restbuf[sizeof(restbuf) - 1] = '\0'; + (void) strncat(restbuf, pe + 1, sizeof(restbuf) - 1 - strlen(restbuf)); *pm = savec; if (s == 0) { sgpathp = gpathp; @@ -700,7 +702,7 @@ gethdir(home) { register struct passwd *pp = getpwnam(home); - if (!pp || home + strlen(pp->pw_dir) >= lastgpathp) + if (!pp || ((home + strlen(pp->pw_dir)) >= lastgpathp)) return (1); (void) strcpy(home, pp->pw_dir); return (0); diff --git a/src/appl/gssftp/ftp/main.c b/src/appl/gssftp/ftp/main.c index 9c1e43a86..6c7e1e91b 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 48f57f93f..e1f69b084 100644 --- a/src/appl/gssftp/ftp/secure.c +++ b/src/appl/gssftp/ftp/secure.c @@ -52,6 +52,11 @@ extern struct sockaddr_in myaddr; extern int dlevel; extern char *auth_type; +/* Some libc's (GNU libc, at least) define MAX as a macro. Forget that. */ +#ifdef MAX +#undef MAX +#endif + #define MAX maxbuf extern unsigned int maxbuf; /* maximum output buffer size */ extern unsigned char *ucbuf; /* cleartext buffer */ diff --git a/src/appl/gssftp/ftpd/ChangeLog b/src/appl/gssftp/ftpd/ChangeLog index 388b4b270..70f2112ce 100644 --- a/src/appl/gssftp/ftpd/ChangeLog +++ b/src/appl/gssftp/ftpd/ChangeLog @@ -1,3 +1,11 @@ +2000-06-14 Tom Yu + + * ftpcmd.y (nonguest): Return $1, not 1, if (!guest). + +2000-05-11 Nalin Dahyabhai + + * ftpd.c (gunique): Make sure that path stored in "new" isn't too long. + 2000-02-18 Ken Raeburn * 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 acd187112..bc252190e 100644 --- a/src/appl/gssftp/ftpd/ftpcmd.y +++ b/src/appl/gssftp/ftpd/ftpcmd.y @@ -865,7 +865,7 @@ nonguest: check_login $$ = 0; } else - $$ = 1; + $$ = $1; } ; %% diff --git a/src/appl/gssftp/ftpd/ftpd.c b/src/appl/gssftp/ftpd/ftpd.c index c7dfc8ad2..047be3562 100644 --- a/src/appl/gssftp/ftpd/ftpd.c +++ b/src/appl/gssftp/ftpd/ftpd.c @@ -2123,7 +2123,8 @@ gunique(local) } if (cp) *cp = '/'; - (void) strcpy(new, local); + (void) strncpy(new, local, sizeof(new) - 1); + new[sizeof(new) - 1] = '\0'; cp = new + strlen(new); *cp++ = '.'; for (count = 1; count < 100; count++) { @@ -2287,7 +2288,8 @@ char *data; syslog(LOG_ERR, "Couldn't canonicalize local hostname"); return 0; } - strcpy(localname, hp->h_name); + strncpy(localname, hp->h_name, sizeof(localname) - 1); + localname[sizeof(localname) - 1] = '\0'; for (service = gss_services; *service; service++) { sprintf(service_name, "%s@%s", *service, localname); diff --git a/src/appl/telnet/libtelnet/ChangeLog b/src/appl/telnet/libtelnet/ChangeLog index 03cb924fa..8b71835eb 100644 --- a/src/appl/telnet/libtelnet/ChangeLog +++ b/src/appl/telnet/libtelnet/ChangeLog @@ -1,3 +1,22 @@ +2000-05-11 Nalin Dahyabhai + + * 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 + + * kerberos5.c (kerberos5_is): Don't overflow buffer "errbuf". + * spx.c (spx_init, spx_send, spx_is): Don't overflow buffer + "targ_printable". + (spx_status): Don't overflow buffer "acl_file". + 1999-10-26 Wilfredo Sanchez * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES, diff --git a/src/appl/telnet/libtelnet/gettytab.c b/src/appl/telnet/libtelnet/gettytab.c index f6ffb7c59..aaad43aad 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 734466e86..eb657aee6 100644 --- a/src/appl/telnet/libtelnet/kerberos.c +++ b/src/appl/telnet/libtelnet/kerberos.c @@ -602,7 +602,9 @@ kerberos4_status(ap, name, level) return(level); if (UserNameRequested && !kuserok(&adat, UserNameRequested)) { - strcpy(name, UserNameRequested); + /* the name buffer comes from telnetd/telnetd{-ktd}.c */ + strncpy(name, UserNameRequested, 255); + name[255] = '\0'; return(AUTH_VALID); } else return(AUTH_USER); diff --git a/src/appl/telnet/libtelnet/kerberos5.c b/src/appl/telnet/libtelnet/kerberos5.c index 6a62f36a3..b4c73980b 100644 --- a/src/appl/telnet/libtelnet/kerberos5.c +++ b/src/appl/telnet/libtelnet/kerberos5.c @@ -423,7 +423,8 @@ kerberos5_is(ap, data, cnt) NULL, keytabid, NULL, &ticket); if (r) { (void) strcpy(errbuf, "krb5_rd_req failed: "); - (void) strcat(errbuf, error_message(r)); + errbuf[sizeof(errbuf) - 1] = '\0'; + (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf)); goto errout; } @@ -440,8 +441,12 @@ kerberos5_is(ap, data, cnt) princ[krb5_princ_component(telnet_context, ticket->server,0)->length] = '\0'; if (strcmp("host", princ)) { - (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"%s\"", - princ, "host"); + if(strlen(princ) < sizeof(errbuf) - 39) { + (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"host\"", + princ); + } else { + (void) sprintf(errbuf, "incorrect service name: principal != \"host\""); + } goto errout; } } else { @@ -455,7 +460,8 @@ kerberos5_is(ap, data, cnt) if (r) { (void) strcpy(errbuf, "krb5_auth_con_getauthenticator failed: "); - (void) strcat(errbuf, error_message(r)); + errbuf[sizeof(errbuf) - 1] = '\0'; + (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf)); goto errout; } if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON && @@ -476,7 +482,8 @@ kerberos5_is(ap, data, cnt) &key); if (r) { (void) strcpy(errbuf, "krb5_auth_con_getkey failed: "); - (void) strcat(errbuf, error_message(r)); + errbuf[sizeof(errbuf) - 1] = '\0'; + (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf)); goto errout; } r = krb5_verify_checksum(telnet_context, @@ -495,7 +502,8 @@ kerberos5_is(ap, data, cnt) if (r) { (void) strcpy(errbuf, "checksum verification failed: "); - (void) strcat(errbuf, error_message(r)); + errbuf[sizeof(errbuf) - 1] = '\0'; + (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf)); goto errout; } krb5_free_keyblock(telnet_context, key); @@ -506,7 +514,8 @@ kerberos5_is(ap, data, cnt) if ((r = krb5_mk_rep(telnet_context, auth_context, &outbuf))) { (void) strcpy(errbuf, "Make reply failed: "); - (void) strcat(errbuf, error_message(r)); + errbuf[sizeof(errbuf) - 1] = '\0'; + (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf)); goto errout; } @@ -560,7 +569,8 @@ kerberos5_is(ap, data, cnt) char errbuf[128]; (void) strcpy(errbuf, "Read forwarded creds failed: "); - (void) strcat(errbuf, error_message(r)); + errbuf[sizeof(errbuf) - 1] = '\0'; + (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf)); Data(ap, KRB_FORWARD_REJECT, errbuf, -1); if (auth_debug_mode) printf( @@ -586,7 +596,8 @@ kerberos5_is(ap, data, cnt) char eerrbuf[329]; strcpy(eerrbuf, "telnetd: "); - strcat(eerrbuf, errbuf); + eerrbuf[sizeof(eerrbuf) - 1] = '\0'; + strncat(eerrbuf, errbuf, sizeof(eerrbuf) - 1 - strlen(eerrbuf)); Data(ap, KRB_REJECT, eerrbuf, -1); } if (auth_debug_mode) @@ -706,7 +717,9 @@ kerberos5_status(ap, name, level) krb5_kuserok(telnet_context, ticket->enc_part2->client, UserNameRequested)) { - strcpy(name, UserNameRequested); + /* the name buffer comes from telnetd/telnetd{-ktd}.c */ + strncpy(name, UserNameRequested, 255); + name[255] = '\0'; return(AUTH_VALID); } else return(AUTH_USER); diff --git a/src/appl/telnet/libtelnet/spx.c b/src/appl/telnet/libtelnet/spx.c index f23490f96..7285d0dd3 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 d8a341e9c..b8f209c30 100644 --- a/src/appl/telnet/telnet/ChangeLog +++ b/src/appl/telnet/telnet/ChangeLog @@ -1,3 +1,18 @@ +2000-05-11 Nalin Dahyabhai + + * 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 + + * commands.c (cmdrc): Don't overflow buffer "rcbuf". + * tn3270.c (settranscom): Don't overflow buffer "transcom". + 2000-02-24 Ezra Peisach * 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 2c80b0b25..8ffba2e32 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 e9939865e..f35cdedaf 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 da98ae6df..7696857c7 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 77aedaf89..c46ae7eb8 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 19f503bd4..82ad84178 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 800c9f87a..ce2686f53 100644 --- a/src/appl/telnet/telnetd/ChangeLog +++ b/src/appl/telnet/telnetd/ChangeLog @@ -1,3 +1,16 @@ +2000-06-29 Tom Yu + + * telnetd.c (doit): Change test for "no authentication" as per + Jeffrey Altman's patch. + +2000-06-29 Nalin Dahyabhai + + * sys_term.c (start_login, Solaris): forcefully terminate "termbuf" + in case the "TERM" environment variable isn't. + * telnet-ktd.c (getterminaltype): Don't overflow buffers "first" and + "netobuf". + (recv_ayt): Forcibly terminate buffer "netobuf". + 2000-05-31 Wilfredo Sanchez * configure.in, defs.h: Check for existance of . diff --git a/src/appl/telnet/telnetd/sys_term.c b/src/appl/telnet/telnetd/sys_term.c index ee8d53d46..b79209d57 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 9ec608fcd..5936e3b5a 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 726746967..f103488cb 100644 --- a/src/appl/telnet/telnetd/telnetd.c +++ b/src/appl/telnet/telnetd/telnetd.c @@ -522,7 +522,7 @@ main(argc, argv) } (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); - if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); exit(1); } @@ -530,7 +530,7 @@ main(argc, argv) perror("listen"); exit(1); } - foo = sizeof sin; + foo = sizeof(sin); ns = accept(s, (struct sockaddr *)&sin, &foo); if (ns < 0) { perror("accept"); @@ -781,34 +781,49 @@ getterminaltype(name) static unsigned char sb[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; - memcpy(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) { + memcpy(nfrontp, sb, sizeof(sb)); + nfrontp += sizeof(sb); + *nfrontp = '\0'; + } } if (his_state_is_will(TELOPT_XDISPLOC)) { static unsigned char sb[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; - memcpy(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) { + memcpy(nfrontp, sb, sizeof(sb)); + nfrontp += sizeof(sb); + *nfrontp = '\0'; + } } if (his_state_is_will(TELOPT_NEW_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; - memcpy(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) { + memcpy(nfrontp, sb, sizeof(sb)); + nfrontp += sizeof(sb); + *nfrontp = '\0'; + } } else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; - memcpy(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + if(nfrontp - netobuf + sizeof(sb) < sizeof(netobuf)) { + memcpy(nfrontp, sb, sizeof(sb)); + nfrontp += sizeof(sb); + *nfrontp = '\0'; + } } if (his_state_is_will(TELOPT_TTYPE)) { - memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; + if(nfrontp - netobuf + sizeof(ttytype_sbbuf) < sizeof(netobuf)) { + memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf)); + nfrontp += sizeof(ttytype_sbbuf); + *nfrontp = '\0'; + } } if (his_state_is_will(TELOPT_TSPEED)) { while (sequenceIs(tspeedsubopt, baseline)) @@ -886,8 +901,11 @@ _gettermname() if (his_state_is_wont(TELOPT_TTYPE)) return; settimer(baseline); - memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; + if(nfrontp - netobuf + sizeof(ttytype_sbbuf)) { + memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf)); + nfrontp += sizeof(ttytype_sbbuf); + *nfrontp = '\0'; + } while (sequenceIs(ttypesubopt, baseline)) ttloop(); } @@ -1009,7 +1027,7 @@ pty_init(); setenv("TERM", *terminaltype ? terminaltype : "network", 1); #if defined (AUTHENTICATION) - if (user_name[0] == '\0') { + if (level < 0 && auth_level > 0) { fatal (net, "No authentication provided"); exit (-1); } @@ -1205,7 +1223,7 @@ telnet(f, p, host) #if defined(SO_OOBINLINE) (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, - (char *)&on, sizeof on); + (char *)&on, sizeof(on)); #endif /* defined(SO_OOBINLINE) */ #ifdef SIGTSTP @@ -1266,7 +1284,8 @@ telnet(f, p, host) HN = getstr("hn", &cp); IM = getstr("im", &cp); if (HN && *HN) - (void) strcpy(host_name, HN); + (void) strncpy(host_name, HN, sizeof(host_name) - 1); + host_name[sizeof(host_name) - 1] = '\0'; if (IM == 0) IM = ""; } else { @@ -1688,8 +1707,10 @@ recv_ayt() return; } #endif - (void) strcpy(nfrontp, "\r\n[Yes]\r\n"); + (void) strncpy(nfrontp, "\r\n[Yes]\r\n", + sizeof(netobuf) - 1 - (nfrontp - netobuf)); nfrontp += 9; + *nfrontp = '\0'; } void