#include "k5-int.h"
#include <stdio.h>
#include <sys/types.h>
#ifdef _WIN32
#include "port-sockets.h"
#else
#include <sys/time.h>
#include <netinet/in.h>
#endif
#include <krb.h>
#include "krb524d.h"
static int krb524d_debug = 0;
static int
krb524_convert_princs(context, client, server, pname, pinst, prealm,
sname, sinst, srealm)
krb5_context context;
krb5_principal client, server;
char *pname, *pinst, *prealm, *sname, *sinst, *srealm;
{
int ret;
if ((ret = krb5_524_conv_principal(context, client, pname, pinst,
prealm)))
return ret;
return krb5_524_conv_principal(context, server, sname, sinst, srealm);
}
int krb524_convert_tkt_skey(context, v5tkt, v4tkt, v5_skey, v4_skey,
saddr)
krb5_context context;
krb5_ticket *v5tkt;
KTEXT_ST *v4tkt;
krb5_keyblock *v5_skey, *v4_skey;
struct sockaddr_in *saddr;
{
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
char sname[ANAME_SZ], sinst[INST_SZ], srealm[REALM_SZ];
krb5_enc_tkt_part *v5etkt;
int ret, lifetime, v4endtime;
krb5_timestamp server_time;
struct sockaddr_in *sinp = (struct sockaddr_in *)saddr;
krb5_address kaddr;
v5tkt->enc_part2 = NULL;
if ((ret = krb5_decrypt_tkt_part(context, v5_skey, v5tkt))) {
return ret;
}
v5etkt = v5tkt->enc_part2;
if (v5etkt->transited.tr_contents.length != 0) {
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
if ((ret = krb524_convert_princs(context, v5etkt->client, v5tkt->server,
pname, pinst, prealm, sname,
sinst, srealm))) {
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
return ret;
}
if ((v5etkt->session->enctype != ENCTYPE_DES_CBC_CRC &&
v5etkt->session->enctype != ENCTYPE_DES_CBC_MD4 &&
v5etkt->session->enctype != ENCTYPE_DES_CBC_MD5) ||
v5etkt->session->length != sizeof(C_Block)) {
if (krb524d_debug)
fprintf(stderr, "v5 session keyblock type %d length %d != C_Block size %d\n",
v5etkt->session->enctype,
v5etkt->session->length,
(int) sizeof(C_Block));
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
return KRB524_BADKEY;
}
if (v5etkt->times.starttime == 0)
v5etkt->times.starttime = v5etkt->times.authtime;
if ((ret = krb5_timeofday(context, &server_time))) {
if (krb524d_debug)
fprintf(stderr, "krb5_timeofday failed!\n");
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
return ret;
}
if ((server_time + context->clockskew >= v5etkt->times.starttime)
&& (server_time - context->clockskew <= v5etkt->times.endtime)) {
lifetime = krb_time_to_life(server_time, v5etkt->times.endtime);
v4endtime = krb_life_to_time(server_time, lifetime);
if (v4endtime > v5etkt->times.endtime)
server_time -= v4endtime - v5etkt->times.endtime;
} else {
if (krb524d_debug)
fprintf(stderr, "v5 ticket time out of bounds\n");
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
if (server_time+context->clockskew < v5etkt->times.starttime)
return KRB5KRB_AP_ERR_TKT_NYV;
else if (server_time-context->clockskew > v5etkt->times.endtime)
return KRB5KRB_AP_ERR_TKT_EXPIRED;
else
return KRB5KRB_AP_ERR_TKT_NYV;
}
kaddr.addrtype = ADDRTYPE_INET;
kaddr.length = sizeof(sinp->sin_addr);
kaddr.contents = (krb5_octet *)&sinp->sin_addr;
if (!krb5_address_search(context, &kaddr, v5etkt->caddrs)) {
if (krb524d_debug)
fprintf(stderr, "Invalid v5creds address information.\n");
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
return KRB524_BADADDR;
}
if (krb524d_debug)
printf("startime = %ld, authtime = %ld, lifetime = %ld\n",
(long) v5etkt->times.starttime,
(long) v5etkt->times.authtime,
(long) lifetime);
if (v4_skey->enctype == ENCTYPE_DES_CBC_CRC) {
ret = krb_create_ticket(v4tkt,
0,
pname,
pinst,
prealm,
sinp->sin_addr.s_addr,
(char *) v5etkt->session->contents,
lifetime,
server_time,
sname,
sinst,
v4_skey->contents);
}
else abort();
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
if (ret == KSUCCESS)
return 0;
else
return KRB524_V4ERR;
}