Merge pull request #138 from abartlet/lorikeet-heimdal-for-upstream
Samba Cross-realm support patches from metze These patches were posted to heimdal-discuss by metze, and there were no objections there.
This commit is contained in:
1067
doc/standardisation/rfc6806.txt
Normal file
1067
doc/standardisation/rfc6806.txt
Normal file
File diff suppressed because it is too large
Load Diff
44
kdc/fast.c
44
kdc/fast.c
@@ -244,8 +244,9 @@ _kdc_fast_mk_error(krb5_context context,
|
|||||||
const KDC_REQ_BODY *req_body,
|
const KDC_REQ_BODY *req_body,
|
||||||
krb5_error_code outer_error,
|
krb5_error_code outer_error,
|
||||||
const char *e_text,
|
const char *e_text,
|
||||||
krb5_principal error_client,
|
|
||||||
krb5_principal error_server,
|
krb5_principal error_server,
|
||||||
|
const PrincipalName *error_client_name,
|
||||||
|
const Realm *error_client_realm,
|
||||||
time_t *csec, int *cusec,
|
time_t *csec, int *cusec,
|
||||||
krb5_data *error_msg)
|
krb5_data *error_msg)
|
||||||
{
|
{
|
||||||
@@ -264,15 +265,16 @@ _kdc_fast_mk_error(krb5_context context,
|
|||||||
|
|
||||||
/* first add the KRB-ERROR to the fast errors */
|
/* first add the KRB-ERROR to the fast errors */
|
||||||
|
|
||||||
ret = krb5_mk_error(context,
|
ret = krb5_mk_error_ext(context,
|
||||||
outer_error,
|
outer_error,
|
||||||
e_text,
|
e_text,
|
||||||
NULL,
|
NULL,
|
||||||
error_client,
|
error_server,
|
||||||
error_server,
|
error_client_name,
|
||||||
NULL,
|
error_client_realm,
|
||||||
NULL,
|
NULL,
|
||||||
&e_data);
|
NULL,
|
||||||
|
&e_data);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -285,7 +287,8 @@ _kdc_fast_mk_error(krb5_context context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (/* hide_principal */ 0) {
|
if (/* hide_principal */ 0) {
|
||||||
error_client = NULL;
|
error_client_name = NULL;
|
||||||
|
error_client_realm = NULL;
|
||||||
error_server = NULL;
|
error_server = NULL;
|
||||||
e_text = NULL;
|
e_text = NULL;
|
||||||
}
|
}
|
||||||
@@ -325,15 +328,16 @@ _kdc_fast_mk_error(krb5_context context,
|
|||||||
krb5_abortx(context, "internal asn.1 error");
|
krb5_abortx(context, "internal asn.1 error");
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = krb5_mk_error(context,
|
ret = krb5_mk_error_ext(context,
|
||||||
outer_error,
|
outer_error,
|
||||||
e_text,
|
e_text,
|
||||||
(e_data.length ? &e_data : NULL),
|
(e_data.length ? &e_data : NULL),
|
||||||
error_client,
|
error_server,
|
||||||
error_server,
|
error_client_name,
|
||||||
csec,
|
error_client_realm,
|
||||||
cusec,
|
csec,
|
||||||
error_msg);
|
cusec,
|
||||||
|
error_msg);
|
||||||
krb5_data_free(&e_data);
|
krb5_data_free(&e_data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -1712,6 +1712,31 @@ _kdc_as_rep(kdc_request_t r,
|
|||||||
kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
|
kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
|
||||||
r->client_name);
|
r->client_name);
|
||||||
goto out;
|
goto out;
|
||||||
|
} else if (ret == HDB_ERR_WRONG_REALM) {
|
||||||
|
char *fixed_client_name = NULL;
|
||||||
|
|
||||||
|
ret = krb5_unparse_name(context, r->client->entry.principal,
|
||||||
|
&fixed_client_name);
|
||||||
|
if (ret) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
|
||||||
|
r->client_name, fixed_client_name);
|
||||||
|
free(fixed_client_name);
|
||||||
|
|
||||||
|
ret = _kdc_fast_mk_error(context, r,
|
||||||
|
&error_method,
|
||||||
|
r->armor_crypto,
|
||||||
|
&req->req_body,
|
||||||
|
KRB5_KDC_ERR_WRONG_REALM,
|
||||||
|
NULL,
|
||||||
|
r->server_princ,
|
||||||
|
NULL,
|
||||||
|
&r->client->entry.principal->realm,
|
||||||
|
NULL, NULL,
|
||||||
|
reply);
|
||||||
|
goto out;
|
||||||
} else if(ret){
|
} else if(ret){
|
||||||
const char *msg = krb5_get_error_message(context, ret);
|
const char *msg = krb5_get_error_message(context, ret);
|
||||||
kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
|
kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
|
||||||
@@ -2193,13 +2218,15 @@ out:
|
|||||||
/*
|
/*
|
||||||
* In case of a non proxy error, build an error message.
|
* In case of a non proxy error, build an error message.
|
||||||
*/
|
*/
|
||||||
if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE) {
|
if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
|
||||||
ret = _kdc_fast_mk_error(context, r,
|
ret = _kdc_fast_mk_error(context, r,
|
||||||
&error_method,
|
&error_method,
|
||||||
r->armor_crypto,
|
r->armor_crypto,
|
||||||
&req->req_body,
|
&req->req_body,
|
||||||
ret, r->e_text,
|
ret, r->e_text,
|
||||||
r->client_princ, r->server_princ,
|
r->server_princ,
|
||||||
|
&r->client_princ->name,
|
||||||
|
&r->client_princ->realm,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
reply);
|
reply);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@@ -1121,15 +1121,14 @@ need_referral(krb5_context context, krb5_kdc_configuration *config,
|
|||||||
|
|
||||||
if (server->name.name_string.len == 1)
|
if (server->name.name_string.len == 1)
|
||||||
name = server->name.name_string.val[0];
|
name = server->name.name_string.val[0];
|
||||||
else if (server->name.name_string.len == 3 &&
|
else if (server->name.name_string.len == 3) {
|
||||||
strcasecmp("E3514235-4B06-11D1-AB04-00C04FC2DCD2", server->name.name_string.val[0]) == 0) {
|
|
||||||
/*
|
/*
|
||||||
This is used to give referrals for the
|
This is used to give referrals for the
|
||||||
E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN
|
E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN
|
||||||
SPN form, which is used for inter-domain communication in AD
|
SPN form, which is used for inter-domain communication in AD
|
||||||
*/
|
*/
|
||||||
name = server->name.name_string.val[2];
|
name = server->name.name_string.val[2];
|
||||||
kdc_log(context, config, 0, "Giving 3 part DRSUAPI referral for %s", name);
|
kdc_log(context, config, 0, "Giving 3 part referral for %s", name);
|
||||||
*realms = malloc(sizeof(char *)*2);
|
*realms = malloc(sizeof(char *)*2);
|
||||||
if (*realms == NULL) {
|
if (*realms == NULL) {
|
||||||
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
|
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
|
||||||
@@ -1648,6 +1647,32 @@ server_lookup:
|
|||||||
if(ret == HDB_ERR_NOT_FOUND_HERE) {
|
if(ret == HDB_ERR_NOT_FOUND_HERE) {
|
||||||
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
|
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
|
||||||
goto out;
|
goto out;
|
||||||
|
} else if (ret == HDB_ERR_WRONG_REALM) {
|
||||||
|
if (ref_realm)
|
||||||
|
free(ref_realm);
|
||||||
|
ref_realm = strdup(server->entry.principal->realm);
|
||||||
|
if (ref_realm == NULL) {
|
||||||
|
ret = ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
kdc_log(context, config, 5,
|
||||||
|
"Returning a referral to realm %s for "
|
||||||
|
"server %s.",
|
||||||
|
ref_realm, spn);
|
||||||
|
krb5_free_principal(context, sp);
|
||||||
|
sp = NULL;
|
||||||
|
free(spn);
|
||||||
|
spn = NULL;
|
||||||
|
ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
|
||||||
|
ref_realm, NULL);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
ret = krb5_unparse_name(context, sp, &spn);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
goto server_lookup;
|
||||||
} else if(ret){
|
} else if(ret){
|
||||||
const char *new_rlm, *msg;
|
const char *new_rlm, *msg;
|
||||||
Realm req_rlm;
|
Realm req_rlm;
|
||||||
@@ -2457,6 +2482,7 @@ out:
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
ret, NULL,
|
ret, NULL,
|
||||||
|
NULL,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
csec, cusec,
|
csec, cusec,
|
||||||
data);
|
data);
|
||||||
|
@@ -101,6 +101,13 @@ _kdc_db_fetch(krb5_context context,
|
|||||||
config->db[i]->hdb_close(context, config->db[i]);
|
config->db[i]->hdb_close(context, config->db[i]);
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
|
case HDB_ERR_WRONG_REALM:
|
||||||
|
/*
|
||||||
|
* the ent->entry.principal just contains hints for the client
|
||||||
|
* to retry. This is important for enterprise principal routing
|
||||||
|
* between trusts.
|
||||||
|
*/
|
||||||
|
/* fall through */
|
||||||
case 0:
|
case 0:
|
||||||
if (db)
|
if (db)
|
||||||
*db = config->db[i];
|
*db = config->db[i];
|
||||||
|
@@ -44,17 +44,43 @@ _gk_wrap_iov(OM_uint32 * minor_status,
|
|||||||
gss_iov_buffer_desc *iov,
|
gss_iov_buffer_desc *iov,
|
||||||
int iov_count)
|
int iov_count)
|
||||||
{
|
{
|
||||||
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
|
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
|
||||||
krb5_context context;
|
krb5_context context;
|
||||||
|
OM_uint32 ret;
|
||||||
|
krb5_keyblock *key;
|
||||||
|
krb5_keytype keytype;
|
||||||
|
|
||||||
GSSAPI_KRB5_INIT (&context);
|
GSSAPI_KRB5_INIT (&context);
|
||||||
|
|
||||||
if (ctx->more_flags & IS_CFX)
|
if (ctx->more_flags & IS_CFX)
|
||||||
return _gssapi_wrap_cfx_iov(minor_status, ctx, context,
|
return _gssapi_wrap_cfx_iov(minor_status, ctx, context,
|
||||||
conf_req_flag, conf_state,
|
conf_req_flag, conf_state,
|
||||||
iov, iov_count);
|
iov, iov_count);
|
||||||
|
|
||||||
return GSS_S_FAILURE;
|
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
|
||||||
|
ret = _gsskrb5i_get_token_key(ctx, context, &key);
|
||||||
|
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||||
|
if (ret) {
|
||||||
|
*minor_status = ret;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
krb5_enctype_to_keytype(context, key->keytype, &keytype);
|
||||||
|
|
||||||
|
switch (keytype) {
|
||||||
|
case KEYTYPE_ARCFOUR:
|
||||||
|
case KEYTYPE_ARCFOUR_56:
|
||||||
|
ret = _gssapi_wrap_iov_arcfour(minor_status, ctx, context,
|
||||||
|
conf_req_flag, conf_state,
|
||||||
|
iov, iov_count, key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = GSS_S_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_free_keyblock(context, key);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
OM_uint32 GSSAPI_CALLCONV
|
OM_uint32 GSSAPI_CALLCONV
|
||||||
@@ -67,6 +93,9 @@ _gk_unwrap_iov(OM_uint32 *minor_status,
|
|||||||
{
|
{
|
||||||
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
|
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
|
||||||
krb5_context context;
|
krb5_context context;
|
||||||
|
OM_uint32 ret;
|
||||||
|
krb5_keytype keytype;
|
||||||
|
krb5_keyblock *key;
|
||||||
|
|
||||||
GSSAPI_KRB5_INIT (&context);
|
GSSAPI_KRB5_INIT (&context);
|
||||||
|
|
||||||
@@ -74,7 +103,30 @@ _gk_unwrap_iov(OM_uint32 *minor_status,
|
|||||||
return _gssapi_unwrap_cfx_iov(minor_status, ctx, context,
|
return _gssapi_unwrap_cfx_iov(minor_status, ctx, context,
|
||||||
conf_state, qop_state, iov, iov_count);
|
conf_state, qop_state, iov, iov_count);
|
||||||
|
|
||||||
return GSS_S_FAILURE;
|
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
|
||||||
|
ret = _gsskrb5i_get_token_key(ctx, context, &key);
|
||||||
|
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||||
|
if (ret) {
|
||||||
|
*minor_status = ret;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
krb5_enctype_to_keytype(context, key->keytype, &keytype);
|
||||||
|
|
||||||
|
switch (keytype) {
|
||||||
|
case KEYTYPE_ARCFOUR:
|
||||||
|
case KEYTYPE_ARCFOUR_56:
|
||||||
|
ret = _gssapi_unwrap_iov_arcfour(minor_status, ctx, context,
|
||||||
|
conf_state, qop_state,
|
||||||
|
iov, iov_count, key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = GSS_S_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_free_keyblock(context, key);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
OM_uint32 GSSAPI_CALLCONV
|
OM_uint32 GSSAPI_CALLCONV
|
||||||
@@ -88,6 +140,9 @@ _gk_wrap_iov_length(OM_uint32 * minor_status,
|
|||||||
{
|
{
|
||||||
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
|
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
|
||||||
krb5_context context;
|
krb5_context context;
|
||||||
|
OM_uint32 ret;
|
||||||
|
krb5_keytype keytype;
|
||||||
|
krb5_keyblock *key;
|
||||||
|
|
||||||
GSSAPI_KRB5_INIT (&context);
|
GSSAPI_KRB5_INIT (&context);
|
||||||
|
|
||||||
@@ -96,5 +151,28 @@ _gk_wrap_iov_length(OM_uint32 * minor_status,
|
|||||||
conf_req_flag, qop_req, conf_state,
|
conf_req_flag, qop_req, conf_state,
|
||||||
iov, iov_count);
|
iov, iov_count);
|
||||||
|
|
||||||
return GSS_S_FAILURE;
|
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
|
||||||
|
ret = _gsskrb5i_get_token_key(ctx, context, &key);
|
||||||
|
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||||
|
if (ret) {
|
||||||
|
*minor_status = ret;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
krb5_enctype_to_keytype(context, key->keytype, &keytype);
|
||||||
|
|
||||||
|
switch (keytype) {
|
||||||
|
case KEYTYPE_ARCFOUR:
|
||||||
|
case KEYTYPE_ARCFOUR_56:
|
||||||
|
ret = _gssapi_wrap_iov_length_arcfour(minor_status, ctx, context,
|
||||||
|
conf_req_flag, qop_req, conf_state,
|
||||||
|
iov, iov_count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = GSS_S_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_free_keyblock(context, key);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
arcfour_mic_key(krb5_context context, krb5_keyblock *key,
|
arcfour_mic_key(krb5_context context, krb5_keyblock *key,
|
||||||
void *cksum_data, size_t cksum_size,
|
const void *cksum_data, size_t cksum_size,
|
||||||
void *key6_data, size_t key6_size)
|
void *key6_data, size_t key6_size)
|
||||||
{
|
{
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
@@ -112,30 +112,73 @@ arcfour_mic_key(krb5_context context, krb5_keyblock *key,
|
|||||||
|
|
||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
arcfour_mic_cksum(krb5_context context,
|
arcfour_mic_cksum_iov(krb5_context context,
|
||||||
krb5_keyblock *key, unsigned usage,
|
krb5_keyblock *key, unsigned usage,
|
||||||
u_char *sgn_cksum, size_t sgn_cksum_sz,
|
u_char *sgn_cksum, size_t sgn_cksum_sz,
|
||||||
const u_char *v1, size_t l1,
|
const u_char *v1, size_t l1,
|
||||||
const void *v2, size_t l2,
|
const void *v2, size_t l2,
|
||||||
const void *v3, size_t l3)
|
const gss_iov_buffer_desc *iov,
|
||||||
|
int iov_count,
|
||||||
|
const gss_iov_buffer_desc *padding)
|
||||||
{
|
{
|
||||||
Checksum CKSUM;
|
Checksum CKSUM;
|
||||||
u_char *ptr;
|
u_char *ptr;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
size_t ofs = 0;
|
||||||
|
int i;
|
||||||
krb5_crypto crypto;
|
krb5_crypto crypto;
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
|
|
||||||
assert(sgn_cksum_sz == 8);
|
assert(sgn_cksum_sz == 8);
|
||||||
|
|
||||||
len = l1 + l2 + l3;
|
len = l1 + l2;
|
||||||
|
|
||||||
|
for (i=0; i < iov_count; i++) {
|
||||||
|
switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
|
||||||
|
case GSS_IOV_BUFFER_TYPE_DATA:
|
||||||
|
case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += iov[i].buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding) {
|
||||||
|
len += padding->buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
ptr = malloc(len);
|
ptr = malloc(len);
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
memcpy(ptr, v1, l1);
|
memcpy(ptr + ofs, v1, l1);
|
||||||
memcpy(ptr + l1, v2, l2);
|
ofs += l1;
|
||||||
memcpy(ptr + l1 + l2, v3, l3);
|
memcpy(ptr + ofs, v2, l2);
|
||||||
|
ofs += l2;
|
||||||
|
|
||||||
|
for (i=0; i < iov_count; i++) {
|
||||||
|
switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
|
||||||
|
case GSS_IOV_BUFFER_TYPE_DATA:
|
||||||
|
case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ptr + ofs,
|
||||||
|
iov[i].buffer.value,
|
||||||
|
iov[i].buffer.length);
|
||||||
|
ofs += iov[i].buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding) {
|
||||||
|
memcpy(ptr + ofs,
|
||||||
|
padding->buffer.value,
|
||||||
|
padding->buffer.length);
|
||||||
|
ofs += padding->buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
ret = krb5_crypto_init(context, key, 0, &crypto);
|
ret = krb5_crypto_init(context, key, 0, &crypto);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -149,6 +192,7 @@ arcfour_mic_cksum(krb5_context context,
|
|||||||
0,
|
0,
|
||||||
ptr, len,
|
ptr, len,
|
||||||
&CKSUM);
|
&CKSUM);
|
||||||
|
memset(ptr, 0, len);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
|
memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
|
||||||
@@ -159,6 +203,26 @@ arcfour_mic_cksum(krb5_context context,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static krb5_error_code
|
||||||
|
arcfour_mic_cksum(krb5_context context,
|
||||||
|
krb5_keyblock *key, unsigned usage,
|
||||||
|
u_char *sgn_cksum, size_t sgn_cksum_sz,
|
||||||
|
const u_char *v1, size_t l1,
|
||||||
|
const void *v2, size_t l2,
|
||||||
|
const void *v3, size_t l3)
|
||||||
|
{
|
||||||
|
gss_iov_buffer_desc iov;
|
||||||
|
|
||||||
|
iov.type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
|
||||||
|
iov.buffer.value = rk_UNCONST(v3);
|
||||||
|
iov.buffer.length = l3;
|
||||||
|
|
||||||
|
return arcfour_mic_cksum_iov(context, key, usage,
|
||||||
|
sgn_cksum, sgn_cksum_sz,
|
||||||
|
v1, l1, v2, l2,
|
||||||
|
&iov, 1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
OM_uint32
|
OM_uint32
|
||||||
_gssapi_get_mic_arcfour(OM_uint32 * minor_status,
|
_gssapi_get_mic_arcfour(OM_uint32 * minor_status,
|
||||||
@@ -760,3 +824,562 @@ _gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
|
|||||||
|
|
||||||
return GSS_S_COMPLETE;
|
return GSS_S_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OM_uint32
|
||||||
|
_gssapi_wrap_iov_length_arcfour(OM_uint32 *minor_status,
|
||||||
|
gsskrb5_ctx ctx,
|
||||||
|
krb5_context context,
|
||||||
|
int conf_req_flag,
|
||||||
|
gss_qop_t qop_req,
|
||||||
|
int *conf_state,
|
||||||
|
gss_iov_buffer_desc *iov,
|
||||||
|
int iov_count)
|
||||||
|
{
|
||||||
|
OM_uint32 major_status;
|
||||||
|
size_t data_len = 0;
|
||||||
|
int i;
|
||||||
|
gss_iov_buffer_desc *header = NULL;
|
||||||
|
gss_iov_buffer_desc *padding = NULL;
|
||||||
|
gss_iov_buffer_desc *trailer = NULL;
|
||||||
|
|
||||||
|
*minor_status = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < iov_count; i++) {
|
||||||
|
switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
|
||||||
|
case GSS_IOV_BUFFER_TYPE_EMPTY:
|
||||||
|
break;
|
||||||
|
case GSS_IOV_BUFFER_TYPE_DATA:
|
||||||
|
data_len += iov[i].buffer.length;
|
||||||
|
break;
|
||||||
|
case GSS_IOV_BUFFER_TYPE_HEADER:
|
||||||
|
if (header != NULL) {
|
||||||
|
*minor_status = EINVAL;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
header = &iov[i];
|
||||||
|
break;
|
||||||
|
case GSS_IOV_BUFFER_TYPE_TRAILER:
|
||||||
|
if (trailer != NULL) {
|
||||||
|
*minor_status = EINVAL;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
trailer = &iov[i];
|
||||||
|
break;
|
||||||
|
case GSS_IOV_BUFFER_TYPE_PADDING:
|
||||||
|
if (padding != NULL) {
|
||||||
|
*minor_status = EINVAL;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
padding = &iov[i];
|
||||||
|
break;
|
||||||
|
case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*minor_status = EINVAL;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer);
|
||||||
|
if (major_status != GSS_S_COMPLETE) {
|
||||||
|
return major_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_DCE_STYLE(ctx)) {
|
||||||
|
size_t len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
||||||
|
size_t total_len;
|
||||||
|
_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
|
||||||
|
header->buffer.length = total_len;
|
||||||
|
} else {
|
||||||
|
size_t len;
|
||||||
|
size_t total_len;
|
||||||
|
if (padding) {
|
||||||
|
data_len += 1; /* padding */
|
||||||
|
}
|
||||||
|
len = data_len + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
||||||
|
_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
|
||||||
|
header->buffer.length = total_len - data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trailer) {
|
||||||
|
trailer->buffer.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding) {
|
||||||
|
padding->buffer.length = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GSS_S_COMPLETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
OM_uint32
|
||||||
|
_gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
|
||||||
|
gsskrb5_ctx ctx,
|
||||||
|
krb5_context context,
|
||||||
|
int conf_req_flag,
|
||||||
|
int *conf_state,
|
||||||
|
gss_iov_buffer_desc *iov,
|
||||||
|
int iov_count,
|
||||||
|
krb5_keyblock *key)
|
||||||
|
{
|
||||||
|
OM_uint32 major_status, junk;
|
||||||
|
gss_iov_buffer_desc *header, *padding, *trailer;
|
||||||
|
krb5_error_code kret;
|
||||||
|
int32_t seq_number;
|
||||||
|
u_char Klocaldata[16], k6_data[16], *p, *p0;
|
||||||
|
size_t make_len = 0;
|
||||||
|
size_t header_len = 0;
|
||||||
|
size_t data_len = 0;
|
||||||
|
krb5_keyblock Klocal;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
|
||||||
|
padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
|
||||||
|
trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
|
||||||
|
|
||||||
|
major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer);
|
||||||
|
if (major_status != GSS_S_COMPLETE) {
|
||||||
|
return major_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < iov_count; i++) {
|
||||||
|
switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
|
||||||
|
case GSS_IOV_BUFFER_TYPE_DATA:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_len += iov[i].buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding) {
|
||||||
|
data_len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_DCE_STYLE(ctx)) {
|
||||||
|
size_t unwrapped_len;
|
||||||
|
unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
||||||
|
_gssapi_encap_length(unwrapped_len,
|
||||||
|
&make_len,
|
||||||
|
&header_len,
|
||||||
|
GSS_KRB5_MECHANISM);
|
||||||
|
} else {
|
||||||
|
size_t unwrapped_len;
|
||||||
|
unwrapped_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + data_len;
|
||||||
|
_gssapi_encap_length(unwrapped_len,
|
||||||
|
&make_len,
|
||||||
|
&header_len,
|
||||||
|
GSS_KRB5_MECHANISM);
|
||||||
|
header_len -= data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) {
|
||||||
|
major_status = _gk_allocate_buffer(minor_status, header,
|
||||||
|
header_len);
|
||||||
|
if (major_status != GSS_S_COMPLETE)
|
||||||
|
goto failure;
|
||||||
|
} else if (header->buffer.length < header_len) {
|
||||||
|
*minor_status = KRB5_BAD_MSIZE;
|
||||||
|
major_status = GSS_S_FAILURE;
|
||||||
|
goto failure;
|
||||||
|
} else {
|
||||||
|
header->buffer.length = header_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding) {
|
||||||
|
if (GSS_IOV_BUFFER_FLAGS(padding->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) {
|
||||||
|
major_status = _gk_allocate_buffer(minor_status, padding, 1);
|
||||||
|
if (major_status != GSS_S_COMPLETE)
|
||||||
|
goto failure;
|
||||||
|
} else if (padding->buffer.length < 1) {
|
||||||
|
*minor_status = KRB5_BAD_MSIZE;
|
||||||
|
major_status = GSS_S_FAILURE;
|
||||||
|
goto failure;
|
||||||
|
} else {
|
||||||
|
padding->buffer.length = 1;
|
||||||
|
}
|
||||||
|
memset(padding->buffer.value, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trailer) {
|
||||||
|
trailer->buffer.length = 0;
|
||||||
|
trailer->buffer.value = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p0 = _gssapi_make_mech_header(header->buffer.value,
|
||||||
|
make_len,
|
||||||
|
GSS_KRB5_MECHANISM);
|
||||||
|
p = p0;
|
||||||
|
|
||||||
|
*p++ = 0x02; /* TOK_ID */
|
||||||
|
*p++ = 0x01;
|
||||||
|
*p++ = 0x11; /* SGN_ALG */
|
||||||
|
*p++ = 0x00;
|
||||||
|
if (conf_req_flag) {
|
||||||
|
*p++ = 0x10; /* SEAL_ALG */
|
||||||
|
*p++ = 0x00;
|
||||||
|
} else {
|
||||||
|
*p++ = 0xff; /* SEAL_ALG */
|
||||||
|
*p++ = 0xff;
|
||||||
|
}
|
||||||
|
*p++ = 0xff; /* Filler */
|
||||||
|
*p++ = 0xff;
|
||||||
|
|
||||||
|
p = NULL;
|
||||||
|
|
||||||
|
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
|
||||||
|
krb5_auth_con_getlocalseqnumber(context,
|
||||||
|
ctx->auth_context,
|
||||||
|
&seq_number);
|
||||||
|
_gsskrb5_encode_be_om_uint32(seq_number, p0 + 8);
|
||||||
|
|
||||||
|
krb5_auth_con_setlocalseqnumber(context,
|
||||||
|
ctx->auth_context,
|
||||||
|
++seq_number);
|
||||||
|
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||||
|
|
||||||
|
memset(p0 + 8 + 4,
|
||||||
|
(ctx->more_flags & LOCAL) ? 0 : 0xff,
|
||||||
|
4);
|
||||||
|
|
||||||
|
krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
|
||||||
|
|
||||||
|
/* Sign Data */
|
||||||
|
kret = arcfour_mic_cksum_iov(context,
|
||||||
|
key, KRB5_KU_USAGE_SEAL,
|
||||||
|
p0 + 16, 8, /* SGN_CKSUM */
|
||||||
|
p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
|
||||||
|
p0 + 24, 8, /* Confounder */
|
||||||
|
iov, iov_count, /* Data + SignOnly */
|
||||||
|
padding); /* padding */
|
||||||
|
if (kret) {
|
||||||
|
*minor_status = kret;
|
||||||
|
major_status = GSS_S_FAILURE;
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
Klocal.keytype = key->keytype;
|
||||||
|
Klocal.keyvalue.data = Klocaldata;
|
||||||
|
Klocal.keyvalue.length = sizeof(Klocaldata);
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
|
||||||
|
}
|
||||||
|
kret = arcfour_mic_key(context, &Klocal,
|
||||||
|
p0 + 8, 4, /* SND_SEQ */
|
||||||
|
k6_data, sizeof(k6_data));
|
||||||
|
memset(Klocaldata, 0, sizeof(Klocaldata));
|
||||||
|
if (kret) {
|
||||||
|
*minor_status = kret;
|
||||||
|
major_status = GSS_S_FAILURE;
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf_req_flag) {
|
||||||
|
EVP_CIPHER_CTX rc4_key;
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_init(&rc4_key);
|
||||||
|
EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
||||||
|
|
||||||
|
/* Confounder */
|
||||||
|
EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8);
|
||||||
|
|
||||||
|
/* Seal Data */
|
||||||
|
for (i=0; i < iov_count; i++) {
|
||||||
|
switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
|
||||||
|
case GSS_IOV_BUFFER_TYPE_DATA:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_Cipher(&rc4_key, iov[i].buffer.value,
|
||||||
|
iov[i].buffer.value, iov[i].buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
if (padding) {
|
||||||
|
EVP_Cipher(&rc4_key, padding->buffer.value,
|
||||||
|
padding->buffer.value, padding->buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup(&rc4_key);
|
||||||
|
}
|
||||||
|
memset(k6_data, 0, sizeof(k6_data));
|
||||||
|
|
||||||
|
kret = arcfour_mic_key(context, key,
|
||||||
|
p0 + 16, 8, /* SGN_CKSUM */
|
||||||
|
k6_data, sizeof(k6_data));
|
||||||
|
if (kret) {
|
||||||
|
*minor_status = kret;
|
||||||
|
major_status = GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EVP_CIPHER_CTX rc4_key;
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_init(&rc4_key);
|
||||||
|
EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
||||||
|
EVP_Cipher(&rc4_key, p0 + 8, p0 + 8, 8); /* SND_SEQ */
|
||||||
|
EVP_CIPHER_CTX_cleanup(&rc4_key);
|
||||||
|
|
||||||
|
memset(k6_data, 0, sizeof(k6_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf_state)
|
||||||
|
*conf_state = conf_req_flag;
|
||||||
|
|
||||||
|
*minor_status = 0;
|
||||||
|
return GSS_S_COMPLETE;
|
||||||
|
|
||||||
|
failure:
|
||||||
|
|
||||||
|
gss_release_iov_buffer(&junk, iov, iov_count);
|
||||||
|
|
||||||
|
return major_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
OM_uint32
|
||||||
|
_gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
|
||||||
|
gsskrb5_ctx ctx,
|
||||||
|
krb5_context context,
|
||||||
|
int *pconf_state,
|
||||||
|
gss_qop_t *pqop_state,
|
||||||
|
gss_iov_buffer_desc *iov,
|
||||||
|
int iov_count,
|
||||||
|
krb5_keyblock *key)
|
||||||
|
{
|
||||||
|
OM_uint32 major_status;
|
||||||
|
gss_iov_buffer_desc *header, *padding, *trailer;
|
||||||
|
krb5_keyblock Klocal;
|
||||||
|
uint8_t Klocaldata[16];
|
||||||
|
uint8_t k6_data[16], snd_seq[8], Confounder[8];
|
||||||
|
uint8_t cksum_data[8];
|
||||||
|
uint8_t *_p = NULL;
|
||||||
|
const uint8_t *p, *p0;
|
||||||
|
size_t verify_len = 0;
|
||||||
|
uint32_t seq_number;
|
||||||
|
size_t hlen = 0;
|
||||||
|
int conf_state;
|
||||||
|
int cmp;
|
||||||
|
size_t i;
|
||||||
|
krb5_error_code kret;
|
||||||
|
OM_uint32 ret;
|
||||||
|
|
||||||
|
if (pconf_state != NULL) {
|
||||||
|
*pconf_state = 0;
|
||||||
|
}
|
||||||
|
if (pqop_state != NULL) {
|
||||||
|
*pqop_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
|
||||||
|
padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
|
||||||
|
trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
|
||||||
|
|
||||||
|
/* Check if the packet is correct */
|
||||||
|
major_status = _gk_verify_buffers(minor_status,
|
||||||
|
ctx,
|
||||||
|
header,
|
||||||
|
padding,
|
||||||
|
trailer);
|
||||||
|
if (major_status != GSS_S_COMPLETE) {
|
||||||
|
return major_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding != NULL && padding->buffer.length != 1) {
|
||||||
|
*minor_status = EINVAL;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_DCE_STYLE(context)) {
|
||||||
|
verify_len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
|
||||||
|
GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
|
||||||
|
if (header->buffer.length > verify_len) {
|
||||||
|
return GSS_S_BAD_MECH;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
verify_len = header->buffer.length;
|
||||||
|
}
|
||||||
|
_p = header->buffer.value;
|
||||||
|
|
||||||
|
ret = _gssapi_verify_mech_header(&_p,
|
||||||
|
verify_len,
|
||||||
|
GSS_KRB5_MECHANISM);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
p0 = _p;
|
||||||
|
|
||||||
|
/* length of mech header */
|
||||||
|
hlen = (p0 - (uint8_t *)header->buffer.value);
|
||||||
|
hlen += GSS_ARCFOUR_WRAP_TOKEN_SIZE;
|
||||||
|
|
||||||
|
if (hlen > header->buffer.length) {
|
||||||
|
return GSS_S_BAD_MECH;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p0;
|
||||||
|
|
||||||
|
if (memcmp(p, "\x02\x01", 2) != 0)
|
||||||
|
return GSS_S_BAD_SIG;
|
||||||
|
p += 2;
|
||||||
|
if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
|
||||||
|
return GSS_S_BAD_SIG;
|
||||||
|
p += 2;
|
||||||
|
|
||||||
|
if (memcmp (p, "\x10\x00", 2) == 0)
|
||||||
|
conf_state = 1;
|
||||||
|
else if (memcmp (p, "\xff\xff", 2) == 0)
|
||||||
|
conf_state = 0;
|
||||||
|
else
|
||||||
|
return GSS_S_BAD_SIG;
|
||||||
|
|
||||||
|
p += 2;
|
||||||
|
if (memcmp (p, "\xff\xff", 2) != 0)
|
||||||
|
return GSS_S_BAD_MIC;
|
||||||
|
p = NULL;
|
||||||
|
|
||||||
|
kret = arcfour_mic_key(context,
|
||||||
|
key,
|
||||||
|
p0 + 16, /* SGN_CKSUM */
|
||||||
|
8, /* SGN_CKSUM_LEN */
|
||||||
|
k6_data,
|
||||||
|
sizeof(k6_data));
|
||||||
|
if (kret) {
|
||||||
|
*minor_status = kret;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EVP_CIPHER_CTX rc4_key;
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_init(&rc4_key);
|
||||||
|
EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
||||||
|
EVP_Cipher(&rc4_key, snd_seq, p0 + 8, 8); /* SND_SEQ */
|
||||||
|
EVP_CIPHER_CTX_cleanup(&rc4_key);
|
||||||
|
|
||||||
|
memset(k6_data, 0, sizeof(k6_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
_gsskrb5_decode_be_om_uint32(snd_seq, &seq_number);
|
||||||
|
|
||||||
|
if (ctx->more_flags & LOCAL) {
|
||||||
|
cmp = memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4);
|
||||||
|
} else {
|
||||||
|
cmp = memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4);
|
||||||
|
}
|
||||||
|
if (cmp != 0) {
|
||||||
|
*minor_status = 0;
|
||||||
|
return GSS_S_BAD_MIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->more_flags & LOCAL) {
|
||||||
|
cmp = memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4);
|
||||||
|
} else {
|
||||||
|
cmp = memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4);
|
||||||
|
}
|
||||||
|
if (cmp != 0) {
|
||||||
|
*minor_status = 0;
|
||||||
|
return GSS_S_BAD_MIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keyblock */
|
||||||
|
Klocal.keytype = key->keytype;
|
||||||
|
Klocal.keyvalue.data = Klocaldata;
|
||||||
|
Klocal.keyvalue.length = sizeof(Klocaldata);
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
|
||||||
|
}
|
||||||
|
|
||||||
|
kret = arcfour_mic_key(context,
|
||||||
|
&Klocal,
|
||||||
|
snd_seq,
|
||||||
|
4,
|
||||||
|
k6_data, sizeof(k6_data));
|
||||||
|
memset(Klocaldata, 0, sizeof(Klocaldata));
|
||||||
|
if (kret) {
|
||||||
|
*minor_status = kret;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf_state == 1) {
|
||||||
|
EVP_CIPHER_CTX rc4_key;
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_init(&rc4_key);
|
||||||
|
EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
|
||||||
|
|
||||||
|
/* Confounder */
|
||||||
|
EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8);
|
||||||
|
|
||||||
|
/* Data */
|
||||||
|
for (i = 0; i < iov_count; i++) {
|
||||||
|
switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
|
||||||
|
case GSS_IOV_BUFFER_TYPE_DATA:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_Cipher(&rc4_key, iov[i].buffer.value,
|
||||||
|
iov[i].buffer.value, iov[i].buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
if (padding) {
|
||||||
|
EVP_Cipher(&rc4_key, padding->buffer.value,
|
||||||
|
padding->buffer.value, padding->buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup(&rc4_key);
|
||||||
|
} else {
|
||||||
|
/* Confounder */
|
||||||
|
memcpy(Confounder, p0 + 24, 8);
|
||||||
|
}
|
||||||
|
memset(k6_data, 0, sizeof(k6_data));
|
||||||
|
|
||||||
|
/* Prepare the buffer for signing */
|
||||||
|
kret = arcfour_mic_cksum_iov(context,
|
||||||
|
key, KRB5_KU_USAGE_SEAL,
|
||||||
|
cksum_data, sizeof(cksum_data),
|
||||||
|
p0, 8,
|
||||||
|
Confounder, sizeof(Confounder),
|
||||||
|
iov, iov_count,
|
||||||
|
padding);
|
||||||
|
if (kret) {
|
||||||
|
*minor_status = kret;
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
|
||||||
|
if (cmp != 0) {
|
||||||
|
*minor_status = 0;
|
||||||
|
return GSS_S_BAD_MIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding) {
|
||||||
|
size_t plen;
|
||||||
|
|
||||||
|
ret = _gssapi_verify_pad(&padding->buffer, 1, &plen);
|
||||||
|
if (ret) {
|
||||||
|
*minor_status = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
|
||||||
|
ret = _gssapi_msg_order_check(ctx->order, seq_number);
|
||||||
|
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pconf_state) {
|
||||||
|
*pconf_state = conf_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
*minor_status = 0;
|
||||||
|
return GSS_S_COMPLETE;
|
||||||
|
}
|
||||||
|
@@ -190,6 +190,9 @@ _gssapi_verify_pad(gss_buffer_t wrapped_token,
|
|||||||
size_t padlength;
|
size_t padlength;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (wrapped_token->length < 1)
|
||||||
|
return GSS_S_BAD_MECH;
|
||||||
|
|
||||||
pad = (u_char *)wrapped_token->value + wrapped_token->length - 1;
|
pad = (u_char *)wrapped_token->value + wrapped_token->length - 1;
|
||||||
padlength = *pad;
|
padlength = *pad;
|
||||||
|
|
||||||
|
@@ -28,5 +28,6 @@ error_code NO_WRITE_SUPPORT, "HDB backend doesn't contain write support"
|
|||||||
error_code NOT_FOUND_HERE, "The secret for this entry is not replicated to this database"
|
error_code NOT_FOUND_HERE, "The secret for this entry is not replicated to this database"
|
||||||
error_code MISUSE, "Incorrect use of the API"
|
error_code MISUSE, "Incorrect use of the API"
|
||||||
error_code KVNO_NOT_FOUND, "Entry key version number not found"
|
error_code KVNO_NOT_FOUND, "Entry key version number not found"
|
||||||
|
error_code WRONG_REALM, "The principal exists in another realm."
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@@ -2330,6 +2330,17 @@ krb5_init_creds_step(krb5_context context,
|
|||||||
ret = krb5_principal_set_realm(context,
|
ret = krb5_principal_set_realm(context,
|
||||||
ctx->cred.client,
|
ctx->cred.client,
|
||||||
*ctx->error.crealm);
|
*ctx->error.crealm);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (krb5_principal_is_krbtgt(context, ctx->cred.server)) {
|
||||||
|
ret = krb5_init_creds_set_service(context, ctx, NULL);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_AS_REQ(&ctx->as_req);
|
||||||
|
memset(&ctx->as_req, 0, sizeof(ctx->as_req));
|
||||||
|
|
||||||
ctx->used_pa_types = 0;
|
ctx->used_pa_types = 0;
|
||||||
} else if (ret == KRB5KDC_ERR_KEY_EXP && ctx->runflags.change_password == 0 && ctx->prompter) {
|
} else if (ret == KRB5KDC_ERR_KEY_EXP && ctx->runflags.change_password == 0 && ctx->prompter) {
|
||||||
@@ -2379,6 +2390,15 @@ krb5_init_creds_step(krb5_context context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->as_req.req_body.cname == NULL) {
|
||||||
|
ret = init_as_req(context, ctx->flags, &ctx->cred,
|
||||||
|
ctx->addrs, ctx->etypes, &ctx->as_req);
|
||||||
|
if (ret) {
|
||||||
|
free_init_creds_ctx(context, ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->as_req.padata) {
|
if (ctx->as_req.padata) {
|
||||||
free_METHOD_DATA(ctx->as_req.padata);
|
free_METHOD_DATA(ctx->as_req.padata);
|
||||||
free(ctx->as_req.padata);
|
free(ctx->as_req.padata);
|
||||||
|
@@ -440,6 +440,7 @@ EXPORTS
|
|||||||
krb5_make_principal
|
krb5_make_principal
|
||||||
krb5_max_sockaddr_size
|
krb5_max_sockaddr_size
|
||||||
krb5_mk_error
|
krb5_mk_error
|
||||||
|
krb5_mk_error_ext
|
||||||
krb5_mk_priv
|
krb5_mk_priv
|
||||||
krb5_mk_rep
|
krb5_mk_rep
|
||||||
krb5_mk_req
|
krb5_mk_req
|
||||||
|
@@ -34,15 +34,16 @@
|
|||||||
#include "krb5_locl.h"
|
#include "krb5_locl.h"
|
||||||
|
|
||||||
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
||||||
krb5_mk_error(krb5_context context,
|
krb5_mk_error_ext(krb5_context context,
|
||||||
krb5_error_code error_code,
|
krb5_error_code error_code,
|
||||||
const char *e_text,
|
const char *e_text,
|
||||||
const krb5_data *e_data,
|
const krb5_data *e_data,
|
||||||
const krb5_principal client,
|
const krb5_principal server,
|
||||||
const krb5_principal server,
|
const PrincipalName *client_name,
|
||||||
time_t *client_time,
|
const Realm *client_realm,
|
||||||
int *client_usec,
|
time_t *client_time,
|
||||||
krb5_data *reply)
|
int *client_usec,
|
||||||
|
krb5_data *reply)
|
||||||
{
|
{
|
||||||
const char *e_text2 = NULL;
|
const char *e_text2 = NULL;
|
||||||
KRB_ERROR msg;
|
KRB_ERROR msg;
|
||||||
@@ -78,10 +79,8 @@ krb5_mk_error(krb5_context context,
|
|||||||
static char unspec[] = "<unspecified realm>";
|
static char unspec[] = "<unspecified realm>";
|
||||||
msg.realm = unspec;
|
msg.realm = unspec;
|
||||||
}
|
}
|
||||||
if(client){
|
msg.crealm = rk_UNCONST(client_realm);
|
||||||
msg.crealm = &client->realm;
|
msg.cname = rk_UNCONST(client_name);
|
||||||
msg.cname = &client->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret);
|
ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret);
|
||||||
if (e_text2)
|
if (e_text2)
|
||||||
@@ -92,3 +91,27 @@ krb5_mk_error(krb5_context context,
|
|||||||
krb5_abortx(context, "internal error in ASN.1 encoder");
|
krb5_abortx(context, "internal error in ASN.1 encoder");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
||||||
|
krb5_mk_error(krb5_context context,
|
||||||
|
krb5_error_code error_code,
|
||||||
|
const char *e_text,
|
||||||
|
const krb5_data *e_data,
|
||||||
|
const krb5_principal client,
|
||||||
|
const krb5_principal server,
|
||||||
|
time_t *client_time,
|
||||||
|
int *client_usec,
|
||||||
|
krb5_data *reply)
|
||||||
|
{
|
||||||
|
const PrincipalName *client_name = NULL;
|
||||||
|
const Realm *client_realm = NULL;
|
||||||
|
|
||||||
|
if (client) {
|
||||||
|
client_realm = &client->realm;
|
||||||
|
client_name = &client->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return krb5_mk_error_ext(context, error_code, e_text, e_data,
|
||||||
|
server, client_name, client_realm,
|
||||||
|
client_time, client_usec, reply);
|
||||||
|
}
|
||||||
|
@@ -595,11 +595,12 @@ verify_logonname(krb5_context context,
|
|||||||
krb5_const_principal principal)
|
krb5_const_principal principal)
|
||||||
{
|
{
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
krb5_principal p2;
|
|
||||||
uint32_t time1, time2;
|
uint32_t time1, time2;
|
||||||
krb5_storage *sp;
|
krb5_storage *sp;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
char *s;
|
char *s = NULL;
|
||||||
|
char *principal_string = NULL;
|
||||||
|
char *logon_string = NULL;
|
||||||
|
|
||||||
sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo,
|
sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo,
|
||||||
logon_name->buffersize);
|
logon_name->buffersize);
|
||||||
@@ -670,31 +671,36 @@ verify_logonname(krb5_context context,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
u8len += 1; /* Add space for NUL */
|
u8len += 1; /* Add space for NUL */
|
||||||
s = malloc(u8len);
|
logon_string = malloc(u8len);
|
||||||
if (s == NULL) {
|
if (logon_string == NULL) {
|
||||||
free(ucs2);
|
free(ucs2);
|
||||||
return krb5_enomem(context);
|
return krb5_enomem(context);
|
||||||
}
|
}
|
||||||
ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len);
|
ret = wind_ucs2utf8(ucs2, ucs2len, logon_string, &u8len);
|
||||||
free(ucs2);
|
free(ucs2);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
free(s);
|
free(logon_string);
|
||||||
krb5_set_error_message(context, ret, "Failed to convert to UTF-8");
|
krb5_set_error_message(context, ret, "Failed to convert to UTF-8");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = krb5_parse_name_flags(context, s,
|
ret = krb5_unparse_name_flags(context, principal,
|
||||||
KRB5_PRINCIPAL_PARSE_NO_REALM |
|
KRB5_PRINCIPAL_UNPARSE_NO_REALM |
|
||||||
KRB5_PRINCIPAL_PARSE_ENTERPRISE, &p2);
|
KRB5_PRINCIPAL_UNPARSE_DISPLAY,
|
||||||
free(s);
|
&principal_string);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
free(logon_string);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) {
|
|
||||||
ret = EINVAL;
|
|
||||||
krb5_set_error_message(context, ret, "PAC logon name mismatch");
|
|
||||||
}
|
}
|
||||||
krb5_free_principal(context, p2);
|
|
||||||
|
ret = strcmp(logon_string, principal_string);
|
||||||
|
if (ret != 0) {
|
||||||
|
ret = EINVAL;
|
||||||
|
krb5_set_error_message(context, ret, "PAC logon name [%s] mismatch principal name [%s]",
|
||||||
|
logon_string, principal_string);
|
||||||
|
}
|
||||||
|
free(logon_string);
|
||||||
|
free(principal_string);
|
||||||
return ret;
|
return ret;
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -433,6 +433,7 @@ HEIMDAL_KRB5_2.0 {
|
|||||||
krb5_make_principal;
|
krb5_make_principal;
|
||||||
krb5_max_sockaddr_size;
|
krb5_max_sockaddr_size;
|
||||||
krb5_mk_error;
|
krb5_mk_error;
|
||||||
|
krb5_mk_error_ext;
|
||||||
krb5_mk_priv;
|
krb5_mk_priv;
|
||||||
krb5_mk_rep;
|
krb5_mk_rep;
|
||||||
krb5_mk_req;
|
krb5_mk_req;
|
||||||
|
@@ -23,6 +23,7 @@ $(libheimntlm_la_OBJECTS): $(srcdir)/version-script.map
|
|||||||
|
|
||||||
libheimntlm_la_LIBADD = \
|
libheimntlm_la_LIBADD = \
|
||||||
../krb5/libkrb5.la \
|
../krb5/libkrb5.la \
|
||||||
|
$(top_builddir)/lib/wind/libwind.la \
|
||||||
$(LIB_hcrypto) \
|
$(LIB_hcrypto) \
|
||||||
$(LIBADD_roken)
|
$(LIBADD_roken)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user