lots of new stuff
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@299 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
3
Makefile
3
Makefile
@@ -4,7 +4,8 @@ CFLAGS=-g
|
||||
|
||||
YFLAGS = -d
|
||||
|
||||
SOURCES = principal.c principal_p.c data.c context.c misc.c string2key.c
|
||||
SOURCES = principal.c principal_p.c data.c context.c misc.c string2key.c \
|
||||
krbhst.c getport.c send_to_kdc.c
|
||||
|
||||
OBJECTS = $(SOURCES:%.c=%.o) config_file.o
|
||||
|
||||
|
256
d.c
Normal file
256
d.c
Normal file
@@ -0,0 +1,256 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <d.h>
|
||||
|
||||
int
|
||||
buf_getbyte (Buffer *b)
|
||||
{
|
||||
if (b->p >= b->buf + b->len)
|
||||
return EOF;
|
||||
return *b->p++;
|
||||
}
|
||||
|
||||
void
|
||||
buf_init (Buffer *b, char *ptr, unsigned len)
|
||||
{
|
||||
b->buf = b->p = ptr;
|
||||
b->len = len;
|
||||
}
|
||||
|
||||
Buffer *
|
||||
buf_derive (Buffer *b, Buffer *tmp, int len)
|
||||
{
|
||||
tmp->buf = tmp->p = b->p;
|
||||
if(len == -1)
|
||||
tmp->len = buf_bytesleft (b);
|
||||
else
|
||||
tmp->len = len;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int
|
||||
buf_bytesleft (Buffer *b)
|
||||
{
|
||||
return b->len - (b->p - b->buf);
|
||||
}
|
||||
|
||||
void
|
||||
buf_advance (Buffer *b, int n)
|
||||
{
|
||||
b->p += n;
|
||||
}
|
||||
|
||||
int
|
||||
buf_length (Buffer *b)
|
||||
{
|
||||
return b->p - b->buf;
|
||||
}
|
||||
|
||||
Identifier *
|
||||
getid (Buffer *b, Identifier *i)
|
||||
{
|
||||
int c, len;
|
||||
|
||||
c = buf_getbyte (b);
|
||||
if (c == EOF)
|
||||
return NULL;
|
||||
i->class = c >> 6;
|
||||
i->type = (c >> 5) & 1;
|
||||
i->tag = c & 0x1F;
|
||||
if (i->tag == 0x1F) {
|
||||
do {
|
||||
c = buf_getbyte (b);
|
||||
if (c == EOF)
|
||||
return NULL;
|
||||
i->tag = i->tag * 0x80 + (c & 0x7F);
|
||||
} while( c & 0x80);
|
||||
}
|
||||
|
||||
c = buf_getbyte (b);
|
||||
if (c == EOF)
|
||||
return NULL;
|
||||
len = c;
|
||||
if (len < 0x80) {
|
||||
i->len = len;
|
||||
} else if(len > 0x80) {
|
||||
len &= 0x7F;
|
||||
i->len = 0;
|
||||
while (len--) {
|
||||
c = buf_getbyte (b);
|
||||
if (c == EOF)
|
||||
return NULL;
|
||||
i->len = i->len * 0x100 + c;
|
||||
}
|
||||
} else if (len == 0x80)
|
||||
i->len = -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
Identifier *
|
||||
matchid (Buffer *b, Identifier *i)
|
||||
{
|
||||
Identifier tmp;
|
||||
|
||||
if (getid (b, &tmp) == NULL)
|
||||
return NULL;
|
||||
if (tmp.class == i->class && tmp.type == i->type && tmp.tag == i->tag) {
|
||||
i->len = tmp.len;
|
||||
return i;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Identifier dummy;
|
||||
|
||||
Identifier *
|
||||
matchid3 (Buffer *b, Identifier *i, Der_class class, Der_type type,
|
||||
unsigned tag)
|
||||
{
|
||||
i->class = class;
|
||||
i->type = type;
|
||||
i->tag = tag;
|
||||
return matchid (b, i);
|
||||
}
|
||||
|
||||
Identifier *
|
||||
matchcontextid (Buffer *b, Identifier *i, int tag)
|
||||
{
|
||||
Identifier tmp;
|
||||
|
||||
if (matchid3 (b, &tmp, CONTEXT, CONS, tag) == NULL ||
|
||||
matchid (b, i) == NULL)
|
||||
return NULL;
|
||||
return i;
|
||||
}
|
||||
|
||||
Identifier *
|
||||
matchcontextid3 (Buffer *b, Identifier *i, Der_class class,
|
||||
Der_type dtype,
|
||||
int type,
|
||||
unsigned tag)
|
||||
{
|
||||
i->class = class;
|
||||
i->type = dtype;
|
||||
i->tag = type;
|
||||
return matchcontextid (b, i, tag);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_integer (Buffer *b, void *val)
|
||||
{
|
||||
int c;
|
||||
int res;
|
||||
int len;
|
||||
|
||||
res = len = 0;
|
||||
while ((c = buf_getbyte (b)) != EOF) {
|
||||
res = res * 0x100 + c;
|
||||
++len;
|
||||
}
|
||||
*((int *)val) = res;
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
der_get_octetstring (Buffer *b, void *val)
|
||||
{
|
||||
krb5_data *str = (krb5_data *)val;
|
||||
int len, c;
|
||||
char *p;
|
||||
|
||||
len = buf_bytesleft (b);
|
||||
str->len = len;
|
||||
str->data = p = malloc (len + 1);
|
||||
while (len && (c = buf_getbyte (b)) != EOF) {
|
||||
*p++ = c;
|
||||
--len;
|
||||
}
|
||||
*p++ = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
der_get_generalizedtime (Buffer *b, void *val)
|
||||
{
|
||||
time_t *t = (time_t *)val;
|
||||
int len;
|
||||
krb5_data str;
|
||||
struct tm tm;
|
||||
|
||||
len = der_get_octetstring (b, &str);
|
||||
sscanf (str.data, "%04d%02d%02d%02d%02d%02dZ",
|
||||
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
|
||||
&tm.tm_min, &tm.tm_sec);
|
||||
tm.tm_year -= 1900;
|
||||
tm.tm_mon -= 1;
|
||||
tm.tm_isdst = 0;
|
||||
|
||||
*t = mktime (&tm);
|
||||
*t -= timezone;
|
||||
|
||||
string_free (str);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int (*get_univ_funcs[])(Buffer *, void *val) = {
|
||||
NULL, /* 0 */
|
||||
NULL, /* 1 */
|
||||
der_get_integer, /* 2 */
|
||||
NULL, /* 3 */
|
||||
der_get_octetstring, /* 4 */
|
||||
NULL, /* 5 */
|
||||
NULL, /* 6 */
|
||||
NULL, /* 7 */
|
||||
NULL, /* 8 */
|
||||
NULL, /* 9 */
|
||||
NULL, /* 10 */
|
||||
NULL, /* 11 */
|
||||
NULL, /* 12 */
|
||||
NULL, /* 13 */
|
||||
NULL, /* 14 */
|
||||
NULL, /* 15 */
|
||||
NULL, /* 16 */
|
||||
NULL, /* 17 */
|
||||
NULL, /* 18 */
|
||||
NULL, /* 19 */
|
||||
NULL, /* 20 */
|
||||
NULL, /* 21 */
|
||||
NULL, /* 22 */
|
||||
NULL, /* 23 */
|
||||
der_get_generalizedtime, /* 24 */
|
||||
NULL, /* 25 */
|
||||
NULL, /* 26 */
|
||||
der_get_octetstring, /* 27 */
|
||||
};
|
||||
|
||||
int
|
||||
der_get_val (Buffer *b, int type, void *val)
|
||||
{
|
||||
return (*(get_univ_funcs[type]))(b, val);
|
||||
}
|
||||
|
||||
void
|
||||
getzeros (Buffer *b, int len)
|
||||
{
|
||||
if (len == -1) {
|
||||
buf_getbyte (b);
|
||||
buf_getbyte (b);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getdata (Buffer *b, Identifier *i, void *arg)
|
||||
{
|
||||
Buffer tmp;
|
||||
int res;
|
||||
|
||||
buf_derive (b, &tmp, i->len);
|
||||
res = der_get_val (&tmp, i->tag, arg);
|
||||
if (i->len == -1) {
|
||||
getzeros (b, i->len);
|
||||
buf_advance (b, res);
|
||||
} else
|
||||
buf_advance (b, i->len);
|
||||
return res;
|
||||
}
|
27
d.h
Normal file
27
d.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <der.h>
|
||||
|
||||
struct Buffer {
|
||||
unsigned char *buf;
|
||||
unsigned char *p;
|
||||
unsigned len;
|
||||
};
|
||||
|
||||
typedef struct Buffer Buffer;
|
||||
|
||||
int buf_getbyte (Buffer *);
|
||||
void buf_init (Buffer *, char *, unsigned);
|
||||
Buffer *buf_derive (Buffer *, Buffer *, int);
|
||||
int buf_bytesleft (Buffer *b);
|
||||
void buf_advance (Buffer *b, int n);
|
||||
int buf_length (Buffer *b);
|
||||
|
||||
struct Identifier {
|
||||
Der_class class;
|
||||
Der_type type;
|
||||
unsigned tag;
|
||||
int len;
|
||||
};
|
||||
|
||||
typedef struct Identifier Identifier;
|
||||
|
||||
Identifier *getid (Buffer *b, Identifier *i);
|
29
der.c
Normal file
29
der.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <der.h>
|
||||
|
||||
/*
|
||||
* Type functions
|
||||
*/
|
||||
|
||||
krb5_data
|
||||
string_make_n (int n, char *s)
|
||||
{
|
||||
krb5_data ret;
|
||||
|
||||
ret.len = n;
|
||||
ret.data = s;
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_data
|
||||
string_make (char *s)
|
||||
{
|
||||
return string_make_n (strlen (s), s);
|
||||
}
|
||||
|
||||
void
|
||||
string_free (krb5_data s)
|
||||
{
|
||||
free (s.data);
|
||||
}
|
30
der.h
Normal file
30
der.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef DER_H
|
||||
|
||||
#define DER_H
|
||||
|
||||
typedef enum {UNIV = 0, APPL = 1, CONTEXT = 2 , PRIVATE = 3} Der_class;
|
||||
|
||||
typedef enum {PRIM = 0, CONS = 1} Der_type;
|
||||
|
||||
/* Universal tags */
|
||||
|
||||
enum {
|
||||
UT_Integer = 2,
|
||||
UT_BitString = 3,
|
||||
UT_OctetString = 4,
|
||||
UT_Null = 5,
|
||||
UT_ObjID = 6,
|
||||
UT_Sequence = 16,
|
||||
UT_Set = 17,
|
||||
UT_PrintableString = 19,
|
||||
UT_IA5String = 22,
|
||||
UT_UTCTime = 23,
|
||||
UT_GeneralizedTime = 24,
|
||||
UT_GeneralString = 27,
|
||||
};
|
||||
|
||||
krb5_data string_make (char *);
|
||||
krb5_data string_make_n (int len, char *);
|
||||
void string_free (krb5_data);
|
||||
|
||||
#endif /* DER_H */
|
179
der_get.c
Normal file
179
der_get.c
Normal file
@@ -0,0 +1,179 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <der.h>
|
||||
|
||||
/*
|
||||
* Functions for parsing DER
|
||||
*/
|
||||
|
||||
unsigned
|
||||
der_get_length (unsigned char *ptr, unsigned *res)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned char c;
|
||||
|
||||
c = *p++;
|
||||
if (c < 0x80) {
|
||||
*res = c;
|
||||
return 1;
|
||||
} else {
|
||||
c &= 0x7F;
|
||||
*res = 0;
|
||||
while (c--)
|
||||
*res = *res * 0x100 + *p++;
|
||||
return p - ptr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_get_tag (unsigned char *ptr, Der_class *class, Der_type *type,
|
||||
unsigned *tag)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned char o1;
|
||||
|
||||
o1 = *p++;
|
||||
*class = o1 >> 6;
|
||||
*type = (o1 >> 5) & 1;
|
||||
*tag = o1 & 0x1F;
|
||||
if (*tag == 0x1F) {
|
||||
do {
|
||||
o1 = *p++;
|
||||
*tag = *tag * 0x80 + (o1 & 0x7F);
|
||||
} while( o1 & 0x80);
|
||||
}
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_get_integer (unsigned char *ptr, int len, void *v)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned *res = v;
|
||||
|
||||
*res = 0;
|
||||
while(len--)
|
||||
*res = *res * 0x100 + *p++;
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_get_octetstring (unsigned char *ptr, int len, void *v)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
krb5_data *res = v;
|
||||
|
||||
res->data = malloc(len + 1);
|
||||
res->len = len;
|
||||
memcpy (*res, p, len);
|
||||
(*res)[len] = '\0';
|
||||
p += len;
|
||||
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
static unsigned (*get_univ_funcs[])(unsigned char *, int len, void *val) = {
|
||||
NULL, /* 0 */
|
||||
NULL, /* 1 */
|
||||
der_get_integer, /* 2 */
|
||||
NULL, /* 3 */
|
||||
der_get_octetstring, /* 4 */
|
||||
NULL, /* 5 */
|
||||
NULL, /* 6 */
|
||||
NULL, /* 7 */
|
||||
NULL, /* 8 */
|
||||
NULL, /* 9 */
|
||||
NULL, /* 10 */
|
||||
NULL, /* 11 */
|
||||
NULL, /* 12 */
|
||||
NULL, /* 13 */
|
||||
NULL, /* 14 */
|
||||
NULL, /* 15 */
|
||||
NULL, /* 16 */
|
||||
NULL, /* 17 */
|
||||
NULL, /* 18 */
|
||||
NULL, /* 19 */
|
||||
NULL, /* 20 */
|
||||
NULL, /* 21 */
|
||||
NULL, /* 22 */
|
||||
NULL, /* 23 */
|
||||
der_get_octetstring, /* 24 */
|
||||
NULL, /* 25 */
|
||||
NULL, /* 26 */
|
||||
der_get_octetstring, /* 27 */
|
||||
};
|
||||
|
||||
unsigned
|
||||
der_get_val (unsigned char *ptr, int type, int len, void *val)
|
||||
{
|
||||
return (*(get_univ_funcs[type]))(ptr, len, val);
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_get_type (unsigned char *ptr, Der_class *class, Der_type *type,
|
||||
unsigned *tag, unsigned *len)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
int
|
||||
der_match_type (unsigned char **ptr, Der_class class, Der_type type,
|
||||
unsigned tag, unsigned *len)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
Der_class c1;
|
||||
Der_type t1;
|
||||
unsigned tag1;
|
||||
|
||||
p += der_get_tag (p, &c1, &t1, &tag1);
|
||||
if (c1 != class || t1 != type || tag != tag1)
|
||||
return -1;
|
||||
p += der_get_length (p, len);
|
||||
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
int
|
||||
der_get_context (unsigned char *ptr, unsigned *tag, unsigned *type,
|
||||
unsigned *len)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
Der_class class;
|
||||
Der_type foo;
|
||||
|
||||
p += der_get_tag (p, &class, &foo, tag);
|
||||
if (class != CONTEXT || foo != CONS )
|
||||
return -1;
|
||||
p += der_get_length (p, len);
|
||||
p += der_get_tag (p, &class, &foo, type);
|
||||
if (class != UNIV || foo != PRIM)
|
||||
return -1;
|
||||
p += der_get_length (p, len);
|
||||
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
int
|
||||
der_match_context (unsigned char *ptr, unsigned tag, int type, void *arg)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
int len;
|
||||
int tlen;
|
||||
|
||||
len = der_match_type (p, CONTEXT, CONS, tag, &tlen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
len = der_match_type (p, UNIV, PRIM, type, &tlen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
|
||||
p += der_get_val (p, type, tlen, arg);
|
||||
|
||||
return p - ptr;
|
||||
}
|
384
e.c
Normal file
384
e.c
Normal file
@@ -0,0 +1,384 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <d.h>
|
||||
#include <k5_der.h>
|
||||
|
||||
int
|
||||
der_get_principalname (Buffer *b, PrincipalName *p)
|
||||
{
|
||||
Identifier i;
|
||||
int cur, max;
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
p->num_strings = 0;
|
||||
|
||||
if (matchid3 (b, &i, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &p->name_type);
|
||||
if (matchcontextid3 (b, &i, UNIV, CONS, UT_Sequence, 1) == NULL)
|
||||
return -1;
|
||||
cur = 0;
|
||||
max = 1;
|
||||
p->names = malloc(sizeof(char *) * max);
|
||||
while (matchid3 (b, &i, UNIV, PRIM, UT_GeneralString)) {
|
||||
if (cur >= max) {
|
||||
max *= 2;
|
||||
p->names = realloc (p->names, sizeof(char *) * max);
|
||||
}
|
||||
getdata (b, &i, &p->names[cur++]);
|
||||
}
|
||||
p->num_strings = cur;
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_encrypteddata (Buffer *b, EncryptedData *e)
|
||||
{
|
||||
Identifier i0, i1, i;
|
||||
int len;
|
||||
|
||||
if (matchid3 (b, &i0, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &e->etype);
|
||||
getid (b, &i);
|
||||
if (i.tag == 1) {
|
||||
int kvno;
|
||||
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_Integer) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &kvno);
|
||||
e->kvno = malloc (sizeof (int));
|
||||
*(e->kvno) = kvno;
|
||||
} else
|
||||
e->kvno = NULL;
|
||||
if (matchid3 (b, &i1, CONTEXT, CONS, 2) == NULL)
|
||||
return -1;
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_OctetString) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &e->cipher);
|
||||
getzeros (b, i1.len);
|
||||
getzeros (b, i0.len);
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_ticket (Buffer *b, Ticket *t)
|
||||
{
|
||||
Identifier i0, i1, i;
|
||||
Buffer tmp;
|
||||
int len;
|
||||
|
||||
if (matchid3 (b, &i0, APPL, CONS, APPL_TICKET) == NULL)
|
||||
return -1;
|
||||
if (matchid3 (b, &i1, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &t->tkt_vno);
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_GeneralString, 1) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &t->realm);
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 2) == NULL)
|
||||
return -1;
|
||||
buf_derive(b, &tmp, i.len);
|
||||
len = der_get_principalname (&tmp, &t->sname);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 3) == NULL)
|
||||
return -1;
|
||||
buf_derive (b, &tmp, i.len);
|
||||
len = der_get_encrypteddata (&tmp, &t->enc_part);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
getzeros (b, i1.len);
|
||||
getzeros (b, i0.len);
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_kdc_rep (Buffer *b, int msg, Kdc_Rep *k)
|
||||
{
|
||||
Identifier i, i0;
|
||||
Buffer tmp;
|
||||
int len;
|
||||
|
||||
if (matchid3 (b, &i0, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
getdata (b, &i, &k->pvno);
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 1) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &k->msg_type);
|
||||
if (k->msg_type != msg)
|
||||
return -1;
|
||||
getid (b, &i);
|
||||
if (i.tag == 2)
|
||||
abort (); /* XXX */
|
||||
if (i.tag != 3)
|
||||
return -1;
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_GeneralString) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &k->realm);
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 4) == NULL)
|
||||
return -1;
|
||||
buf_derive(b, &tmp, i.len);
|
||||
len = der_get_principalname (&tmp, &k->cname);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 5) == NULL)
|
||||
return -1;
|
||||
buf_derive(b, &tmp, i.len);
|
||||
len = der_get_ticket (&tmp, &k->ticket);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 6) == NULL)
|
||||
return -1;
|
||||
buf_derive(b, &tmp, i.len);
|
||||
len = der_get_encrypteddata (&tmp, &k->enc_part);
|
||||
if(len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
getzeros (b, i0.len);
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
static int
|
||||
der_get_kdc_rep_msg (Buffer *b, int msg, Kdc_Rep *a)
|
||||
{
|
||||
Identifier i;
|
||||
|
||||
if (matchid3(b, &i, APPL, CONS, msg) == NULL)
|
||||
return -1;
|
||||
return der_get_kdc_rep (b, msg, a);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_as_rep (Buffer *b, As_Rep *a)
|
||||
{
|
||||
return der_get_kdc_rep_msg (b, KRB_AS_REP, a);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_tgs_rep (Buffer *b, Tgs_Rep *a)
|
||||
{
|
||||
return der_get_kdc_rep_msg (b, KRB_TGS_REP, a);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_encryptionkey (Buffer *b, EncryptionKey *k)
|
||||
{
|
||||
Identifier i;
|
||||
|
||||
if (matchid3 (b, &i, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &k->keytype);
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_OctetString, 1) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &k->keyvalue);
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_hostaddresses (Buffer *b, HostAddresses *h)
|
||||
{
|
||||
Identifier i;
|
||||
int cur, max;
|
||||
|
||||
if (matchid3 (b, &i, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
cur = 0;
|
||||
max = 1;
|
||||
h->addrs = malloc (sizeof (*h->addrs));
|
||||
while (matchid3 (b, &i, UNIV, CONS, UT_Sequence)) {
|
||||
if (cur >= max) {
|
||||
max *= 2;
|
||||
h->addrs = realloc (h->addrs, sizeof(*h->addrs) * max);
|
||||
}
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &h->addrs[cur].addr_type);
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_OctetString, 1) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &h->addrs[cur].addr);
|
||||
++cur;
|
||||
}
|
||||
h->number = cur;
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_lastreq (Buffer *b, LastReq *l)
|
||||
{
|
||||
Identifier i;
|
||||
int cur, max;
|
||||
|
||||
if (matchid3 (b, &i, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
cur = 0;
|
||||
max = 1;
|
||||
l->values = malloc (sizeof(*l->values));
|
||||
while (matchid3 (b, &i, UNIV, CONS, UT_Sequence)) {
|
||||
if (cur >= max) {
|
||||
max *= 2;
|
||||
l->values = realloc (l->values, sizeof (*l->values) * max);
|
||||
}
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 0) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &l->values[cur].lr_type);
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_GeneralizedTime, 1) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &l->values[cur].lr_value);
|
||||
++cur;
|
||||
}
|
||||
l->number = cur;
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_ticketflags (Buffer *b, TicketFlags *t)
|
||||
{
|
||||
Identifier i;
|
||||
|
||||
return buf_bytesleft (b);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_enckdcreppart (Buffer *b, int msg, EncKdcRepPart *a)
|
||||
{
|
||||
Identifier i;
|
||||
Buffer tmp;
|
||||
int len;
|
||||
|
||||
if (matchid3 (b, &i, UNIV, CONS, UT_Sequence) == NULL)
|
||||
return -1;
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 0) == NULL)
|
||||
return -1;
|
||||
buf_derive (b, &tmp, i.len);
|
||||
len = der_get_encryptionkey (&tmp, &a->key);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 1) == NULL)
|
||||
return -1;
|
||||
buf_derive (b, &tmp, i.len);
|
||||
len = der_get_lastreq (&tmp, &a->req);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_Integer, 2) == NULL)
|
||||
return -1;
|
||||
getdata (b, &i, &a->nonce);
|
||||
getid (b, &i);
|
||||
if (i.tag == 3) {
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_GeneralizedTime) == NULL)
|
||||
return NULL;
|
||||
|
||||
a->key_expiration = malloc (sizeof(*a->key_expiration));
|
||||
getdata (b, &i, a->key_expiration);
|
||||
getid (b, &i);
|
||||
} else
|
||||
a->key_expiration = NULL;
|
||||
if (i.tag != 4)
|
||||
return NULL;
|
||||
buf_derive (b, &tmp, i.len);
|
||||
len = der_get_ticketflags (&tmp, &a->flags);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
if (matchcontextid3 (b, &i, UNIV, PRIM, UT_GeneralizedTime, 5) == NULL)
|
||||
return NULL;
|
||||
getdata (b, &i, &a->authtime);
|
||||
getid (b, &i);
|
||||
if (i.tag == 6) {
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_GeneralizedTime) == NULL)
|
||||
return NULL;
|
||||
|
||||
a->starttime = malloc (sizeof(*a->starttime));
|
||||
getdata (b, &i, a->starttime);
|
||||
getid (b, &i);
|
||||
} else
|
||||
a->starttime = NULL;
|
||||
if (i.tag != 7)
|
||||
return NULL;
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_GeneralizedTime) == NULL)
|
||||
return NULL;
|
||||
getdata (b, &i, &a->authtime);
|
||||
getid (b, &i);
|
||||
if (i.tag == 8) {
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_GeneralizedTime) == NULL)
|
||||
return NULL;
|
||||
|
||||
a->renew_till = malloc (sizeof(*a->renew_till));
|
||||
getdata (b, &i, a->renew_till);
|
||||
getid (b, &i);
|
||||
} else
|
||||
a->renew_till = NULL;
|
||||
if (i.tag != 9)
|
||||
return NULL;
|
||||
if (matchid3 (b, &i, UNIV, PRIM, UT_GeneralString) == NULL)
|
||||
return NULL;
|
||||
getdata (b, &i, &a->srealm);
|
||||
if (matchid3 (b, &i, CONTEXT, CONS, 10) == NULL)
|
||||
return NULL;
|
||||
buf_derive(b, &tmp, i.len);
|
||||
len = der_get_principalname (&tmp, &a->sname);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
getid (b, &i);
|
||||
if (i.tag == 11) {
|
||||
buf_derive (b, &tmp, i.len);
|
||||
len = der_get_hostaddresses (&tmp, &a->caddr);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
buf_advance (b, len);
|
||||
getzeros (b, i.len);
|
||||
} else
|
||||
a->caddr.number = 0;
|
||||
return buf_length (b);
|
||||
}
|
||||
|
||||
static int
|
||||
der_get_enckdcreppart_msg (Buffer *b, int msg, EncKdcRepPart *a)
|
||||
{
|
||||
Identifier i;
|
||||
|
||||
if (matchid3 (b, &i, APPL, CONS, msg) == NULL)
|
||||
return -1;
|
||||
return der_get_enckdcreppart (b, msg, a);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_encasreppart (Buffer *b, EncASRepPart *a)
|
||||
{
|
||||
return der_get_enckdcreppart_msg (b, KRB_ENCASREPPART, a);
|
||||
}
|
||||
|
||||
int
|
||||
der_get_enctgsreppart (Buffer *b, EncTGSRepPart *a)
|
||||
{
|
||||
return der_get_enckdcreppart_msg (b, KRB_ENCKDCREPPART, a);
|
||||
}
|
90
get_in_tkt.c
90
get_in_tkt.c
@@ -1,5 +1,35 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
static krb5_error_code
|
||||
krb5_get_salt (krb5_principal princ,
|
||||
krb5_data realm,
|
||||
krb5_data *salt)
|
||||
{
|
||||
size_t len;
|
||||
int i;
|
||||
krb5_error_code err;
|
||||
char *p;
|
||||
|
||||
len = realm->len;
|
||||
for (i = 0; i < princ->ncomp; ++i)
|
||||
len += princ->comp[i].length;
|
||||
err = krb5_alloc (salt, len);
|
||||
if (err)
|
||||
return err;
|
||||
p = salt->data;
|
||||
strncpy (p, realm->data, realm->len);
|
||||
p += realm->len;
|
||||
for (i = 0; i < princ->cnomp; ++i) {
|
||||
strncpy (p, princ->comp[i].data, princ->comp[i].length);
|
||||
p += princ->comp[i].length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
krb5_error_code
|
||||
krb5_get_in_tkt(krb5_context context,
|
||||
krb5_flags options,
|
||||
@@ -14,5 +44,65 @@ krb5_get_in_tkt(krb5_context context,
|
||||
krb5_ccache ccache,
|
||||
krb5_kdc_rep **ret_as_reply)
|
||||
{
|
||||
As_Req a;
|
||||
Kdc_Rep rep;
|
||||
krb5_principal server;
|
||||
krb5_data req, resp;
|
||||
char buf[BUFSIZ];
|
||||
Buffer buf;
|
||||
krb5_data salt;
|
||||
krb5_keyblock *key;
|
||||
|
||||
server.type = KRB_NT_SRV_INST;
|
||||
server.ncomp = 2;
|
||||
server.comp = malloc (sizeof(*server.comp) * server.ncomp);
|
||||
server.comp[0] = string_make ("krbtgt");
|
||||
server.comp[1] = creds->client.realm;
|
||||
|
||||
a.pvno = 5;
|
||||
a.msg_type = KRB_AS_REQ;
|
||||
/* a.kdc_options */
|
||||
a.cname = &creds->client;
|
||||
a.sname = &server;
|
||||
a.realm = creds->client.realm;
|
||||
a.till = creds->times.endtime;
|
||||
a.nonce = 17;
|
||||
if (etypes)
|
||||
a.etypes = etypes;
|
||||
else
|
||||
a.etypes = context->etypes;
|
||||
if (addrs)
|
||||
a.addresses = addrs;
|
||||
else
|
||||
a.addresses = krb5_get_all_client_addrs ();
|
||||
|
||||
req.data = buf;
|
||||
|
||||
req.len = der_put_as_req (req.data + sizeof(buf) - 1, &a);
|
||||
string_free (server.comp[0]);
|
||||
free (server.comp);
|
||||
if (addrs == NULL)
|
||||
free (a.addresses);
|
||||
|
||||
err = krb5_sendto_kdc (context, &req, a.realm, &resp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
buf_init (&buffer, resp.data, resp.len);
|
||||
if (der_get_as_rep (&buffer, &rep) == -1) {
|
||||
return ASN1_PARSE_ERROR;
|
||||
}
|
||||
err = krb5_get_salt (creds->client, creds->client.realm, &salt);
|
||||
if (err)
|
||||
return err;
|
||||
err = (*key_proc)(context, b.enc_part.etype, salt, keyseed, &key);
|
||||
krb5_data_free (&salt);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = (*decrypt_proc)(context, key, decryptarg, &rep);
|
||||
memset (&key.contents.data, 0, key.contents.length);
|
||||
krb5_data_free (&key.contents);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
41
get_in_tkt_pw.c
Normal file
41
get_in_tkt_pw.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
static krb5_error_code
|
||||
key_proc (krb5_context context,
|
||||
krb5_keytype type,
|
||||
krb5_data *salt,
|
||||
krb5_const_pointer keyseed,
|
||||
krb5_keyblock **key)
|
||||
{
|
||||
krb5_error_code err;
|
||||
char *password = (char *)keyseed;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
key = malloc (sizeof (*key));
|
||||
if (key == NULL)
|
||||
return ENOMEM;
|
||||
key->keytype = type;
|
||||
if (password == NULL) {
|
||||
des_read_pw_string (buf, sizeof(buf), "Password: ", 0);
|
||||
password = buf;
|
||||
}
|
||||
err = krb5_string_to_key (password, salt, key);
|
||||
memset (buf, 0, sizeof(buf));
|
||||
return err;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
krb5_get_in_tkt_with_password (krb5_context context,
|
||||
krb5_flags options,
|
||||
krb5_address *const *addrs,
|
||||
const krb5_enctype *etypes,
|
||||
const krb5_preauthtype *pre_auth_types,
|
||||
const char *password,
|
||||
krb5_ccache ccache,
|
||||
krb5_creds *creds,
|
||||
krb5_kdc-rep **ret_as_reply)
|
||||
{
|
||||
return krb5_get_in_tkt (context, options, addrs, etypes,
|
||||
pre_auth_types, key_proc, password,
|
||||
NULL, NULL, creds, cache, ret_as_reply);
|
||||
}
|
17
get_port.c
Normal file
17
get_port.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <krb5_locl.h>
|
||||
|
||||
int
|
||||
krb5_getportbyname (const char *service,
|
||||
const char *proto,
|
||||
int default_port)
|
||||
{
|
||||
struct servent *sp;
|
||||
|
||||
if ((sp = getservbyname (service, proto)) == NULL) {
|
||||
fprintf (stderr, "%s/%s unknown service, "
|
||||
"using default port %d\n", service, proto,
|
||||
ntohs(default_port));
|
||||
return default_port;
|
||||
} else
|
||||
return sp->s_port;
|
||||
}
|
252
k5_der.c
Normal file
252
k5_der.c
Normal file
@@ -0,0 +1,252 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <k5_der.h>
|
||||
|
||||
static void
|
||||
time2generalizedtime (krb5_data *s, time_t t)
|
||||
{
|
||||
struct tm *tm;
|
||||
|
||||
s->data = malloc(16);
|
||||
s->len = 15;
|
||||
tm = gmtime (&t);
|
||||
sprintf (s->data, "%04d%02d%02d%02d%02d%02dZ", tm->tm_year + 1900,
|
||||
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_put_context_etypes (unsigned char *ptr, int tag,
|
||||
EncryptionType *etypes, unsigned num_etypes)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
int i;
|
||||
|
||||
for (i = num_etypes - 1; i >= 0; --i)
|
||||
p -= der_put_type_and_value (p, UT_Integer, &etypes[i]);
|
||||
p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p);
|
||||
p -= der_put_type (p, CONTEXT, CONS, tag, ptr - p);
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_put_context_principalname (unsigned char *ptr, int tag,
|
||||
PrincipalName *name)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
int i;
|
||||
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
for (i = name->num_strings - 1; i >= 0; --i)
|
||||
p -= der_put_type_and_value (p, UT_GeneralString,
|
||||
&name->names[i]);
|
||||
p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p);
|
||||
p -= der_put_type (p, CONTEXT, CONS, 1, ptr - p);
|
||||
p -= der_put_context (p, 0, UT_Integer, &name->name_type);
|
||||
p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p);
|
||||
p -= der_put_type (p, CONTEXT, CONS, tag, ptr - p);
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_put_context_kdcoptions (unsigned char *ptr, int tag, KdcOptions *k)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
/* XXX */
|
||||
|
||||
*p-- = '\0';
|
||||
*p-- = '\0';
|
||||
*p-- = '\0';
|
||||
*p-- = '\0';
|
||||
*p-- = '\0';
|
||||
*p-- = 5;
|
||||
*p-- = 3;
|
||||
p -= der_put_type (p, CONTEXT, CONS, tag, ptr - p);
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_put_context_hostaddresses (unsigned char *ptr, int tag,
|
||||
HostAddress *addrs,
|
||||
unsigned naddr)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
int i;
|
||||
|
||||
for(i = naddr - 1; i >= 0; --i) {
|
||||
p -= der_put_context (p, 1, UT_OctetString, &addrs[i].addr);
|
||||
p -= der_put_context (p, 0, UT_Integer, &addrs[i].addr_type);
|
||||
}
|
||||
p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p);
|
||||
p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p);
|
||||
p -= der_put_type (p, CONTEXT, CONS, tag, ptr - p);
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_put_kdc_req_body (unsigned char *ptr, Kdc_Req *k)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned random = 17;
|
||||
|
||||
/* additional-tickets[11] SEQUENCE OF Ticket OPTIONAL */
|
||||
/* enc-authorization-data[10] EncryptedData OPTIONAL */
|
||||
p -= der_put_context_hostaddresses (p, 9, k->addrs,
|
||||
k->num_addrs);
|
||||
/* addresses[9] HostAddresses OPTIONAL */
|
||||
p -= der_put_context_etypes (p, 8, k->etypes, k->num_etypes);
|
||||
p -= der_put_context (p, 7, UT_Integer, &random);
|
||||
/* rtime[6] KerberosTime OPTIONAL */
|
||||
{
|
||||
krb5_data t;
|
||||
|
||||
time2generalizedtime (&t, k->till);
|
||||
p -= der_put_context (p, 5, UT_GeneralizedTime, &t);
|
||||
string_free (t);
|
||||
}
|
||||
/* from[4] KerberosTime OPTIONAL */
|
||||
p -= der_put_context_principalname (p, 3, k->sname);
|
||||
p -= der_put_context (p, 2, UT_GeneralString, &k->realm);
|
||||
p -= der_put_context_principalname (p, 1, k->cname);
|
||||
p -= der_put_context_kdcoptions (p, 0, &k->kdc_options);
|
||||
p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p);
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_put_kdc_req (unsigned char *ptr, int msg_type, Kdc_Req *k)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
|
||||
p -= der_put_kdc_req_body (p, k);
|
||||
p -= der_put_type (p, CONTEXT, CONS, 4, ptr - p);
|
||||
/* padata[3] SEQUENCE OF PA-DATA OPTIONAL */
|
||||
p -= der_put_context (p, 2, UT_Integer, &k->msg_type);
|
||||
p -= der_put_context (p, 1, UT_Integer, &k->pvno);
|
||||
p -= der_put_type (p, UNIV, CONS, UT_Sequence, ptr - p);
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
unsigned
|
||||
der_put_as_req (unsigned char *ptr, As_Req *a)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
|
||||
p -= der_put_kdc_req (p, a->msg_type, a);
|
||||
p -= der_put_type (p, APPL, CONS, a->msg_type, ptr - p);
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
* Get functions
|
||||
*/
|
||||
|
||||
int
|
||||
der_get_principalname (unsigned char *ptr, Principalname *name)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned char *p0;
|
||||
int tlen, tlen2;
|
||||
|
||||
len = der_match_type (p, UNIV, CONS, UT_Sequence, &tlen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
p0 = p;
|
||||
len = der_match_context (p, 0, UT_Integer, &name->name_type);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
len = der_match_type (p, CONTEXT, CONS, 1, &tlen2);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p =+ len;
|
||||
len = der_match_type ()
|
||||
while(p < p0 + tlen) {
|
||||
}
|
||||
|
||||
|
||||
return ptr - p;
|
||||
}
|
||||
|
||||
int
|
||||
der_get_kdc_rep (unsigned char *ptr, unsigned mylen, int msg_type,
|
||||
Kdc_Rep *k)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
unsigned tlen, slen;
|
||||
int len;
|
||||
unsigned kvno, msg1;
|
||||
unsigned tag;
|
||||
int type;
|
||||
|
||||
len = der_match_type (p, UNIV, CONS, UT_Sequence, &tlen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
len = der_match_context (p, 0, UT_Integer, &kvno);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
if (kvno != 5)
|
||||
return -1;
|
||||
len = der_match_context (p, 1, UT_Integer, &msg1);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
if (msg1 != msg_type)
|
||||
return -1;
|
||||
len = der_get_context (p, &tag, &type, &tlen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
if (tag == 2)
|
||||
abort (); /* XXX */
|
||||
else if (tag == 3) {
|
||||
p += der_get_val (p, UT_GeneralString, tlen, &k->realm);
|
||||
}
|
||||
len = der_get_context (p, &tag, &type, &tlen);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
der_get_principalname
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
int
|
||||
der_get_as_rep (unsigned char *ptr, As_Rep *a)
|
||||
{
|
||||
unsigned char *p = ptr;
|
||||
int len;
|
||||
unsigned tlen;
|
||||
|
||||
len = der_match_type (p, APPL, CONS, KRB_AS_REP, &tlen);
|
||||
if(len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
len = der_get_kdc_rep (p, tlen, KRB_AS_REP, a);
|
||||
if (len < 0)
|
||||
return len;
|
||||
else
|
||||
p += len;
|
||||
|
||||
return p - ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
189
k5_der.h
Normal file
189
k5_der.h
Normal file
@@ -0,0 +1,189 @@
|
||||
#include <der.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
* Message types.
|
||||
*/
|
||||
|
||||
enum {
|
||||
KRB_AS_REQ = 10,
|
||||
KRB_AS_REP = 11,
|
||||
KRB_TGS_REQ = 12,
|
||||
KRB_TGS_REP = 13,
|
||||
KRB_AP_REQ = 14,
|
||||
KRB_AP_REP = 15,
|
||||
KRB_SAFE = 20,
|
||||
KRB_PRIV = 21,
|
||||
KRB_CRED = 22,
|
||||
KRB_ENCASREPPART = 25,
|
||||
KRB_ENCKDCREPPART = 26,
|
||||
KRB_ERROR = 30
|
||||
};
|
||||
|
||||
/*
|
||||
* Application
|
||||
*/
|
||||
|
||||
enum {
|
||||
APPL_TICKET = 1
|
||||
};
|
||||
|
||||
struct HostAddress {
|
||||
int addr_type;
|
||||
krb5_data addr;
|
||||
};
|
||||
|
||||
typedef struct HostAddress HostAddress;
|
||||
|
||||
struct HostAddresses {
|
||||
int number;
|
||||
HostAddress *addrs;
|
||||
};
|
||||
|
||||
typedef struct HostAddresses HostAddresses;
|
||||
|
||||
struct PrincipalName {
|
||||
int name_type;
|
||||
unsigned num_strings;
|
||||
krb5_data *names;
|
||||
};
|
||||
|
||||
enum {
|
||||
nt_unknown = 0,
|
||||
nt_principal = 1,
|
||||
nt_srv_inst = 2,
|
||||
nt_srv_hst = 3,
|
||||
nt_srv_xhst = 4,
|
||||
nt_uid = 5
|
||||
};
|
||||
|
||||
typedef struct PrincipalName PrincipalName;
|
||||
|
||||
struct KdcOptions {
|
||||
unsigned
|
||||
reserved : 1,
|
||||
forwardable : 1,
|
||||
forwarded : 1,
|
||||
proxiable : 1,
|
||||
proxy : 1,
|
||||
allow_postdate : 1,
|
||||
postdated : 1,
|
||||
unused7 : 1,
|
||||
renewable : 1,
|
||||
unused9 : 1,
|
||||
unused10 : 1,
|
||||
unused11 : 1,
|
||||
renewable_ok : 1,
|
||||
enc_tkt_in_skey : 1,
|
||||
renew : 1,
|
||||
validate : 1;
|
||||
};
|
||||
|
||||
typedef struct KdcOptions KdcOptions;
|
||||
|
||||
typedef krb5_data Realm;
|
||||
|
||||
typedef int EncryptionType;
|
||||
|
||||
struct Kdc_Req {
|
||||
int pvno;
|
||||
int msg_type;
|
||||
KdcOptions kdc_options;
|
||||
PrincipalName *cname;
|
||||
Realm realm;
|
||||
PrincipalName *sname;
|
||||
time_t till;
|
||||
unsigned num_etypes;
|
||||
EncryptionType *etypes;
|
||||
HostAddress *addrs;
|
||||
unsigned num_addrs;
|
||||
};
|
||||
|
||||
typedef struct Kdc_Req Kdc_Req;
|
||||
|
||||
typedef Kdc_Req As_Req;
|
||||
|
||||
struct EncryptedData {
|
||||
int etype;
|
||||
int *kvno;
|
||||
krb5_data cipher;
|
||||
};
|
||||
|
||||
typedef struct EncryptedData EncryptedData;
|
||||
|
||||
struct Ticket {
|
||||
int tkt_vno;
|
||||
Realm realm;
|
||||
PrincipalName sname;
|
||||
EncryptedData enc_part;
|
||||
};
|
||||
|
||||
typedef struct Ticket Ticket;
|
||||
|
||||
struct Kdc_Rep {
|
||||
int pvno;
|
||||
int msg_type;
|
||||
Realm realm;
|
||||
PrincipalName cname;
|
||||
Ticket ticket;
|
||||
EncryptedData enc_part;
|
||||
};
|
||||
|
||||
typedef struct Kdc_Rep Kdc_Rep;
|
||||
|
||||
typedef Kdc_Rep As_Rep;
|
||||
|
||||
typedef Kdc_Rep Tgs_Rep;
|
||||
|
||||
struct EncryptionKey {
|
||||
int keytype;
|
||||
krb5_data keyvalue;
|
||||
};
|
||||
|
||||
typedef struct EncryptionKey EncryptionKey;
|
||||
|
||||
struct LastReq {
|
||||
int number;
|
||||
struct {
|
||||
int lr_type;
|
||||
time_t lr_value;
|
||||
} *values;
|
||||
};
|
||||
|
||||
typedef struct LastReq LastReq;
|
||||
|
||||
struct TicketFlags {
|
||||
unsigned forwardable:1,
|
||||
forwarded:1,
|
||||
proxiable:1,
|
||||
proxy:1,
|
||||
may_postdate:1,
|
||||
postdated:1,
|
||||
invalid:1,
|
||||
renewable:1,
|
||||
initial:1,
|
||||
pre_authent:1,
|
||||
hw_authent:1;
|
||||
};
|
||||
|
||||
typedef struct TicketFlags TicketFlags;
|
||||
|
||||
struct EncKdcRepPart {
|
||||
EncryptionKey key;
|
||||
LastReq req;
|
||||
int nonce;
|
||||
time_t *key_expiration;
|
||||
TicketFlags flags;
|
||||
time_t authtime;
|
||||
time_t *starttime;
|
||||
time_t endtime;
|
||||
time_t *renew_till;
|
||||
Realm srealm;
|
||||
PrincipalName sname;
|
||||
HostAddresses caddr;
|
||||
};
|
||||
|
||||
typedef struct EncKdcRepPart EncKdcRepPart;
|
||||
|
||||
typedef EncKdcRepPart EncASRepPart;
|
||||
typedef EncKdcRepPart EncTGSRepPart;
|
27
krbhst.c
Normal file
27
krbhst.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
krb5_error_code
|
||||
krb5_get_krbhst (krb5_context context,
|
||||
const krb5_data *realm,
|
||||
char ***hostlist)
|
||||
{
|
||||
krb5_error_code err;
|
||||
char buf[BUFSIZ];
|
||||
char *val;
|
||||
|
||||
sprintf (buf, "realms %s kdc", realm.data);
|
||||
err = krb5_get_config_tag (context.cf, buf, &val);
|
||||
if (err)
|
||||
return err;
|
||||
**hostlist = malloc (2 * sizeof (char *));
|
||||
(*hostlist)[0] = val;
|
||||
(*hostlist)[1] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
krb5_free_krbhst (krb5_context context,
|
||||
char *const *hostlist)
|
||||
{
|
||||
free (hostlist);
|
||||
}
|
@@ -1,5 +1,35 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
static krb5_error_code
|
||||
krb5_get_salt (krb5_principal princ,
|
||||
krb5_data realm,
|
||||
krb5_data *salt)
|
||||
{
|
||||
size_t len;
|
||||
int i;
|
||||
krb5_error_code err;
|
||||
char *p;
|
||||
|
||||
len = realm->len;
|
||||
for (i = 0; i < princ->ncomp; ++i)
|
||||
len += princ->comp[i].length;
|
||||
err = krb5_alloc (salt, len);
|
||||
if (err)
|
||||
return err;
|
||||
p = salt->data;
|
||||
strncpy (p, realm->data, realm->len);
|
||||
p += realm->len;
|
||||
for (i = 0; i < princ->cnomp; ++i) {
|
||||
strncpy (p, princ->comp[i].data, princ->comp[i].length);
|
||||
p += princ->comp[i].length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
krb5_error_code
|
||||
krb5_get_in_tkt(krb5_context context,
|
||||
krb5_flags options,
|
||||
@@ -14,5 +44,65 @@ krb5_get_in_tkt(krb5_context context,
|
||||
krb5_ccache ccache,
|
||||
krb5_kdc_rep **ret_as_reply)
|
||||
{
|
||||
As_Req a;
|
||||
Kdc_Rep rep;
|
||||
krb5_principal server;
|
||||
krb5_data req, resp;
|
||||
char buf[BUFSIZ];
|
||||
Buffer buf;
|
||||
krb5_data salt;
|
||||
krb5_keyblock *key;
|
||||
|
||||
server.type = KRB_NT_SRV_INST;
|
||||
server.ncomp = 2;
|
||||
server.comp = malloc (sizeof(*server.comp) * server.ncomp);
|
||||
server.comp[0] = string_make ("krbtgt");
|
||||
server.comp[1] = creds->client.realm;
|
||||
|
||||
a.pvno = 5;
|
||||
a.msg_type = KRB_AS_REQ;
|
||||
/* a.kdc_options */
|
||||
a.cname = &creds->client;
|
||||
a.sname = &server;
|
||||
a.realm = creds->client.realm;
|
||||
a.till = creds->times.endtime;
|
||||
a.nonce = 17;
|
||||
if (etypes)
|
||||
a.etypes = etypes;
|
||||
else
|
||||
a.etypes = context->etypes;
|
||||
if (addrs)
|
||||
a.addresses = addrs;
|
||||
else
|
||||
a.addresses = krb5_get_all_client_addrs ();
|
||||
|
||||
req.data = buf;
|
||||
|
||||
req.len = der_put_as_req (req.data + sizeof(buf) - 1, &a);
|
||||
string_free (server.comp[0]);
|
||||
free (server.comp);
|
||||
if (addrs == NULL)
|
||||
free (a.addresses);
|
||||
|
||||
err = krb5_sendto_kdc (context, &req, a.realm, &resp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
buf_init (&buffer, resp.data, resp.len);
|
||||
if (der_get_as_rep (&buffer, &rep) == -1) {
|
||||
return ASN1_PARSE_ERROR;
|
||||
}
|
||||
err = krb5_get_salt (creds->client, creds->client.realm, &salt);
|
||||
if (err)
|
||||
return err;
|
||||
err = (*key_proc)(context, b.enc_part.etype, salt, keyseed, &key);
|
||||
krb5_data_free (&salt);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = (*decrypt_proc)(context, key, decryptarg, &rep);
|
||||
memset (&key.contents.data, 0, key.contents.length);
|
||||
krb5_data_free (&key.contents);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
41
lib/krb5/get_in_tkt_pw.c
Normal file
41
lib/krb5/get_in_tkt_pw.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
static krb5_error_code
|
||||
key_proc (krb5_context context,
|
||||
krb5_keytype type,
|
||||
krb5_data *salt,
|
||||
krb5_const_pointer keyseed,
|
||||
krb5_keyblock **key)
|
||||
{
|
||||
krb5_error_code err;
|
||||
char *password = (char *)keyseed;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
key = malloc (sizeof (*key));
|
||||
if (key == NULL)
|
||||
return ENOMEM;
|
||||
key->keytype = type;
|
||||
if (password == NULL) {
|
||||
des_read_pw_string (buf, sizeof(buf), "Password: ", 0);
|
||||
password = buf;
|
||||
}
|
||||
err = krb5_string_to_key (password, salt, key);
|
||||
memset (buf, 0, sizeof(buf));
|
||||
return err;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
krb5_get_in_tkt_with_password (krb5_context context,
|
||||
krb5_flags options,
|
||||
krb5_address *const *addrs,
|
||||
const krb5_enctype *etypes,
|
||||
const krb5_preauthtype *pre_auth_types,
|
||||
const char *password,
|
||||
krb5_ccache ccache,
|
||||
krb5_creds *creds,
|
||||
krb5_kdc-rep **ret_as_reply)
|
||||
{
|
||||
return krb5_get_in_tkt (context, options, addrs, etypes,
|
||||
pre_auth_types, key_proc, password,
|
||||
NULL, NULL, creds, cache, ret_as_reply);
|
||||
}
|
17
lib/krb5/get_port.c
Normal file
17
lib/krb5/get_port.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <krb5_locl.h>
|
||||
|
||||
int
|
||||
krb5_getportbyname (const char *service,
|
||||
const char *proto,
|
||||
int default_port)
|
||||
{
|
||||
struct servent *sp;
|
||||
|
||||
if ((sp = getservbyname (service, proto)) == NULL) {
|
||||
fprintf (stderr, "%s/%s unknown service, "
|
||||
"using default port %d\n", service, proto,
|
||||
ntohs(default_port));
|
||||
return default_port;
|
||||
} else
|
||||
return sp->s_port;
|
||||
}
|
27
lib/krb5/krbhst.c
Normal file
27
lib/krb5/krbhst.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
krb5_error_code
|
||||
krb5_get_krbhst (krb5_context context,
|
||||
const krb5_data *realm,
|
||||
char ***hostlist)
|
||||
{
|
||||
krb5_error_code err;
|
||||
char buf[BUFSIZ];
|
||||
char *val;
|
||||
|
||||
sprintf (buf, "realms %s kdc", realm.data);
|
||||
err = krb5_get_config_tag (context.cf, buf, &val);
|
||||
if (err)
|
||||
return err;
|
||||
**hostlist = malloc (2 * sizeof (char *));
|
||||
(*hostlist)[0] = val;
|
||||
(*hostlist)[1] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
krb5_free_krbhst (krb5_context context,
|
||||
char *const *hostlist)
|
||||
{
|
||||
free (hostlist);
|
||||
}
|
85
lib/krb5/send_to_kdc.c
Normal file
85
lib/krb5/send_to_kdc.c
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
static int
|
||||
send_and_recv (int fd,
|
||||
struct sockaddr_in *addr,
|
||||
krb5_data *send,
|
||||
krb5_data *recv)
|
||||
{
|
||||
struct fdset fdset;
|
||||
struct timeval timeout;
|
||||
int ret;
|
||||
long nbytes;
|
||||
|
||||
if (sendto (fd, send->data, send->len, 0,
|
||||
(struct sockaddr *)addr, sizeof(*addr)) < 0)
|
||||
return -1;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
ret = select (fd + 1, &fdset, NULL, NULL, &timeout);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
else {
|
||||
ioctl (fd, FIONREAD, &nbytes);
|
||||
|
||||
nbytes -= sizeof(struct udphdr) + sizeof(struct iphdr);
|
||||
|
||||
recv->data = malloc (nbytes);
|
||||
ret = recvfrom (fd, recv->data, nbytes, 0, NULL, 0);
|
||||
if (ret < 0) {
|
||||
free (recv->data);
|
||||
return -1;
|
||||
}
|
||||
recv->data = realloc (recv->data, ret);
|
||||
recv->len = ret;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
krb5_sentdo_kdc (krb5_context context,
|
||||
const krb5_data *send,
|
||||
const krb5_data *realm,
|
||||
krb5_data *receive)
|
||||
{
|
||||
krb5_error_code err;
|
||||
char **hostlist, **hp, *p;
|
||||
struct hostent *hostent;
|
||||
int fd;
|
||||
int port;
|
||||
int i;
|
||||
|
||||
port = krb5_getportbyname ("kerberos", "udp", htons(750));
|
||||
fd = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
|
||||
err = krb5_get_krbhst (context, realm, &hostlist);
|
||||
if (err) {
|
||||
close (fd);
|
||||
return err;
|
||||
}
|
||||
for (i = 0; i < 3; ++i)
|
||||
for (hp = hostlist; p = *hp; ++hp) {
|
||||
char *addr;
|
||||
|
||||
hostent = gethostbyname (p);
|
||||
while (addr = *hostent->h_addr_list++) {
|
||||
struct sockaddr_in a;
|
||||
|
||||
memset (a, 0, sizeof(a));
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = port;
|
||||
a.sin_addr = *((struct in_addr *)addr);
|
||||
|
||||
if (send_and_recv (fd, &a, send, recv) == 0) {
|
||||
krb5_free_krbhst (context, hostlist);
|
||||
return KDC_ERR_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
krb5_free_krbhst (context, hostlist);
|
||||
return KRB5_KDC_UNREACH;
|
||||
}
|
141
lib/krb5/str2key.c
Normal file
141
lib/krb5/str2key.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#include <krb5_locl.h>
|
||||
|
||||
/*
|
||||
* Reverse 8 bytes
|
||||
*/
|
||||
|
||||
static void
|
||||
reverse (unsigned char *s)
|
||||
{
|
||||
static unsigned char tbl[] = {
|
||||
0x0,
|
||||
0x8,
|
||||
0x4,
|
||||
0xC,
|
||||
0x2,
|
||||
0xA,
|
||||
0x6,
|
||||
0xE,
|
||||
0x1,
|
||||
0x9,
|
||||
0x5,
|
||||
0xD,
|
||||
0x3,
|
||||
0xB,
|
||||
0x7,
|
||||
0xF
|
||||
};
|
||||
|
||||
char tmp;
|
||||
|
||||
#define REVONE(str, i, j) \
|
||||
do { tmp = str[i]; str[i] = str[j]; str[j] = tmp;} while(0)
|
||||
|
||||
REVONE(s,0,7);
|
||||
REVONE(s,1,6);
|
||||
REVONE(s,2,5);
|
||||
REVONE(s,3,4);
|
||||
#undef REVONE
|
||||
|
||||
#define REVTWO(q) \
|
||||
q = (tbl[q & 0x0F] << 4) | (tbl[q >> 4])
|
||||
|
||||
REVTWO(s[0]);
|
||||
REVTWO(s[1]);
|
||||
REVTWO(s[2]);
|
||||
REVTWO(s[3]);
|
||||
REVTWO(s[4]);
|
||||
REVTWO(s[5]);
|
||||
REVTWO(s[6]);
|
||||
REVTWO(s[7]);
|
||||
|
||||
#undef REVTWO
|
||||
}
|
||||
|
||||
/*
|
||||
* A = A xor B. A & B is 8 bytes.
|
||||
*/
|
||||
|
||||
static void
|
||||
xor (unsigned char *a, unsigned char *b)
|
||||
{
|
||||
a[0] ^= b[0];
|
||||
a[1] ^= b[1];
|
||||
a[2] ^= b[2];
|
||||
a[3] ^= b[3];
|
||||
a[4] ^= b[4];
|
||||
a[5] ^= b[5];
|
||||
a[6] ^= b[6];
|
||||
a[7] ^= b[7];
|
||||
}
|
||||
|
||||
/*
|
||||
* Init a from b
|
||||
*/
|
||||
|
||||
static void
|
||||
init (unsigned char *a, unsigned char *b)
|
||||
{
|
||||
a[0] = b[0] << 1;
|
||||
a[1] = b[1] << 1;
|
||||
a[2] = b[2] << 1;
|
||||
a[3] = b[3] << 1;
|
||||
a[4] = b[4] << 1;
|
||||
a[5] = b[5] << 1;
|
||||
a[6] = b[6] << 1;
|
||||
a[7] = b[7] << 1;
|
||||
}
|
||||
|
||||
void
|
||||
krb5_string_to_key (char *str,
|
||||
krb5_data *salt,
|
||||
krb5_keyblock *key)
|
||||
{
|
||||
int odd, i;
|
||||
size_t len;
|
||||
char *s, *p;
|
||||
des_cblock tempkey;
|
||||
des_key_schedule sched;
|
||||
krb5_error_code err;
|
||||
|
||||
len = strlen(str) + salt->len;
|
||||
#if 1
|
||||
len = (len + 7) / 8 * 8;
|
||||
#endif
|
||||
p = s = malloc (len);
|
||||
if (p == NULL)
|
||||
return ENOMEM;
|
||||
err = krb5_data_alloc (&key->contents, sizeof(des_cblock));
|
||||
if (err) {
|
||||
free (p);
|
||||
return err;
|
||||
}
|
||||
memset (s, 0, len);
|
||||
strncpy (p, str, strlen(str));
|
||||
p += strlen(str);
|
||||
strncpy (p, salt->data, salt->len);
|
||||
odd = 1;
|
||||
memset (tempkey, 0, sizeof(tempkey));
|
||||
for (i = 0; i < len; i += 8) {
|
||||
unsigned char tmp[8];
|
||||
|
||||
init (tmp, &s[i]);
|
||||
|
||||
if (odd == 0) {
|
||||
odd = 1;
|
||||
reverse (tmp);
|
||||
init (tmp, tmp);
|
||||
} else
|
||||
odd = 0;
|
||||
xor (tempkey, tmp);
|
||||
}
|
||||
des_set_odd_parity (&tempkey);
|
||||
des_set_key (&tempkey, sched);
|
||||
des_cbc_cksum ((des_cblock *)s, &tempkey, len, sched, &tempkey);
|
||||
free (s);
|
||||
des_set_odd_parity (&tempkey);
|
||||
if (des_is_weak_key (&tempkey))
|
||||
xor ((char *)&tempkey, "0x000x000x000x000x000x000x000xF0");
|
||||
memcpy (key->contents.data, &tempkey, sizeof(tempkey));
|
||||
return 0;
|
||||
}
|
85
send_to_kdc.c
Normal file
85
send_to_kdc.c
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "krb5_locl.h"
|
||||
|
||||
static int
|
||||
send_and_recv (int fd,
|
||||
struct sockaddr_in *addr,
|
||||
krb5_data *send,
|
||||
krb5_data *recv)
|
||||
{
|
||||
struct fdset fdset;
|
||||
struct timeval timeout;
|
||||
int ret;
|
||||
long nbytes;
|
||||
|
||||
if (sendto (fd, send->data, send->len, 0,
|
||||
(struct sockaddr *)addr, sizeof(*addr)) < 0)
|
||||
return -1;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
ret = select (fd + 1, &fdset, NULL, NULL, &timeout);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
else {
|
||||
ioctl (fd, FIONREAD, &nbytes);
|
||||
|
||||
nbytes -= sizeof(struct udphdr) + sizeof(struct iphdr);
|
||||
|
||||
recv->data = malloc (nbytes);
|
||||
ret = recvfrom (fd, recv->data, nbytes, 0, NULL, 0);
|
||||
if (ret < 0) {
|
||||
free (recv->data);
|
||||
return -1;
|
||||
}
|
||||
recv->data = realloc (recv->data, ret);
|
||||
recv->len = ret;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
krb5_sentdo_kdc (krb5_context context,
|
||||
const krb5_data *send,
|
||||
const krb5_data *realm,
|
||||
krb5_data *receive)
|
||||
{
|
||||
krb5_error_code err;
|
||||
char **hostlist, **hp, *p;
|
||||
struct hostent *hostent;
|
||||
int fd;
|
||||
int port;
|
||||
int i;
|
||||
|
||||
port = krb5_getportbyname ("kerberos", "udp", htons(750));
|
||||
fd = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
|
||||
err = krb5_get_krbhst (context, realm, &hostlist);
|
||||
if (err) {
|
||||
close (fd);
|
||||
return err;
|
||||
}
|
||||
for (i = 0; i < 3; ++i)
|
||||
for (hp = hostlist; p = *hp; ++hp) {
|
||||
char *addr;
|
||||
|
||||
hostent = gethostbyname (p);
|
||||
while (addr = *hostent->h_addr_list++) {
|
||||
struct sockaddr_in a;
|
||||
|
||||
memset (a, 0, sizeof(a));
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = port;
|
||||
a.sin_addr = *((struct in_addr *)addr);
|
||||
|
||||
if (send_and_recv (fd, &a, send, recv) == 0) {
|
||||
krb5_free_krbhst (context, hostlist);
|
||||
return KDC_ERR_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
krb5_free_krbhst (context, hostlist);
|
||||
return KRB5_KDC_UNREACH;
|
||||
}
|
141
str2key.c
Normal file
141
str2key.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#include <krb5_locl.h>
|
||||
|
||||
/*
|
||||
* Reverse 8 bytes
|
||||
*/
|
||||
|
||||
static void
|
||||
reverse (unsigned char *s)
|
||||
{
|
||||
static unsigned char tbl[] = {
|
||||
0x0,
|
||||
0x8,
|
||||
0x4,
|
||||
0xC,
|
||||
0x2,
|
||||
0xA,
|
||||
0x6,
|
||||
0xE,
|
||||
0x1,
|
||||
0x9,
|
||||
0x5,
|
||||
0xD,
|
||||
0x3,
|
||||
0xB,
|
||||
0x7,
|
||||
0xF
|
||||
};
|
||||
|
||||
char tmp;
|
||||
|
||||
#define REVONE(str, i, j) \
|
||||
do { tmp = str[i]; str[i] = str[j]; str[j] = tmp;} while(0)
|
||||
|
||||
REVONE(s,0,7);
|
||||
REVONE(s,1,6);
|
||||
REVONE(s,2,5);
|
||||
REVONE(s,3,4);
|
||||
#undef REVONE
|
||||
|
||||
#define REVTWO(q) \
|
||||
q = (tbl[q & 0x0F] << 4) | (tbl[q >> 4])
|
||||
|
||||
REVTWO(s[0]);
|
||||
REVTWO(s[1]);
|
||||
REVTWO(s[2]);
|
||||
REVTWO(s[3]);
|
||||
REVTWO(s[4]);
|
||||
REVTWO(s[5]);
|
||||
REVTWO(s[6]);
|
||||
REVTWO(s[7]);
|
||||
|
||||
#undef REVTWO
|
||||
}
|
||||
|
||||
/*
|
||||
* A = A xor B. A & B is 8 bytes.
|
||||
*/
|
||||
|
||||
static void
|
||||
xor (unsigned char *a, unsigned char *b)
|
||||
{
|
||||
a[0] ^= b[0];
|
||||
a[1] ^= b[1];
|
||||
a[2] ^= b[2];
|
||||
a[3] ^= b[3];
|
||||
a[4] ^= b[4];
|
||||
a[5] ^= b[5];
|
||||
a[6] ^= b[6];
|
||||
a[7] ^= b[7];
|
||||
}
|
||||
|
||||
/*
|
||||
* Init a from b
|
||||
*/
|
||||
|
||||
static void
|
||||
init (unsigned char *a, unsigned char *b)
|
||||
{
|
||||
a[0] = b[0] << 1;
|
||||
a[1] = b[1] << 1;
|
||||
a[2] = b[2] << 1;
|
||||
a[3] = b[3] << 1;
|
||||
a[4] = b[4] << 1;
|
||||
a[5] = b[5] << 1;
|
||||
a[6] = b[6] << 1;
|
||||
a[7] = b[7] << 1;
|
||||
}
|
||||
|
||||
void
|
||||
krb5_string_to_key (char *str,
|
||||
krb5_data *salt,
|
||||
krb5_keyblock *key)
|
||||
{
|
||||
int odd, i;
|
||||
size_t len;
|
||||
char *s, *p;
|
||||
des_cblock tempkey;
|
||||
des_key_schedule sched;
|
||||
krb5_error_code err;
|
||||
|
||||
len = strlen(str) + salt->len;
|
||||
#if 1
|
||||
len = (len + 7) / 8 * 8;
|
||||
#endif
|
||||
p = s = malloc (len);
|
||||
if (p == NULL)
|
||||
return ENOMEM;
|
||||
err = krb5_data_alloc (&key->contents, sizeof(des_cblock));
|
||||
if (err) {
|
||||
free (p);
|
||||
return err;
|
||||
}
|
||||
memset (s, 0, len);
|
||||
strncpy (p, str, strlen(str));
|
||||
p += strlen(str);
|
||||
strncpy (p, salt->data, salt->len);
|
||||
odd = 1;
|
||||
memset (tempkey, 0, sizeof(tempkey));
|
||||
for (i = 0; i < len; i += 8) {
|
||||
unsigned char tmp[8];
|
||||
|
||||
init (tmp, &s[i]);
|
||||
|
||||
if (odd == 0) {
|
||||
odd = 1;
|
||||
reverse (tmp);
|
||||
init (tmp, tmp);
|
||||
} else
|
||||
odd = 0;
|
||||
xor (tempkey, tmp);
|
||||
}
|
||||
des_set_odd_parity (&tempkey);
|
||||
des_set_key (&tempkey, sched);
|
||||
des_cbc_cksum ((des_cblock *)s, &tempkey, len, sched, &tempkey);
|
||||
free (s);
|
||||
des_set_odd_parity (&tempkey);
|
||||
if (des_is_weak_key (&tempkey))
|
||||
xor ((char *)&tempkey, "0x000x000x000x000x000x000x000xF0");
|
||||
memcpy (key->contents.data, &tempkey, sizeof(tempkey));
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user