The beginnings of a kdc.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1305 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Johan Danielsson
1997-03-08 10:39:43 +00:00
parent 835a7af102
commit 69816ce6c5
10 changed files with 813 additions and 0 deletions

10
admin/Makefile.am Normal file
View File

@@ -0,0 +1,10 @@
# $Id$
AUTOHEADER_FLAGS = no-dependencies
INCLUDES = -I$(top_builddir)/include
bin_PROGRAMS = load string2key kdc
LDADD = -L$(top_builddir)/lib/krb5 -lkrb5 -L$(top_builddir)/lib/des -ldes -L$(top_builddir)/lib/asn1 -lasn1

99
admin/load.c Normal file
View File

@@ -0,0 +1,99 @@
#include "kdc_locl.h"
RCSID("$Id$");
int main(int argc, char **argv)
{
FILE *f;
DB *db;
krb5_context context;
char s[1024];
char *p;
int line;
unsigned char key_buf[1024];
unsigned char *q;
unsigned char value_buf[1024];
krb5_keyblock keyblock;
DBT key, value;
int err;
int i;
krb5_storage *sp;
struct entry e;
krb5_principal princ;
krb5_init_context(&context);
f = fopen(argv[1], "r");
db = dbopen(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0600, DB_BTREE, NULL);
line = 0;
while(fgets(s, sizeof(s), f)){
line++;
e.principal = s;
for(p = s; *p; p++){
if(*p == '\\')
p++;
else if(isspace(*p)) {
*p == 0;
break;
}
}
*p++ = 0;
while(*p && isspace(*p)) p++;
e.key = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
while(*p && isspace(*p)) p++;
e.kvno = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
while(*p && isspace(*p)) p++;
e.max_life = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
e.max_renew = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
err = krb5_parse_name(context, e.principal, &princ);
if(err){
fprintf(stderr, "%s:%s:%s (%s)\n",
argv[1],
line,
krb5_get_err_text(context, err),
e.principal);
continue;
}
sp = krb5_storage_from_mem(key_buf, sizeof(key_buf));
princ->type = 0;
krb5_store_principal(sp, princ);
key.data = key_buf;
key.size = sp->seek(sp, 0, SEEK_CUR);
krb5_storage_free(sp);
keyblock.keytype = KEYTYPE_DES;
keyblock.contents.data = malloc(strlen(e.key)/2+1);
for(i = 0; i < strlen(e.key); i += 2){
sscanf(e.key + i, "%2x",
(unsigned char *)keyblock.contents.data + (i/2));
}
keyblock.contents.length = i / 2;
sp = krb5_storage_from_mem(value_buf, sizeof(value_buf));
krb5_store_keyblock(sp, keyblock);
krb5_store_int32(sp, atoi(e.kvno));
krb5_store_int32(sp, atoi(e.max_life));
krb5_store_int32(sp, atoi(e.max_renew));
value.data = value_buf;
value.size = sp->seek(sp, 0, SEEK_CUR);
db->put(db, &key, &value, 0);
krb5_storage_free(sp);
}
db->close(db);
}

99
kadmin/load.c Normal file
View File

@@ -0,0 +1,99 @@
#include "kdc_locl.h"
RCSID("$Id$");
int main(int argc, char **argv)
{
FILE *f;
DB *db;
krb5_context context;
char s[1024];
char *p;
int line;
unsigned char key_buf[1024];
unsigned char *q;
unsigned char value_buf[1024];
krb5_keyblock keyblock;
DBT key, value;
int err;
int i;
krb5_storage *sp;
struct entry e;
krb5_principal princ;
krb5_init_context(&context);
f = fopen(argv[1], "r");
db = dbopen(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0600, DB_BTREE, NULL);
line = 0;
while(fgets(s, sizeof(s), f)){
line++;
e.principal = s;
for(p = s; *p; p++){
if(*p == '\\')
p++;
else if(isspace(*p)) {
*p == 0;
break;
}
}
*p++ = 0;
while(*p && isspace(*p)) p++;
e.key = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
while(*p && isspace(*p)) p++;
e.kvno = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
while(*p && isspace(*p)) p++;
e.max_life = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
e.max_renew = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
err = krb5_parse_name(context, e.principal, &princ);
if(err){
fprintf(stderr, "%s:%s:%s (%s)\n",
argv[1],
line,
krb5_get_err_text(context, err),
e.principal);
continue;
}
sp = krb5_storage_from_mem(key_buf, sizeof(key_buf));
princ->type = 0;
krb5_store_principal(sp, princ);
key.data = key_buf;
key.size = sp->seek(sp, 0, SEEK_CUR);
krb5_storage_free(sp);
keyblock.keytype = KEYTYPE_DES;
keyblock.contents.data = malloc(strlen(e.key)/2+1);
for(i = 0; i < strlen(e.key); i += 2){
sscanf(e.key + i, "%2x",
(unsigned char *)keyblock.contents.data + (i/2));
}
keyblock.contents.length = i / 2;
sp = krb5_storage_from_mem(value_buf, sizeof(value_buf));
krb5_store_keyblock(sp, keyblock);
krb5_store_int32(sp, atoi(e.kvno));
krb5_store_int32(sp, atoi(e.max_life));
krb5_store_int32(sp, atoi(e.max_renew));
value.data = value_buf;
value.size = sp->seek(sp, 0, SEEK_CUR);
db->put(db, &key, &value, 0);
krb5_storage_free(sp);
}
db->close(db);
}

10
kdc/Makefile.am Normal file
View File

@@ -0,0 +1,10 @@
# $Id$
AUTOHEADER_FLAGS = no-dependencies
INCLUDES = -I$(top_builddir)/include
bin_PROGRAMS = load string2key kdc
LDADD = -L$(top_builddir)/lib/krb5 -lkrb5 -L$(top_builddir)/lib/des -ldes -L$(top_builddir)/lib/asn1 -lasn1

214
kdc/kdc.c Normal file
View File

@@ -0,0 +1,214 @@
#include "kdc_locl.h"
RCSID("$Id$");
struct db_entry*
db_fetch(krb5_context context, krb5_principal princ)
{
DB *db;
DBT key, value;
krb5_storage *sp;
struct db_entry *ent;
int i;
int32_t tmp;
key.size = princ->realm.length;
for(i = 0; i < princ->ncomp; i++)
key.size += princ->comp[i].length;
key.size += (princ->ncomp + 3) * 4;
key.data = malloc(key.size);
sp = krb5_storage_from_mem(key.data, key.size);
tmp = princ->type;
princ->type = 0;
krb5_store_principal(sp, princ);
princ->type = tmp;
krb5_storage_free(sp);
db = dbopen("foo.db", O_RDONLY, 0, DB_BTREE, NULL);
if(db->get(db, &key, &value, 0)){
db->close(db);
return NULL;
}
sp = krb5_storage_from_mem(value.data, value.size);
ent = malloc(sizeof(struct db_entry));
krb5_copy_principal(context, princ, &ent->principal);
krb5_ret_keyblock(sp, &ent->keyblock);
krb5_ret_int32(sp, &tmp);
ent->kvno = tmp;
krb5_ret_int32(sp, &tmp);
ent->max_life = tmp;
krb5_ret_int32(sp, &tmp);
ent->max_renew = tmp;
krb5_storage_free(sp);
db->close(db);
return ent;
}
krb5_error_code
krb5_encrypt (krb5_context context,
void *ptr,
size_t len,
krb5_keyblock *keyblock,
krb5_data *result);
krb5_error_code
foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len)
{
krb5_error_code err;
krb5_principal princ;
unsigned char key_buf[1024];
unsigned char *q;
DB *db;
DBT key, value;
struct timeval now;
KDC_REP rep;
EncTicketPart et;
EncKDCRepPart ek;
struct db_entry *cname, *sname;
err = principalname2krb5_principal (&princ,
*req->req_body.cname,
req->req_body.realm);
if(err) return err;
cname = db_fetch(context, princ);
krb5_free_principal(princ);
err = principalname2krb5_principal (&princ,
*req->req_body.sname,
req->req_body.realm);
if(err) return err;
sname = db_fetch(context, princ);
krb5_free_principal(princ);
memset(&rep, 0, sizeof(rep));
rep.pvno = 5;
rep.msg_type = krb_as_rep;
rep.crealm = req->req_body.realm;
krb5_principal2principalname(&rep.cname, cname->principal);
memset(&rep.ticket, 0, sizeof(rep.ticket));
rep.ticket.tkt_vno = 5;
rep.ticket.realm = req->req_body.realm;
krb5_principal2principalname(&rep.ticket.sname, sname->principal);
memset(&et, 0, sizeof(et));
et.flags.initial = 1;
et.key.keytype = sname->keyblock.keytype;
et.key.keyvalue.data = sname->keyblock.contents.data;
et.key.keyvalue.length = sname->keyblock.contents.length;
et.crealm = req->req_body.realm;
krb5_principal2principalname(&et.cname, cname->principal);
gettimeofday(&now, NULL);
et.authtime = now.tv_sec;
{
time_t till;
till = req->req_body.till;
till = MIN(till, now.tv_sec + sname->max_life);
till = MIN(till, now.tv_sec + cname->max_life);
et.endtime = till;
}
memset(&ek, 0, sizeof(ek));
ek.key = et.key;
ek.last_req.len = 1;
ek.last_req.val = malloc(sizeof(*ek.last_req.val));
ek.last_req.val->lr_type = 1;
ek.last_req.val->lr_value = 0;
ek.nonce = req->req_body.nonce;
ek.flags = et.flags;
ek.authtime = et.authtime;
ek.starttime = et.starttime;
ek.endtime = et.endtime;
ek.renew_till = et.renew_till;
ek.srealm = et.crealm;
krb5_principal2principalname(&ek.sname, sname->principal);
{
unsigned char buf[1024];
err = encode_EncTicketPart(buf + sizeof(buf) - 1, sizeof(buf), &et);
rep.ticket.enc_part.etype = ETYPE_DES_CBC_CRC;
rep.ticket.enc_part.kvno = NULL;
err = krb5_encrypt(context, buf + sizeof(buf) - err, err,
&sname->keyblock,
&rep.ticket.enc_part.cipher);
err = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), &ek);
rep.enc_part.etype = ETYPE_DES_CBC_CRC;
rep.enc_part.kvno = NULL;
err = krb5_encrypt(context, buf + sizeof(buf) - err, err,
&cname->keyblock,
&rep.enc_part.cipher);
*len = encode_AS_REP(reply + 1023, 1024, &rep);
memmove(reply, reply + 1024 - *len, *len);
}
return 0;
}
int
kerberos(krb5_context context, unsigned char *buf, size_t len)
{
KDC_REQ req;
int i;
i = decode_AS_REQ(buf, len, &req);
if(i >= 0){
foo(context, &req, buf, &len);
return len;
}
i = decode_TGS_REQ(buf, len, &req);
if(i >= 0){
foo(context, &req, buf, &len);
return len;
}
return -1;
}
main(int argc, char **argv)
{
krb5_context context;
int s = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sin;
int one = 1;
if(s < 0){
perror("socket");
exit(1);
}
krb5_init_context(&context);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(88);
if(bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0){
perror("bind");
exit(1);
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
while(1){
fd_set fds;
unsigned char buf[1024];
size_t len;
FD_ZERO(&fds);
FD_SET(s, &fds);
if(select(s + 1, &fds, NULL, NULL, NULL) < 0){
perror("select");
exit(1);
}
if(FD_ISSET(s, &fds)){
struct sockaddr_in from;
int from_len = sizeof(from);
len = recvfrom(s, buf, sizeof(buf), 0,
(struct sockaddr*)&from, &from_len);
len = kerberos(context, buf, len);
sendto(s, buf, len, 0,
(struct sockaddr*)&from, from_len);
}
}
}

17
kdc/kdc.h Normal file
View File

@@ -0,0 +1,17 @@
/*
* $Id$
*/
#ifndef __KDC_H__
#define __KDC_H__
struct db_entry{
krb5_principal principal;
krb5_keyblock keyblock;
int kvno;
time_t max_life;
time_t max_renew;
};
#endif /* __KDC_H__ */

31
kdc/kdc_locl.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* $Id$
*/
#ifndef __KDC_LOCL_H__
#define __KDC_LOCL_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <db.h>
#include <krb5.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "kdc.h"
struct entry{
char *principal;
char *key;
char *kvno;
char *max_life;
char *max_renew;
};
#endif /* __KDC_LOCL_H__ */

214
kdc/kerberos5.c Normal file
View File

@@ -0,0 +1,214 @@
#include "kdc_locl.h"
RCSID("$Id$");
struct db_entry*
db_fetch(krb5_context context, krb5_principal princ)
{
DB *db;
DBT key, value;
krb5_storage *sp;
struct db_entry *ent;
int i;
int32_t tmp;
key.size = princ->realm.length;
for(i = 0; i < princ->ncomp; i++)
key.size += princ->comp[i].length;
key.size += (princ->ncomp + 3) * 4;
key.data = malloc(key.size);
sp = krb5_storage_from_mem(key.data, key.size);
tmp = princ->type;
princ->type = 0;
krb5_store_principal(sp, princ);
princ->type = tmp;
krb5_storage_free(sp);
db = dbopen("foo.db", O_RDONLY, 0, DB_BTREE, NULL);
if(db->get(db, &key, &value, 0)){
db->close(db);
return NULL;
}
sp = krb5_storage_from_mem(value.data, value.size);
ent = malloc(sizeof(struct db_entry));
krb5_copy_principal(context, princ, &ent->principal);
krb5_ret_keyblock(sp, &ent->keyblock);
krb5_ret_int32(sp, &tmp);
ent->kvno = tmp;
krb5_ret_int32(sp, &tmp);
ent->max_life = tmp;
krb5_ret_int32(sp, &tmp);
ent->max_renew = tmp;
krb5_storage_free(sp);
db->close(db);
return ent;
}
krb5_error_code
krb5_encrypt (krb5_context context,
void *ptr,
size_t len,
krb5_keyblock *keyblock,
krb5_data *result);
krb5_error_code
foo(krb5_context context, KDC_REQ *req, unsigned char *reply, size_t *len)
{
krb5_error_code err;
krb5_principal princ;
unsigned char key_buf[1024];
unsigned char *q;
DB *db;
DBT key, value;
struct timeval now;
KDC_REP rep;
EncTicketPart et;
EncKDCRepPart ek;
struct db_entry *cname, *sname;
err = principalname2krb5_principal (&princ,
*req->req_body.cname,
req->req_body.realm);
if(err) return err;
cname = db_fetch(context, princ);
krb5_free_principal(princ);
err = principalname2krb5_principal (&princ,
*req->req_body.sname,
req->req_body.realm);
if(err) return err;
sname = db_fetch(context, princ);
krb5_free_principal(princ);
memset(&rep, 0, sizeof(rep));
rep.pvno = 5;
rep.msg_type = krb_as_rep;
rep.crealm = req->req_body.realm;
krb5_principal2principalname(&rep.cname, cname->principal);
memset(&rep.ticket, 0, sizeof(rep.ticket));
rep.ticket.tkt_vno = 5;
rep.ticket.realm = req->req_body.realm;
krb5_principal2principalname(&rep.ticket.sname, sname->principal);
memset(&et, 0, sizeof(et));
et.flags.initial = 1;
et.key.keytype = sname->keyblock.keytype;
et.key.keyvalue.data = sname->keyblock.contents.data;
et.key.keyvalue.length = sname->keyblock.contents.length;
et.crealm = req->req_body.realm;
krb5_principal2principalname(&et.cname, cname->principal);
gettimeofday(&now, NULL);
et.authtime = now.tv_sec;
{
time_t till;
till = req->req_body.till;
till = MIN(till, now.tv_sec + sname->max_life);
till = MIN(till, now.tv_sec + cname->max_life);
et.endtime = till;
}
memset(&ek, 0, sizeof(ek));
ek.key = et.key;
ek.last_req.len = 1;
ek.last_req.val = malloc(sizeof(*ek.last_req.val));
ek.last_req.val->lr_type = 1;
ek.last_req.val->lr_value = 0;
ek.nonce = req->req_body.nonce;
ek.flags = et.flags;
ek.authtime = et.authtime;
ek.starttime = et.starttime;
ek.endtime = et.endtime;
ek.renew_till = et.renew_till;
ek.srealm = et.crealm;
krb5_principal2principalname(&ek.sname, sname->principal);
{
unsigned char buf[1024];
err = encode_EncTicketPart(buf + sizeof(buf) - 1, sizeof(buf), &et);
rep.ticket.enc_part.etype = ETYPE_DES_CBC_CRC;
rep.ticket.enc_part.kvno = NULL;
err = krb5_encrypt(context, buf + sizeof(buf) - err, err,
&sname->keyblock,
&rep.ticket.enc_part.cipher);
err = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), &ek);
rep.enc_part.etype = ETYPE_DES_CBC_CRC;
rep.enc_part.kvno = NULL;
err = krb5_encrypt(context, buf + sizeof(buf) - err, err,
&cname->keyblock,
&rep.enc_part.cipher);
*len = encode_AS_REP(reply + 1023, 1024, &rep);
memmove(reply, reply + 1024 - *len, *len);
}
return 0;
}
int
kerberos(krb5_context context, unsigned char *buf, size_t len)
{
KDC_REQ req;
int i;
i = decode_AS_REQ(buf, len, &req);
if(i >= 0){
foo(context, &req, buf, &len);
return len;
}
i = decode_TGS_REQ(buf, len, &req);
if(i >= 0){
foo(context, &req, buf, &len);
return len;
}
return -1;
}
main(int argc, char **argv)
{
krb5_context context;
int s = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sin;
int one = 1;
if(s < 0){
perror("socket");
exit(1);
}
krb5_init_context(&context);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(88);
if(bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0){
perror("bind");
exit(1);
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
while(1){
fd_set fds;
unsigned char buf[1024];
size_t len;
FD_ZERO(&fds);
FD_SET(s, &fds);
if(select(s + 1, &fds, NULL, NULL, NULL) < 0){
perror("select");
exit(1);
}
if(FD_ISSET(s, &fds)){
struct sockaddr_in from;
int from_len = sizeof(from);
len = recvfrom(s, buf, sizeof(buf), 0,
(struct sockaddr*)&from, &from_len);
len = kerberos(context, buf, len);
sendto(s, buf, len, 0,
(struct sockaddr*)&from, from_len);
}
}
}

99
kdc/load.c Normal file
View File

@@ -0,0 +1,99 @@
#include "kdc_locl.h"
RCSID("$Id$");
int main(int argc, char **argv)
{
FILE *f;
DB *db;
krb5_context context;
char s[1024];
char *p;
int line;
unsigned char key_buf[1024];
unsigned char *q;
unsigned char value_buf[1024];
krb5_keyblock keyblock;
DBT key, value;
int err;
int i;
krb5_storage *sp;
struct entry e;
krb5_principal princ;
krb5_init_context(&context);
f = fopen(argv[1], "r");
db = dbopen(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0600, DB_BTREE, NULL);
line = 0;
while(fgets(s, sizeof(s), f)){
line++;
e.principal = s;
for(p = s; *p; p++){
if(*p == '\\')
p++;
else if(isspace(*p)) {
*p == 0;
break;
}
}
*p++ = 0;
while(*p && isspace(*p)) p++;
e.key = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
while(*p && isspace(*p)) p++;
e.kvno = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
while(*p && isspace(*p)) p++;
e.max_life = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
e.max_renew = p;
while(*p && !isspace(*p))
*p++;
*p++ = 0;
err = krb5_parse_name(context, e.principal, &princ);
if(err){
fprintf(stderr, "%s:%s:%s (%s)\n",
argv[1],
line,
krb5_get_err_text(context, err),
e.principal);
continue;
}
sp = krb5_storage_from_mem(key_buf, sizeof(key_buf));
princ->type = 0;
krb5_store_principal(sp, princ);
key.data = key_buf;
key.size = sp->seek(sp, 0, SEEK_CUR);
krb5_storage_free(sp);
keyblock.keytype = KEYTYPE_DES;
keyblock.contents.data = malloc(strlen(e.key)/2+1);
for(i = 0; i < strlen(e.key); i += 2){
sscanf(e.key + i, "%2x",
(unsigned char *)keyblock.contents.data + (i/2));
}
keyblock.contents.length = i / 2;
sp = krb5_storage_from_mem(value_buf, sizeof(value_buf));
krb5_store_keyblock(sp, keyblock);
krb5_store_int32(sp, atoi(e.kvno));
krb5_store_int32(sp, atoi(e.max_life));
krb5_store_int32(sp, atoi(e.max_renew));
value.data = value_buf;
value.size = sp->seek(sp, 0, SEEK_CUR);
db->put(db, &key, &value, 0);
krb5_storage_free(sp);
}
db->close(db);
}

20
kdc/string2key.c Normal file
View File

@@ -0,0 +1,20 @@
#include "kdc_locl.h"
RCSID("$Id$");
int main(int argc, char **argv)
{
krb5_context context;
krb5_principal princ;
krb5_data salt;
krb5_keyblock key;
int i;
krb5_init_context(&context);
krb5_parse_name(context, argv[1], &princ);
salt.length = salt.data = 0;
krb5_get_salt(princ, &salt);
krb5_string_to_key(argv[2], &salt, &key);
for(i = 0; i < key.contents.length; i++)
printf("%02x", ((unsigned char*)key.contents.data)[i]);
printf("\n");
}