Verify LOGON_NAME.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@18987 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
196
lib/krb5/pac.c
196
lib/krb5/pac.c
@@ -40,7 +40,7 @@ struct PAC_INFO_BUFFER {
|
|||||||
uint32_t buffersize;
|
uint32_t buffersize;
|
||||||
uint32_t offset_hi;
|
uint32_t offset_hi;
|
||||||
uint32_t offset_lo;
|
uint32_t offset_lo;
|
||||||
} PAC_INFO_BUFFER;
|
};
|
||||||
|
|
||||||
struct PACTYPE {
|
struct PACTYPE {
|
||||||
uint32_t numbuffers;
|
uint32_t numbuffers;
|
||||||
@@ -106,7 +106,8 @@ _krb5_pac_parse(krb5_context context, const void *ptr, size_t len,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->pac = calloc(1, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1)));
|
p->pac = calloc(1,
|
||||||
|
sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1)));
|
||||||
if (p->pac == NULL) {
|
if (p->pac == NULL) {
|
||||||
ret = ENOMEM;
|
ret = ENOMEM;
|
||||||
krb5_set_error_string(context, "out of memory");
|
krb5_set_error_string(context, "out of memory");
|
||||||
@@ -277,60 +278,92 @@ out:
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
krb5_error_code
|
#define NTTIME_EPOCH 0x019DB1DED53E8000LL
|
||||||
_krb5_pac_verify(krb5_context context,
|
|
||||||
struct krb5_pac *pac,
|
static uint64_t
|
||||||
|
unix2nttime(time_t unix_time)
|
||||||
|
{
|
||||||
|
long long wt;
|
||||||
|
wt = unix_time * (uint64_t)10000000 + (uint64_t)NTTIME_EPOCH;
|
||||||
|
return wt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static krb5_error_code
|
||||||
|
verify_logonname(krb5_context context,
|
||||||
|
const struct PAC_INFO_BUFFER *logon_name,
|
||||||
|
krb5_data *data,
|
||||||
time_t authtime,
|
time_t authtime,
|
||||||
krb5_principal principal,
|
krb5_principal principal)
|
||||||
krb5_keyblock *server,
|
|
||||||
krb5_keyblock *privsvr)
|
|
||||||
{
|
{
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
|
krb5_principal p2;
|
||||||
|
uint32_t time1, time2;
|
||||||
|
krb5_storage *sp;
|
||||||
|
uint16_t len;
|
||||||
|
char *s;
|
||||||
|
|
||||||
if (pac->server_checksum == NULL)
|
sp = krb5_storage_from_mem((char *)data->data + logon_name->offset_lo,
|
||||||
return EINVAL;
|
logon_name->buffersize);
|
||||||
if (pac->privsvr_checksum == NULL)
|
if (sp == NULL) {
|
||||||
return EINVAL;
|
krb5_set_error_string(context, "Out of memory");
|
||||||
if (pac->logon_name == NULL)
|
return ENOMEM;
|
||||||
return EINVAL;
|
}
|
||||||
|
|
||||||
if (authtime && principal) {
|
krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
|
||||||
uint32_t time1, time2;
|
|
||||||
krb5_storage *sp;
|
|
||||||
uint16_t len;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
sp = krb5_storage_from_mem((char *)pac->data.data
|
VCHECK(ret, krb5_ret_uint32(sp, &time1), out);
|
||||||
+ pac->logon_name->offset_lo,
|
VCHECK(ret, krb5_ret_uint32(sp, &time2), out);
|
||||||
pac->logon_name->buffersize);
|
|
||||||
if (sp == NULL)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
|
{
|
||||||
|
uint64_t t1, t2;
|
||||||
VCHECK(ret, krb5_ret_uint32(sp, &time1), out);
|
t1 = unix2nttime(authtime);
|
||||||
VCHECK(ret, krb5_ret_uint32(sp, &time2), out);
|
t2 = ((uint64_t)time2 << 32) | time1;
|
||||||
/* XXX check timestamp */
|
if (t1 != t2) {
|
||||||
/* t = time1 + (time2 << 32) * 10000000; */
|
|
||||||
/* t2 = to_windows_time(authtime, &t2); */
|
|
||||||
/* if (t != t2) { return EINVAL; } */
|
|
||||||
VCHECK(ret, krb5_ret_uint16(sp, &len), out);
|
|
||||||
if (len == 0)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
s = malloc(len);
|
|
||||||
if (s == NULL) {
|
|
||||||
krb5_storage_free(sp);
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
ret = krb5_storage_read(sp, s, len);
|
|
||||||
if (ret != len) {
|
|
||||||
krb5_storage_free(sp);
|
krb5_storage_free(sp);
|
||||||
|
krb5_set_error_string(context, "PAC timestamp mismatch");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
VCHECK(ret, krb5_ret_uint16(sp, &len), out);
|
||||||
|
if (len == 0) {
|
||||||
krb5_storage_free(sp);
|
krb5_storage_free(sp);
|
||||||
#if 0
|
krb5_set_error_string(context, "PAC logon name length missing");
|
||||||
krb5_principal p2;
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = malloc(len);
|
||||||
|
if (s == NULL) {
|
||||||
|
krb5_storage_free(sp);
|
||||||
|
krb5_set_error_string(context, "Out of memory");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
ret = krb5_storage_read(sp, s, len);
|
||||||
|
if (ret != len) {
|
||||||
|
krb5_storage_free(sp);
|
||||||
|
krb5_set_error_string(context, "Failed to read pac logon name");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
krb5_storage_free(sp);
|
||||||
|
#if 1 /* cheat for know */
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (len & 1) {
|
||||||
|
krb5_set_error_string(context, "PAC logon name mailformed");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len / 2; i++) {
|
||||||
|
if (s[(i * 2) + 1]) {
|
||||||
|
krb5_set_error_string(context, "PAC logon name not ASCII");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
s[i] = s[i * 2];
|
||||||
|
}
|
||||||
|
s[i] = '\0';
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
uint16_t *ucs2;
|
uint16_t *ucs2;
|
||||||
ssize_t ucs2len;
|
ssize_t ucs2len;
|
||||||
size_t u8len;
|
size_t u8len;
|
||||||
@@ -350,17 +383,51 @@ _krb5_pac_verify(krb5_context context,
|
|||||||
abort();
|
abort();
|
||||||
wind_ucs2toutf8(ucs2, ucs2len, s, &u8len);
|
wind_ucs2toutf8(ucs2, ucs2len, s, &u8len);
|
||||||
free(ucs2);
|
free(ucs2);
|
||||||
|
|
||||||
ret = krb5_parse_name_flags(context, s, &p2);
|
|
||||||
free(s);
|
|
||||||
|
|
||||||
if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE)
|
|
||||||
ret = EINVAL;
|
|
||||||
krb5_free_principal(context, p2);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2);
|
||||||
|
free(s);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) {
|
||||||
|
krb5_set_error_string(context, "PAC logon name mismatch");
|
||||||
|
ret = EINVAL;
|
||||||
|
}
|
||||||
|
krb5_free_principal(context, p2);
|
||||||
|
return ret;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
krb5_error_code
|
||||||
|
_krb5_pac_verify(krb5_context context,
|
||||||
|
struct krb5_pac *pac,
|
||||||
|
time_t authtime,
|
||||||
|
krb5_principal principal,
|
||||||
|
krb5_keyblock *server,
|
||||||
|
krb5_keyblock *privsvr)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
|
||||||
|
if (pac->server_checksum == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
if (pac->privsvr_checksum == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
if (pac->logon_name == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
ret = verify_logonname(context,
|
||||||
|
pac->logon_name,
|
||||||
|
&pac->data,
|
||||||
|
authtime,
|
||||||
|
principal);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in the service case, clean out data option of the privsvr and
|
* in the service case, clean out data option of the privsvr and
|
||||||
@@ -409,19 +476,6 @@ _krb5_pac_verify(krb5_context context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
krb5_error_code
|
|
||||||
_krb5_pac_make(krb5_context context, struct krb5_pac *pac, krb5_data *data)
|
|
||||||
{
|
|
||||||
return EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -443,7 +497,7 @@ _krb5_pac_sign(krb5_context context,
|
|||||||
num++;
|
num++;
|
||||||
if (pac->privsvr_checksum == NULL)
|
if (pac->privsvr_checksum == NULL)
|
||||||
num++;
|
num++;
|
||||||
if (pac->privsvr_checksum == NULL)
|
if (pac->logon_name == NULL)
|
||||||
num++;
|
num++;
|
||||||
if (num) {
|
if (num) {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
@@ -461,6 +515,10 @@ _krb5_pac_sign(krb5_context context,
|
|||||||
pac->privsvr_checksum = &pac->pac->buffers[pac->pac->numbuffers++];
|
pac->privsvr_checksum = &pac->pac->buffers[pac->pac->numbuffers++];
|
||||||
memset(pac->privsvr_checksum, 0, sizeof(*pac->privsvr_checksum));
|
memset(pac->privsvr_checksum, 0, sizeof(*pac->privsvr_checksum));
|
||||||
}
|
}
|
||||||
|
if (pac->logon_name == NULL) {
|
||||||
|
pac->logon_name = &pac->pac->buffers[pac->pac->numbuffers++];
|
||||||
|
memset(pac->logon_name, 0, sizeof(*pac->logon_name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user