aboutsummaryrefslogtreecommitdiff
path: root/src/appl/bsd
diff options
context:
space:
mode:
authorno author <devnull@mit.edu>2003-04-09 00:10:14 +0000
committerno author <devnull@mit.edu>2003-04-09 00:10:14 +0000
commit9dc0f646d42648fbbde44799c00b25d97d9cbc98 (patch)
treed7e1bad8215f92673f94df55881b676002da7e8b /src/appl/bsd
parent38037332d7af42124646c268874e0833bd8ec30e (diff)
downloadkrb5-krb5-1.2.8-final.zip
krb5-krb5-1.2.8-final.tar.gz
krb5-krb5-1.2.8-final.tar.bz2
This commit was manufactured by cvs2svn to create tagkrb5-1.2.8-final
'krb5-1-2-8-final'. git-svn-id: svn://anonsvn.mit.edu/krb5/tags/krb5-1-2-8-final@15331 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/appl/bsd')
-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
18 files changed, 989 insertions, 327 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) {