aboutsummaryrefslogtreecommitdiff
path: root/src/appl/bsd/kcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/appl/bsd/kcmd.c')
-rw-r--r--src/appl/bsd/kcmd.c197
1 files changed, 149 insertions, 48 deletions
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