Cygnus's libkstream, from cryptosrc-us.
This commit is contained in:
parent
2a744b7dce
commit
a6ab2c35f2
12
lib/libkstream/Makefile
Normal file
12
lib/libkstream/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
# $NetBSD: Makefile,v 1.1.1.1 2000/06/17 06:24:28 thorpej Exp $
|
||||
|
||||
LIB= kstream
|
||||
|
||||
SRCS= kstream.c kstream-des.c
|
||||
|
||||
COPTS+= -g
|
||||
|
||||
SHLIB_MAJOR?= 1
|
||||
SHLIB_MINOR?= 0
|
||||
|
||||
.include <bsd.lib.mk>
|
339
lib/libkstream/kstream-des.c
Normal file
339
lib/libkstream/kstream-des.c
Normal file
@ -0,0 +1,339 @@
|
||||
/* $NetBSD: kstream-des.c,v 1.1.1.1 2000/06/17 06:24:28 thorpej Exp $ */
|
||||
|
||||
/* DES-encrypted-stream implementation for MIT Kerberos.
|
||||
Written by Ken Raeburn (Raeburn@Cygnus.COM), based on algorithms
|
||||
in the original MIT Kerberos code.
|
||||
Copyright (C) 1991, 1992 by Cygnus Support.
|
||||
|
||||
This file is distributed under the same terms as Kerberos.
|
||||
For copying and distribution information, please see the file
|
||||
<kerberosIV/mit-copyright.h>.
|
||||
|
||||
from: kstream-des.c,v 1.9 1996/06/02 07:37:27 ghudson Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <des.h>
|
||||
#include <kerberosIV/kstream.h>
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
long align_me;
|
||||
double align_me_harder;
|
||||
Key_schedule sched;
|
||||
} u;
|
||||
des_cblock ivec;
|
||||
} kstream_des_init_block;
|
||||
|
||||
typedef struct {
|
||||
kstream_des_init_block x;
|
||||
int no_right_justify;
|
||||
int protect_rlogin_oob;
|
||||
char *buf1, *buf2;
|
||||
size_t len1, len2;
|
||||
} priv;
|
||||
|
||||
typedef struct kstream_data_block ksdb;
|
||||
|
||||
/* The data stream consists of four bytes representing a net-order
|
||||
integer, followed by enough data to produce that many
|
||||
cleartext bytes. This means the size of that data must be rounded
|
||||
up to a multiple of 8, even though the cleartext may only be one
|
||||
byte. For blocks of less than eight bytes, most software (well,
|
||||
exactly half of the two already-existing programs, and all of the
|
||||
ones we write using this library :-) pads on the *left* with
|
||||
random values.
|
||||
|
||||
Some existing software that we have to be compatible with may send
|
||||
blocks of data that decrypt to more than 8 bytes, but not an exact
|
||||
multiple. In that case, the padding is on the right, as would be
|
||||
considered "normal". This software currently will not generate such
|
||||
a sequence, but a future version could. Don't break compatibility
|
||||
with that mode. */
|
||||
|
||||
#ifdef sun
|
||||
static kstream_ptr losing_realloc (old_ptr, new_size)
|
||||
kstream_ptr old_ptr;
|
||||
size_t new_size;
|
||||
{
|
||||
return old_ptr ? realloc (old_ptr, new_size) : malloc (new_size);
|
||||
}
|
||||
#define realloc losing_realloc
|
||||
#endif
|
||||
|
||||
/* Do the actual encryption work. This routine will handle chunks of
|
||||
any size up to 16 bytes, or any multiple of 8 over that. It makes
|
||||
the padding a little easier to write it this way. Handling sizes
|
||||
between 8 and 16 is an annoyance, but rlogin actually relies on being
|
||||
able to send 12 bytes in one chunk. Bleah! */
|
||||
static void
|
||||
do_encrypt (out, inp, p)
|
||||
ksdb *out;
|
||||
ksdb *inp;
|
||||
priv *p;
|
||||
{
|
||||
union {
|
||||
char buf[16];
|
||||
int junk[16 / sizeof (int)];
|
||||
} u;
|
||||
ksdb in;
|
||||
char *ptr;
|
||||
static int seeded;
|
||||
|
||||
if (!seeded) {
|
||||
srandom ((int) time ((time_t *) 0));
|
||||
seeded = 1;
|
||||
}
|
||||
|
||||
in = *inp;
|
||||
if (in.length < 8)
|
||||
{
|
||||
if (! p->no_right_justify)
|
||||
{
|
||||
u.junk[0] = random ();
|
||||
memcpy (u.buf + 8 - in.length, in.ptr, in.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
u.junk[(sizeof (u.junk[0]) + 7) / sizeof (u.junk[0]) - 1] = random ();
|
||||
memcpy (u.buf, in.ptr, in.length);
|
||||
}
|
||||
in.ptr = u.buf;
|
||||
in.length = 8;
|
||||
}
|
||||
else if (in.length == 8)
|
||||
{
|
||||
memcpy (u.buf, in.ptr, 8);
|
||||
in.ptr = u.buf;
|
||||
}
|
||||
else if (in.length < sizeof (u.buf))
|
||||
{
|
||||
if (in.length % 8 == 0)
|
||||
abort ();
|
||||
u.junk[(sizeof (u.junk) / sizeof (u.junk[0])) - 1] = random ();
|
||||
memcpy (u.buf, in.ptr, in.length);
|
||||
in.ptr = u.buf;
|
||||
}
|
||||
else if (in.length % 8 != 0)
|
||||
abort ();
|
||||
{
|
||||
unsigned long x;
|
||||
x = inp->length; /* not in.length! */
|
||||
ptr = (char *) out->ptr;
|
||||
ptr[3] = x & 0xff; x >>= 8;
|
||||
ptr[2] = x & 0xff; x >>= 8;
|
||||
ptr[1] = x & 0xff; x >>= 8;
|
||||
ptr[0] = x & 0xff; x >>= 8;
|
||||
ptr += 4;
|
||||
if (x)
|
||||
abort ();
|
||||
}
|
||||
des_pcbc_encrypt ((des_cblock *)in.ptr, (des_cblock *)ptr, in.length,
|
||||
p->x.u.sched, (des_cblock *)p->x.ivec, ENCRYPT);
|
||||
out->ptr = ptr + ((in.length + 7) & ~7);
|
||||
}
|
||||
|
||||
static int
|
||||
encrypt (outp, inp, k)
|
||||
ksdb *outp;
|
||||
ksdb *inp;
|
||||
kstream k;
|
||||
{
|
||||
const int small_block_size = 16;
|
||||
priv *p = (priv *) k->data;
|
||||
|
||||
if (inp->length > small_block_size && inp->length % 8 != 0)
|
||||
{
|
||||
/* do two */
|
||||
ksdb in, out;
|
||||
size_t sz;
|
||||
|
||||
in.ptr = inp->ptr;
|
||||
in.length = inp->length & ~7;
|
||||
sz = in.length + 4; /* first block */
|
||||
sz += 8 + 4; /* second block */
|
||||
outp->length = sz;
|
||||
out.ptr = outp->ptr = p->buf1 = realloc (p->buf1, sz);
|
||||
out.length = sz;
|
||||
assert (out.ptr != 0 || out.length == 0);
|
||||
do_encrypt (&out, &in, p);
|
||||
in.ptr = (char *) in.ptr + in.length;
|
||||
in.length = inp->length - in.length;
|
||||
do_encrypt (&out, &in, p);
|
||||
return inp->length;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t sz = (inp->length + 7) & ~7;
|
||||
sz += 4;
|
||||
outp->length = sz;
|
||||
outp->ptr = p->buf1 = realloc (p->buf1, sz);
|
||||
assert (outp->ptr != 0 || outp->length == 0);
|
||||
do_encrypt (outp, inp, p);
|
||||
outp->ptr = p->buf1;
|
||||
return inp->length;
|
||||
}
|
||||
}
|
||||
|
||||
int _kstream_des_debug_OOB = 0;
|
||||
|
||||
static int
|
||||
decrypt (outp, inp, k)
|
||||
ksdb *outp;
|
||||
ksdb *inp;
|
||||
kstream k;
|
||||
{
|
||||
char *ptr = inp->ptr;
|
||||
unsigned long x = 0;
|
||||
int error_count = 0;
|
||||
size_t sz;
|
||||
priv *p = (priv *) k->data;
|
||||
|
||||
if(inp->length < 1) return -12; /* make sure we have at least one byte */
|
||||
if (p->protect_rlogin_oob) {
|
||||
/* here's where we handle an attack. The first byte ends up being the
|
||||
highest. If it's not zero, skip it. If it is zero, we can't detect it,
|
||||
and we still lose... */
|
||||
x = *ptr & 0xff; /* get the first char */
|
||||
while (x) {
|
||||
if(_kstream_des_debug_OOB) fprintf(stderr,"BAD BYTE %02x\n\r", x);
|
||||
error_count++; /* count the bad byte */
|
||||
ptr++; /* and skip it */
|
||||
if(inp->length == error_count) {
|
||||
return -12; /* we've used up all of the input */
|
||||
}
|
||||
x = *ptr & 0xff; /* get the next potentially first char */
|
||||
}
|
||||
ptr++;
|
||||
} else {
|
||||
x <<= 8; x += *ptr++ & 0xff;
|
||||
}
|
||||
|
||||
|
||||
/* If we've got four bytes, we can at least determine the correct
|
||||
amount that still needs to be read. If not, we can assume a
|
||||
minimum of 12 good bytes (4-byte length plus one 8-byte block)
|
||||
and we know how many of the ones we've got are bad. */
|
||||
if (inp->length < 4 + error_count)
|
||||
return inp->length - error_count - 12;
|
||||
|
||||
/* x <<= 8; x += *ptr++ & 0xff; */ /* x already has first byte loaded */
|
||||
x <<= 8; x += *ptr++ & 0xff;
|
||||
x <<= 8; x += *ptr++ & 0xff;
|
||||
x <<= 8; x += *ptr++ & 0xff;
|
||||
sz = (x + 7) & ~7;
|
||||
if (inp->length < sz + 4 + error_count)
|
||||
return - (sz + 4 + error_count - inp->length);
|
||||
assert (sz <= sizeof (k->in_crypt.data));
|
||||
|
||||
if (p->buf1)
|
||||
p->buf1 = realloc (p->buf1, sz);
|
||||
else
|
||||
p->buf1 = malloc (sz);
|
||||
assert (p->buf1 != 0 || sz == 0);
|
||||
outp->ptr = p->buf1;
|
||||
outp->length = x;
|
||||
pcbc_encrypt ((des_cblock *)ptr, (des_cblock *)outp->ptr, sz, p->x.u.sched,
|
||||
(des_cblock *)p->x.ivec, DECRYPT);
|
||||
if (p->no_right_justify == 0
|
||||
&& x < 8)
|
||||
outp->ptr = p->buf1 + 8 - x;
|
||||
return sz + 4 + error_count;
|
||||
}
|
||||
|
||||
static int
|
||||
init (k, data)
|
||||
kstream k;
|
||||
void *data;
|
||||
{
|
||||
priv *p;
|
||||
|
||||
p = (priv *) malloc (sizeof (priv));
|
||||
k->data = (kstream_ptr) p;
|
||||
if (!p)
|
||||
return errno;
|
||||
p->buf1 = p->buf2 = 0;
|
||||
p->len1 = p->len2 = 0;
|
||||
p->no_right_justify = 0;
|
||||
p->protect_rlogin_oob = 0;
|
||||
p->x = * (kstream_des_init_block *) data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rcp_init (k, data)
|
||||
kstream k;
|
||||
void *data;
|
||||
{
|
||||
int x = init (k, data);
|
||||
((priv *)(k->data))->no_right_justify = 1;
|
||||
return x;
|
||||
}
|
||||
|
||||
static int
|
||||
rlogin_init (k, data)
|
||||
kstream k;
|
||||
void *data;
|
||||
{
|
||||
int x = init (k, data);
|
||||
((priv *)(k->data))->protect_rlogin_oob = 1;
|
||||
return x;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy (k)
|
||||
kstream k;
|
||||
{
|
||||
priv *p = (priv *) k->data;
|
||||
if (p->buf1)
|
||||
free (p->buf1);
|
||||
memset (p, '\\', sizeof (*p)); /* scribble to make sure it's gone */
|
||||
free (p);
|
||||
k->data = 0;
|
||||
}
|
||||
|
||||
static const struct kstream_crypt_ctl_block kstream_des_ccb = {
|
||||
encrypt, decrypt, rlogin_init, destroy
|
||||
};
|
||||
|
||||
static const struct kstream_crypt_ctl_block kstream_des_rcp_ccb = {
|
||||
encrypt, decrypt, rcp_init, destroy
|
||||
};
|
||||
|
||||
kstream
|
||||
kstream_create_rlogin_from_fd (fd, P_sched, ivec)
|
||||
int fd;
|
||||
kstream_ptr P_sched;
|
||||
des_cblock (*ivec);
|
||||
{
|
||||
Key_schedule *sched = (Key_schedule *) P_sched;
|
||||
kstream_des_init_block x;
|
||||
kstream k;
|
||||
memcpy (&x.u.sched, sched, sizeof (Key_schedule));
|
||||
memcpy (&x.ivec, ivec, sizeof (des_cblock));
|
||||
k = kstream_create_from_fd (fd, &kstream_des_ccb, &x);
|
||||
memset (&x, '\\', sizeof (x));
|
||||
return k;
|
||||
}
|
||||
|
||||
kstream
|
||||
kstream_create_rcp_from_fd (fd, P_sched, ivec)
|
||||
int fd;
|
||||
kstream_ptr P_sched;
|
||||
des_cblock (*ivec);
|
||||
{
|
||||
Key_schedule *sched = (Key_schedule *) P_sched;
|
||||
kstream_des_init_block x;
|
||||
kstream k;
|
||||
memcpy (&x.u.sched, sched, sizeof (Key_schedule));
|
||||
memcpy (&x.ivec, ivec, sizeof (des_cblock));
|
||||
k = kstream_create_from_fd (fd, &kstream_des_rcp_ccb, &x);
|
||||
memset (&x, '\\', sizeof (x));
|
||||
return k;
|
||||
}
|
377
lib/libkstream/kstream.c
Normal file
377
lib/libkstream/kstream.c
Normal file
@ -0,0 +1,377 @@
|
||||
/* $NetBSD: kstream.c,v 1.1.1.1 2000/06/17 06:24:28 thorpej Exp $ */
|
||||
|
||||
/* Encrypted-stream implementation for MIT Kerberos.
|
||||
Written by Ken Raeburn (Raeburn@Cygnus.COM).
|
||||
Copyright (C) 1991, 1992 by Cygnus Support.
|
||||
|
||||
This file is distributed under the same terms as Kerberos.
|
||||
For copying and distribution information, please see the file
|
||||
<kerberosIV/mit-copyright.h>.
|
||||
|
||||
from: kstream.c,v 1.7 1996/06/02 07:37:27 ghudson Exp $
|
||||
*/
|
||||
|
||||
/* Current assumptions:
|
||||
* the encryption/decryption routine may change the size of the data
|
||||
significantly, in either direction, and need not be consistent
|
||||
about it. (e.g., a pipe to "compress" could be used.)
|
||||
* encryption/decryption may not consume all characters passed, but
|
||||
will consume some, or will return a negative number indicating how
|
||||
many more characters should be read before it will be able to do
|
||||
anything with the data. (A return value of -1 is always safe; so
|
||||
is calling the crypt routine again without enough data.)
|
||||
* the file descriptor used is not set to non-blocking.
|
||||
* no other routines will do i/o on that file descriptor while this
|
||||
library is using it. (out-of-band messages are probably okay.)
|
||||
|
||||
Bugs:
|
||||
* if the encryption package cannot handle arbitrarily small data,
|
||||
flushing the outgoing stream may not work.
|
||||
|
||||
ToDo: Lots.
|
||||
* completion of the code...
|
||||
* begin testing
|
||||
* buffering (efficiency)
|
||||
* reduce data copying for large buffers that get sent immediately
|
||||
* error handling
|
||||
* consistency in error reporting conventions
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Only use alloca if we've got gcc 2 or better */
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ >= 2
|
||||
#define alloca __builtin_alloca
|
||||
#define HAS_ALLOCA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <kerberosIV/kstream.h>
|
||||
#ifdef __STDC__
|
||||
int krb_net_write (int, char *, int);
|
||||
int krb_net_read (int, char *, int);
|
||||
#else
|
||||
int krb_net_write ();
|
||||
int krb_net_read ();
|
||||
void abort ();
|
||||
char *memmove ();
|
||||
void *memcpy ();
|
||||
char *malloc ();
|
||||
char *realloc ();
|
||||
void free ();
|
||||
#endif
|
||||
extern int errno;
|
||||
|
||||
#ifdef sun
|
||||
#ifndef solaris20
|
||||
/* SunOS has no memmove, but bcopy overlaps correctly */
|
||||
#define memmove(dest,src,size) bcopy(src,dest,size)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void fifo__init (this)
|
||||
fifo *this;
|
||||
{
|
||||
this->next_write = this->next_read = 0;
|
||||
memset (this->data, 0, sizeof (this->data));
|
||||
}
|
||||
static char *fifo__data_start (this)
|
||||
fifo *this;
|
||||
{
|
||||
return this->data + this->next_read;
|
||||
}
|
||||
static size_t fifo__bytes_available (this)
|
||||
fifo *this;
|
||||
{
|
||||
return this->next_write - this->next_read;
|
||||
}
|
||||
static size_t fifo__space_available (this)
|
||||
fifo *this;
|
||||
{
|
||||
return sizeof (this->data) - fifo__bytes_available (this);
|
||||
}
|
||||
static int fifo__append (this, ptr, len)
|
||||
fifo *this;
|
||||
const char *ptr;
|
||||
size_t len;
|
||||
{
|
||||
if (len > fifo__space_available (this))
|
||||
len = fifo__space_available (this);
|
||||
if (sizeof (this->data) - this->next_write < len)
|
||||
{
|
||||
memmove (this->data, this->data + this->next_read,
|
||||
this->next_write - this->next_read);
|
||||
this->next_write -= this->next_read;
|
||||
this->next_read = 0;
|
||||
}
|
||||
memcpy (this->data + this->next_write, ptr, len);
|
||||
this->next_write += len;
|
||||
return len;
|
||||
}
|
||||
static int fifo__extract (this, ptr, len)
|
||||
fifo *this;
|
||||
char *ptr;
|
||||
size_t len;
|
||||
{
|
||||
size_t n = fifo__bytes_available (this);
|
||||
if (len > n)
|
||||
len = n;
|
||||
if (ptr)
|
||||
memcpy (ptr, this->data + this->next_read, len);
|
||||
this->next_read += len;
|
||||
if (this->next_read == this->next_write)
|
||||
this->next_read = this->next_write = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void kstream_rec__init (this)
|
||||
kstream_rec *this;
|
||||
{
|
||||
fifo__init (&this->in_crypt);
|
||||
fifo__init (&this->in_clear);
|
||||
fifo__init (&this->out_clear);
|
||||
}
|
||||
|
||||
kstream
|
||||
kstream_create_from_fd (fd, ctl, data)
|
||||
int fd;
|
||||
const struct kstream_crypt_ctl_block *ctl;
|
||||
void *data;
|
||||
{
|
||||
kstream k;
|
||||
k = (kstream) malloc (sizeof (kstream_rec));
|
||||
if (!k)
|
||||
return 0;
|
||||
kstream_rec__init (k);
|
||||
k->ctl = ctl;
|
||||
k->data = 0;
|
||||
k->fd = fd;
|
||||
k->buffering = 1; /* why not? */
|
||||
if (ctl && ctl->init && (ctl->init) (k, data) != 0)
|
||||
{
|
||||
free (k);
|
||||
return 0;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
int
|
||||
kstream_destroy (k)
|
||||
kstream k;
|
||||
{
|
||||
int x = kstream_flush (k);
|
||||
if (k->ctl && k->ctl->destroy)
|
||||
(k->ctl->destroy) (k);
|
||||
free (k);
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
kstream_set_buffer_mode (k, mode)
|
||||
kstream k;
|
||||
int mode;
|
||||
{
|
||||
k->buffering = mode;
|
||||
}
|
||||
|
||||
int
|
||||
kstream_write (k, p_data, p_len)
|
||||
kstream k;
|
||||
kstream_ptr p_data;
|
||||
size_t p_len;
|
||||
{
|
||||
size_t len = p_len;
|
||||
char *data = p_data;
|
||||
int x = 0;
|
||||
fifo *out = &k->out_clear;
|
||||
|
||||
assert (k != 0);
|
||||
|
||||
while (len)
|
||||
{
|
||||
x = fifo__append (out, data, len);
|
||||
assert (x >= 0);
|
||||
data += x;
|
||||
len -= x;
|
||||
if (len == 0 && k->buffering != 0)
|
||||
return p_len;
|
||||
x = kstream_flush (k);
|
||||
if (x < 0)
|
||||
return x;
|
||||
}
|
||||
return p_len;
|
||||
}
|
||||
|
||||
int
|
||||
kstream_flush (k)
|
||||
kstream k;
|
||||
{
|
||||
int x, n;
|
||||
fifo *out = &k->out_clear;
|
||||
struct kstream_data_block kd_out, kd_in;
|
||||
|
||||
assert (k != 0);
|
||||
|
||||
if (k->ctl == 0)
|
||||
{
|
||||
int n = fifo__bytes_available (out);
|
||||
x = krb_net_write (k->fd, fifo__data_start (out), n);
|
||||
if (x < 0)
|
||||
return x;
|
||||
else if (x != n)
|
||||
abort ();
|
||||
fifo__extract (out, 0, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = fifo__bytes_available (out);
|
||||
kd_in.length = n;
|
||||
kd_in.ptr = fifo__data_start (out);
|
||||
kd_out.ptr = 0;
|
||||
kd_out.length = 0;
|
||||
while (fifo__bytes_available (out))
|
||||
{
|
||||
x = (k->ctl->encrypt) (&kd_out, &kd_in, k);
|
||||
if (x < 0)
|
||||
return x;
|
||||
else if (x == 0)
|
||||
return -1;
|
||||
/* x is number of input characters processed */
|
||||
fifo__extract (out, 0, x);
|
||||
x = krb_net_write (k->fd, kd_out.ptr, kd_out.length);
|
||||
if (x < 0)
|
||||
return x;
|
||||
else if (x != kd_out.length)
|
||||
abort ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
kstream_read (k, p_data, p_len)
|
||||
kstream k;
|
||||
kstream_ptr p_data;
|
||||
size_t p_len;
|
||||
{
|
||||
char *data = p_data;
|
||||
size_t len = p_len;
|
||||
int n;
|
||||
fifo *in = &k->in_clear, *crypt;
|
||||
struct kstream_data_block kd_out, kd_in;
|
||||
|
||||
assert (k != 0);
|
||||
|
||||
read_clear:
|
||||
if (k->ctl == 0)
|
||||
return read (k->fd, data, len);
|
||||
|
||||
if (fifo__bytes_available (in) > 0)
|
||||
return fifo__extract (in, data, len);
|
||||
|
||||
crypt = &k->in_crypt;
|
||||
try_2:
|
||||
kd_out.ptr = 0;
|
||||
kd_out.length = 0;
|
||||
kd_in.length = fifo__bytes_available (crypt);
|
||||
kd_in.ptr = fifo__data_start (crypt);
|
||||
if (kd_in.length == 0)
|
||||
{
|
||||
n = -1;
|
||||
goto read_source;
|
||||
}
|
||||
n = (k->ctl->decrypt) (&kd_out, &kd_in, k);
|
||||
if (n > 0)
|
||||
{
|
||||
/* Succeeded in decrypting some data. */
|
||||
fifo__extract (crypt, 0, n);
|
||||
{
|
||||
int n2;
|
||||
n = kd_out.length;
|
||||
n2 = fifo__append (in, kd_out.ptr, kd_out.length);
|
||||
assert (n == n2);
|
||||
}
|
||||
goto read_clear;
|
||||
}
|
||||
else if (n == 0)
|
||||
assert (n != 0); /* not handling errors yet */
|
||||
|
||||
read_source:
|
||||
{
|
||||
size_t sz;
|
||||
static char *buf;
|
||||
sz = -n;
|
||||
if (sz > fifo__space_available (crypt))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "insufficient space avail (%d, want %d)\n",
|
||||
fifo__space_available (crypt), sz);
|
||||
#endif
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAS_ALLOCA
|
||||
buf = alloca (sz);
|
||||
#else
|
||||
if (buf)
|
||||
buf = realloc (buf, sz);
|
||||
else
|
||||
buf = malloc (sz);
|
||||
assert(buf);
|
||||
#endif
|
||||
while (sz > 0)
|
||||
{
|
||||
int n2;
|
||||
n2 = krb_net_read (k->fd, buf, sz);
|
||||
if (n2 < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror ("kstream_read: krb_net_read");
|
||||
#endif
|
||||
return n2;
|
||||
}
|
||||
else if (n2 == 0)
|
||||
return 0;
|
||||
fifo__append (crypt, buf, n2);
|
||||
sz -= n2;
|
||||
}
|
||||
goto try_2;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
extern "C" {
|
||||
|
||||
/* simple rotate */
|
||||
|
||||
typedef struct kstream_data_block DB;
|
||||
|
||||
static int
|
||||
move (DB *out, DB *in, kstream k, int direction)
|
||||
{
|
||||
int i, x;
|
||||
static char *ptr;
|
||||
char *inp = in->ptr;
|
||||
if (in->length == 0) return -1;
|
||||
/* Sun's realloc loses on null pointers. */
|
||||
ptr = ptr ? realloc (ptr, in->length) : malloc (in->length);
|
||||
out->ptr = ptr;
|
||||
if (!ptr) return 0;
|
||||
out->length = in->length;
|
||||
x = direction ? +1 : -1;
|
||||
for (i = in->length; i-- > 0; )
|
||||
ptr[i] = inp[i] + x;
|
||||
return in->length;
|
||||
}
|
||||
|
||||
static int emove (DB *out, DB *in, kstream k) { return move (out, in, k, 0); }
|
||||
static int dmove (DB *out, DB *in, kstream k) { return move (out, in, k, 1); }
|
||||
extern const struct kstream_crypt_ctl_block rot1_ccb = {
|
||||
emove, dmove, 0, 0
|
||||
};
|
||||
}
|
||||
#endif
|
100
lib/libkstream/kstream.h
Normal file
100
lib/libkstream/kstream.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* Header file for encrypted-stream library.
|
||||
Written by Ken Raeburn (Raeburn@Cygnus.COM).
|
||||
Copyright (C) 1991, 1992 by Cygnus Support.
|
||||
|
||||
This file is distributed under the same terms as Kerberos.
|
||||
For copying and distribution information, please see the file
|
||||
<mit-copyright.h>.
|
||||
|
||||
$NetBSD: kstream.h,v 1.1.1.1 2000/06/17 06:24:28 thorpej Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* for size_t */
|
||||
|
||||
/* Each stream is set up for two-way communication; if buffering is
|
||||
requested, output will be flushed before input is read, or when
|
||||
kstream_flush is called. */
|
||||
|
||||
#if defined (__STDC__) || defined (__cplusplus)
|
||||
typedef void *kstream_ptr;
|
||||
#else
|
||||
typedef char *kstream_ptr;
|
||||
#endif
|
||||
typedef struct kstream_rec *kstream;
|
||||
struct kstream_data_block {
|
||||
kstream_ptr ptr;
|
||||
size_t length;
|
||||
};
|
||||
struct kstream_crypt_ctl_block {
|
||||
/* Don't rely on anything in this structure.
|
||||
It is almost guaranteed to change.
|
||||
Right now, it's just a hack so we can bang out the interface
|
||||
in some form that lets us run both rcp and rlogin. This is also
|
||||
the only reason the contents of this structure are public. */
|
||||
#if defined (__STDC__) || defined (__cplusplus)
|
||||
int (*encrypt) (struct kstream_data_block *, /* output -- written */
|
||||
struct kstream_data_block*, /* input */
|
||||
kstream str
|
||||
); /* ret val = # input bytes used */
|
||||
int (*decrypt) (struct kstream_data_block *, /* output -- written */
|
||||
struct kstream_data_block*, /* input */
|
||||
kstream str
|
||||
); /* ret val = # input bytes used */
|
||||
int (*init) (kstream str, kstream_ptr data);
|
||||
void (*destroy) (kstream str);
|
||||
#else
|
||||
int (*encrypt) (), (*decrypt) (), (*init) ();
|
||||
void (*destroy) ();
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ctl==0 means no encryption. data is specific to crypt functions */
|
||||
#if defined (__STDC__) || defined (__cplusplus)
|
||||
kstream kstream_create_from_fd (int fd,
|
||||
const struct kstream_crypt_ctl_block *ctl,
|
||||
kstream_ptr data);
|
||||
/* There should be a "standard" DES mode used here somewhere.
|
||||
These differ, and I haven't chosen one over the other (yet). */
|
||||
kstream kstream_create_rlogin_from_fd (int fd, void* sched,
|
||||
unsigned char (*ivec)[8]);
|
||||
kstream kstream_create_rcp_from_fd (int fd, void* sched,
|
||||
unsigned char (*ivec)[8]);
|
||||
int kstream_write (kstream, void*, size_t);
|
||||
int kstream_read (kstream, void*, size_t);
|
||||
int kstream_flush (kstream);
|
||||
int kstream_destroy (kstream);
|
||||
void kstream_set_buffer_mode (kstream, int);
|
||||
#else
|
||||
kstream kstream_create_from_fd (),
|
||||
kstream_create_rlogin_from_fd (),
|
||||
kstream_create_rcp_from_fd ();
|
||||
void kstream_set_buffer_mode ();
|
||||
#endif
|
||||
|
||||
#if 0 /* Perhaps someday... */
|
||||
kstream kstream_create (principal, host, port, ...);
|
||||
#endif
|
||||
|
||||
#if !defined (__STDC__) && !defined (__cplusplus) && !defined (const)
|
||||
#define const /* empty */
|
||||
#endif
|
||||
|
||||
typedef struct fifo {
|
||||
char data[10*1024];
|
||||
size_t next_write, next_read;
|
||||
} fifo;
|
||||
|
||||
typedef struct kstream_rec {
|
||||
const struct kstream_crypt_ctl_block *ctl;
|
||||
int fd;
|
||||
int buffering : 2;
|
||||
kstream_ptr data;
|
||||
/* These should be made pointers as soon as code has been
|
||||
written to reallocate them. Also, it would be more efficient
|
||||
to use pointers into the buffers, rather than continually shifting
|
||||
them down so unprocessed data starts at index 0. */
|
||||
/* incoming */
|
||||
fifo in_crypt, in_clear;
|
||||
/* outgoing */
|
||||
fifo out_clear;
|
||||
} kstream_rec;
|
Loading…
Reference in New Issue
Block a user